{{ partial "version-banner.html" . }} {{ if not .Site.Params.ui.breadcrumb_disable }}{{ partial "breadcrumb.html" . }}{{ end }} From 98dd79517acef8f25a7be0ebca7290b31783f968 Mon Sep 17 00:00:00 2001 From: Varsha Date: Sat, 31 Oct 2020 04:44:32 -0700 Subject: [PATCH 183/376] docs/olm-integration/generation.md: add optional validator operatorhub docs (#4150) Description of the change: Add doc on validation of custom categories Motivation for the change: Follow up of #4109 Signed-off-by: reinvantveer --- website/content/en/docs/olm-integration/generation.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/website/content/en/docs/olm-integration/generation.md b/website/content/en/docs/olm-integration/generation.md index 65a91f3a16c..89b02c35268 100644 --- a/website/content/en/docs/olm-integration/generation.md +++ b/website/content/en/docs/olm-integration/generation.md @@ -153,6 +153,9 @@ bundle: ... operator-sdk bundle validate ./bundle --select-optional name=operatorhub ``` +Documentation on optional validators: +- [`operatorhub`][operatorhub_validator] + ### Package manifests format A [package manifests][package-manifests] format consists of on-disk manifests (CSV, CRDs and other supported kinds) @@ -320,3 +323,4 @@ being managed, each with a `name` and `url`. [csv-markers]:/docs/building-operators/golang/references/markers [operatorhub]:https://operatorhub.io/ [scorecard]:/docs/advanced-topics/scorecard +[operatorhub_validator]: https://olm.operatorframework.io/docs/tasks/validate-package/#validation From 2788c1fdebc352ac92c7b0771c2053a9d0237eba Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Sat, 31 Oct 2020 12:06:01 -0700 Subject: [PATCH 184/376] internal/*: define ImageVersion, which is set to the most recent (#4083) of operator-sdk repo tag or release commit's future tag. This variable is consumed by ansible-operator, helm-operator, and scorecard plugins Makefile: set IMAGE_VERSION to v1.1.0, and set ImageVersion in ldflags internal/version: removed GoVersion in favor of using runtime.Version() in dependent packages Signed-off-by: reinvantveer --- Makefile | 6 +++++ changelog/fragments/go-version-bug.yaml | 4 ++++ internal/cmd/ansible-operator/version/cmd.go | 2 +- .../cmd/ansible-operator/version/cmd_test.go | 2 +- internal/cmd/helm-operator/version/cmd.go | 2 +- .../cmd/helm-operator/version/cmd_test.go | 2 +- internal/cmd/operator-sdk/version/cmd.go | 2 +- internal/cmd/operator-sdk/version/cmd_test.go | 2 +- internal/plugins/ansible/v1/scaffolds/init.go | 23 ++++++++++++------- .../internal/templates/dockerfile.go | 16 +++++++++---- .../scaffolds/internal/templates/makefile.go | 10 ++++---- internal/plugins/helm/v1/scaffolds/init.go | 15 ++++++------ .../internal/templates/dockerfile.go | 8 ++++++- .../scaffolds/internal/templates/makefile.go | 10 ++++---- internal/plugins/scorecard/init.go | 7 +++--- internal/version/version.go | 15 ++++++------ 16 files changed, 76 insertions(+), 50 deletions(-) create mode 100644 changelog/fragments/go-version-bug.yaml diff --git a/Makefile b/Makefile index 9e05f83e85c..d7d38c14e91 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,10 @@ SHELL = /bin/bash +# IMAGE_VERSION represents the ansible-operator, helm-operator, and scorecard subproject versions. +# This value must be updated to the release tag of the most recent release, a change that must +# occur in the release commit. IMAGE_VERSION will be removed once each subproject that uses this +# version is moved to a separate repo and release process. +export IMAGE_VERSION = v1.1.0 # Build-time variables to inject into binaries export SIMPLE_VERSION = $(shell (test "$(shell git describe)" = "$(shell git describe --abbrev=0)" && echo $(shell git describe)) || echo $(shell git describe --abbrev=0)+git) export GIT_VERSION = $(shell git describe --dirty --tags --always) @@ -20,6 +25,7 @@ GO_BUILD_ARGS = \ -X '$(REPO)/internal/version.GitVersion=$(GIT_VERSION)' \ -X '$(REPO)/internal/version.GitCommit=$(GIT_COMMIT)' \ -X '$(REPO)/internal/version.KubernetesVersion=v$(K8S_VERSION)' \ + -X '$(REPO)/internal/version.ImageVersion=$(IMAGE_VERSION)' \ " \ export GO111MODULE = on diff --git a/changelog/fragments/go-version-bug.yaml b/changelog/fragments/go-version-bug.yaml new file mode 100644 index 00000000000..e4377758e95 --- /dev/null +++ b/changelog/fragments/go-version-bug.yaml @@ -0,0 +1,4 @@ +entries: + - description: > + Removed redundant platform information from `operator-sdk version` output + kind: bugfix diff --git a/internal/cmd/ansible-operator/version/cmd.go b/internal/cmd/ansible-operator/version/cmd.go index 2ec726f339f..4c57673bbe2 100644 --- a/internal/cmd/ansible-operator/version/cmd.go +++ b/internal/cmd/ansible-operator/version/cmd.go @@ -40,5 +40,5 @@ func run() { version = ver.Version } fmt.Printf("ansible-operator version: %q, commit: %q, kubernetes version: %q, go version: %q, GOOS: %q, GOARCH: %q\n", - version, ver.GitCommit, ver.KubernetesVersion, ver.GoVersion, runtime.GOOS, runtime.GOARCH) + version, ver.GitCommit, ver.KubernetesVersion, runtime.Version(), runtime.GOOS, runtime.GOARCH) } diff --git a/internal/cmd/ansible-operator/version/cmd_test.go b/internal/cmd/ansible-operator/version/cmd_test.go index 35487f6825c..8def44ddd9a 100644 --- a/internal/cmd/ansible-operator/version/cmd_test.go +++ b/internal/cmd/ansible-operator/version/cmd_test.go @@ -57,7 +57,7 @@ var _ = Describe("Running a version command", func() { Expect(stdoutString).To(ContainSubstring(fmt.Sprintf("version: %q", version))) Expect(stdoutString).To(ContainSubstring(fmt.Sprintf("commit: %q", ver.GitCommit))) Expect(stdoutString).To(ContainSubstring(fmt.Sprintf("kubernetes version: %q", ver.KubernetesVersion))) - Expect(stdoutString).To(ContainSubstring(fmt.Sprintf("go version: %q", ver.GoVersion))) + Expect(stdoutString).To(ContainSubstring(fmt.Sprintf("go version: %q", runtime.Version()))) Expect(stdoutString).To(ContainSubstring(fmt.Sprintf("GOOS: %q", runtime.GOOS))) Expect(stdoutString).To(ContainSubstring(fmt.Sprintf("GOARCH: %q", runtime.GOARCH))) }) diff --git a/internal/cmd/helm-operator/version/cmd.go b/internal/cmd/helm-operator/version/cmd.go index 38ff3684f2a..832da13117d 100644 --- a/internal/cmd/helm-operator/version/cmd.go +++ b/internal/cmd/helm-operator/version/cmd.go @@ -40,5 +40,5 @@ func run() { version = ver.Version } fmt.Printf("helm-operator version: %q, commit: %q, kubernetes version: %q, go version: %q, GOOS: %q, GOARCH: %q\n", - version, ver.GitCommit, ver.KubernetesVersion, ver.GoVersion, runtime.GOOS, runtime.GOARCH) + version, ver.GitCommit, ver.KubernetesVersion, runtime.Version(), runtime.GOOS, runtime.GOARCH) } diff --git a/internal/cmd/helm-operator/version/cmd_test.go b/internal/cmd/helm-operator/version/cmd_test.go index 35487f6825c..8def44ddd9a 100644 --- a/internal/cmd/helm-operator/version/cmd_test.go +++ b/internal/cmd/helm-operator/version/cmd_test.go @@ -57,7 +57,7 @@ var _ = Describe("Running a version command", func() { Expect(stdoutString).To(ContainSubstring(fmt.Sprintf("version: %q", version))) Expect(stdoutString).To(ContainSubstring(fmt.Sprintf("commit: %q", ver.GitCommit))) Expect(stdoutString).To(ContainSubstring(fmt.Sprintf("kubernetes version: %q", ver.KubernetesVersion))) - Expect(stdoutString).To(ContainSubstring(fmt.Sprintf("go version: %q", ver.GoVersion))) + Expect(stdoutString).To(ContainSubstring(fmt.Sprintf("go version: %q", runtime.Version()))) Expect(stdoutString).To(ContainSubstring(fmt.Sprintf("GOOS: %q", runtime.GOOS))) Expect(stdoutString).To(ContainSubstring(fmt.Sprintf("GOARCH: %q", runtime.GOARCH))) }) diff --git a/internal/cmd/operator-sdk/version/cmd.go b/internal/cmd/operator-sdk/version/cmd.go index d30ade81600..ca4684a23f9 100644 --- a/internal/cmd/operator-sdk/version/cmd.go +++ b/internal/cmd/operator-sdk/version/cmd.go @@ -36,5 +36,5 @@ func NewCmd() *cobra.Command { func run() { fmt.Printf("operator-sdk version: %q, commit: %q, kubernetes version: %q, go version: %q, GOOS: %q, GOARCH: %q\n", - ver.GitVersion, ver.GitCommit, ver.KubernetesVersion, ver.GoVersion, runtime.GOOS, runtime.GOARCH) + ver.GitVersion, ver.GitCommit, ver.KubernetesVersion, runtime.Version(), runtime.GOOS, runtime.GOARCH) } diff --git a/internal/cmd/operator-sdk/version/cmd_test.go b/internal/cmd/operator-sdk/version/cmd_test.go index 35487f6825c..8def44ddd9a 100644 --- a/internal/cmd/operator-sdk/version/cmd_test.go +++ b/internal/cmd/operator-sdk/version/cmd_test.go @@ -57,7 +57,7 @@ var _ = Describe("Running a version command", func() { Expect(stdoutString).To(ContainSubstring(fmt.Sprintf("version: %q", version))) Expect(stdoutString).To(ContainSubstring(fmt.Sprintf("commit: %q", ver.GitCommit))) Expect(stdoutString).To(ContainSubstring(fmt.Sprintf("kubernetes version: %q", ver.KubernetesVersion))) - Expect(stdoutString).To(ContainSubstring(fmt.Sprintf("go version: %q", ver.GoVersion))) + Expect(stdoutString).To(ContainSubstring(fmt.Sprintf("go version: %q", runtime.Version()))) Expect(stdoutString).To(ContainSubstring(fmt.Sprintf("GOOS: %q", runtime.GOOS))) Expect(stdoutString).To(ContainSubstring(fmt.Sprintf("GOARCH: %q", runtime.GOARCH))) }) diff --git a/internal/plugins/ansible/v1/scaffolds/init.go b/internal/plugins/ansible/v1/scaffolds/init.go index 3340ed36729..8a36534b04a 100644 --- a/internal/plugins/ansible/v1/scaffolds/init.go +++ b/internal/plugins/ansible/v1/scaffolds/init.go @@ -22,6 +22,7 @@ import ( "sigs.k8s.io/kubebuilder/pkg/model/config" "sigs.k8s.io/kubebuilder/pkg/plugin/scaffold" + "github.com/operator-framework/operator-sdk/internal/kubebuilder/machinery" "github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/scaffolds/internal/templates" "github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/scaffolds/internal/templates/config/kdefault" "github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/scaffolds/internal/templates/config/manager" @@ -32,18 +33,20 @@ import ( "github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mdefault" "github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mkind" "github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/scaffolds/internal/templates/playbooks" - ansibleroles "github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/scaffolds/internal/templates/roles" - - "github.com/operator-framework/operator-sdk/internal/kubebuilder/machinery" + "github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/scaffolds/internal/templates/roles" + "github.com/operator-framework/operator-sdk/internal/version" ) const ( - // KustomizeVersion is the kubernetes-sigs/kustomize version to be used in the project - KustomizeVersion = "v3.5.4" + // kustomizeVersion is the sigs.k8s.io/kustomize version to be used in the project + kustomizeVersion = "v3.5.4" imageName = "controller:latest" ) +// ansibleOperatorVersion is set to the version of ansible-operator at compile-time. +var ansibleOperatorVersion = version.ImageVersion + var _ scaffold.Scaffolder = &initScaffolder{} type initScaffolder struct { @@ -79,7 +82,12 @@ func (s *initScaffolder) Scaffold() error { func (s *initScaffolder) scaffold() error { return machinery.NewScaffold().Execute( s.newUniverse(), - &templates.Dockerfile{}, + &templates.Dockerfile{AnsibleOperatorVersion: ansibleOperatorVersion}, + &templates.Makefile{ + Image: imageName, + KustomizeVersion: kustomizeVersion, + AnsibleOperatorVersion: ansibleOperatorVersion, + }, &templates.GitIgnore{}, &templates.RequirementsYml{}, &templates.Watches{}, @@ -103,8 +111,7 @@ func (s *initScaffolder) scaffold() error { &kdefault.Kustomize{}, &kdefault.AuthProxyPatch{}, - &templates.Makefile{}, - &ansibleroles.Placeholder{}, + &roles.Placeholder{}, &playbooks.Placeholder{}, &mdefault.Converge{}, diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/dockerfile.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/dockerfile.go index d36779a9863..0ded63efd59 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/dockerfile.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/dockerfile.go @@ -15,12 +15,11 @@ package templates import ( - "strings" + "errors" "sigs.k8s.io/kubebuilder/pkg/model/file" "github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/constants" - "github.com/operator-framework/operator-sdk/internal/version" ) var _ file.Template = &Dockerfile{} @@ -28,8 +27,10 @@ var _ file.Template = &Dockerfile{} // Dockerfile scaffolds a Dockerfile for building a main type Dockerfile struct { file.TemplateMixin - ImageTag string + // AnsibleOperatorVersion is the version of the Dockerfile's base image. + AnsibleOperatorVersion string + // These variables are always overwritten. RolesDir string PlaybooksDir string } @@ -41,13 +42,18 @@ func (f *Dockerfile) SetTemplateDefaults() error { } f.TemplateBody = dockerfileTemplate + + if f.AnsibleOperatorVersion == "" { + return errors.New("ansible-operator version is required in scaffold") + } + f.RolesDir = constants.RolesDir f.PlaybooksDir = constants.PlaybooksDir - f.ImageTag = strings.TrimSuffix(version.Version, "+git") + return nil } -const dockerfileTemplate = `FROM quay.io/operator-framework/ansible-operator:{{.ImageTag}} +const dockerfileTemplate = `FROM quay.io/operator-framework/ansible-operator:{{ .AnsibleOperatorVersion }} COPY requirements.yml ${HOME}/requirements.yml RUN ansible-galaxy collection install -r ${HOME}/requirements.yml \ diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/makefile.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/makefile.go index 52e3187bb10..eed94ddd3bf 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/makefile.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/makefile.go @@ -18,11 +18,9 @@ limitations under the License. package templates import ( - "strings" + "errors" "sigs.k8s.io/kubebuilder/pkg/model/file" - - "github.com/operator-framework/operator-sdk/internal/version" ) var _ file.Template = &Makefile{} @@ -37,7 +35,7 @@ type Makefile struct { // Kustomize version to use in the project KustomizeVersion string - // AnsibleOperatorVersion is the version of the base image and operator binary used in the project + // AnsibleOperatorVersion is the version of the ansible-operator binary downloaded by the Makefile. AnsibleOperatorVersion string } @@ -56,11 +54,11 @@ func (f *Makefile) SetTemplateDefaults() error { } if f.KustomizeVersion == "" { - f.KustomizeVersion = "v3.5.4" + return errors.New("kustomize version is required in scaffold") } if f.AnsibleOperatorVersion == "" { - f.AnsibleOperatorVersion = strings.TrimSuffix(version.Version, "+git") + return errors.New("ansible-operator version is required in scaffold") } return nil diff --git a/internal/plugins/helm/v1/scaffolds/init.go b/internal/plugins/helm/v1/scaffolds/init.go index 0dc4ea68ed4..6c37374ae30 100644 --- a/internal/plugins/helm/v1/scaffolds/init.go +++ b/internal/plugins/helm/v1/scaffolds/init.go @@ -19,7 +19,6 @@ package scaffolds import ( "os" - "strings" "sigs.k8s.io/kubebuilder/pkg/model" "sigs.k8s.io/kubebuilder/pkg/model/config" @@ -36,14 +35,14 @@ import ( ) const ( - // KustomizeVersion is the kubernetes-sigs/kustomize version to be used in the project - KustomizeVersion = "v3.5.4" + // kustomizeVersion is the sigs.k8s.io/kustomize version to be used in the project + kustomizeVersion = "v3.5.4" imageName = "controller:latest" ) -// HelmOperatorVersion is the version of the helm binary used in the Makefile -var HelmOperatorVersion = strings.TrimSuffix(version.Version, "+git") +// helmOperatorVersion is set to the version of helm-operator at compile-time. +var helmOperatorVersion = version.ImageVersion var _ scaffold.Scaffolder = &initScaffolder{} @@ -84,13 +83,13 @@ func (s *initScaffolder) scaffold() error { return machinery.NewScaffold().Execute( s.newUniverse(), &templates.Dockerfile{ - HelmOperatorVersion: HelmOperatorVersion, + HelmOperatorVersion: helmOperatorVersion, }, &templates.GitIgnore{}, &templates.Makefile{ Image: imageName, - KustomizeVersion: KustomizeVersion, - HelmOperatorVersion: HelmOperatorVersion, + KustomizeVersion: kustomizeVersion, + HelmOperatorVersion: helmOperatorVersion, }, &templates.Watches{}, &rbac.AuthProxyRole{}, diff --git a/internal/plugins/helm/v1/scaffolds/internal/templates/dockerfile.go b/internal/plugins/helm/v1/scaffolds/internal/templates/dockerfile.go index 7c542765193..f02fc1b546b 100644 --- a/internal/plugins/helm/v1/scaffolds/internal/templates/dockerfile.go +++ b/internal/plugins/helm/v1/scaffolds/internal/templates/dockerfile.go @@ -15,6 +15,8 @@ package templates import ( + "errors" + "sigs.k8s.io/kubebuilder/pkg/model/file" ) @@ -24,7 +26,7 @@ var _ file.Template = &Dockerfile{} type Dockerfile struct { file.TemplateMixin - // HelmOperatorVersion is the version of the base image and operator binary used in the project + // HelmOperatorVersion is the version of the Dockerfile's base image. HelmOperatorVersion string } @@ -36,6 +38,10 @@ func (f *Dockerfile) SetTemplateDefaults() error { f.TemplateBody = dockerfileTemplate + if f.HelmOperatorVersion == "" { + return errors.New("helm-operator version is required in scaffold") + } + return nil } diff --git a/internal/plugins/helm/v1/scaffolds/internal/templates/makefile.go b/internal/plugins/helm/v1/scaffolds/internal/templates/makefile.go index b57b87821fd..95adbe5dba4 100644 --- a/internal/plugins/helm/v1/scaffolds/internal/templates/makefile.go +++ b/internal/plugins/helm/v1/scaffolds/internal/templates/makefile.go @@ -18,11 +18,9 @@ limitations under the License. package templates import ( - "strings" + "errors" "sigs.k8s.io/kubebuilder/pkg/model/file" - - "github.com/operator-framework/operator-sdk/internal/version" ) var _ file.Template = &Makefile{} @@ -37,7 +35,7 @@ type Makefile struct { // Kustomize version to use in the project KustomizeVersion string - // HelmOperatorVersion is the version of the base image and operator binary used in the project + // HelmOperatorVersion is the version of the helm-operator binary downloaded by the Makefile. HelmOperatorVersion string } @@ -56,11 +54,11 @@ func (f *Makefile) SetTemplateDefaults() error { } if f.KustomizeVersion == "" { - f.KustomizeVersion = "v3.5.4" + return errors.New("kustomize version is required in scaffold") } if f.HelmOperatorVersion == "" { - f.HelmOperatorVersion = strings.TrimSuffix(version.Version, "+git") + return errors.New("helm-operator version is required in scaffold") } return nil diff --git a/internal/plugins/scorecard/init.go b/internal/plugins/scorecard/init.go index f128516e3ad..6db3d2510ec 100644 --- a/internal/plugins/scorecard/init.go +++ b/internal/plugins/scorecard/init.go @@ -20,7 +20,6 @@ import ( "io/ioutil" "os" "path/filepath" - "strings" "text/template" "github.com/operator-framework/api/pkg/apis/scorecard/v1alpha3" @@ -33,6 +32,9 @@ import ( "github.com/operator-framework/operator-sdk/internal/version" ) +// scorecardVersion is set to the version of scorecard at compile-time. +var scorecardVersion = version.ImageVersion + const ( // kustomization.yaml file template for the scorecard componentconfig. This should always be written to // config/scorecard/kustomization.yaml since it only references files in config. @@ -63,8 +65,7 @@ const ( ) // defaultTestImageTag points to the latest-released image. -var defaultTestImageTag = fmt.Sprintf("quay.io/operator-framework/scorecard-test:%s", - strings.TrimSuffix(version.Version, "+git")) +var defaultTestImageTag = fmt.Sprintf("quay.io/operator-framework/scorecard-test:%s", scorecardVersion) // defaultDir is the default directory in which to generate kustomize bases and the kustomization.yaml. var defaultDir = filepath.Join("config", "scorecard") diff --git a/internal/version/version.go b/internal/version/version.go index e3e1573a4bf..71ccfee4308 100644 --- a/internal/version/version.go +++ b/internal/version/version.go @@ -14,16 +14,17 @@ package version -import ( - "fmt" - "runtime" -) - -//var needs to be used instead of const for ldflags +// var needs to be used instead of const for ldflags var ( Version = "unknown" GitVersion = "unknown" GitCommit = "unknown" KubernetesVersion = "unknown" - GoVersion = fmt.Sprintf("%s %s/%s", runtime.Version(), runtime.GOOS, runtime.GOARCH) + + // ImageVersion represents the ansible-operator, helm-operator, and scorecard subproject versions, + // which is used in each plugin to specify binary and/or image versions. This is set to the + // most recent operator-sdk release tag such that samples are generated with the correct versions + // in a release commit. Once each element that uses this version is moved to a separate repo + // and release process, this variable will be removed. + ImageVersion = "unknown" ) From b9baabfd54f361bc69b67cb44f3ea7dd212ae312 Mon Sep 17 00:00:00 2001 From: Joe Lanford Date: Mon, 2 Nov 2020 09:44:54 -0500 Subject: [PATCH 185/376] test/e2e-helm: use generated helm sample (#4134) Signed-off-by: reinvantveer --- internal/testutils/utils.go | 1 - test/e2e-helm/e2e_helm_cluster_test.go | 49 +++++++++++++------------- test/e2e-helm/e2e_helm_suite_test.go | 33 +++++++---------- 3 files changed, 37 insertions(+), 46 deletions(-) diff --git a/internal/testutils/utils.go b/internal/testutils/utils.go index 52a36726c73..8f1d2076ed2 100644 --- a/internal/testutils/utils.go +++ b/internal/testutils/utils.go @@ -28,7 +28,6 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - kbtestutils "sigs.k8s.io/kubebuilder/test/e2e/utils" ) diff --git a/test/e2e-helm/e2e_helm_cluster_test.go b/test/e2e-helm/e2e_helm_cluster_test.go index 5068959284b..23cdbdbbd22 100644 --- a/test/e2e-helm/e2e_helm_cluster_test.go +++ b/test/e2e-helm/e2e_helm_cluster_test.go @@ -30,13 +30,11 @@ import ( var _ = Describe("Running Helm projects", func() { var controllerPodName string + var metricsClusterRoleBindingName string Context("built with operator-sdk", func() { BeforeEach(func() { - By("enabling Prometheus via the kustomization.yaml") - Expect(kbtestutils.UncommentCode( - filepath.Join(tc.Dir, "config", "default", "kustomization.yaml"), - "#- ../prometheus", "#")).To(Succeed()) + metricsClusterRoleBindingName = fmt.Sprintf("%s-metrics-reader", tc.ProjectName) By("deploying project on the cluster") err := tc.Make("deploy", "IMG="+tc.ImageName) @@ -53,7 +51,7 @@ var _ = Describe("Running Helm projects", func() { By("cleaning up permissions") _, _ = tc.Kubectl.Command("delete", "clusterrolebinding", - fmt.Sprintf("metrics-%s", tc.TestSuffix)) + metricsClusterRoleBindingName) By("undeploy project") _ = tc.Make("undeploy") @@ -110,19 +108,24 @@ var _ = Describe("Running Helm projects", func() { _, err := tc.Kubectl.Get( true, "ServiceMonitor", - fmt.Sprintf("e2e-%s-controller-manager-metrics-monitor", tc.TestSuffix)) + fmt.Sprintf("%s-controller-manager-metrics-monitor", tc.ProjectName)) Expect(err).NotTo(HaveOccurred()) By("ensuring the created metrics Service for the manager") _, err = tc.Kubectl.Get( true, "Service", - fmt.Sprintf("e2e-%s-controller-manager-metrics-service", tc.TestSuffix)) + fmt.Sprintf("%s-controller-manager-metrics-service", tc.ProjectName)) Expect(err).NotTo(HaveOccurred()) - By("creating an instance of release(CR)") sampleFile := filepath.Join("config", "samples", fmt.Sprintf("%s_%s_%s.yaml", tc.Group, tc.Version, strings.ToLower(tc.Kind))) + + By("updating replicaCount to 1 in the CR manifest") + err = testutils.ReplaceInFile(filepath.Join(tc.Dir, sampleFile), "replicaCount: 3", "replicaCount: 1") + Expect(err).NotTo(HaveOccurred()) + + By("creating an instance of release(CR)") _, err = tc.Kubectl.Apply(false, "-f", sampleFile) Expect(err).NotTo(HaveOccurred()) @@ -141,14 +144,14 @@ var _ = Describe("Running Helm projects", func() { Expect(err).NotTo(HaveOccurred()) Expect(len(releaseName)).NotTo(BeIdenticalTo(0)) - By("checking the release(CR) deployment status") + By("checking the release(CR) statefulset status") verifyReleaseUp := func() string { output, err := tc.Kubectl.Command( - "rollout", "status", "deployment", releaseName) + "rollout", "status", "statefulset", releaseName) Expect(err).NotTo(HaveOccurred()) return output } - Eventually(verifyReleaseUp, time.Minute, time.Second).Should(ContainSubstring("successfully rolled out")) + Eventually(verifyReleaseUp, time.Minute, time.Second).Should(ContainSubstring("statefulset rolling update complete")) By("ensuring the created Service for the release(CR)") crServiceName, err := tc.Kubectl.Get( @@ -158,19 +161,19 @@ var _ = Describe("Running Helm projects", func() { Expect(err).NotTo(HaveOccurred()) Expect(len(crServiceName)).NotTo(BeIdenticalTo(0)) - By("scaling deployment replicas to 2") + By("scaling statefulset replicas to 2") _, err = tc.Kubectl.Command( - "scale", "deployment", releaseName, "--replicas", "2") + "scale", "statefulset", releaseName, "--replicas", "2") Expect(err).NotTo(HaveOccurred()) - By("verifying the deployment automatically scales back down to 1") + By("verifying the statefulset automatically scales back down to 1") verifyRelease := func() error { replicas, err := tc.Kubectl.Get( false, - "deployment", releaseName, "-o", "jsonpath={..spec.replicas}") + "statefulset", releaseName, "-o", "jsonpath={..spec.replicas}") Expect(err).NotTo(HaveOccurred()) if replicas != "1" { - return fmt.Errorf("release(CR) deployment with %s replicas", replicas) + return fmt.Errorf("release(CR) statefulset with %s replicas", replicas) } return nil } @@ -193,14 +196,14 @@ var _ = Describe("Running Helm projects", func() { Eventually(managerContainerLogsAfterUpdateCR, time.Minute, time.Second).Should( ContainSubstring("Upgraded release")) - By("checking Deployment replicas spec is equals 2") + By("checking StatefulSet replicas spec is equals 2") verifyReleaseUpgrade := func() error { replicas, err := tc.Kubectl.Get( false, - "deployment", releaseName, "-o", "jsonpath={..spec.replicas}") + "statefulset", releaseName, "-o", "jsonpath={..spec.replicas}") Expect(err).NotTo(HaveOccurred()) if replicas != "2" { - return fmt.Errorf("release(CR) deployment with %s replicas", replicas) + return fmt.Errorf("release(CR) statefulset with %s replicas", replicas) } return nil } @@ -209,9 +212,8 @@ var _ = Describe("Running Helm projects", func() { By("granting permissions to access the metrics and read the token") _, err = tc.Kubectl.Command( "create", - "clusterrolebinding", - fmt.Sprintf("metrics-%s", tc.TestSuffix), - fmt.Sprintf("--clusterrole=e2e-%s-metrics-reader", tc.TestSuffix), + "clusterrolebinding", metricsClusterRoleBindingName, + fmt.Sprintf("--clusterrole=%s-metrics-reader", tc.ProjectName), fmt.Sprintf("--serviceaccount=%s:default", tc.Kubectl.Namespace)) Expect(err).NotTo(HaveOccurred()) @@ -232,8 +234,7 @@ var _ = Describe("Running Helm projects", func() { cmdOpts := []string{ "run", "--generator=run-pod/v1", "curl", "--image=curlimages/curl:7.68.0", "--restart=OnFailure", "--", "curl", "-v", "-k", "-H", fmt.Sprintf(`Authorization: Bearer %s`, token), - fmt.Sprintf("https://e2e-%v-controller-manager-metrics-service.e2e-%v-system.svc:8443/metrics", - tc.TestSuffix, tc.TestSuffix), + fmt.Sprintf("https://%s-controller-manager-metrics-service.%s.svc:8443/metrics", tc.ProjectName, tc.Kubectl.Namespace), } _, err = tc.Kubectl.CommandInNamespace(cmdOpts...) Expect(err).NotTo(HaveOccurred()) diff --git a/test/e2e-helm/e2e_helm_suite_test.go b/test/e2e-helm/e2e_helm_suite_test.go index a01b464c3dd..12e96f845dd 100644 --- a/test/e2e-helm/e2e_helm_suite_test.go +++ b/test/e2e-helm/e2e_helm_suite_test.go @@ -15,6 +15,8 @@ package e2e_helm_test import ( + "fmt" + "os/exec" "path/filepath" "testing" @@ -45,8 +47,16 @@ var _ = BeforeSuite(func() { tc, err = testutils.NewTestContext(testutils.BinaryName, "GO111MODULE=on") Expect(err).NotTo(HaveOccurred()) - By("creating a new directory") - Expect(tc.Prepare()).To(Succeed()) + tc.Domain = "example.com" + tc.Group = "cache" + tc.Version = "v1alpha1" + tc.Kind = "Memcached" + tc.Resources = "memcacheds" + tc.ProjectName = "memcached-operator" + tc.Kubectl.Namespace = fmt.Sprintf("%s-system", tc.ProjectName) + + By("copying sample to a temporary e2e directory") + Expect(exec.Command("cp", "-r", "../../testdata/helm/memcached-operator", tc.Dir).Run()).To(Succeed()) By("fetching the current-context") tc.Kubectx, err = tc.Kubectl.Command("config", "current-context") @@ -55,33 +65,14 @@ var _ = BeforeSuite(func() { By("preparing the prerequisites on cluster") tc.InstallPrerequisites() - By("initializing a Helm project") - err = tc.Init( - "--plugins", "helm", - "--project-version", "3-alpha", - "--domain", tc.Domain) - Expect(err).NotTo(HaveOccurred()) - By("using dev image for scorecard-test") err = tc.ReplaceScorecardImagesForDev() Expect(err).NotTo(HaveOccurred()) - By("creating an API definition") - err = tc.CreateAPI( - "--group", tc.Group, - "--version", tc.Version, - "--kind", tc.Kind) - Expect(err).NotTo(HaveOccurred()) - By("replacing project Dockerfile to use Helm base image with the dev tag") err = testutils.ReplaceRegexInFile(filepath.Join(tc.Dir, "Dockerfile"), "quay.io/operator-framework/helm-operator:.*", "quay.io/operator-framework/helm-operator:dev") Expect(err).Should(Succeed()) - By("turning off interactive prompts for all generation tasks.") - replace := "operator-sdk generate kustomize manifests" - err = testutils.ReplaceInFile(filepath.Join(tc.Dir, "Makefile"), replace, replace+" --interactive=false") - Expect(err).Should(Succeed()) - By("checking the kustomize setup") err = tc.Make("kustomize") Expect(err).NotTo(HaveOccurred()) From b289844dcf940c86844e4c0013e1b2513a57ba98 Mon Sep 17 00:00:00 2001 From: Alessandro Rossi <4215912+kubealex@users.noreply.github.com> Date: Mon, 2 Nov 2020 16:22:00 +0100 Subject: [PATCH 186/376] docs/building-operators/helm/tutorial: remove unsupported 'operator-sdk run local' (#4159) Related to #4158 - Removing the choice to run it locally with operator-sdk run local that is not supported. Signed-off-by: reinvantveer --- .../docs/building-operators/helm/tutorial.md | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/website/content/en/docs/building-operators/helm/tutorial.md b/website/content/en/docs/building-operators/helm/tutorial.md index 39168583bcc..02273bf636b 100644 --- a/website/content/en/docs/building-operators/helm/tutorial.md +++ b/website/content/en/docs/building-operators/helm/tutorial.md @@ -206,23 +206,7 @@ nginx-operator-controller-manager 1/1 1 1 1 This method is preferred during the development cycle to speed up deployment and testing. Run the operator locally with the default Kubernetes config file present at -`$HOME/.kube/config`: - -```sh -$ make run -INFO[0000] Go Version: go1.10.3 -INFO[0000] Go OS/Arch: linux/amd64 -INFO[0000] operator-sdk Version: v0.1.1+git -``` - -Run the operator locally with a provided Kubernetes config file: - -```sh -$ operator-sdk run local --kubeconfig= -INFO[0000] Go Version: go1.10.3 -INFO[0000] Go OS/Arch: linux/amd64 -INFO[0000] operator-sdk Version: v0.2.0+git -``` +`$HOME/.kube/config` via the Makefile target `make run`. ### 3. Deploy your Operator with the Operator Lifecycle Manager (OLM) From 6aa375fbd72d2a9815d3779156d07bd0a58fa064 Mon Sep 17 00:00:00 2001 From: Tim Flannagan Date: Mon, 2 Nov 2020 11:19:39 -0500 Subject: [PATCH 187/376] website: Fix the watches.yaml backticks in the Ansible migration guide (#4164) Update the ansible/migration.md documentation, adding the closing backtick to the missing watches.yaml mentions. Signed-off-by: reinvantveer --- .../content/en/docs/building-operators/ansible/migration.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/content/en/docs/building-operators/ansible/migration.md b/website/content/en/docs/building-operators/ansible/migration.md index 05f48573e14..825d6ffd8ad 100644 --- a/website/content/en/docs/building-operators/ansible/migration.md +++ b/website/content/en/docs/building-operators/ansible/migration.md @@ -88,9 +88,9 @@ spec: size: 3 ``` -### Migrating `watches.yaml +### Migrating `watches.yaml` -Update the `watches.yaml` file with your `roles/playbooks` and check if you have custom options in the `watches.yaml` file of your existing project. If so, update the new `watches.yaml file to match. +Update the `watches.yaml` file with your `roles/playbooks` and check if you have custom options in the `watches.yaml` file of your existing project. If so, update the new `watches.yaml` file to match. In our example, we will replace `# FIXME: Specify the role or playbook for this resource.` with our previous role and it will look like: From 8f534964552c4707483eb8d395efea092df4bff6 Mon Sep 17 00:00:00 2001 From: Austin Macdonald Date: Mon, 2 Nov 2020 16:19:58 -0500 Subject: [PATCH 188/376] Docs: Re-enable compact left-side bar (#4167) Without this feature, the left bar is far too long to be useful. Signed-off-by: reinvantveer --- website/config.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/website/config.toml b/website/config.toml index f4d8f435ee0..636cd10ca17 100644 --- a/website/config.toml +++ b/website/config.toml @@ -117,6 +117,8 @@ algolia_docsearch = false # User interface configuration [params.ui] +# Enable to show the side bar menu in its compact state. +sidebar_menu_compact = true # Set to true to disable breadcrumb navigation. breadcrumb_disable = false # Set to true to hide the sidebar search box (the top nav search box will still be displayed if search is enabled) From b485b877e45f353e6241d41d7c0e4e0c347cabc0 Mon Sep 17 00:00:00 2001 From: Joe Lanford Date: Mon, 2 Nov 2020 17:06:28 -0500 Subject: [PATCH 189/376] operator-sdk/internal/generate: fix CSV path segments for multi-field structs (#4166) Co-authored-by: Eric Stroczynski Signed-off-by: reinvantveer --- .../fix-csv-generate-path-segments.yaml | 5 +++ .../bases/definitions/ast.go | 4 ++- ...ith-ui-metadata.clusterserviceversion.yaml | 29 ++++++++++++++++ ...cached-operator.clusterserviceversion.yaml | 29 ++++++++++++++++ .../go/api/v1alpha1/memcached_types.go | 34 +++++++++++++++++++ 5 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 changelog/fragments/fix-csv-generate-path-segments.yaml diff --git a/changelog/fragments/fix-csv-generate-path-segments.yaml b/changelog/fragments/fix-csv-generate-path-segments.yaml new file mode 100644 index 00000000000..7a675b3b19f --- /dev/null +++ b/changelog/fragments/fix-csv-generate-path-segments.yaml @@ -0,0 +1,5 @@ +entries: + - description: > + Fixed an issue during CSV generation that caused incorrect paths to + be used in `specDescriptors` and `statusDescriptors`. + kind: "bugfix" diff --git a/internal/generate/clusterserviceversion/bases/definitions/ast.go b/internal/generate/clusterserviceversion/bases/definitions/ast.go index 6ecbb08cf17..bdfad9fb42f 100644 --- a/internal/generate/clusterserviceversion/bases/definitions/ast.go +++ b/internal/generate/clusterserviceversion/bases/definitions/ast.go @@ -66,9 +66,11 @@ func (g generator) getMarkedChildrenOfField(root markers.FieldInfo) (map[string] } // Create a new set of path segments using the parent's segments // and add the field to the next fields to search. + parentSegments := make([]string, len(field.pathSegments), len(field.pathSegments)+1) + copy(parentSegments, field.pathSegments) f := &fieldInfo{ FieldInfo: finfo, - pathSegments: append(field.pathSegments, segment), + pathSegments: append(parentSegments, segment), } fields = append(fields, f) // Marked fields get collected for the caller to parse. diff --git a/internal/generate/testdata/clusterserviceversions/bases/with-ui-metadata.clusterserviceversion.yaml b/internal/generate/testdata/clusterserviceversions/bases/with-ui-metadata.clusterserviceversion.yaml index c613212c873..d2c60cd35ad 100644 --- a/internal/generate/testdata/clusterserviceversions/bases/with-ui-metadata.clusterserviceversion.yaml +++ b/internal/generate/testdata/clusterserviceversions/bases/with-ui-metadata.clusterserviceversion.yaml @@ -15,6 +15,35 @@ spec: kind: Memcached name: memcacheds.cache.example.com specDescriptors: + - description: List of Providers + displayName: Providers + path: providers + - description: Foo represents the Foo provider + displayName: Foo Provider + path: providers[0].foo + - description: CredentialsSecret is a reference to a secret containing authentication details for the Foo server + displayName: Secret Containing the Credentials + path: providers[0].foo.credentialsSecret + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Secret + - description: Key represents the specific key to reference from the secret + displayName: Key within the secret + path: providers[0].foo.credentialsSecret.key + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:advanced + - urn:alm:descriptor:com.tectonic.ui:text + - description: Name represents the name of the secret + displayName: Name of the secret + path: providers[0].foo.credentialsSecret.name + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:advanced + - urn:alm:descriptor:com.tectonic.ui:text + - description: Namespace represents the namespace containing the secret + displayName: Namespace containing the secret + path: providers[0].foo.credentialsSecret.namespace + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:advanced + - urn:alm:descriptor:com.tectonic.ui:text - description: Size is the size of the memcached deployment displayName: Size path: size diff --git a/internal/generate/testdata/clusterserviceversions/output/memcached-operator.clusterserviceversion.yaml b/internal/generate/testdata/clusterserviceversions/output/memcached-operator.clusterserviceversion.yaml index fc8cd8a179a..d16c653170f 100644 --- a/internal/generate/testdata/clusterserviceversions/output/memcached-operator.clusterserviceversion.yaml +++ b/internal/generate/testdata/clusterserviceversions/output/memcached-operator.clusterserviceversion.yaml @@ -27,6 +27,35 @@ spec: kind: Memcached name: memcacheds.cache.example.com specDescriptors: + - description: List of Providers + displayName: Providers + path: providers + - description: Foo represents the Foo provider + displayName: Foo Provider + path: providers[0].foo + - description: CredentialsSecret is a reference to a secret containing authentication details for the Foo server + displayName: Secret Containing the Credentials + path: providers[0].foo.credentialsSecret + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Secret + - description: Key represents the specific key to reference from the secret + displayName: Key within the secret + path: providers[0].foo.credentialsSecret.key + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:advanced + - urn:alm:descriptor:com.tectonic.ui:text + - description: Name represents the name of the secret + displayName: Name of the secret + path: providers[0].foo.credentialsSecret.name + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:advanced + - urn:alm:descriptor:com.tectonic.ui:text + - description: Namespace represents the namespace containing the secret + displayName: Namespace containing the secret + path: providers[0].foo.credentialsSecret.namespace + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:advanced + - urn:alm:descriptor:com.tectonic.ui:text - description: Size is the size of the memcached deployment displayName: Size path: size diff --git a/internal/generate/testdata/go/api/v1alpha1/memcached_types.go b/internal/generate/testdata/go/api/v1alpha1/memcached_types.go index 99b77521bf4..ea5b3d6dd35 100644 --- a/internal/generate/testdata/go/api/v1alpha1/memcached_types.go +++ b/internal/generate/testdata/go/api/v1alpha1/memcached_types.go @@ -23,6 +23,40 @@ type MemcachedSpec struct { // Size is the size of the memcached deployment // +operator-sdk:csv:customresourcedefinitions:type=spec Size int32 `json:"size"` + + // List of Providers + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Providers" + Providers []Provider `json:"providers,omitempty"` +} + +// Provider represents the container for a single provider +type Provider struct { + // Foo represents the Foo provider + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Foo Provider" + Foo *FooProvider `json:"foo,omitempty"` +} + +// FooProvider represents integration with Foo +type FooProvider struct { + // CredentialsSecret is a reference to a secret containing authentication details for the Foo server + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Secret Containing the Credentials",xDescriptors="urn:alm:descriptor:io.kubernetes:Secret" + // +kubebuilder:validation:Required + CredentialsSecret *SecretRef `json:"credentialsSecret"` +} + +// SecretRef represents a reference to an item within a Secret +type SecretRef struct { + // Name represents the name of the secret + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Name of the secret",xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:com.tectonic.ui:text"} + Name string `json:"name"` + + // Namespace represents the namespace containing the secret + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Namespace containing the secret",xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:com.tectonic.ui:text"} + Namespace string `json:"namespace"` + + // Key represents the specific key to reference from the secret + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Key within the secret",xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced","urn:alm:descriptor:com.tectonic.ui:text"} + Key string `json:"key,omitempty"` } // MemcachedStatus defines the observed state of Memcached From a656aa9e468784988e715c534253a3eef2120168 Mon Sep 17 00:00:00 2001 From: Camila Macedo Date: Wed, 4 Nov 2020 14:12:23 +0000 Subject: [PATCH 190/376] testutils/cleanup: remove InstallOLM method that is no lonnger used (#4155) Signed-off-by: reinvantveer --- internal/testutils/utils.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/internal/testutils/utils.go b/internal/testutils/utils.go index 8f1d2076ed2..8a8283ddd34 100644 --- a/internal/testutils/utils.go +++ b/internal/testutils/utils.go @@ -59,12 +59,6 @@ func NewTestContext(binary string, env ...string) (tc TestContext, err error) { return tc, err } -// InstallOLM runs 'operator-sdk olm install' and returns any errors emitted by that command. -func (tc TestContext) InstallOLM() error { - err := tc.InstallOLMVersion("latest") - return err -} - // InstallOLM runs 'operator-sdk olm install' for specific version // and returns any errors emitted by that command. func (tc TestContext) InstallOLMVersion(version string) error { From 8dc6a636826ed57d9519c679eb1dabadd0f38f48 Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Wed, 4 Nov 2020 10:58:48 -0800 Subject: [PATCH 191/376] internal/olm/installer: prepend 'v' to semvers >= 0.17.0 (#4181) Signed-off-by: reinvantveer --- changelog/fragments/olm-version-v.yaml | 4 + internal/olm/installer/client.go | 21 ++++- internal/olm/installer/client_test.go | 80 +++++++++++++++++++ .../olm/installer/installer_suite_test.go | 27 +++++++ 4 files changed, 130 insertions(+), 2 deletions(-) create mode 100644 changelog/fragments/olm-version-v.yaml create mode 100644 internal/olm/installer/client_test.go create mode 100644 internal/olm/installer/installer_suite_test.go diff --git a/changelog/fragments/olm-version-v.yaml b/changelog/fragments/olm-version-v.yaml new file mode 100644 index 00000000000..b49e302d5c6 --- /dev/null +++ b/changelog/fragments/olm-version-v.yaml @@ -0,0 +1,4 @@ +entries: + - description: > + Format version string passed to `olm` subcommands so releases download correctly. + kind: bugfix diff --git a/internal/olm/installer/client.go b/internal/olm/installer/client.go index 206a4d3e9ef..cbd44acb7db 100644 --- a/internal/olm/installer/client.go +++ b/internal/olm/installer/client.go @@ -27,6 +27,7 @@ import ( "net/http" "time" + "github.com/blang/semver" olmapiv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1" olmmanifests "github.com/operator-framework/operator-sdk/internal/bindata/olm" log "github.com/sirupsen/logrus" @@ -176,13 +177,15 @@ func (c Client) GetStatus(ctx context.Context, namespace, version string) (*olmr func (c Client) getResources(ctx context.Context, version string) ([]unstructured.Unstructured, error) { log.Infof("Fetching CRDs for version %q", version) + version = formatVersion(version) + var crdResources, olmResources []unstructured.Unstructured var err error // If the manifests for the requested version are saved as bindata in SDK, use // them instead of fetching them from if olmmanifests.HasVersion(version) { - log.Infof("Using locally stored resource manifests") + log.Infof("Using locally stored resource manifests for resolved version %q", version) crdResources, err = getPackagedManifests(crdManifestBindataPath) if err != nil { return nil, err @@ -193,7 +196,7 @@ func (c Client) getResources(ctx context.Context, version string) ([]unstructure return nil, err } } else { - log.Infof("Fetching resources for version %q", version) + log.Infof("Fetching resources for resolved version %q", version) crdResources, err = c.getCRDs(ctx, version) if err != nil { return nil, fmt.Errorf("failed to fetch CRDs: %v", err) @@ -241,6 +244,20 @@ func getPackagedManifests(manifestPath string) ([]unstructured.Unstructured, err return resources, nil } +// formatVersion returns version if version is not semver, or version prepended with "v" +// if version < 0.17.0 (when OLM changed release tag formats). +func formatVersion(version string) string { + sv, err := semver.ParseTolerant(version) + if err != nil { + // Use version as-is, since it might not be semver intentionally. + return version + } + if sv.Major == 0 && sv.Minor < 17 { + return sv.String() + } + return "v" + sv.String() +} + func (c Client) crdsURL(version string) string { return fmt.Sprintf("%s/crds.yaml", c.getBaseDownloadURL(version)) } diff --git a/internal/olm/installer/client_test.go b/internal/olm/installer/client_test.go new file mode 100644 index 00000000000..af411fa9857 --- /dev/null +++ b/internal/olm/installer/client_test.go @@ -0,0 +1,80 @@ +// Copyright 2020 The Operator-SDK 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. + +package installer + +import ( + "fmt" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("helpers", func() { + Describe("formatVersion", func() { + const ( + latest = "latest" + zeroSixteen = "0.16.0" + vZeroSixteen = "v" + zeroSixteen + zeroSixteenOne = "0.16.1" + vZeroSixteenOne = "v" + zeroSixteenOne + zeroSeventeen = "0.17.0" + vZeroSeventeen = "v" + zeroSeventeen + zeroSeventeenOne = "0.17.1" + vZeroSeventeenOne = "v" + zeroSeventeenOne + oneTwoThree = "1.2.3" + vOneTwoThree = "v" + oneTwoThree + ) + + It("returns a non semantic version as-is", func() { + By(fmt.Sprintf("receiving %s", latest)) + Expect(formatVersion(latest)).To(Equal(latest)) + }) + + It("returns a v-prepended semantic version", func() { + By(fmt.Sprintf("receiving %s", zeroSeventeen)) + Expect(formatVersion(zeroSeventeen)).To(Equal(vZeroSeventeen)) + + By(fmt.Sprintf("receiving %s", vZeroSeventeen)) + Expect(formatVersion(vZeroSeventeen)).To(Equal(vZeroSeventeen)) + + By(fmt.Sprintf("receiving %s", zeroSeventeenOne)) + Expect(formatVersion(zeroSeventeenOne)).To(Equal(vZeroSeventeenOne)) + + By(fmt.Sprintf("receiving %s", vZeroSeventeenOne)) + Expect(formatVersion(vZeroSeventeenOne)).To(Equal(vZeroSeventeenOne)) + + By(fmt.Sprintf("receiving %s", oneTwoThree)) + Expect(formatVersion(oneTwoThree)).To(Equal(vOneTwoThree)) + + By(fmt.Sprintf("receiving %s", vOneTwoThree)) + Expect(formatVersion(vOneTwoThree)).To(Equal(vOneTwoThree)) + }) + + It("returns a format semantic version", func() { + By(fmt.Sprintf("receiving %s", zeroSixteen)) + Expect(formatVersion(zeroSixteen)).To(Equal(zeroSixteen)) + + By(fmt.Sprintf("receiving %s", vZeroSixteen)) + Expect(formatVersion(vZeroSixteen)).To(Equal(zeroSixteen)) + + By(fmt.Sprintf("receiving %s", zeroSixteenOne)) + Expect(formatVersion(zeroSixteenOne)).To(Equal(zeroSixteenOne)) + + By(fmt.Sprintf("receiving %s", vZeroSixteenOne)) + Expect(formatVersion(vZeroSixteenOne)).To(Equal(zeroSixteenOne)) + }) + + }) +}) diff --git a/internal/olm/installer/installer_suite_test.go b/internal/olm/installer/installer_suite_test.go new file mode 100644 index 00000000000..4537dee2a21 --- /dev/null +++ b/internal/olm/installer/installer_suite_test.go @@ -0,0 +1,27 @@ +// Copyright 2020 The Operator-SDK 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. + +package installer + +import ( + "testing" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +func TestRegistry(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Installer Suite") +} From 3739d0b56315e983af78f8740988f2054357bb0d Mon Sep 17 00:00:00 2001 From: Camila Macedo Date: Wed, 4 Nov 2020 21:52:52 +0000 Subject: [PATCH 192/376] add finalizer rbac permission to the go/sample and doc steps (#4162) **Description of the change:** - Add the RBAC finalizer permission to allow users to test the Go sample project on OCP - See that for v3+ plugins this permission will be added by default - See that it was added as a NOTE to the quick start and by default in the tutorial in order to avoid the issue faced in https://github.com/operator-framework/operator-sdk/issues/3477 **Motivation for the change:** Closes : https://github.com/operator-framework/operator-sdk/issues/3477 Co-authored-by: Joe Lanford Signed-off-by: reinvantveer --- .../internal/go/memcached_with_webhooks.go | 1 + ...emcached-operator.clusterserviceversion.yaml | 6 ++++++ .../go/memcached-operator/config/rbac/role.yaml | 6 ++++++ .../controllers/memcached_controller.go | 1 + .../docs/building-operators/golang/tutorial.md | 1 + website/content/en/docs/faqs/faqs.md | 17 +++++++++++++++++ 6 files changed, 32 insertions(+) diff --git a/hack/generate/samples/internal/go/memcached_with_webhooks.go b/hack/generate/samples/internal/go/memcached_with_webhooks.go index 68efcf41f86..78b770b4d64 100644 --- a/hack/generate/samples/internal/go/memcached_with_webhooks.go +++ b/hack/generate/samples/internal/go/memcached_with_webhooks.go @@ -257,6 +257,7 @@ func GenerateMemcachedGoWithWebhooksSample(samplesPath string) { } const rbacFragment = ` +// +kubebuilder:rbac:groups=cache.example.com,resources=memcacheds/finalizers,verbs=update // +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=core,resources=pods,verbs=get;list;` diff --git a/testdata/go/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml b/testdata/go/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml index a2f264b8659..89a0fa6d67a 100644 --- a/testdata/go/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml +++ b/testdata/go/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml @@ -62,6 +62,12 @@ spec: - patch - update - watch + - apiGroups: + - cache.example.com + resources: + - memcacheds/finalizers + verbs: + - update - apiGroups: - cache.example.com resources: diff --git a/testdata/go/memcached-operator/config/rbac/role.yaml b/testdata/go/memcached-operator/config/rbac/role.yaml index 388e574679f..e32a4510071 100644 --- a/testdata/go/memcached-operator/config/rbac/role.yaml +++ b/testdata/go/memcached-operator/config/rbac/role.yaml @@ -30,6 +30,12 @@ rules: - patch - update - watch +- apiGroups: + - cache.example.com + resources: + - memcacheds/finalizers + verbs: + - update - apiGroups: - cache.example.com resources: diff --git a/testdata/go/memcached-operator/controllers/memcached_controller.go b/testdata/go/memcached-operator/controllers/memcached_controller.go index 36751ea2d0c..846dba8510e 100644 --- a/testdata/go/memcached-operator/controllers/memcached_controller.go +++ b/testdata/go/memcached-operator/controllers/memcached_controller.go @@ -44,6 +44,7 @@ type MemcachedReconciler struct { // +kubebuilder:rbac:groups=cache.example.com,resources=memcacheds,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=cache.example.com,resources=memcacheds/status,verbs=get;update;patch +// +kubebuilder:rbac:groups=cache.example.com,resources=memcacheds/finalizers,verbs=update // +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=core,resources=pods,verbs=get;list; diff --git a/website/content/en/docs/building-operators/golang/tutorial.md b/website/content/en/docs/building-operators/golang/tutorial.md index f8c94f6c49f..d0edbd169c5 100644 --- a/website/content/en/docs/building-operators/golang/tutorial.md +++ b/website/content/en/docs/building-operators/golang/tutorial.md @@ -258,6 +258,7 @@ The controller needs certain RBAC permissions to interact with the resources it ```Go // +kubebuilder:rbac:groups=cache.example.com,resources=memcacheds,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=cache.example.com,resources=memcacheds/status,verbs=get;update;patch +// +kubebuilder:rbac:groups=cache.example.com,resources=memcacheds/finalizers,verbs=update // +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=core,resources=pods,verbs=get;list; diff --git a/website/content/en/docs/faqs/faqs.md b/website/content/en/docs/faqs/faqs.md index 24da3d9e6ca..db93d3b8289 100644 --- a/website/content/en/docs/faqs/faqs.md +++ b/website/content/en/docs/faqs/faqs.md @@ -102,9 +102,26 @@ func (r *ReconcileMemcached) Reconcile(request reconcile.Request) (reconcile.Res } ``` +## I keep hitting errors like "is forbidden: cannot set blockOwnerDeletion if an ownerReference refers to a resource you can't set finalizers on:", how do I fix this? + +If you are facing this issue, it means that the operator is missing the required RBAC permissions to update finalizers on the APIs it manages. This permission is necessary if the [OwnerReferencesPermissionEnforcement][owner-references-permission-enforcement] plugin is enabled in your cluster. + +For Helm and Ansible operators, this permission is configured by default. However for Go operators, it may be necessary to add this permission yourself. + +In Go operators, RBAC permissions are configured via [RBAC markers][rbac-markers], which are used to generate and update the manifest files present in `config/rbac/`. Add the following marker line on your controller's `Reconcile()` method: + +```go +// +kubebuilder:rbac:groups=cache.example.com,resources=memcacheds/finalizers,verbs=update +``` + +To update `config/rbac/role.yaml` after changing the markers, run `make manifests`. + + [kube-apiserver_options]: https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/#options [controller-runtime_faq]: https://github.com/kubernetes-sigs/controller-runtime/blob/master/FAQ.md#q-how-do-i-have-different-logic-in-my-reconciler-for-different-types-of-events-eg-create-update-delete [finalizer]:/docs/building-operators/golang/advanced-topics/#handle-cleanup-on-deletion [cr-faq]:https://github.com/kubernetes-sigs/controller-runtime/blob/master/FAQ.md [client.Reader]:https://godoc.org/sigs.k8s.io/controller-runtime/pkg/client#Reader [rbac]:https://kubernetes.io/docs/reference/access-authn-authz/rbac/ +[owner-references-permission-enforcement]: https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#ownerreferencespermissionenforcement +[rbac-markers]: https://book.kubebuilder.io/reference/markers/rbac.html From 9dfa4f03bc3303145e44e4581bfb6917a0c5841a Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Wed, 4 Nov 2020 16:32:10 -0800 Subject: [PATCH 193/376] docs/olm-integration/quickstart-package-manifests.md: fix Makefile target link (#4185) Signed-off-by: reinvantveer --- .../en/docs/olm-integration/quickstart-package-manifests.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/content/en/docs/olm-integration/quickstart-package-manifests.md b/website/content/en/docs/olm-integration/quickstart-package-manifests.md index da83602ef16..32f4ac345f9 100644 --- a/website/content/en/docs/olm-integration/quickstart-package-manifests.md +++ b/website/content/en/docs/olm-integration/quickstart-package-manifests.md @@ -5,7 +5,7 @@ weight: 2 --- This guide assumes you have followed the introduction and *Setup* section of the [bundle quickstart][quickstart-bundle], -and have added the `packagemanifests` target to your `Makefile` as described [here][doc-olm-generate]. +and have added the `packagemanifests` target to your `Makefile` as described [here][doc-packagemanifests-makefile]. **Important:** this guide assumes your project was scaffolded with `operator-sdk init --project-version=3-alpha`. These features are unavailable to projects of version `2` or less; this information can be found by inspecting @@ -93,5 +93,5 @@ INFO[0001] operator "memcached-operator" uninstalled [operator-registry]:https://github.com/operator-framework/operator-registry [cli-run-packagemanifests]:/docs/cli/operator-sdk_run_packagemanifests [cli-cleanup]:/docs/cli/operator-sdk_cleanup -[doc-olm-generate]:/docs/olm-integration/generation#overview +[doc-packagemanifests-makefile]:/docs/olm-integration/generation/#package-manifests-format [doc-testing-deployment]:/docs/olm-integration/testing-deployment From 267b1e08ef2ed997f73d78b35130adb17ee17af3 Mon Sep 17 00:00:00 2001 From: Sascha Marcel Schmidt Date: Thu, 5 Nov 2020 12:24:33 +0100 Subject: [PATCH 194/376] website/content/en/docs/building-operators/ansible/reference/advanced_options.md: fix minor typo (#4194) Signed-off-by: reinvantveer --- .../building-operators/ansible/reference/advanced_options.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/content/en/docs/building-operators/ansible/reference/advanced_options.md b/website/content/en/docs/building-operators/ansible/reference/advanced_options.md index 7db0f1edfbf..9aa859e1d1d 100644 --- a/website/content/en/docs/building-operators/ansible/reference/advanced_options.md +++ b/website/content/en/docs/building-operators/ansible/reference/advanced_options.md @@ -114,7 +114,7 @@ supports two Kinds -- `MongoDB` and `PostgreSQL` -- in the `db.example.com` Group. We have only recently implemented the support for the `MongoDB` Kind so we want reconciles for this Kind to be more verbose. Our operator container's spec in our `config/manager/manager.yaml` and `config/default/auth_proxy_patch.yaml` -files might contiain something like: +files might contain something like: ```yaml - name: manager From 7f217840bc8791278488a43b63bd4a36b610e384 Mon Sep 17 00:00:00 2001 From: Camila Macedo Date: Thu, 5 Nov 2020 13:56:24 +0000 Subject: [PATCH 195/376] test-e2e/ansible : using samples (#4142) **Description of the change:** Use Memcached sample instead of re-generate the project. **Motivation for the change:** operator-framework/enhancements#47 Signed-off-by: reinvantveer --- .../samples/internal/ansible/constants.go | 44 ++------ .../samples/internal/ansible/molecule.go | 2 +- test/e2e-ansible/e2e_ansible_cluster_test.go | 23 ++-- test/e2e-ansible/e2e_ansible_olm_test.go | 6 +- test/e2e-ansible/e2e_ansible_suite_test.go | 101 +++--------------- .../roles/memcached/tasks/main.yml | 7 ++ 6 files changed, 43 insertions(+), 140 deletions(-) diff --git a/hack/generate/samples/internal/ansible/constants.go b/hack/generate/samples/internal/ansible/constants.go index 329d0d88822..0391156e332 100644 --- a/hack/generate/samples/internal/ansible/constants.go +++ b/hack/generate/samples/internal/ansible/constants.go @@ -23,6 +23,8 @@ const roleFragment = ` metadata: name: '{{ ansible_operator_meta.name }}-memcached' namespace: '{{ ansible_operator_meta.namespace }}' + labels: + app: memcached spec: replicas: "{{size}}" selector: @@ -44,6 +46,11 @@ const roleFragment = ` image: "docker.io/memcached:1.4.36-alpine" ports: - containerPort: 11211 + readinessProbe: + tcpSocket: + port: 11211 + initialDelaySeconds: 3 + periodSeconds: 3 ` const defaultsFragment = `size: 1` @@ -296,43 +303,6 @@ const molecuTaskToCheckConfigMap = ` ` const memcachedWithBlackListTask = ` -- name: start memcached - community.kubernetes.k8s: - definition: - kind: Deployment - apiVersion: apps/v1 - metadata: - name: '{{ ansible_operator_meta.name }}-memcached' - namespace: '{{ ansible_operator_meta.namespace }}' - labels: - app: memcached - spec: - replicas: "{{size}}" - selector: - matchLabels: - app: memcached - template: - metadata: - labels: - app: memcached - spec: - containers: - - name: memcached - command: - - memcached - - -m=64 - - -o - - modern - - -v - image: "docker.io/memcached:1.4.36-alpine" - ports: - - containerPort: 11211 - readinessProbe: - tcpSocket: - port: 11211 - initialDelaySeconds: 3 - periodSeconds: 3 - - operator_sdk.util.k8s_status: api_version: cache.example.com/v1alpha1 kind: Memcached diff --git a/hack/generate/samples/internal/ansible/molecule.go b/hack/generate/samples/internal/ansible/molecule.go index 7c3c74cd83f..5c960b353e8 100644 --- a/hack/generate/samples/internal/ansible/molecule.go +++ b/hack/generate/samples/internal/ansible/molecule.go @@ -85,7 +85,7 @@ func (ma *MoleculeAnsible) Run() { pkg.CheckError("replacing in role.yml", err) log.Infof("adding Memcached mock task to the role with black list") - err = testutils.ReplaceInFile(filepath.Join(ma.ctx.Dir, "roles", strings.ToLower(ma.ctx.Kind), "tasks", "main.yml"), + err = kbtestutils.InsertCode(filepath.Join(ma.ctx.Dir, "roles", strings.ToLower(ma.ctx.Kind), "tasks", "main.yml"), roleFragment, memcachedWithBlackListTask) pkg.CheckError("replacing in tasks/main.yml", err) diff --git a/test/e2e-ansible/e2e_ansible_cluster_test.go b/test/e2e-ansible/e2e_ansible_cluster_test.go index 214f6354cb2..acb7ff836e1 100644 --- a/test/e2e-ansible/e2e_ansible_cluster_test.go +++ b/test/e2e-ansible/e2e_ansible_cluster_test.go @@ -34,9 +34,12 @@ var _ = Describe("Running ansible projects", func() { var fooSampleFile string var memfinSampleFile string var memcachedDeployment string + var metricsClusterRoleBindingName string Context("built with operator-sdk", func() { BeforeEach(func() { + metricsClusterRoleBindingName = fmt.Sprintf("%s-metrics-reader", tc.ProjectName) + By("checking samples") memcachedSampleFile = filepath.Join(tc.Dir, "config", "samples", fmt.Sprintf("%s_%s_%s.yaml", tc.Group, tc.Version, strings.ToLower(tc.Kind))) @@ -45,11 +48,6 @@ var _ = Describe("Running ansible projects", func() { memfinSampleFile = filepath.Join(tc.Dir, "config", "samples", fmt.Sprintf("%s_%s_memfin.yaml", tc.Group, tc.Version)) - By("enabling Prometheus via the kustomization.yaml") - Expect(kbtestutils.UncommentCode( - filepath.Join(tc.Dir, "config", "default", "kustomization.yaml"), - "#- ../prometheus", "#")).To(Succeed()) - By("deploying project on the cluster") err := tc.Make("deploy", "IMG="+tc.ImageName) Expect(err).NotTo(HaveOccurred()) @@ -65,7 +63,7 @@ var _ = Describe("Running ansible projects", func() { By("cleaning up permissions") _, _ = tc.Kubectl.Command("delete", "clusterrolebinding", - fmt.Sprintf("metrics-%s", tc.TestSuffix)) + metricsClusterRoleBindingName) By("undeploy project") _ = tc.Make("undeploy") @@ -122,14 +120,14 @@ var _ = Describe("Running ansible projects", func() { _, err := tc.Kubectl.Get( true, "ServiceMonitor", - fmt.Sprintf("e2e-%s-controller-manager-metrics-monitor", tc.TestSuffix)) + fmt.Sprintf("%s-controller-manager-metrics-monitor", tc.ProjectName)) Expect(err).NotTo(HaveOccurred()) By("ensuring the created metrics Service for the manager") _, err = tc.Kubectl.Get( true, "Service", - fmt.Sprintf("e2e-%s-controller-manager-metrics-service", tc.TestSuffix)) + fmt.Sprintf("%s-controller-manager-metrics-service", tc.ProjectName)) Expect(err).NotTo(HaveOccurred()) By("create custom resource (Memcached CR)") @@ -263,9 +261,8 @@ var _ = Describe("Running ansible projects", func() { By("granting permissions to access the metrics and read the token") _, err = tc.Kubectl.Command( "create", - "clusterrolebinding", - fmt.Sprintf("metrics-%s", tc.TestSuffix), - fmt.Sprintf("--clusterrole=e2e-%s-metrics-reader", tc.TestSuffix), + "clusterrolebinding", metricsClusterRoleBindingName, + fmt.Sprintf("--clusterrole=%s-metrics-reader", tc.ProjectName), fmt.Sprintf("--serviceaccount=%s:default", tc.Kubectl.Namespace)) Expect(err).NotTo(HaveOccurred()) @@ -286,8 +283,8 @@ var _ = Describe("Running ansible projects", func() { cmdOpts := []string{ "run", "--generator=run-pod/v1", "curl", "--image=curlimages/curl:7.68.0", "--restart=OnFailure", "--", "curl", "-v", "-k", "-H", fmt.Sprintf(`Authorization: Bearer %s`, token), - fmt.Sprintf("https://e2e-%v-controller-manager-metrics-service.e2e-%v-system.svc:8443/metrics", - tc.TestSuffix, tc.TestSuffix), + fmt.Sprintf("https://%s-controller-manager-metrics-service.%s.svc:8443/metrics", + tc.ProjectName, tc.Kubectl.Namespace), } _, err = tc.Kubectl.CommandInNamespace(cmdOpts...) Expect(err).NotTo(HaveOccurred()) diff --git a/test/e2e-ansible/e2e_ansible_olm_test.go b/test/e2e-ansible/e2e_ansible_olm_test.go index ffc1b8eb50e..a78d261b25b 100644 --- a/test/e2e-ansible/e2e_ansible_olm_test.go +++ b/test/e2e-ansible/e2e_ansible_olm_test.go @@ -26,12 +26,8 @@ var _ = Describe("Integrating ansible Projects with OLM", func() { const operatorVersion = "0.0.1" It("should generate and run a valid OLM bundle and packagemanifests", func() { - By("turning off interactive prompts for all generation tasks.") - err := tc.DisableOLMBundleInteractiveMode() - Expect(err).NotTo(HaveOccurred()) - By("building the bundle") - err = tc.Make("bundle", "IMG="+tc.ImageName) + err := tc.Make("bundle", "IMG="+tc.ImageName) Expect(err).NotTo(HaveOccurred()) By("building the operator bundle image") diff --git a/test/e2e-ansible/e2e_ansible_suite_test.go b/test/e2e-ansible/e2e_ansible_suite_test.go index 4fe07b553c2..6ea680ffd11 100644 --- a/test/e2e-ansible/e2e_ansible_suite_test.go +++ b/test/e2e-ansible/e2e_ansible_suite_test.go @@ -16,10 +16,13 @@ package e2e_ansible_test import ( "fmt" + "os/exec" "path/filepath" "strings" "testing" + kbtestutils "sigs.k8s.io/kubebuilder/test/e2e/utils" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -47,8 +50,15 @@ var _ = BeforeSuite(func() { tc, err = testutils.NewTestContext(testutils.BinaryName, "GO111MODULE=on") Expect(err).NotTo(HaveOccurred()) - By("creating the repository") - Expect(tc.Prepare()).To(Succeed()) + tc.Domain = "example.com" + tc.Version = "v1alpha1" + tc.Group = "cache" + tc.Kind = "Memcached" + tc.ProjectName = "memcached-operator" + tc.Kubectl.Namespace = fmt.Sprintf("%s-system", tc.ProjectName) + + By("copying sample to a temporary e2e directory") + Expect(exec.Command("cp", "-r", "../../testdata/ansible/memcached-operator", tc.Dir).Run()).To(Succeed()) By("fetching the current-context") tc.Kubectx, err = tc.Kubectl.Command("config", "current-context") @@ -57,50 +67,17 @@ var _ = BeforeSuite(func() { By("preparing the prerequisites on cluster") tc.InstallPrerequisites() - By("setting domain and GVK") - tc.Domain = "example.com" - tc.Version = "v1alpha1" - tc.Group = "ansible" - tc.Kind = "Memcached" - - By("initializing a ansible project") - err = tc.Init( - "--plugins", "ansible", - "--project-version", "3-alpha", - "--domain", tc.Domain) - Expect(err).NotTo(HaveOccurred()) - By("using dev image for scorecard-test") err = tc.ReplaceScorecardImagesForDev() Expect(err).NotTo(HaveOccurred()) - By("creating the Memcached API") - err = tc.CreateAPI( - "--group", tc.Group, - "--version", tc.Version, - "--kind", tc.Kind, - "--generate-playbook", - "--generate-role") - Expect(err).NotTo(HaveOccurred()) - By("replacing project Dockerfile to use ansible base image with the dev tag") err = testutils.ReplaceRegexInFile(filepath.Join(tc.Dir, "Dockerfile"), "quay.io/operator-framework/ansible-operator:.*", "quay.io/operator-framework/ansible-operator:dev") Expect(err).Should(Succeed()) By("adding Memcached mock task to the role") - err = testutils.ReplaceInFile(filepath.Join(tc.Dir, "roles", strings.ToLower(tc.Kind), "tasks", "main.yml"), - fmt.Sprintf("# tasks file for %s", tc.Kind), memcachedWithBlackListTask) - Expect(err).NotTo(HaveOccurred()) - - By("setting defaults to Memcached") - err = testutils.ReplaceInFile(filepath.Join(tc.Dir, "roles", strings.ToLower(tc.Kind), "defaults", "main.yml"), - fmt.Sprintf("# defaults file for %s", tc.Kind), "size: 1") - Expect(err).NotTo(HaveOccurred()) - - By("updating Memcached sample") - memcachedSampleFile := filepath.Join(tc.Dir, "config", "samples", - fmt.Sprintf("%s_%s_%s.yaml", tc.Group, tc.Version, strings.ToLower(tc.Kind))) - err = testutils.ReplaceInFile(memcachedSampleFile, "foo: bar", "size: 1") + err = kbtestutils.InsertCode(filepath.Join(tc.Dir, "roles", strings.ToLower(tc.Kind), "tasks", "main.yml"), + "periodSeconds: 3", memcachedWithBlackListTask) Expect(err).NotTo(HaveOccurred()) By("creating an API definition to add a task to delete the config map") @@ -134,15 +111,6 @@ var _ = BeforeSuite(func() { "# +kubebuilder:scaffold:rules", rolesForBaseOperator) Expect(err).NotTo(HaveOccurred()) - By("turning off interactive prompts for all generation tasks.") - replace := "operator-sdk generate kustomize manifests" - err = testutils.ReplaceInFile(filepath.Join(tc.Dir, "Makefile"), replace, replace+" --interactive=false") - Expect(err).NotTo(HaveOccurred()) - - By("checking the kustomize setup") - err = tc.Make("kustomize") - Expect(err).NotTo(HaveOccurred()) - By("building the project image") err = tc.Make("docker-build", "IMG="+tc.ImageName) Expect(err).NotTo(HaveOccurred()) @@ -168,45 +136,10 @@ var _ = AfterSuite(func() { tc.Destroy() }) -const memcachedWithBlackListTask = `- name: start memcached - community.kubernetes.k8s: - definition: - kind: Deployment - apiVersion: apps/v1 - metadata: - name: '{{ ansible_operator_meta.name }}-memcached' - namespace: '{{ ansible_operator_meta.namespace }}' - labels: - app: memcached - spec: - replicas: "{{size}}" - selector: - matchLabels: - app: memcached - template: - metadata: - labels: - app: memcached - spec: - containers: - - name: memcached - command: - - memcached - - -m=64 - - -o - - modern - - -v - image: "docker.io/memcached:1.4.36-alpine" - ports: - - containerPort: 11211 - readinessProbe: - tcpSocket: - port: 11211 - initialDelaySeconds: 3 - periodSeconds: 3 +const memcachedWithBlackListTask = ` - operator_sdk.util.k8s_status: - api_version: ansible.example.com/v1alpha1 + api_version: cache.example.com/v1alpha1 kind: Memcached name: "{{ ansible_operator_meta.name }}" namespace: "{{ ansible_operator_meta.namespace }}" @@ -257,7 +190,7 @@ const taskToDeleteConfigMap = `- name: delete configmap for test const memcachedWatchCustomizations = `playbook: playbooks/memcached.yml finalizer: - name: finalizer.ansible.example.com + name: finalizer.cache.example.com role: memfin blacklist: - group: "" diff --git a/testdata/ansible/memcached-operator/roles/memcached/tasks/main.yml b/testdata/ansible/memcached-operator/roles/memcached/tasks/main.yml index b22e92f69cb..ac84d9bc0f8 100644 --- a/testdata/ansible/memcached-operator/roles/memcached/tasks/main.yml +++ b/testdata/ansible/memcached-operator/roles/memcached/tasks/main.yml @@ -8,6 +8,8 @@ metadata: name: '{{ ansible_operator_meta.name }}-memcached' namespace: '{{ ansible_operator_meta.namespace }}' + labels: + app: memcached spec: replicas: "{{size}}" selector: @@ -29,4 +31,9 @@ image: "docker.io/memcached:1.4.36-alpine" ports: - containerPort: 11211 + readinessProbe: + tcpSocket: + port: 11211 + initialDelaySeconds: 3 + periodSeconds: 3 From 4e42c0a0001b56f070e6ae4f8927e9ee16a4c07b Mon Sep 17 00:00:00 2001 From: Austin Macdonald Date: Thu, 5 Nov 2020 12:17:29 -0500 Subject: [PATCH 196/376] Add unit tests for operator_installer.go (#4165) Add unit tests for operator_installer.go and olm_resources.go Signed-off-by: reinvantveer --- .../operator/registry/olm_resources_test.go | 45 +++++ .../operator/registry/operator_installer.go | 6 +- .../registry/operator_installer_test.go | 171 +++++++++++++++++- 3 files changed, 212 insertions(+), 10 deletions(-) create mode 100644 internal/olm/operator/registry/olm_resources_test.go diff --git a/internal/olm/operator/registry/olm_resources_test.go b/internal/olm/operator/registry/olm_resources_test.go new file mode 100644 index 00000000000..33816b36b99 --- /dev/null +++ b/internal/olm/operator/registry/olm_resources_test.go @@ -0,0 +1,45 @@ +// Copyright 2020 The Operator-SDK 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. + +package registry + +import ( + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("newCatalogSource", func() { + Describe("newCatalogSource", func() { + It("should create a CatalogSource with name and namespace set", func() { + cs := newCatalogSource("fakeName", "fakeNS") + Expect(cs.ObjectMeta.Name).To(Equal("fakeName")) + Expect(cs.ObjectMeta.Namespace).To(Equal("fakeNS")) + }) + }) + Describe("withSDKPublisher", func() { + It("should set the display name and publisher of a CatalogSource", func() { + cs := newCatalogSource("fakeName", "fakeNS", withSDKPublisher("fakeDisplay")) + Expect(cs.Spec.DisplayName).To(Equal("fakeDisplay")) + Expect(cs.Spec.Publisher).To(Equal("operator-sdk")) + }) + }) + Describe("withInstallPlanApproval", func() { + It("should set the display name and publisher of a CatalogSource", func() { + cs := newCatalogSource("fakeName", "fakeNS", withSDKPublisher("fakeDisplay")) + Expect(cs.Spec.DisplayName).To(Equal("fakeDisplay")) + Expect(cs.Spec.Publisher).To(Equal("operator-sdk")) + }) + }) + +}) diff --git a/internal/olm/operator/registry/operator_installer.go b/internal/olm/operator/registry/operator_installer.go index 4d5448ba58b..aa1b68e0849 100644 --- a/internal/olm/operator/registry/operator_installer.go +++ b/internal/olm/operator/registry/operator_installer.go @@ -72,7 +72,7 @@ func (o OperatorInstaller) InstallOperator(ctx context.Context) (*v1alpha1.Clust var subscription *v1alpha1.Subscription // Create Subscription - if subscription, err = o.createSubscription(ctx, cs); err != nil { + if subscription, err = o.createSubscription(ctx, cs.GetName()); err != nil { return nil, err } @@ -208,10 +208,10 @@ func (o OperatorInstaller) getOperatorGroup(ctx context.Context) (*v1.OperatorGr return &ogList.Items[0], true, nil } -func (o OperatorInstaller) createSubscription(ctx context.Context, cs *v1alpha1.CatalogSource) (*v1alpha1.Subscription, error) { +func (o OperatorInstaller) createSubscription(ctx context.Context, csName string) (*v1alpha1.Subscription, error) { sub := newSubscription(o.StartingCSV, o.cfg.Namespace, withPackageChannel(o.PackageName, o.Channel, o.StartingCSV), - withCatalogSource(cs.GetName(), o.cfg.Namespace), + withCatalogSource(csName, o.cfg.Namespace), withInstallPlanApproval(v1alpha1.ApprovalManual)) if err := o.cfg.Client.Create(ctx, sub); err != nil { diff --git a/internal/olm/operator/registry/operator_installer_test.go b/internal/olm/operator/registry/operator_installer_test.go index c6a48b38361..0719600ed99 100644 --- a/internal/olm/operator/registry/operator_installer_test.go +++ b/internal/olm/operator/registry/operator_installer_test.go @@ -21,7 +21,10 @@ import ( . "github.com/onsi/gomega" v1 "github.com/operator-framework/api/pkg/operators/v1" "github.com/operator-framework/api/pkg/operators/v1alpha1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/sets" crclient "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/fake" @@ -30,8 +33,167 @@ import ( ) var _ = Describe("OperatorInstaller", func() { - Describe("InstallOperator", func() { - // TODO: fill this in once run bundle is done + Describe("NewOperatorInstaller", func() { + It("should create an OperatorInstaller", func() { + cfg := &operator.Configuration{} + oi := NewOperatorInstaller(cfg) + Expect(oi).ToNot(BeNil()) + }) + }) + + Describe("createSubscription", func() { + var ( + oi *OperatorInstaller + sch *runtime.Scheme + ) + BeforeEach(func() { + // Setup and fake client + cfg := &operator.Configuration{} + sch = runtime.NewScheme() + Expect(v1.AddToScheme(sch)).To(Succeed()) + Expect(v1alpha1.AddToScheme(sch)).To(Succeed()) + cfg.Client = fake.NewFakeClientWithScheme(sch) + + oi = NewOperatorInstaller(cfg) + oi.StartingCSV = "fakeName" + oi.cfg.Namespace = "fakeNS" + }) + + It("should create the subscription with the fake client", func() { + sub, err := oi.createSubscription(context.TODO(), "huzzah") + Expect(err).ToNot(HaveOccurred()) + + retSub := &v1alpha1.Subscription{} + subKey := types.NamespacedName{ + Namespace: sub.GetNamespace(), + Name: sub.GetName(), + } + err = oi.cfg.Client.Get(context.TODO(), subKey, retSub) + Expect(err).ToNot(HaveOccurred()) + Expect(retSub.GetName()).To(Equal(sub.GetName())) + Expect(retSub.GetNamespace()).To(Equal(sub.GetNamespace())) + }) + + It("should pass through any client errors (duplicate)", func() { + + sub := newSubscription(oi.StartingCSV, oi.cfg.Namespace, withCatalogSource("duplicate", oi.cfg.Namespace)) + oi.cfg.Client = fake.NewFakeClientWithScheme(sch, sub) + + _, err := oi.createSubscription(context.TODO(), "duplicate") + Expect(err).To(HaveOccurred()) + Expect(err.Error()).Should(ContainSubstring("error creating subscription")) + }) + }) + + Describe("approveInstallPlan", func() { + var ( + oi *OperatorInstaller + sch *runtime.Scheme + ) + BeforeEach(func() { + cfg := &operator.Configuration{} + sch = runtime.NewScheme() + Expect(v1alpha1.AddToScheme(sch)).To(Succeed()) + oi = NewOperatorInstaller(cfg) + }) + + It("should update the install plan", func() { + oi.cfg.Client = fake.NewFakeClientWithScheme(sch, + &v1alpha1.InstallPlan{ + ObjectMeta: metav1.ObjectMeta{ + Name: "fakeName", + Namespace: "fakeNS", + }, + }, + ) + + ip := &v1alpha1.InstallPlan{} + ipKey := types.NamespacedName{ + Namespace: "fakeNS", + Name: "fakeName", + } + + err := oi.cfg.Client.Get(context.TODO(), ipKey, ip) + Expect(err).ToNot(HaveOccurred()) + Expect(ip.Name).To(Equal("fakeName")) + Expect(ip.Namespace).To(Equal("fakeNS")) + + // Test + sub := &v1alpha1.Subscription{ + Status: v1alpha1.SubscriptionStatus{ + InstallPlanRef: &corev1.ObjectReference{ + Name: "fakeName", + Namespace: "fakeNS", + }, + }, + } + err = oi.approveInstallPlan(context.TODO(), sub) + Expect(err).ToNot(HaveOccurred()) + err = oi.cfg.Client.Get(context.TODO(), ipKey, ip) + Expect(err).ToNot(HaveOccurred()) + Expect(ip.Name).To(Equal("fakeName")) + Expect(ip.Namespace).To(Equal("fakeNS")) + Expect(ip.Spec.Approved).To(Equal(true)) + }) + It("should return an error if the install plan does not exist.", func() { + oi.cfg.Client = fake.NewFakeClientWithScheme(sch) + sub := &v1alpha1.Subscription{ + Status: v1alpha1.SubscriptionStatus{ + InstallPlanRef: &corev1.ObjectReference{ + Name: "fakeName", + Namespace: "fakeNS", + }, + }, + } + err := oi.approveInstallPlan(context.TODO(), sub) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).Should(ContainSubstring("error getting install plan")) + }) + }) + + Describe("waitForInstallPlan", func() { + var ( + oi *OperatorInstaller + sch *runtime.Scheme + ) + BeforeEach(func() { + // Setup and fake client + cfg := &operator.Configuration{} + sch = runtime.NewScheme() + Expect(v1alpha1.AddToScheme(sch)).To(Succeed()) + cfg.Client = fake.NewFakeClientWithScheme(sch) + + oi = NewOperatorInstaller(cfg) + oi.StartingCSV = "fakeName" + oi.cfg.Namespace = "fakeNS" + }) + It("should return an error if the subscription does not exist.", func() { + sub := newSubscription(oi.StartingCSV, oi.cfg.Namespace, withCatalogSource("duplicate", oi.cfg.Namespace)) + + err := oi.waitForInstallPlan(context.TODO(), sub) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).Should(ContainSubstring("install plan is not available for the subscription")) + + }) + It("should return if subscription has an install plan.", func() { + sub := &v1alpha1.Subscription{ + ObjectMeta: metav1.ObjectMeta{ + Name: "fakeName", + Namespace: "fakeNS", + }, + Status: v1alpha1.SubscriptionStatus{ + InstallPlanRef: &corev1.ObjectReference{ + Name: "fakeName", + Namespace: "fakeNS", + }, + }, + } + err := oi.cfg.Client.Create(context.TODO(), sub) + Expect(err).ToNot(HaveOccurred()) + + err = oi.waitForInstallPlan(context.TODO(), sub) + Expect(err).ToNot(HaveOccurred()) + }) }) Describe("ensureOperatorGroup", func() { @@ -212,7 +374,6 @@ var _ = Describe("OperatorInstaller", func() { }) }) }) - Describe("createOperatorGroup", func() { var ( oi OperatorInstaller @@ -335,10 +496,6 @@ var _ = Describe("OperatorInstaller", func() { }) }) - Describe("createSubscription", func() { - // TODO: add them as part of a different story - }) - Describe("getTargetNamespaces", func() { var ( oi OperatorInstaller From 30c54602112e6b1f0d32189bf0fe302b7390b7be Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Thu, 5 Nov 2020 09:20:50 -0800 Subject: [PATCH 197/376] Makefile: add submodule checkout to 'test-links' (#4186) Signed-off-by: reinvantveer --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index d7d38c14e91..4acf67b0a76 100644 --- a/Makefile +++ b/Makefile @@ -110,6 +110,7 @@ test-sanity: generate fix ## Test repo formatting, linting, etc. .PHONY: test-links test-links: ## Test doc links + git submodule update --init --recursive website/ ./hack/check-links.sh .PHONY: test-unit From feb6a79a1e2e03bc49f5bc2ca13c711304bd3f2d Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Fri, 6 Nov 2020 09:00:25 -0800 Subject: [PATCH 198/376] Makfile,testdata: bump IMAGE_VERSION to v1.2.0, regenerate samples (#4197) testdata: regenerate with v1.2.0 tag Signed-off-by: reinvantveer --- Makefile | 2 +- testdata/ansible/memcached-operator/Dockerfile | 2 +- testdata/ansible/memcached-operator/Makefile | 4 ++-- .../bundle/tests/scorecard/config.yaml | 12 ++++++------ .../config/scorecard/patches/basic.config.yaml | 2 +- .../config/scorecard/patches/olm.config.yaml | 10 +++++----- .../bundle/tests/scorecard/config.yaml | 12 ++++++------ .../config/scorecard/patches/basic.config.yaml | 2 +- .../config/scorecard/patches/olm.config.yaml | 10 +++++----- testdata/helm/memcached-operator/Dockerfile | 2 +- testdata/helm/memcached-operator/Makefile | 4 ++-- .../bundle/tests/scorecard/config.yaml | 12 ++++++------ .../config/scorecard/patches/basic.config.yaml | 2 +- .../config/scorecard/patches/olm.config.yaml | 10 +++++----- 14 files changed, 43 insertions(+), 43 deletions(-) diff --git a/Makefile b/Makefile index 4acf67b0a76..aaeaadc2e10 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ SHELL = /bin/bash # This value must be updated to the release tag of the most recent release, a change that must # occur in the release commit. IMAGE_VERSION will be removed once each subproject that uses this # version is moved to a separate repo and release process. -export IMAGE_VERSION = v1.1.0 +export IMAGE_VERSION = v1.2.0 # Build-time variables to inject into binaries export SIMPLE_VERSION = $(shell (test "$(shell git describe)" = "$(shell git describe --abbrev=0)" && echo $(shell git describe)) || echo $(shell git describe --abbrev=0)+git) export GIT_VERSION = $(shell git describe --dirty --tags --always) diff --git a/testdata/ansible/memcached-operator/Dockerfile b/testdata/ansible/memcached-operator/Dockerfile index d054420c002..04e5216dcbe 100644 --- a/testdata/ansible/memcached-operator/Dockerfile +++ b/testdata/ansible/memcached-operator/Dockerfile @@ -1,4 +1,4 @@ -FROM quay.io/operator-framework/ansible-operator:v1.1.0 +FROM quay.io/operator-framework/ansible-operator:v1.2.0 COPY requirements.yml ${HOME}/requirements.yml RUN ansible-galaxy collection install -r ${HOME}/requirements.yml \ diff --git a/testdata/ansible/memcached-operator/Makefile b/testdata/ansible/memcached-operator/Makefile index b7a6e4c6585..eed3911bc98 100644 --- a/testdata/ansible/memcached-operator/Makefile +++ b/testdata/ansible/memcached-operator/Makefile @@ -69,8 +69,8 @@ ifeq (, $(shell which ansible-operator 2>/dev/null)) @{ \ set -e ;\ mkdir -p bin ;\ - curl -LO https://github.com/operator-framework/operator-sdk/releases/download/v1.1.0/ansible-operator-v1.1.0-$(ARCHOPER)-$(OSOPER) ;\ - mv ansible-operator-v1.1.0-$(ARCHOPER)-$(OSOPER) ./bin/ansible-operator ;\ + curl -LO https://github.com/operator-framework/operator-sdk/releases/download/v1.2.0/ansible-operator-v1.2.0-$(ARCHOPER)-$(OSOPER) ;\ + mv ansible-operator-v1.2.0-$(ARCHOPER)-$(OSOPER) ./bin/ansible-operator ;\ chmod +x ./bin/ansible-operator ;\ } ANSIBLE_OPERATOR=$(realpath ./bin/ansible-operator) diff --git a/testdata/ansible/memcached-operator/bundle/tests/scorecard/config.yaml b/testdata/ansible/memcached-operator/bundle/tests/scorecard/config.yaml index 83bc60f0570..e39a5d88b57 100644 --- a/testdata/ansible/memcached-operator/bundle/tests/scorecard/config.yaml +++ b/testdata/ansible/memcached-operator/bundle/tests/scorecard/config.yaml @@ -8,42 +8,42 @@ stages: - entrypoint: - scorecard-test - basic-check-spec - image: quay.io/operator-framework/scorecard-test:v1.1.0 + image: quay.io/operator-framework/scorecard-test:v1.2.0 labels: suite: basic test: basic-check-spec-test - entrypoint: - scorecard-test - olm-bundle-validation - image: quay.io/operator-framework/scorecard-test:v1.1.0 + image: quay.io/operator-framework/scorecard-test:v1.2.0 labels: suite: olm test: olm-bundle-validation-test - entrypoint: - scorecard-test - olm-crds-have-validation - image: quay.io/operator-framework/scorecard-test:v1.1.0 + image: quay.io/operator-framework/scorecard-test:v1.2.0 labels: suite: olm test: olm-crds-have-validation-test - entrypoint: - scorecard-test - olm-crds-have-resources - image: quay.io/operator-framework/scorecard-test:v1.1.0 + image: quay.io/operator-framework/scorecard-test:v1.2.0 labels: suite: olm test: olm-crds-have-resources-test - entrypoint: - scorecard-test - olm-spec-descriptors - image: quay.io/operator-framework/scorecard-test:v1.1.0 + image: quay.io/operator-framework/scorecard-test:v1.2.0 labels: suite: olm test: olm-spec-descriptors-test - entrypoint: - scorecard-test - olm-status-descriptors - image: quay.io/operator-framework/scorecard-test:v1.1.0 + image: quay.io/operator-framework/scorecard-test:v1.2.0 labels: suite: olm test: olm-status-descriptors-test diff --git a/testdata/ansible/memcached-operator/config/scorecard/patches/basic.config.yaml b/testdata/ansible/memcached-operator/config/scorecard/patches/basic.config.yaml index 39576a573b2..f80c746f9e7 100644 --- a/testdata/ansible/memcached-operator/config/scorecard/patches/basic.config.yaml +++ b/testdata/ansible/memcached-operator/config/scorecard/patches/basic.config.yaml @@ -4,7 +4,7 @@ entrypoint: - scorecard-test - basic-check-spec - image: quay.io/operator-framework/scorecard-test:v1.1.0 + image: quay.io/operator-framework/scorecard-test:v1.2.0 labels: suite: basic test: basic-check-spec-test diff --git a/testdata/ansible/memcached-operator/config/scorecard/patches/olm.config.yaml b/testdata/ansible/memcached-operator/config/scorecard/patches/olm.config.yaml index 8102e4db2da..ef6834b1e3d 100644 --- a/testdata/ansible/memcached-operator/config/scorecard/patches/olm.config.yaml +++ b/testdata/ansible/memcached-operator/config/scorecard/patches/olm.config.yaml @@ -4,7 +4,7 @@ entrypoint: - scorecard-test - olm-bundle-validation - image: quay.io/operator-framework/scorecard-test:v1.1.0 + image: quay.io/operator-framework/scorecard-test:v1.2.0 labels: suite: olm test: olm-bundle-validation-test @@ -14,7 +14,7 @@ entrypoint: - scorecard-test - olm-crds-have-validation - image: quay.io/operator-framework/scorecard-test:v1.1.0 + image: quay.io/operator-framework/scorecard-test:v1.2.0 labels: suite: olm test: olm-crds-have-validation-test @@ -24,7 +24,7 @@ entrypoint: - scorecard-test - olm-crds-have-resources - image: quay.io/operator-framework/scorecard-test:v1.1.0 + image: quay.io/operator-framework/scorecard-test:v1.2.0 labels: suite: olm test: olm-crds-have-resources-test @@ -34,7 +34,7 @@ entrypoint: - scorecard-test - olm-spec-descriptors - image: quay.io/operator-framework/scorecard-test:v1.1.0 + image: quay.io/operator-framework/scorecard-test:v1.2.0 labels: suite: olm test: olm-spec-descriptors-test @@ -44,7 +44,7 @@ entrypoint: - scorecard-test - olm-status-descriptors - image: quay.io/operator-framework/scorecard-test:v1.1.0 + image: quay.io/operator-framework/scorecard-test:v1.2.0 labels: suite: olm test: olm-status-descriptors-test diff --git a/testdata/go/memcached-operator/bundle/tests/scorecard/config.yaml b/testdata/go/memcached-operator/bundle/tests/scorecard/config.yaml index 83bc60f0570..e39a5d88b57 100644 --- a/testdata/go/memcached-operator/bundle/tests/scorecard/config.yaml +++ b/testdata/go/memcached-operator/bundle/tests/scorecard/config.yaml @@ -8,42 +8,42 @@ stages: - entrypoint: - scorecard-test - basic-check-spec - image: quay.io/operator-framework/scorecard-test:v1.1.0 + image: quay.io/operator-framework/scorecard-test:v1.2.0 labels: suite: basic test: basic-check-spec-test - entrypoint: - scorecard-test - olm-bundle-validation - image: quay.io/operator-framework/scorecard-test:v1.1.0 + image: quay.io/operator-framework/scorecard-test:v1.2.0 labels: suite: olm test: olm-bundle-validation-test - entrypoint: - scorecard-test - olm-crds-have-validation - image: quay.io/operator-framework/scorecard-test:v1.1.0 + image: quay.io/operator-framework/scorecard-test:v1.2.0 labels: suite: olm test: olm-crds-have-validation-test - entrypoint: - scorecard-test - olm-crds-have-resources - image: quay.io/operator-framework/scorecard-test:v1.1.0 + image: quay.io/operator-framework/scorecard-test:v1.2.0 labels: suite: olm test: olm-crds-have-resources-test - entrypoint: - scorecard-test - olm-spec-descriptors - image: quay.io/operator-framework/scorecard-test:v1.1.0 + image: quay.io/operator-framework/scorecard-test:v1.2.0 labels: suite: olm test: olm-spec-descriptors-test - entrypoint: - scorecard-test - olm-status-descriptors - image: quay.io/operator-framework/scorecard-test:v1.1.0 + image: quay.io/operator-framework/scorecard-test:v1.2.0 labels: suite: olm test: olm-status-descriptors-test diff --git a/testdata/go/memcached-operator/config/scorecard/patches/basic.config.yaml b/testdata/go/memcached-operator/config/scorecard/patches/basic.config.yaml index 39576a573b2..f80c746f9e7 100644 --- a/testdata/go/memcached-operator/config/scorecard/patches/basic.config.yaml +++ b/testdata/go/memcached-operator/config/scorecard/patches/basic.config.yaml @@ -4,7 +4,7 @@ entrypoint: - scorecard-test - basic-check-spec - image: quay.io/operator-framework/scorecard-test:v1.1.0 + image: quay.io/operator-framework/scorecard-test:v1.2.0 labels: suite: basic test: basic-check-spec-test diff --git a/testdata/go/memcached-operator/config/scorecard/patches/olm.config.yaml b/testdata/go/memcached-operator/config/scorecard/patches/olm.config.yaml index 8102e4db2da..ef6834b1e3d 100644 --- a/testdata/go/memcached-operator/config/scorecard/patches/olm.config.yaml +++ b/testdata/go/memcached-operator/config/scorecard/patches/olm.config.yaml @@ -4,7 +4,7 @@ entrypoint: - scorecard-test - olm-bundle-validation - image: quay.io/operator-framework/scorecard-test:v1.1.0 + image: quay.io/operator-framework/scorecard-test:v1.2.0 labels: suite: olm test: olm-bundle-validation-test @@ -14,7 +14,7 @@ entrypoint: - scorecard-test - olm-crds-have-validation - image: quay.io/operator-framework/scorecard-test:v1.1.0 + image: quay.io/operator-framework/scorecard-test:v1.2.0 labels: suite: olm test: olm-crds-have-validation-test @@ -24,7 +24,7 @@ entrypoint: - scorecard-test - olm-crds-have-resources - image: quay.io/operator-framework/scorecard-test:v1.1.0 + image: quay.io/operator-framework/scorecard-test:v1.2.0 labels: suite: olm test: olm-crds-have-resources-test @@ -34,7 +34,7 @@ entrypoint: - scorecard-test - olm-spec-descriptors - image: quay.io/operator-framework/scorecard-test:v1.1.0 + image: quay.io/operator-framework/scorecard-test:v1.2.0 labels: suite: olm test: olm-spec-descriptors-test @@ -44,7 +44,7 @@ entrypoint: - scorecard-test - olm-status-descriptors - image: quay.io/operator-framework/scorecard-test:v1.1.0 + image: quay.io/operator-framework/scorecard-test:v1.2.0 labels: suite: olm test: olm-status-descriptors-test diff --git a/testdata/helm/memcached-operator/Dockerfile b/testdata/helm/memcached-operator/Dockerfile index 19096a3f00d..594ad0c9f84 100644 --- a/testdata/helm/memcached-operator/Dockerfile +++ b/testdata/helm/memcached-operator/Dockerfile @@ -1,5 +1,5 @@ # Build the manager binary -FROM quay.io/operator-framework/helm-operator:v1.1.0 +FROM quay.io/operator-framework/helm-operator:v1.2.0 ENV HOME=/opt/helm COPY watches.yaml ${HOME}/watches.yaml diff --git a/testdata/helm/memcached-operator/Makefile b/testdata/helm/memcached-operator/Makefile index 63dacab47b7..6e63eef6a39 100644 --- a/testdata/helm/memcached-operator/Makefile +++ b/testdata/helm/memcached-operator/Makefile @@ -69,8 +69,8 @@ ifeq (, $(shell which helm-operator 2>/dev/null)) @{ \ set -e ;\ mkdir -p bin ;\ - curl -LO https://github.com/operator-framework/operator-sdk/releases/download/v1.1.0/helm-operator-v1.1.0-$(ARCHOPER)-$(OSOPER) ;\ - mv helm-operator-v1.1.0-$(ARCHOPER)-$(OSOPER) ./bin/helm-operator ;\ + curl -LO https://github.com/operator-framework/operator-sdk/releases/download/v1.2.0/helm-operator-v1.2.0-$(ARCHOPER)-$(OSOPER) ;\ + mv helm-operator-v1.2.0-$(ARCHOPER)-$(OSOPER) ./bin/helm-operator ;\ chmod +x ./bin/helm-operator ;\ } HELM_OPERATOR=$(realpath ./bin/helm-operator) diff --git a/testdata/helm/memcached-operator/bundle/tests/scorecard/config.yaml b/testdata/helm/memcached-operator/bundle/tests/scorecard/config.yaml index 83bc60f0570..e39a5d88b57 100644 --- a/testdata/helm/memcached-operator/bundle/tests/scorecard/config.yaml +++ b/testdata/helm/memcached-operator/bundle/tests/scorecard/config.yaml @@ -8,42 +8,42 @@ stages: - entrypoint: - scorecard-test - basic-check-spec - image: quay.io/operator-framework/scorecard-test:v1.1.0 + image: quay.io/operator-framework/scorecard-test:v1.2.0 labels: suite: basic test: basic-check-spec-test - entrypoint: - scorecard-test - olm-bundle-validation - image: quay.io/operator-framework/scorecard-test:v1.1.0 + image: quay.io/operator-framework/scorecard-test:v1.2.0 labels: suite: olm test: olm-bundle-validation-test - entrypoint: - scorecard-test - olm-crds-have-validation - image: quay.io/operator-framework/scorecard-test:v1.1.0 + image: quay.io/operator-framework/scorecard-test:v1.2.0 labels: suite: olm test: olm-crds-have-validation-test - entrypoint: - scorecard-test - olm-crds-have-resources - image: quay.io/operator-framework/scorecard-test:v1.1.0 + image: quay.io/operator-framework/scorecard-test:v1.2.0 labels: suite: olm test: olm-crds-have-resources-test - entrypoint: - scorecard-test - olm-spec-descriptors - image: quay.io/operator-framework/scorecard-test:v1.1.0 + image: quay.io/operator-framework/scorecard-test:v1.2.0 labels: suite: olm test: olm-spec-descriptors-test - entrypoint: - scorecard-test - olm-status-descriptors - image: quay.io/operator-framework/scorecard-test:v1.1.0 + image: quay.io/operator-framework/scorecard-test:v1.2.0 labels: suite: olm test: olm-status-descriptors-test diff --git a/testdata/helm/memcached-operator/config/scorecard/patches/basic.config.yaml b/testdata/helm/memcached-operator/config/scorecard/patches/basic.config.yaml index 39576a573b2..f80c746f9e7 100644 --- a/testdata/helm/memcached-operator/config/scorecard/patches/basic.config.yaml +++ b/testdata/helm/memcached-operator/config/scorecard/patches/basic.config.yaml @@ -4,7 +4,7 @@ entrypoint: - scorecard-test - basic-check-spec - image: quay.io/operator-framework/scorecard-test:v1.1.0 + image: quay.io/operator-framework/scorecard-test:v1.2.0 labels: suite: basic test: basic-check-spec-test diff --git a/testdata/helm/memcached-operator/config/scorecard/patches/olm.config.yaml b/testdata/helm/memcached-operator/config/scorecard/patches/olm.config.yaml index 8102e4db2da..ef6834b1e3d 100644 --- a/testdata/helm/memcached-operator/config/scorecard/patches/olm.config.yaml +++ b/testdata/helm/memcached-operator/config/scorecard/patches/olm.config.yaml @@ -4,7 +4,7 @@ entrypoint: - scorecard-test - olm-bundle-validation - image: quay.io/operator-framework/scorecard-test:v1.1.0 + image: quay.io/operator-framework/scorecard-test:v1.2.0 labels: suite: olm test: olm-bundle-validation-test @@ -14,7 +14,7 @@ entrypoint: - scorecard-test - olm-crds-have-validation - image: quay.io/operator-framework/scorecard-test:v1.1.0 + image: quay.io/operator-framework/scorecard-test:v1.2.0 labels: suite: olm test: olm-crds-have-validation-test @@ -24,7 +24,7 @@ entrypoint: - scorecard-test - olm-crds-have-resources - image: quay.io/operator-framework/scorecard-test:v1.1.0 + image: quay.io/operator-framework/scorecard-test:v1.2.0 labels: suite: olm test: olm-crds-have-resources-test @@ -34,7 +34,7 @@ entrypoint: - scorecard-test - olm-spec-descriptors - image: quay.io/operator-framework/scorecard-test:v1.1.0 + image: quay.io/operator-framework/scorecard-test:v1.2.0 labels: suite: olm test: olm-spec-descriptors-test @@ -44,7 +44,7 @@ entrypoint: - scorecard-test - olm-status-descriptors - image: quay.io/operator-framework/scorecard-test:v1.1.0 + image: quay.io/operator-framework/scorecard-test:v1.2.0 labels: suite: olm test: olm-status-descriptors-test From 853dfa92aac17051a5231124de876bb5367e22d6 Mon Sep 17 00:00:00 2001 From: Jonathan Berkhahn Date: Fri, 6 Nov 2020 09:43:43 -0800 Subject: [PATCH 199/376] ansible-operator,helm-operator: improve executable help text (#4187) Co-authored-by: Eric Stroczynski Signed-off-by: reinvantveer --- changelog/fragments/ansible-helm-help-text.yaml | 5 +++++ cmd/ansible-operator/main.go | 5 +++++ cmd/helm-operator/main.go | 5 +++++ 3 files changed, 15 insertions(+) create mode 100644 changelog/fragments/ansible-helm-help-text.yaml diff --git a/changelog/fragments/ansible-helm-help-text.yaml b/changelog/fragments/ansible-helm-help-text.yaml new file mode 100644 index 00000000000..4376918c0e6 --- /dev/null +++ b/changelog/fragments/ansible-helm-help-text.yaml @@ -0,0 +1,5 @@ +entries: + - description: > + Improved `ansible-operator` and `helm-operator` help text + kind: change + breaking: false diff --git a/cmd/ansible-operator/main.go b/cmd/ansible-operator/main.go index 12f79ce7807..567e8925bee 100644 --- a/cmd/ansible-operator/main.go +++ b/cmd/ansible-operator/main.go @@ -26,6 +26,11 @@ import ( func main() { root := cobra.Command{ + Short: "Reconcile an Ansible operator project using ansible-runner", + Long: `This binary runs an Ansible operator that reconciles Kubernetes resources +managed by the ansible-runner program. It can be run either directly or from an Ansible +operator project's image entrypoint +`, Use: "ansible-operator", } diff --git a/cmd/helm-operator/main.go b/cmd/helm-operator/main.go index c223adcea3c..795ee80797f 100644 --- a/cmd/helm-operator/main.go +++ b/cmd/helm-operator/main.go @@ -26,6 +26,11 @@ import ( func main() { root := cobra.Command{ + Short: "Reconcile an Helm operator project using helm", + Long: `This binary runs a Helm operator that reconciles Kubernetes resources +managed by the helm program. It can be run either directly or from a Helm operator +project's image entrypoint +`, Use: "helm-operator", } From e8927f444f671811cd10d6aef428a3204bd4a3e4 Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Fri, 6 Nov 2020 12:12:55 -0800 Subject: [PATCH 200/376] deps: exclude github.com/spf13/viper@v1.3.2 to fix CVE-2018-1098 (#4199) Signed-off-by: reinvantveer --- changelog/fragments/CVE-2018-1098.yaml | 4 ++++ go.mod | 2 ++ go.sum | 5 ----- 3 files changed, 6 insertions(+), 5 deletions(-) create mode 100644 changelog/fragments/CVE-2018-1098.yaml diff --git a/changelog/fragments/CVE-2018-1098.yaml b/changelog/fragments/CVE-2018-1098.yaml new file mode 100644 index 00000000000..5898213f944 --- /dev/null +++ b/changelog/fragments/CVE-2018-1098.yaml @@ -0,0 +1,4 @@ +entries: + - description: > + Excluded `github.com/spf13/viper@v1.3.2` to fix CVE-2018-1098 + kind: bugfix diff --git a/go.mod b/go.mod index 6fb5aa7106c..b77db9dc392 100644 --- a/go.mod +++ b/go.mod @@ -43,3 +43,5 @@ replace ( github.com/mattn/go-sqlite3 => github.com/mattn/go-sqlite3 v1.10.0 golang.org/x/text => golang.org/x/text v0.3.3 // Required to fix CVE-2020-14040 ) + +exclude github.com/spf13/viper v1.3.2 // Required to fix CVE-2018-1098 diff --git a/go.sum b/go.sum index 3e1b52adba4..5bab10b2423 100644 --- a/go.sum +++ b/go.sum @@ -146,7 +146,6 @@ github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd h1:JNn81o/xG+8N github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -790,7 +789,6 @@ github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= @@ -813,7 +811,6 @@ github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhV github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= @@ -879,7 +876,6 @@ go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -963,7 +959,6 @@ golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190102155601-82a175fd1598/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= From 86f14f24ba3cdee5f9ccfea10500a063f527f650 Mon Sep 17 00:00:00 2001 From: Varsha Date: Fri, 6 Nov 2020 13:49:05 -0800 Subject: [PATCH 201/376] [webhook] Add targetPort while scaffolding csv (#4178) * [webhook] Specify ports while scaffolding csv * update samples * update csv tests Signed-off-by: reinvantveer --- .../clusterserviceversion_updaters.go | 63 ++++++++++++++----- .../clusterserviceversion_updaters_test.go | 24 +++---- ...cached-operator.clusterserviceversion.yaml | 4 ++ ...cached-operator.clusterserviceversion.yaml | 4 ++ 4 files changed, 67 insertions(+), 28 deletions(-) diff --git a/internal/generate/clusterserviceversion/clusterserviceversion_updaters.go b/internal/generate/clusterserviceversion/clusterserviceversion_updaters.go index a8fc1992b9b..faf8911686c 100644 --- a/internal/generate/clusterserviceversion/clusterserviceversion_updaters.go +++ b/internal/generate/clusterserviceversion/clusterserviceversion_updaters.go @@ -269,23 +269,36 @@ func applyCustomResourceDefinitions(c *collector.Manifests, csv *operatorsv1alph // applyWebhooks updates csv's webhookDefinitions with any mutating and validating webhooks in the collector. func applyWebhooks(c *collector.Manifests, csv *operatorsv1alpha1.ClusterServiceVersion) { webhookDescriptions := []operatorsv1alpha1.WebhookDescription{} + for _, webhook := range c.ValidatingWebhooks { - depName, serviceName := findMatchingDeploymentAndServiceForWebhook(c, webhook.ClientConfig) - if serviceName == "" && depName == "" { + var validatingServiceName string + depName, svc := findMatchingDeploymentAndServiceForWebhook(c, webhook.ClientConfig) + + if svc != nil { + validatingServiceName = svc.GetName() + } + + if validatingServiceName == "" && depName == "" { log.Infof("No service found for validating webhook %q", webhook.Name) } else if depName == "" { - log.Infof("No deployment is selected by service %q for validating webhook %q", serviceName, webhook.Name) + log.Infof("No deployment is selected by service %q for validating webhook %q", validatingServiceName, webhook.Name) } - webhookDescriptions = append(webhookDescriptions, validatingToWebhookDescription(webhook, depName)) + webhookDescriptions = append(webhookDescriptions, validatingToWebhookDescription(webhook, depName, svc)) } for _, webhook := range c.MutatingWebhooks { - depName, serviceName := findMatchingDeploymentAndServiceForWebhook(c, webhook.ClientConfig) - if serviceName == "" && depName == "" { + var mutatingServiceName string + depName, svc := findMatchingDeploymentAndServiceForWebhook(c, webhook.ClientConfig) + + if svc != nil { + mutatingServiceName = svc.GetName() + } + + if mutatingServiceName == "" && depName == "" { log.Infof("No service found for mutating webhook %q", webhook.Name) } else if depName == "" { - log.Infof("No deployment is selected by service %q for mutating webhook %q", serviceName, webhook.Name) + log.Infof("No deployment is selected by service %q for mutating webhook %q", mutatingServiceName, webhook.Name) } - webhookDescriptions = append(webhookDescriptions, mutatingToWebhookDescription(webhook, depName)) + webhookDescriptions = append(webhookDescriptions, mutatingToWebhookDescription(webhook, depName, svc)) } csv.Spec.WebhookDefinitions = webhookDescriptions } @@ -294,7 +307,7 @@ func applyWebhooks(c *collector.Manifests, csv *operatorsv1alpha1.ClusterService var defaultAdmissionReviewVersions = []string{"v1beta1"} // validatingToWebhookDescription transforms webhook into a WebhookDescription. -func validatingToWebhookDescription(webhook admissionregv1.ValidatingWebhook, depName string) operatorsv1alpha1.WebhookDescription { +func validatingToWebhookDescription(webhook admissionregv1.ValidatingWebhook, depName string, ws *corev1.Service) operatorsv1alpha1.WebhookDescription { description := operatorsv1alpha1.WebhookDescription{ Type: operatorsv1alpha1.ValidatingAdmissionWebhook, GenerateName: webhook.Name, @@ -315,8 +328,18 @@ func validatingToWebhookDescription(webhook admissionregv1.ValidatingWebhook, de } if serviceRef := webhook.ClientConfig.Service; serviceRef != nil { + var webhookServiceRefPort int32 = 443 if serviceRef.Port != nil { - description.ContainerPort = *serviceRef.Port + webhookServiceRefPort = *serviceRef.Port + } + if ws != nil { + for _, port := range ws.Spec.Ports { + if webhookServiceRefPort == port.Port { + description.ContainerPort = port.Port + description.TargetPort = &port.TargetPort + break + } + } } description.DeploymentName = depName if description.DeploymentName == "" { @@ -328,7 +351,7 @@ func validatingToWebhookDescription(webhook admissionregv1.ValidatingWebhook, de } // mutatingToWebhookDescription transforms webhook into a WebhookDescription. -func mutatingToWebhookDescription(webhook admissionregv1.MutatingWebhook, depName string) operatorsv1alpha1.WebhookDescription { +func mutatingToWebhookDescription(webhook admissionregv1.MutatingWebhook, depName string, ws *corev1.Service) operatorsv1alpha1.WebhookDescription { description := operatorsv1alpha1.WebhookDescription{ Type: operatorsv1alpha1.MutatingAdmissionWebhook, GenerateName: webhook.Name, @@ -350,8 +373,18 @@ func mutatingToWebhookDescription(webhook admissionregv1.MutatingWebhook, depNam } if serviceRef := webhook.ClientConfig.Service; serviceRef != nil { + var webhookServiceRefPort int32 = 443 if serviceRef.Port != nil { - description.ContainerPort = *serviceRef.Port + webhookServiceRefPort = *serviceRef.Port + } + if ws != nil { + for _, port := range ws.Spec.Ports { + if webhookServiceRefPort == port.Port { + description.ContainerPort = port.Port + description.TargetPort = &port.TargetPort + break + } + } } description.DeploymentName = depName if description.DeploymentName == "" { @@ -365,7 +398,7 @@ func mutatingToWebhookDescription(webhook admissionregv1.MutatingWebhook, depNam // findMatchingDeploymentAndServiceForWebhook matches a Service to a webhook's client config (if it uses a service) // then matches that Service to a Deployment by comparing label selectors (if the Service uses label selectors). // The names of both Service and Deployment are returned if found. -func findMatchingDeploymentAndServiceForWebhook(c *collector.Manifests, wcc admissionregv1.WebhookClientConfig) (depName, serviceName string) { +func findMatchingDeploymentAndServiceForWebhook(c *collector.Manifests, wcc admissionregv1.WebhookClientConfig) (depName string, ws *corev1.Service) { // Return if a service reference is not specified, since a URL will be in that case. if wcc.Service == nil { return @@ -373,7 +406,6 @@ func findMatchingDeploymentAndServiceForWebhook(c *collector.Manifests, wcc admi // Find the matching service, if any. The webhook server may be externally managed // if no service is created by the operator. - var ws *corev1.Service for i, service := range c.Services { if service.GetName() == wcc.Service.Name { ws = &c.Services[i] @@ -383,7 +415,6 @@ func findMatchingDeploymentAndServiceForWebhook(c *collector.Manifests, wcc admi if ws == nil { return } - serviceName = ws.GetName() // Only ExternalName-type services cannot have selectors. if ws.Spec.Type == corev1.ServiceTypeExternalName { @@ -416,7 +447,7 @@ func findMatchingDeploymentAndServiceForWebhook(c *collector.Manifests, wcc admi } } - return depName, serviceName + return depName, ws } // applyCustomResources updates csv's "alm-examples" annotation with the diff --git a/internal/generate/clusterserviceversion/clusterserviceversion_updaters_test.go b/internal/generate/clusterserviceversion/clusterserviceversion_updaters_test.go index 0e92f5a0ad9..5e0d42f927e 100644 --- a/internal/generate/clusterserviceversion/clusterserviceversion_updaters_test.go +++ b/internal/generate/clusterserviceversion/clusterserviceversion_updaters_test.go @@ -49,9 +49,9 @@ var _ = Describe("findMatchingDeploymentAndServiceForWebhook", func() { c.Deployments = []appsv1.Deployment{newDeployment(depName1, labels)} c.Services = []corev1.Service{newService(serviceName1, labels)} wcc.Service.Name = serviceName1 - depName, serviceName := findMatchingDeploymentAndServiceForWebhook(c, wcc) + depName, service := findMatchingDeploymentAndServiceForWebhook(c, wcc) Expect(depName).To(Equal(depName1)) - Expect(serviceName).To(Equal(serviceName1)) + Expect(service.GetName()).To(Equal(serviceName1)) }) By("parsing two deployments and two services with non-intersecting labels") @@ -67,9 +67,9 @@ var _ = Describe("findMatchingDeploymentAndServiceForWebhook", func() { newService(serviceName2, labels2), } wcc.Service.Name = serviceName1 - depName, serviceName := findMatchingDeploymentAndServiceForWebhook(c, wcc) + depName, service := findMatchingDeploymentAndServiceForWebhook(c, wcc) Expect(depName).To(Equal(depName1)) - Expect(serviceName).To(Equal(serviceName1)) + Expect(service.GetName()).To(Equal(serviceName1)) }) By("parsing two deployments and two services with a label subset") @@ -82,9 +82,9 @@ var _ = Describe("findMatchingDeploymentAndServiceForWebhook", func() { } c.Services = []corev1.Service{newService(serviceName1, labels1)} wcc.Service.Name = serviceName1 - depName, serviceName := findMatchingDeploymentAndServiceForWebhook(c, wcc) + depName, service := findMatchingDeploymentAndServiceForWebhook(c, wcc) Expect(depName).To(Equal(depName2)) - Expect(serviceName).To(Equal(serviceName1)) + Expect(service.GetName()).To(Equal(serviceName1)) }) }) @@ -95,9 +95,9 @@ var _ = Describe("findMatchingDeploymentAndServiceForWebhook", func() { c.Deployments = []appsv1.Deployment{newDeployment(depName1, labels)} c.Services = []corev1.Service{newService(serviceName1, labels)} wcc.Service.Name = serviceName2 - depName, serviceName := findMatchingDeploymentAndServiceForWebhook(c, wcc) + depName, service := findMatchingDeploymentAndServiceForWebhook(c, wcc) Expect(depName).To(BeEmpty()) - Expect(serviceName).To(BeEmpty()) + Expect(service).To(BeNil()) }) }) @@ -109,9 +109,9 @@ var _ = Describe("findMatchingDeploymentAndServiceForWebhook", func() { c.Deployments = []appsv1.Deployment{newDeployment(depName1, labels1)} c.Services = []corev1.Service{newService(serviceName1, labels2)} wcc.Service.Name = serviceName1 - depName, serviceName := findMatchingDeploymentAndServiceForWebhook(c, wcc) + depName, service := findMatchingDeploymentAndServiceForWebhook(c, wcc) Expect(depName).To(BeEmpty()) - Expect(serviceName).To(Equal(serviceName1)) + Expect(service.GetName()).To(Equal(serviceName1)) }) By("parsing one deployment and one service with two intersecting labels") @@ -121,9 +121,9 @@ var _ = Describe("findMatchingDeploymentAndServiceForWebhook", func() { c.Deployments = []appsv1.Deployment{newDeployment(depName1, labels1)} c.Services = []corev1.Service{newService(serviceName1, labels2)} wcc.Service.Name = serviceName1 - depName, serviceName := findMatchingDeploymentAndServiceForWebhook(c, wcc) + depName, service := findMatchingDeploymentAndServiceForWebhook(c, wcc) Expect(depName).To(BeEmpty()) - Expect(serviceName).To(Equal(serviceName1)) + Expect(service.GetName()).To(Equal(serviceName1)) }) }) }) diff --git a/internal/generate/testdata/clusterserviceversions/output/memcached-operator.clusterserviceversion.yaml b/internal/generate/testdata/clusterserviceversions/output/memcached-operator.clusterserviceversion.yaml index d16c653170f..9cf1d1491cc 100644 --- a/internal/generate/testdata/clusterserviceversions/output/memcached-operator.clusterserviceversion.yaml +++ b/internal/generate/testdata/clusterserviceversions/output/memcached-operator.clusterserviceversion.yaml @@ -215,6 +215,7 @@ spec: webhookdefinitions: - admissionReviewVersions: - v1beta1 + containerPort: 443 deploymentName: memcached-operator-controller-manager failurePolicy: Fail generateName: vmemcached.kb.io @@ -229,10 +230,12 @@ spec: resources: - memcacheds sideEffects: None + targetPort: 9443 type: ValidatingAdmissionWebhook webhookPath: /validate-cache-my-domain-v1alpha1-memcached - admissionReviewVersions: - v1beta1 + containerPort: 443 deploymentName: memcached-operator-controller-manager failurePolicy: Fail generateName: mmemcached.kb.io @@ -247,5 +250,6 @@ spec: resources: - memcacheds sideEffects: None + targetPort: 9443 type: MutatingAdmissionWebhook webhookPath: /mutate-cache-my-domain-v1alpha1-memcached diff --git a/testdata/go/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml b/testdata/go/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml index 89a0fa6d67a..d50d3167974 100644 --- a/testdata/go/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml +++ b/testdata/go/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml @@ -205,6 +205,7 @@ spec: webhookdefinitions: - admissionReviewVersions: - v1beta1 + containerPort: 443 deploymentName: memcached-operator-controller-manager failurePolicy: Fail generateName: vmemcached.kb.io @@ -219,10 +220,12 @@ spec: resources: - memcacheds sideEffects: None + targetPort: 9443 type: ValidatingAdmissionWebhook webhookPath: /validate-cache-example-com-v1alpha1-memcached - admissionReviewVersions: - v1beta1 + containerPort: 443 deploymentName: memcached-operator-controller-manager failurePolicy: Fail generateName: mmemcached.kb.io @@ -237,5 +240,6 @@ spec: resources: - memcacheds sideEffects: None + targetPort: 9443 type: MutatingAdmissionWebhook webhookPath: /mutate-cache-example-com-v1alpha1-memcached From a4f6ff725ab782660b4b1039fa36105d4f28078c Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Mon, 9 Nov 2020 09:30:57 -0800 Subject: [PATCH 202/376] hack/check-links.sh: add 'ignore' check options (#4205) hack/check-links.sh: ignore urls containing github.com/operator-framework/operator-sdk/edit/master/ hack/*: move test_lib.sh functions into common.sh and import common.sh where applicable Signed-off-by: reinvantveer --- hack/check-error-log-msg-format.sh | 2 +- hack/check-license.sh | 2 +- hack/check-links.sh | 13 ++++++--- hack/lib/common.sh | 40 +++++++++++++++++++++++++++ hack/lib/test_lib.sh | 43 ------------------------------ hack/tests/e2e-ansible-molecule.sh | 1 - hack/tests/integration.sh | 1 - 7 files changed, 52 insertions(+), 50 deletions(-) delete mode 100644 hack/lib/test_lib.sh diff --git a/hack/check-error-log-msg-format.sh b/hack/check-error-log-msg-format.sh index 279a69b8dfb..7aef3604dc9 100755 --- a/hack/check-error-log-msg-format.sh +++ b/hack/check-error-log-msg-format.sh @@ -3,7 +3,7 @@ set -o nounset set -o pipefail -source "hack/lib/test_lib.sh" +source "hack/lib/common.sh" echo "Checking format of error and log messages..." allfiles=$(listFiles|grep -v ./internal/bindata/...) diff --git a/hack/check-license.sh b/hack/check-license.sh index 0d61cee180c..1c10c64ae63 100755 --- a/hack/check-license.sh +++ b/hack/check-license.sh @@ -4,7 +4,7 @@ set -o errexit set -o nounset set -o pipefail -source "hack/lib/test_lib.sh" +source "hack/lib/common.sh" echo "Checking for license header..." allfiles=$(listFiles|grep -v ./internal/bindata/...) diff --git a/hack/check-links.sh b/hack/check-links.sh index 15a3b87eb89..e9ef07a3830 100755 --- a/hack/check-links.sh +++ b/hack/check-links.sh @@ -4,8 +4,15 @@ set -e source ./hack/lib/common.sh -header_text "Building the site and checking links" +header_text "Building the website" docker volume create sdk-html +trap_add "docker volume rm sdk-html" EXIT docker run --rm -v "$(pwd):/src" -v sdk-html:/src/website/public klakegg/hugo:0.73.0-ext-ubuntu -s website -docker run --rm -v sdk-html:/target mtlynch/htmlproofer /target --empty-alt-ignore --http-status-ignore 429 --allow_hash_href -docker volume rm sdk-html + +header_text "Checking links" +# For config explanation: https://github.com/gjtorikian/html-proofer#special-cases-for-the-command-line +docker run --rm -v sdk-html:/target klakegg/html-proofer:latest /target \ + --empty-alt-ignore \ + --http-status-ignore 429 \ + --allow_hash_href \ + --url-ignore "/github.com\/operator-framework\/operator-sdk\/edit\/master\//" diff --git a/hack/lib/common.sh b/hack/lib/common.sh index 0abbe0e1cb0..3a4f899b29d 100644 --- a/hack/lib/common.sh +++ b/hack/lib/common.sh @@ -24,3 +24,43 @@ function header_text { function error_text { echo "$error_color$*$reset_color" } + +#=================================================================== +# FUNCTION trap_add () +# +# Purpose: prepends a command to a trap +# +# - 1st arg: code to add +# - remaining args: names of traps to modify +# +# Example: trap_add 'echo "in trap DEBUG"' DEBUG +# +# See: http://stackoverflow.com/questions/3338030/multiple-bash-traps-for-the-same-signal +#=================================================================== +function trap_add() { + trap_add_cmd=$1; shift || fatal "${FUNCNAME} usage error" + new_cmd= + for trap_add_name in "$@"; do + # Grab the currently defined trap commands for this trap + existing_cmd=`trap -p "${trap_add_name}" | awk -F"'" '{print $2}'` + + # Define default command + [ -z "${existing_cmd}" ] && existing_cmd="echo exiting @ `date`" + + # Generate the new command + new_cmd="${trap_add_cmd};${existing_cmd}" + + # Assign the test + trap "${new_cmd}" "${trap_add_name}" || \ + fatal "unable to add to trap ${trap_add_name}" + done +} + +function listPkgDirs() { + go list -f '{{.Dir}}' ./cmd/... ./test/... ./internal/... | grep -v generated +} + +function listFiles() { + # pipeline is much faster than for loop + listPkgDirs | xargs -I {} find {} -name '*.go' | grep -v generated +} diff --git a/hack/lib/test_lib.sh b/hack/lib/test_lib.sh deleted file mode 100644 index 44e222c2e71..00000000000 --- a/hack/lib/test_lib.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env bash - -source hack/lib/common.sh - -function listPkgDirs() { - go list -f '{{.Dir}}' ./cmd/... ./test/... ./internal/... | grep -v generated -} - -function listFiles() { - # pipeline is much faster than for loop - listPkgDirs | xargs -I {} find {} -name '*.go' | grep -v generated -} - -#=================================================================== -# FUNCTION trap_add () -# -# Purpose: prepends a command to a trap -# -# - 1st arg: code to add -# - remaining args: names of traps to modify -# -# Example: trap_add 'echo "in trap DEBUG"' DEBUG -# -# See: http://stackoverflow.com/questions/3338030/multiple-bash-traps-for-the-same-signal -#=================================================================== -function trap_add() { - trap_add_cmd=$1; shift || fatal "${FUNCNAME} usage error" - new_cmd= - for trap_add_name in "$@"; do - # Grab the currently defined trap commands for this trap - existing_cmd=`trap -p "${trap_add_name}" | awk -F"'" '{print $2}'` - - # Define default command - [ -z "${existing_cmd}" ] && existing_cmd="echo exiting @ `date`" - - # Generate the new command - new_cmd="${trap_add_cmd};${existing_cmd}" - - # Assign the test - trap "${new_cmd}" "${trap_add_name}" || \ - fatal "unable to add to trap ${trap_add_name}" - done -} diff --git a/hack/tests/e2e-ansible-molecule.sh b/hack/tests/e2e-ansible-molecule.sh index 3cc39c8b93a..a2449fe734e 100755 --- a/hack/tests/e2e-ansible-molecule.sh +++ b/hack/tests/e2e-ansible-molecule.sh @@ -1,7 +1,6 @@ #!/usr/bin/env bash source hack/lib/common.sh -source hack/lib/test_lib.sh source hack/lib/image_lib.sh set -eu diff --git a/hack/tests/integration.sh b/hack/tests/integration.sh index 5805b7e9e98..91a76b247c5 100755 --- a/hack/tests/integration.sh +++ b/hack/tests/integration.sh @@ -3,7 +3,6 @@ set -eu source hack/lib/common.sh -source hack/lib/test_lib.sh source hack/lib/image_lib.sh TMPDIR="$(mktemp -d -p /tmp memcached-operator-XXXX)" From 7c6d2d5433465926e48c33d1d0aea658925528a4 Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Mon, 9 Nov 2020 09:58:06 -0800 Subject: [PATCH 203/376] release v1.2.0 (#4201) Signed-off-by: reinvantveer --- CHANGELOG.md | 28 ++++++++++ changelog/fragments/CVE-2018-1098.yaml | 4 -- .../fragments/ansible-helm-help-text.yaml | 5 -- ...ted-makefile-bundle-prerequisite-task.yaml | 27 ---------- .../fragments/bundle-pm-supported-kinds.yaml | 3 -- changelog/fragments/fix-cleanup.yaml | 7 --- .../fix-csv-generate-path-segments.yaml | 5 -- .../fix-helm-finalizers-permissions.yaml | 7 --- changelog/fragments/go-version-bug.yaml | 4 -- changelog/fragments/olm-version-v.yaml | 4 -- changelog/fragments/plugins-use-rbac-v1.yaml | 6 --- .../fragments/return-olm-install-error.yaml | 5 -- .../scorecard-status-descriptor-test.yaml | 16 ------ changelog/fragments/upgrade-kb.yaml | 54 ------------------- .../upgrade-operator-framework-api.yaml | 31 ----------- website/config.toml | 8 ++- .../docs/installation/install-operator-sdk.md | 2 +- .../en/docs/upgrading-sdk-version/v1.2.0.md | 22 ++++++++ 18 files changed, 57 insertions(+), 181 deletions(-) delete mode 100644 changelog/fragments/CVE-2018-1098.yaml delete mode 100644 changelog/fragments/ansible-helm-help-text.yaml delete mode 100644 changelog/fragments/autogenerated-makefile-bundle-prerequisite-task.yaml delete mode 100644 changelog/fragments/bundle-pm-supported-kinds.yaml delete mode 100644 changelog/fragments/fix-cleanup.yaml delete mode 100644 changelog/fragments/fix-csv-generate-path-segments.yaml delete mode 100644 changelog/fragments/fix-helm-finalizers-permissions.yaml delete mode 100644 changelog/fragments/go-version-bug.yaml delete mode 100644 changelog/fragments/olm-version-v.yaml delete mode 100644 changelog/fragments/plugins-use-rbac-v1.yaml delete mode 100644 changelog/fragments/return-olm-install-error.yaml delete mode 100644 changelog/fragments/scorecard-status-descriptor-test.yaml delete mode 100644 changelog/fragments/upgrade-kb.yaml delete mode 100644 changelog/fragments/upgrade-operator-framework-api.yaml create mode 100644 website/content/en/docs/upgrading-sdk-version/v1.2.0.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 1378241b96f..08efe9354e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,31 @@ +## v1.2.0 + +### Additions + +- Enabled definition of custom categories encoded as [JSON file(s)](https://olm.operatorframework.io/docs/tasks/validate-package/#validation) for the `operatorhub` validator. ([#4109](https://github.com/operator-framework/operator-sdk/pull/4109)) + +### Changes + +- Improved `ansible-operator` and `helm-operator` help text. ([#4187](https://github.com/operator-framework/operator-sdk/pull/4187)) +- When generating bundles and package manifests, add all resources supported by OLM. ([#4137](https://github.com/operator-framework/operator-sdk/pull/4137)) +- `olm` and `run` subcommands will print aggregated resource errors when either OLM or an operator fail to install, respectively. ([#3787](https://github.com/operator-framework/operator-sdk/pull/3787)) +- Upgraded `sigs.k8s.io/controller-runtime` from `v0.6.2` to [`v0.6.3`](https://github.com/kubernetes-sigs/controller-runtime/releases/tag/v0.6.3). ([#4062](https://github.com/operator-framework/operator-sdk/pull/4062)) + +### Bug Fixes + +- Set a generated CSV's `.spec.webhookdefinitions[].{targetPort,containerPort}` values from webhook `Service` ports. ([#4178](https://github.com/operator-framework/operator-sdk/pull/4178)) +- Excluded `github.com/spf13/viper@v1.3.2` to fix CVE-2018-1098. ([#4199](https://github.com/operator-framework/operator-sdk/pull/4199)) +- Added the `kustomize` make dependency to the `bundle` target scaffolded for Golang projects to install `kustomize` before running. ([#4090](https://github.com/operator-framework/operator-sdk/pull/4090)) +- Fixed an issue in `operator-sdk cleanup` that caused `CatalogSource` and `OperatorGroup` objects not to be cleaned up if a previous `operator-sdk run` command failed. ([#4089](https://github.com/operator-framework/operator-sdk/pull/4089)) +- Fixed an issue during CSV generation that caused incorrect paths to be used in `specDescriptors` and `statusDescriptors`. ([#4166](https://github.com/operator-framework/operator-sdk/pull/4166)) +- In Helm projects, fixed operator RBAC permissions to support the OwnerReferencesPermissionEnforcement admission plugin by adding a `/finalizers` rule in the operator's role. ([#4105](https://github.com/operator-framework/operator-sdk/pull/4105)) +- Removed redundant platform information from `operator-sdk version` output. ([#4083](https://github.com/operator-framework/operator-sdk/pull/4083)) +- Format version string passed to `olm` subcommands so releases download correctly. ([#4181](https://github.com/operator-framework/operator-sdk/pull/4181)) +- In Go, Ansible, and Helm operators, updated the `metrics-reader` ClusterRole to use `rbac.authorization.k8s.io/v1` to be consistent with all other scaffolded RBAC resources. ([#4136](https://github.com/operator-framework/operator-sdk/pull/4136)) +- Modified `olm-status-descriptors-test` to only validate if the status-descriptors are present in CRD. ([#4009](https://github.com/operator-framework/operator-sdk/pull/4009)) +- Webhook container port specified in CSV defaults to `443` if not specified by the user. ([#4109](https://github.com/operator-framework/operator-sdk/pull/4109)) +- For Golang based operators with multigroup support, fixed `envtest.Environment.CRDDirectoryPaths` in scaffolded `controllers//suite_test.go` files. ([#4062](https://github.com/operator-framework/operator-sdk/pull/4062)) + ## v1.1.0 ### Additions diff --git a/changelog/fragments/CVE-2018-1098.yaml b/changelog/fragments/CVE-2018-1098.yaml deleted file mode 100644 index 5898213f944..00000000000 --- a/changelog/fragments/CVE-2018-1098.yaml +++ /dev/null @@ -1,4 +0,0 @@ -entries: - - description: > - Excluded `github.com/spf13/viper@v1.3.2` to fix CVE-2018-1098 - kind: bugfix diff --git a/changelog/fragments/ansible-helm-help-text.yaml b/changelog/fragments/ansible-helm-help-text.yaml deleted file mode 100644 index 4376918c0e6..00000000000 --- a/changelog/fragments/ansible-helm-help-text.yaml +++ /dev/null @@ -1,5 +0,0 @@ -entries: - - description: > - Improved `ansible-operator` and `helm-operator` help text - kind: change - breaking: false diff --git a/changelog/fragments/autogenerated-makefile-bundle-prerequisite-task.yaml b/changelog/fragments/autogenerated-makefile-bundle-prerequisite-task.yaml deleted file mode 100644 index 85de7d1367e..00000000000 --- a/changelog/fragments/autogenerated-makefile-bundle-prerequisite-task.yaml +++ /dev/null @@ -1,27 +0,0 @@ -# entries is a list of entries to include in -# release notes and/or the migration guide -entries: - - description: > - Added the `kustomize` make dependency to the `bundle` - target scaffolded for Golang projects to install - `kustomize` before running. - - # kind is one of: - # - addition - # - change - # - deprecation - # - removal - # - bugfix - kind: bugfix - - # Is this a breaking change? - breaking: false - - # Migration can be defined to automatically add a section to - # the migration guide. This is required for breaking changes. - migration: - header: (Golang based operators) Update Makefile's bundle target - body: > - In the `Makefile` file, replace `bundle: manifests` - with `bundle: manifests kustomize` to call the kustomize - target when the `bundle` target is used. diff --git a/changelog/fragments/bundle-pm-supported-kinds.yaml b/changelog/fragments/bundle-pm-supported-kinds.yaml deleted file mode 100644 index 11d276fb800..00000000000 --- a/changelog/fragments/bundle-pm-supported-kinds.yaml +++ /dev/null @@ -1,3 +0,0 @@ -entries: - - description: When generating bundles and packagemanifests, add all resources supported by OLM. - kind: change diff --git a/changelog/fragments/fix-cleanup.yaml b/changelog/fragments/fix-cleanup.yaml deleted file mode 100644 index 28a4337d604..00000000000 --- a/changelog/fragments/fix-cleanup.yaml +++ /dev/null @@ -1,7 +0,0 @@ -entries: - - description: > - Fixed an issue in `operator-sdk cleanup` that caused `CatalogSource` - and `OperatorGroup` objects not to be cleaned up if a - previous `operator-sdk run` command failed. - kind: bugfix - breaking: false diff --git a/changelog/fragments/fix-csv-generate-path-segments.yaml b/changelog/fragments/fix-csv-generate-path-segments.yaml deleted file mode 100644 index 7a675b3b19f..00000000000 --- a/changelog/fragments/fix-csv-generate-path-segments.yaml +++ /dev/null @@ -1,5 +0,0 @@ -entries: - - description: > - Fixed an issue during CSV generation that caused incorrect paths to - be used in `specDescriptors` and `statusDescriptors`. - kind: "bugfix" diff --git a/changelog/fragments/fix-helm-finalizers-permissions.yaml b/changelog/fragments/fix-helm-finalizers-permissions.yaml deleted file mode 100644 index 0a4fb2198bc..00000000000 --- a/changelog/fragments/fix-helm-finalizers-permissions.yaml +++ /dev/null @@ -1,7 +0,0 @@ -# entries is a list of entries to include in -# release notes and/or the migration guide -entries: - - description: > - In Helm projects, fix operator RBAC permissions to support the OwnerReferencesPermissionEnforcement admission plugin by adding a `/finalizers` rule in the operator's role. - kind: "bugfix" - breaking: false diff --git a/changelog/fragments/go-version-bug.yaml b/changelog/fragments/go-version-bug.yaml deleted file mode 100644 index e4377758e95..00000000000 --- a/changelog/fragments/go-version-bug.yaml +++ /dev/null @@ -1,4 +0,0 @@ -entries: - - description: > - Removed redundant platform information from `operator-sdk version` output - kind: bugfix diff --git a/changelog/fragments/olm-version-v.yaml b/changelog/fragments/olm-version-v.yaml deleted file mode 100644 index b49e302d5c6..00000000000 --- a/changelog/fragments/olm-version-v.yaml +++ /dev/null @@ -1,4 +0,0 @@ -entries: - - description: > - Format version string passed to `olm` subcommands so releases download correctly. - kind: bugfix diff --git a/changelog/fragments/plugins-use-rbac-v1.yaml b/changelog/fragments/plugins-use-rbac-v1.yaml deleted file mode 100644 index 7ec4a3d3cdd..00000000000 --- a/changelog/fragments/plugins-use-rbac-v1.yaml +++ /dev/null @@ -1,6 +0,0 @@ -entries: - - description: > - In Go, Ansible, and Helm operators, updated the `metrics-reader` ClusterRole - to use `rbac.authorization.k8s.io/v1` to be consistent with all other - scaffolded RBAC resources. - kind: "bugfix" diff --git a/changelog/fragments/return-olm-install-error.yaml b/changelog/fragments/return-olm-install-error.yaml deleted file mode 100644 index ad29e9f19fe..00000000000 --- a/changelog/fragments/return-olm-install-error.yaml +++ /dev/null @@ -1,5 +0,0 @@ -entries: - - description: > - `olm` and `run` subcommands will print aggregated resource errors when either OLM or an operator fail to install, respectively. - kind: change - diff --git a/changelog/fragments/scorecard-status-descriptor-test.yaml b/changelog/fragments/scorecard-status-descriptor-test.yaml deleted file mode 100644 index cea8ff976ff..00000000000 --- a/changelog/fragments/scorecard-status-descriptor-test.yaml +++ /dev/null @@ -1,16 +0,0 @@ -# entries is a list of entries to include in -# release notes and/or the migration guide -entries: - - description: > - Modify `olm-status-descriptors-test` to only validate if the status-descriptors are present in CRD. - - # kind is one of: - # - addition - # - change - # - deprecation - # - removal - # - bugfix - kind: "bugfix" - - # Is this a breaking change? - breaking: false diff --git a/changelog/fragments/upgrade-kb.yaml b/changelog/fragments/upgrade-kb.yaml deleted file mode 100644 index 2e520c6fa44..00000000000 --- a/changelog/fragments/upgrade-kb.yaml +++ /dev/null @@ -1,54 +0,0 @@ -# entries is a list of entries to include in -# release notes and/or the migration guide -entries: - - description: > - Upgrade sigs.k8s.io/controller-runtime dependency version from `v0.6.2` to - [`v0.6.3`](https://github.com/kubernetes-sigs/controller-runtime/releases/tag/v0.6.3). - - # kind is one of: - # - addition - # - change - # - deprecation - # - removal - # - bugfix - kind: "change" - - # Is this a breaking change? - breaking: false - - # Migration can be defined to automatically add a section to - # the migration guide. This is required for breaking changes. - migration: - header: (Golang based operators) Upgrade sigs.k8s.io/controller-runtime version to v0.6.3 - body: > - In the `go.mod` file replace `sigs.k8s.io/controller-runtime v0.6.2` - with `sigs.k8s.io/controller-runtime v0.6.3` and then run `go mod tidy`. - - description: > - For Golang based operators with multigroup support, fix scaffolded `controllers//suite_test.go` to have - a correct `envtest.Environment.CRDDirectoryPaths` ([kubebuilder#1665](https://github.com/kubernetes-sigs/kubebuilder/pull/1665)). - - # kind is one of: - # - addition - # - change - # - deprecation - # - removal - # - bugfix - kind: "change" - - # Is this a breaking change? - breaking: false - - # Migration can be defined to automatically add a section to - # the migration guide. This is required for breaking changes. - migration: - header: (Golang based operators with multigroup support) Fix `CRDDirectoryPath` in `controllers//suite_test.go` - body: > - If your project is multi-group, then replace - `CRDDirectoryPaths: []string{filepath.Join("..", "config", "crd", "bases")},` with - `CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")},` - in `suite_test.go` files found in `controllers//` directories. Otherwise, the tests will fail since - this EnvTest will not be looking for the CRD's in the correct location. For more info, see - [kubebuilder#1665](https://github.com/kubernetes-sigs/kubebuilder/issues/1665). - - - diff --git a/changelog/fragments/upgrade-operator-framework-api.yaml b/changelog/fragments/upgrade-operator-framework-api.yaml deleted file mode 100644 index d3c2930a91e..00000000000 --- a/changelog/fragments/upgrade-operator-framework-api.yaml +++ /dev/null @@ -1,31 +0,0 @@ -# entries is a list of entries to include in -# release notes and/or the migration guide -entries: - - description: > - Enabled definition of custom categories encoded as [JSON file(s)](https://olm.operatorframework.io/docs/tasks/validate-package/#validation) - for the `operatorhub` validator. - - # kind is one of: - # - addition - # - change - # - deprecation - # - removal - # - bugfix - kind: "addition" - - # Is this a breaking change? - breaking: false - - - description: > - Webhook container port specified in CSV defaults to `443` if not specified by the user. - - # kind is one of: - # - addition - # - change - # - deprecation - # - removal - # - bugfix - kind: "bugfix" - - # Is this a breaking change? - breaking: false diff --git a/website/config.toml b/website/config.toml index 636cd10ca17..4fb81698b8f 100644 --- a/website/config.toml +++ b/website/config.toml @@ -94,6 +94,10 @@ algolia_docsearch = false version = "Latest Release" url = "https://sdk.operatorframework.io" +[[params.versions]] + version = "v1.2" + url = "https://v1-2-x.sdk.operatorframework.io" + [[params.versions]] version = "v1.1" url = "https://v1-1-x.sdk.operatorframework.io" @@ -119,7 +123,7 @@ algolia_docsearch = false [params.ui] # Enable to show the side bar menu in its compact state. sidebar_menu_compact = true -# Set to true to disable breadcrumb navigation. +# Set to true to disable breadcrumb navigation. breadcrumb_disable = false # Set to true to hide the sidebar search box (the top nav search box will still be displayed if search is enabled) sidebar_search_disable = true @@ -157,7 +161,7 @@ no = 'Sorry to hear that. Please /suite_test.go` + +If your project is multi-group, then replace `CRDDirectoryPaths: []string{filepath.Join("..", "config", "crd", "bases")},` with `CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")},` in `suite_test.go` files found in `controllers//` directories. Otherwise, the tests will fail since this EnvTest will not be looking for the CRD's in the correct location. For more info, see [kubebuilder#1665](https://github.com/kubernetes-sigs/kubebuilder/issues/1665). + +_See [#4062](https://github.com/operator-framework/operator-sdk/pull/4062) for more details._ From db2ab95136c6935b43f34d975cc5fb47961d9034 Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Mon, 9 Nov 2020 19:36:50 -0800 Subject: [PATCH 204/376] hack/generate/samples: strip operator-sdk metrics annotations (#4213) This commit removes metrics annotations from samples in testdata/, which are inherently versioned by git. Removing these annotations permits proper release tagging of samples. hack/generate/samples: add `SampleContext.StripBundleAnnotations()` which removes all operator-sdk metrics labels from metadata and manifests in a bundle *: rename exported testutils to align with their functionality Signed-off-by: reinvantveer --- .../samples/internal/ansible/memcached.go | 2 +- .../internal/go/memcached_with_webhooks.go | 2 +- .../samples/internal/helm/memcached.go | 2 +- hack/generate/samples/internal/pkg/utils.go | 75 +++++++++++++++++-- internal/testutils/olm.go | 2 +- test/e2e-go/e2e_go_olm_test.go | 2 +- test/e2e-go/e2e_go_suite_test.go | 2 +- .../memcached-operator/bundle.Dockerfile | 3 - ...cached-operator.clusterserviceversion.yaml | 2 - .../bundle/metadata/annotations.yaml | 3 - ...cached-operator.clusterserviceversion.yaml | 2 - .../go/memcached-operator/bundle.Dockerfile | 3 - ...cached-operator.clusterserviceversion.yaml | 2 - .../bundle/metadata/annotations.yaml | 3 - ...cached-operator.clusterserviceversion.yaml | 2 - .../helm/memcached-operator/bundle.Dockerfile | 3 - ...cached-operator.clusterserviceversion.yaml | 2 - .../bundle/metadata/annotations.yaml | 3 - ...cached-operator.clusterserviceversion.yaml | 2 - 19 files changed, 76 insertions(+), 41 deletions(-) diff --git a/hack/generate/samples/internal/ansible/memcached.go b/hack/generate/samples/internal/ansible/memcached.go index 46b04edca41..76b9808dcea 100644 --- a/hack/generate/samples/internal/ansible/memcached.go +++ b/hack/generate/samples/internal/ansible/memcached.go @@ -76,7 +76,7 @@ func (ma *MemcachedAnsible) Run() { ma.addingAnsibleTask() ma.addingMoleculeMockData() - pkg.RunOlmIntegration(ma.ctx) + ma.ctx.CreateBundle() } // addingMoleculeMockData will customize the molecule data diff --git a/hack/generate/samples/internal/go/memcached_with_webhooks.go b/hack/generate/samples/internal/go/memcached_with_webhooks.go index 78b770b4d64..cf925b82d43 100644 --- a/hack/generate/samples/internal/go/memcached_with_webhooks.go +++ b/hack/generate/samples/internal/go/memcached_with_webhooks.go @@ -90,7 +90,7 @@ func (mh *MemcachedGoWithWebhooks) Run() { mh.implementingWebhooks() mh.uncommentKustomizationFile() - pkg.RunOlmIntegration(mh.ctx) + mh.ctx.CreateBundle() // Clean up built binaries, if any. pkg.CheckError("cleaning up", os.RemoveAll(filepath.Join(mh.ctx.Dir, "bin"))) diff --git a/hack/generate/samples/internal/helm/memcached.go b/hack/generate/samples/internal/helm/memcached.go index 928eb3d67f7..a78a57cb8b6 100644 --- a/hack/generate/samples/internal/helm/memcached.go +++ b/hack/generate/samples/internal/helm/memcached.go @@ -103,7 +103,7 @@ func (mh *MemcachedHelm) Run() { "# +kubebuilder:scaffold:rules", policyRolesFragment) pkg.CheckError("adding customized roles", err) - pkg.RunOlmIntegration(mh.ctx) + mh.ctx.CreateBundle() } // GenerateMemcachedHelmSample will call all actions to create the directory and generate the sample diff --git a/hack/generate/samples/internal/pkg/utils.go b/hack/generate/samples/internal/pkg/utils.go index e5a7aca79ee..6af0efc42d3 100644 --- a/hack/generate/samples/internal/pkg/utils.go +++ b/hack/generate/samples/internal/pkg/utils.go @@ -15,12 +15,19 @@ package pkg import ( + "fmt" + "io/ioutil" "os" + "path/filepath" + "regexp" log "github.com/sirupsen/logrus" + "sigs.k8s.io/kubebuilder/pkg/model/config" + + "github.com/operator-framework/operator-sdk/internal/annotations/metrics" ) -// CheckError will check the error and exit with 1 when as errors +// CheckError will exit with exit code 1 when err is not nil. func CheckError(msg string, err error) { if err != nil { log.Errorf("error %s: %s", msg, err) @@ -28,15 +35,73 @@ func CheckError(msg string, err error) { } } -// RunOlmIntegration runs all commands to integrate the project with OLM -func RunOlmIntegration(ctx *SampleContext) { +// CreateBundle runs all commands to create an operator bundle. +func (ctx *SampleContext) CreateBundle() { log.Infof("integrating project with OLM") - err := ctx.DisableOLMBundleInteractiveMode() - CheckError("disabling the OLM bundle", err) + err := ctx.DisableManifestsInteractiveMode() + CheckError("disabling `generate kustomize manifests` interactive mode", err) err = ctx.Make("bundle", "IMG="+ctx.ImageName) CheckError("running make bundle", err) + err = ctx.StripBundleAnnotations() + CheckError("stripping bundle annotations", err) + err = ctx.Make("bundle-build", "BUNDLE_IMG="+ctx.BundleImageName) CheckError("running make bundle-build", err) } + +// StripBundleAnnotations removes all annotations applied to bundle manifests and metadata +// by operator-sdk/internal/annotations/metrics annotators. Doing so decouples samples +// from which operator-sdk version they were build with, as this information is already +// available in git history. +func (ctx SampleContext) StripBundleAnnotations() (err error) { + // Remove metadata labels. + metadataAnnotations := metrics.MakeBundleMetadataLabels(&config.Config{}) + metadataFiles := []string{ + filepath.Join(ctx.Dir, "bundle", "metadata", "annotations.yaml"), + filepath.Join(ctx.Dir, "bundle.Dockerfile"), + } + if err = removeAllAnnotationLines(metadataAnnotations, metadataFiles); err != nil { + return err + } + + // Remove manifests annotations. + manifestsAnnotations := metrics.MakeBundleObjectAnnotations(&config.Config{}) + manifestsFiles := []string{ + filepath.Join(ctx.Dir, "bundle", "manifests", ctx.ProjectName+".clusterserviceversion.yaml"), + filepath.Join(ctx.Dir, "config", "manifests", "bases", ctx.ProjectName+".clusterserviceversion.yaml"), + } + if err = removeAllAnnotationLines(manifestsAnnotations, manifestsFiles); err != nil { + return err + } + + return nil +} + +// removeAllAnnotationLines removes each line containing a key in annotations from all files at filePaths. +func removeAllAnnotationLines(annotations map[string]string, filePaths []string) error { + var annotationREs []*regexp.Regexp + for annotation := range annotations { + re, err := regexp.Compile(".+" + regexp.QuoteMeta(annotation) + ".+\n") + if err != nil { + return fmt.Errorf("compiling annotation regexp: %v", err) + } + annotationREs = append(annotationREs, re) + } + + for _, file := range filePaths { + b, err := ioutil.ReadFile(file) + if err != nil { + return err + } + for _, re := range annotationREs { + b = re.ReplaceAll(b, []byte{}) + } + err = ioutil.WriteFile(file, b, 0644) + if err != nil { + return err + } + } + return nil +} diff --git a/internal/testutils/olm.go b/internal/testutils/olm.go index b40dcf39973..31285e4dc42 100644 --- a/internal/testutils/olm.go +++ b/internal/testutils/olm.go @@ -82,7 +82,7 @@ func (tc TestContext) AddPackagemanifestsTarget() error { } // DisableOLMBundleInterativeMode will update the Makefile to disable the interactive mode -func (tc TestContext) DisableOLMBundleInteractiveMode() error { +func (tc TestContext) DisableManifestsInteractiveMode() error { // Todo: check if we cannot improve it since the replace/content will exists in the // pkgmanifest target if it be scaffolded before this call content := "operator-sdk generate kustomize manifests" diff --git a/test/e2e-go/e2e_go_olm_test.go b/test/e2e-go/e2e_go_olm_test.go index 0221fff564e..f4df883f07e 100644 --- a/test/e2e-go/e2e_go_olm_test.go +++ b/test/e2e-go/e2e_go_olm_test.go @@ -27,7 +27,7 @@ var _ = Describe("Integrating Go Projects with OLM", func() { It("should generate and run a valid OLM bundle and packagemanifests", func() { By("turning off interactive prompts for all generation tasks.") - err := tc.DisableOLMBundleInteractiveMode() + err := tc.DisableManifestsInteractiveMode() Expect(err).NotTo(HaveOccurred()) By("building the bundle") diff --git a/test/e2e-go/e2e_go_suite_test.go b/test/e2e-go/e2e_go_suite_test.go index d5af4fc77ce..e5add77c4ce 100644 --- a/test/e2e-go/e2e_go_suite_test.go +++ b/test/e2e-go/e2e_go_suite_test.go @@ -101,7 +101,7 @@ var _ = BeforeSuite(func() { "#- ../prometheus", "#")).To(Succeed()) By("turning off interactive prompts for all generation tasks.") - err = tc.DisableOLMBundleInteractiveMode() + err = tc.DisableManifestsInteractiveMode() Expect(err).NotTo(HaveOccurred()) By("checking the kustomize setup") diff --git a/testdata/ansible/memcached-operator/bundle.Dockerfile b/testdata/ansible/memcached-operator/bundle.Dockerfile index 61aa2904f63..4f7ff821ae5 100644 --- a/testdata/ansible/memcached-operator/bundle.Dockerfile +++ b/testdata/ansible/memcached-operator/bundle.Dockerfile @@ -5,9 +5,6 @@ LABEL operators.operatorframework.io.bundle.manifests.v1=manifests/ LABEL operators.operatorframework.io.bundle.metadata.v1=metadata/ LABEL operators.operatorframework.io.bundle.package.v1=memcached-operator LABEL operators.operatorframework.io.bundle.channels.v1=alpha -LABEL operators.operatorframework.io.metrics.builder=operator-sdk-v1.1.0+git -LABEL operators.operatorframework.io.metrics.mediatype.v1=metrics+v1 -LABEL operators.operatorframework.io.metrics.project_layout=ansible.sdk.operatorframework.io/v1 LABEL operators.operatorframework.io.test.config.v1=tests/scorecard/ LABEL operators.operatorframework.io.test.mediatype.v1=scorecard+v1 COPY bundle/manifests /manifests/ diff --git a/testdata/ansible/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml b/testdata/ansible/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml index 4f0369a6f38..43f07252740 100644 --- a/testdata/ansible/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml +++ b/testdata/ansible/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml @@ -16,8 +16,6 @@ metadata: } ] capabilities: Basic Install - operators.operatorframework.io/builder: operator-sdk-v1.1.0+git - operators.operatorframework.io/project_layout: ansible.sdk.operatorframework.io/v1 name: memcached-operator.v0.0.1 namespace: placeholder spec: diff --git a/testdata/ansible/memcached-operator/bundle/metadata/annotations.yaml b/testdata/ansible/memcached-operator/bundle/metadata/annotations.yaml index 83ffd1659c7..9c65a477b22 100644 --- a/testdata/ansible/memcached-operator/bundle/metadata/annotations.yaml +++ b/testdata/ansible/memcached-operator/bundle/metadata/annotations.yaml @@ -4,8 +4,5 @@ annotations: operators.operatorframework.io.bundle.mediatype.v1: registry+v1 operators.operatorframework.io.bundle.metadata.v1: metadata/ operators.operatorframework.io.bundle.package.v1: memcached-operator - operators.operatorframework.io.metrics.builder: operator-sdk-v1.1.0+git - operators.operatorframework.io.metrics.mediatype.v1: metrics+v1 - operators.operatorframework.io.metrics.project_layout: ansible.sdk.operatorframework.io/v1 operators.operatorframework.io.test.config.v1: tests/scorecard/ operators.operatorframework.io.test.mediatype.v1: scorecard+v1 diff --git a/testdata/ansible/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml b/testdata/ansible/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml index 6858f70a3a3..e0831a96a16 100644 --- a/testdata/ansible/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml +++ b/testdata/ansible/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml @@ -4,8 +4,6 @@ metadata: annotations: alm-examples: '[]' capabilities: Basic Install - operators.operatorframework.io/builder: operator-sdk-v1.1.0+git - operators.operatorframework.io/project_layout: ansible.sdk.operatorframework.io/v1 name: memcached-operator.vX.Y.Z namespace: placeholder spec: diff --git a/testdata/go/memcached-operator/bundle.Dockerfile b/testdata/go/memcached-operator/bundle.Dockerfile index be09ab9f7d7..4f7ff821ae5 100644 --- a/testdata/go/memcached-operator/bundle.Dockerfile +++ b/testdata/go/memcached-operator/bundle.Dockerfile @@ -5,9 +5,6 @@ LABEL operators.operatorframework.io.bundle.manifests.v1=manifests/ LABEL operators.operatorframework.io.bundle.metadata.v1=metadata/ LABEL operators.operatorframework.io.bundle.package.v1=memcached-operator LABEL operators.operatorframework.io.bundle.channels.v1=alpha -LABEL operators.operatorframework.io.metrics.builder=operator-sdk-v1.1.0+git -LABEL operators.operatorframework.io.metrics.mediatype.v1=metrics+v1 -LABEL operators.operatorframework.io.metrics.project_layout=go.kubebuilder.io/v2 LABEL operators.operatorframework.io.test.config.v1=tests/scorecard/ LABEL operators.operatorframework.io.test.mediatype.v1=scorecard+v1 COPY bundle/manifests /manifests/ diff --git a/testdata/go/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml b/testdata/go/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml index d50d3167974..3f59a770118 100644 --- a/testdata/go/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml +++ b/testdata/go/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml @@ -16,8 +16,6 @@ metadata: } ] capabilities: Basic Install - operators.operatorframework.io/builder: operator-sdk-v1.1.0+git - operators.operatorframework.io/project_layout: go.kubebuilder.io/v2 name: memcached-operator.v0.0.1 namespace: placeholder spec: diff --git a/testdata/go/memcached-operator/bundle/metadata/annotations.yaml b/testdata/go/memcached-operator/bundle/metadata/annotations.yaml index 5650d6bee5e..9c65a477b22 100644 --- a/testdata/go/memcached-operator/bundle/metadata/annotations.yaml +++ b/testdata/go/memcached-operator/bundle/metadata/annotations.yaml @@ -4,8 +4,5 @@ annotations: operators.operatorframework.io.bundle.mediatype.v1: registry+v1 operators.operatorframework.io.bundle.metadata.v1: metadata/ operators.operatorframework.io.bundle.package.v1: memcached-operator - operators.operatorframework.io.metrics.builder: operator-sdk-v1.1.0+git - operators.operatorframework.io.metrics.mediatype.v1: metrics+v1 - operators.operatorframework.io.metrics.project_layout: go.kubebuilder.io/v2 operators.operatorframework.io.test.config.v1: tests/scorecard/ operators.operatorframework.io.test.mediatype.v1: scorecard+v1 diff --git a/testdata/go/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml b/testdata/go/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml index ac4894aacc6..7171abf6739 100644 --- a/testdata/go/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml +++ b/testdata/go/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml @@ -4,8 +4,6 @@ metadata: annotations: alm-examples: '[]' capabilities: Basic Install - operators.operatorframework.io/builder: operator-sdk-v1.1.0+git - operators.operatorframework.io/project_layout: go.kubebuilder.io/v2 name: memcached-operator.vX.Y.Z namespace: placeholder spec: diff --git a/testdata/helm/memcached-operator/bundle.Dockerfile b/testdata/helm/memcached-operator/bundle.Dockerfile index dbe4bc593bc..4f7ff821ae5 100644 --- a/testdata/helm/memcached-operator/bundle.Dockerfile +++ b/testdata/helm/memcached-operator/bundle.Dockerfile @@ -5,9 +5,6 @@ LABEL operators.operatorframework.io.bundle.manifests.v1=manifests/ LABEL operators.operatorframework.io.bundle.metadata.v1=metadata/ LABEL operators.operatorframework.io.bundle.package.v1=memcached-operator LABEL operators.operatorframework.io.bundle.channels.v1=alpha -LABEL operators.operatorframework.io.metrics.builder=operator-sdk-v1.1.0+git -LABEL operators.operatorframework.io.metrics.mediatype.v1=metrics+v1 -LABEL operators.operatorframework.io.metrics.project_layout=helm.sdk.operatorframework.io/v1 LABEL operators.operatorframework.io.test.config.v1=tests/scorecard/ LABEL operators.operatorframework.io.test.mediatype.v1=scorecard+v1 COPY bundle/manifests /manifests/ diff --git a/testdata/helm/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml b/testdata/helm/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml index 38ba82ed9cc..eba15872125 100644 --- a/testdata/helm/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml +++ b/testdata/helm/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml @@ -56,8 +56,6 @@ metadata: } ] capabilities: Basic Install - operators.operatorframework.io/builder: operator-sdk-v1.1.0+git - operators.operatorframework.io/project_layout: helm.sdk.operatorframework.io/v1 name: memcached-operator.v0.0.1 namespace: placeholder spec: diff --git a/testdata/helm/memcached-operator/bundle/metadata/annotations.yaml b/testdata/helm/memcached-operator/bundle/metadata/annotations.yaml index 0112602ae33..9c65a477b22 100644 --- a/testdata/helm/memcached-operator/bundle/metadata/annotations.yaml +++ b/testdata/helm/memcached-operator/bundle/metadata/annotations.yaml @@ -4,8 +4,5 @@ annotations: operators.operatorframework.io.bundle.mediatype.v1: registry+v1 operators.operatorframework.io.bundle.metadata.v1: metadata/ operators.operatorframework.io.bundle.package.v1: memcached-operator - operators.operatorframework.io.metrics.builder: operator-sdk-v1.1.0+git - operators.operatorframework.io.metrics.mediatype.v1: metrics+v1 - operators.operatorframework.io.metrics.project_layout: helm.sdk.operatorframework.io/v1 operators.operatorframework.io.test.config.v1: tests/scorecard/ operators.operatorframework.io.test.mediatype.v1: scorecard+v1 diff --git a/testdata/helm/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml b/testdata/helm/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml index 3549dc65d82..e0831a96a16 100644 --- a/testdata/helm/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml +++ b/testdata/helm/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml @@ -4,8 +4,6 @@ metadata: annotations: alm-examples: '[]' capabilities: Basic Install - operators.operatorframework.io/builder: operator-sdk-v1.1.0+git - operators.operatorframework.io/project_layout: helm.sdk.operatorframework.io/v1 name: memcached-operator.vX.Y.Z namespace: placeholder spec: From 2de188439299d8d7ef2d387227954129ea99db02 Mon Sep 17 00:00:00 2001 From: Kyle Zhan Date: Wed, 11 Nov 2020 04:14:45 +0800 Subject: [PATCH 205/376] fix typo in scorecard content of website (#4208) Signed-off-by: reinvantveer --- website/content/en/docs/advanced-topics/scorecard/scorecard.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/content/en/docs/advanced-topics/scorecard/scorecard.md b/website/content/en/docs/advanced-topics/scorecard/scorecard.md index 15551f274bb..99c1a393faa 100644 --- a/website/content/en/docs/advanced-topics/scorecard/scorecard.md +++ b/website/content/en/docs/advanced-topics/scorecard/scorecard.md @@ -43,7 +43,7 @@ and copy scaffolded files: ``` The default config generated by this kustomization can be immediately run against your operator. See the [config file section](#config-file) for an explanation of the configuration file format. -1. (Re)enerate [bundle][quickstart-bundle] manifests and metadata for your Operator. +1. (Re)generate [bundle][quickstart-bundle] manifests and metadata for your Operator. `make bundle` will automatically add scorecard annotations to your bundle's metadata, which is used by the `scorecard` command to run tests. 1. Execute the [`scorecard` command][cli-scorecard]. See the [command args section](#command-args) From 1e53f804fab0d0d1010cea51eb6bd5f145a81e64 Mon Sep 17 00:00:00 2001 From: Venkatramanan Srinivasan Date: Tue, 10 Nov 2020 13:15:43 -0700 Subject: [PATCH 206/376] Add tests for registry/configmap.go (#4188) Signed-off-by: reinvantveer --- .../olm/operator/registry/configmap_test.go | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 internal/olm/operator/registry/configmap_test.go diff --git a/internal/olm/operator/registry/configmap_test.go b/internal/olm/operator/registry/configmap_test.go new file mode 100644 index 00000000000..871cc2ed508 --- /dev/null +++ b/internal/olm/operator/registry/configmap_test.go @@ -0,0 +1,78 @@ +// Copyright 2020 The Operator-SDK 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. +package registry + +import ( + "context" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "sigs.k8s.io/controller-runtime/pkg/client/fake" + + apimanifests "github.com/operator-framework/api/pkg/manifests" + "github.com/operator-framework/operator-sdk/internal/olm/operator" +) + +var _ = Describe("Configmap", func() { + + Describe("NewConfigMapCatalogCreator", func() { + It("should return a configmapcreator instance", func() { + cfg := operator.Configuration{ + Namespace: "testns", + } + + ctlog := NewConfigMapCatalogCreator(&cfg) + Expect(ctlog.cfg.Namespace).Should(Equal(cfg.Namespace)) + }) + }) + + Describe("CreateCatalog", func() { + It("should return an error if creation fails", func() { + ctlog := &ConfigMapCatalogCreator{ + cfg: &operator.Configuration{ + Namespace: "testns", + Client: fake.NewFakeClient(newCatalogSource("pkgName", "testns", withSDKPublisher("pkgName"))), + }, + Package: &apimanifests.PackageManifest{ + PackageName: "pkgName", + }, + } + + x, err := ctlog.CreateCatalog(context.TODO(), "pkgName") + Expect(err.Error()).Should(ContainSubstring("error creating catalog source")) + Expect(x).Should(BeNil()) + }) + }) + + Describe("updateCatalogSource", func() { + It("should update the catalog source", func() { + cs := newCatalogSource("pkgName", "testns", withSDKPublisher("pkgName")) + ctlog := &ConfigMapCatalogCreator{ + cfg: &operator.Configuration{ + Namespace: "testns", + Client: fake.NewFakeClient(cs), + }, + Package: &apimanifests.PackageManifest{ + PackageName: "pkgName", + }, + } + expected := cs.DeepCopy() + err := ctlog.updateCatalogSource(context.TODO(), cs) + + Expect(err).Should(BeNil()) + Expect(expected.Spec.Address).ShouldNot(Equal(cs.Spec.Address)) + Expect(expected.Spec.SourceType).ShouldNot(Equal(cs.Spec.SourceType)) + }) + }) +}) From b60b5f7ebae7cf7d5334f95df6019bf2b024aa10 Mon Sep 17 00:00:00 2001 From: Frederic Giloux Date: Tue, 10 Nov 2020 23:02:20 +0100 Subject: [PATCH 207/376] Closes #4146 - provides instructions on how to set up a target to undeploy the operator (#4163) Adds instructions on how to set up a target to undeploy the operator. Modifies the deployment namespace so that it does not match an existing namespace. Signed-off-by: reinvantveer --- .../building-operators/golang/tutorial.md | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/website/content/en/docs/building-operators/golang/tutorial.md b/website/content/en/docs/building-operators/golang/tutorial.md index d0edbd169c5..3b5ef25d730 100644 --- a/website/content/en/docs/building-operators/golang/tutorial.md +++ b/website/content/en/docs/building-operators/golang/tutorial.md @@ -330,11 +330,7 @@ The name and tag of the image (`IMG=/:tag`) in both #### Deploy the operator -For this example we will run the operator in the `default` namespace which can be specified for all resources in `config/default/kustomization.yaml`: - -```sh -$ cd config/default/ && kustomize edit set namespace "default" && cd ../.. -``` +By default, a new namespace is created with name `-system`, i.e. memcached-operator-system and will be used for the deployment. Run the following to deploy the operator. This will also install the RBAC manifests from `config/rbac`. @@ -348,7 +344,7 @@ in the cluster or `make deploy` will fail when creating the cert-manager resourc Verify that the memcached-operator is up and running: ```console -$ kubectl get deployment +$ kubectl get deployment -n memcached-operator-system NAME READY UP-TO-DATE AVAILABLE AGE memcached-operator-controller-manager 1/1 1 1 8m ``` @@ -436,12 +432,19 @@ memcached-sample 5/5 5 5 3m ### Cleanup -```sh -$ kubectl delete -f config/samples/cache_v1alpha1_memcached.yaml -$ kubectl delete deployments,service -l control-plane=controller-manager -$ kubectl delete role,rolebinding --all +A new target can be added into the Makefile for cleaning up the resources that have been created along this tutorial: + +```make +# Undeploy controller from the configured Kubernetes cluster +undeploy: + $(KUSTOMIZE) build config/default | kubectl delete -f - ``` +Once that's done the simple command below will delete all the resources: + +```sh +$ make undeploy +``` ## Further steps From e51b6b64f734e7bb0c83ae14a70ff80425fcceaa Mon Sep 17 00:00:00 2001 From: Joe Lanford Date: Tue, 10 Nov 2020 21:36:56 -0500 Subject: [PATCH 208/376] release/Makefile: honor GOOS and GOARCH when building release binaries (#4219) Signed-off-by: reinvantveer --- release/Makefile | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/release/Makefile b/release/Makefile index f9e4834639f..0d748ed3c12 100644 --- a/release/Makefile +++ b/release/Makefile @@ -77,26 +77,23 @@ dist/operator-sdk-%-x86_64-linux-gnu: GOARGS = GOOS=linux GOARCH=amd64 dist/operator-sdk-%-x86_64-apple-darwin: GOARGS = GOOS=darwin GOARCH=amd64 dist/operator-sdk-%-ppc64le-linux-gnu: GOARGS = GOOS=linux GOARCH=ppc64le dist/operator-sdk-%-s390x-linux-gnu: GOARGS = GOOS=linux GOARCH=s390x -dist/operator-sdk-%-linux-gnu: GOARGS = GOOS=linux dist/ansible-operator-%-aarch64-linux-gnu: GOARGS = GOOS=linux GOARCH=arm64 dist/ansible-operator-%-x86_64-linux-gnu: GOARGS = GOOS=linux GOARCH=amd64 dist/ansible-operator-%-x86_64-apple-darwin: GOARGS = GOOS=darwin GOARCH=amd64 dist/ansible-operator-%-ppc64le-linux-gnu: GOARGS = GOOS=linux GOARCH=ppc64le dist/ansible-operator-%-s390x-linux-gnu: GOARGS = GOOS=linux GOARCH=s390x -dist/ansible-operator-%-linux-gnu: GOARGS = GOOS=linux dist/helm-operator-%-aarch64-linux-gnu: GOARGS = GOOS=linux GOARCH=arm64 dist/helm-operator-%-x86_64-linux-gnu: GOARGS = GOOS=linux GOARCH=amd64 dist/helm-operator-%-x86_64-apple-darwin: GOARGS = GOOS=darwin GOARCH=amd64 dist/helm-operator-%-ppc64le-linux-gnu: GOARGS = GOOS=linux GOARCH=ppc64le dist/helm-operator-%-s390x-linux-gnu: GOARGS = GOOS=linux GOARCH=s390x -dist/helm-operator-%-linux-gnu: GOARGS = GOOS=linux dist/%: ## Build the operator-sdk release binaries { \ cmdpkg=$$(echo $* | sed -E "s/(operator-sdk|ansible-operator|helm-operator).*/\1/"); \ - go build $(GO_BUILD_ARGS) -o $@ ./cmd/$$cmdpkg; \ + $(GOARGS) go build $(GO_BUILD_ARGS) -o $@ ./cmd/$$cmdpkg; \ } dist/%.asc: ## Create release signatures for operator-sdk release binaries From 4279d1eb156ec8c7608cccc400638b5cdce670c2 Mon Sep 17 00:00:00 2001 From: Camila Macedo Date: Wed, 11 Nov 2020 16:06:10 +0000 Subject: [PATCH 209/376] feat: doc standard for changelog (#4218) Signed-off-by: reinvantveer --- changelog/fragments/00-template.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/changelog/fragments/00-template.yaml b/changelog/fragments/00-template.yaml index 44f68b5ba65..cae69e430fe 100644 --- a/changelog/fragments/00-template.yaml +++ b/changelog/fragments/00-template.yaml @@ -7,6 +7,11 @@ entries: the YAML string '>' operator means you can write your entry multiple lines and it will still be parsed as a single line. + If an operator type's plugin is being changed then prefix the description with + "(/)", ex. "(go/v2)". + If an operator type's runtime is being changed, use then prefix the description + with "For -based operators,", ex. "For Go-based operators". + # kind is one of: # - addition # - change From e045743fc6d354bf5890c87b1843e5a33116d04e Mon Sep 17 00:00:00 2001 From: Camila Macedo Date: Wed, 11 Nov 2020 17:52:37 +0000 Subject: [PATCH 210/376] increase timmeout for teh scorecard tests (#4222) Signed-off-by: reinvantveer --- test/e2e-ansible/e2e_ansible_scorecard_test.go | 4 ++-- test/e2e-go/e2e_go_scorecard_test.go | 6 +++--- test/e2e-helm/e2e_helm_scorecard_test.go | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/test/e2e-ansible/e2e_ansible_scorecard_test.go b/test/e2e-ansible/e2e_ansible_scorecard_test.go index 14fac5ad02c..0afddd4a1d4 100644 --- a/test/e2e-ansible/e2e_ansible_scorecard_test.go +++ b/test/e2e-ansible/e2e_ansible_scorecard_test.go @@ -40,7 +40,7 @@ var _ = Describe("Testing Ansible Projects with Scorecard", func() { runScorecardCmd := exec.Command(tc.BinaryName, "scorecard", "bundle", "--selector=suite=basic", "--output=json", - "--wait-time=60s") + "--wait-time=120s") scorecardOutputBytes, err := tc.Run(runScorecardCmd) Expect(err).NotTo(HaveOccurred()) err = json.Unmarshal(scorecardOutputBytes, &scorecardOutput) @@ -52,7 +52,7 @@ var _ = Describe("Testing Ansible Projects with Scorecard", func() { runOLMScorecardCmd := exec.Command(tc.BinaryName, "scorecard", "bundle", "--selector=suite=olm", "--output=json", - "--wait-time=60s") + "--wait-time=120s") scorecardOutputBytes, err = tc.Run(runOLMScorecardCmd) Expect(err).To(HaveOccurred()) err = json.Unmarshal(scorecardOutputBytes, &scorecardOutput) diff --git a/test/e2e-go/e2e_go_scorecard_test.go b/test/e2e-go/e2e_go_scorecard_test.go index 80b7e661999..f028c6f12e2 100644 --- a/test/e2e-go/e2e_go_scorecard_test.go +++ b/test/e2e-go/e2e_go_scorecard_test.go @@ -40,7 +40,7 @@ var _ = Describe("Testing Go Projects with Scorecard", func() { runScorecardCmd := exec.Command(tc.BinaryName, "scorecard", "bundle", "--selector=suite=basic", "--output=json", - "--wait-time=60s") + "--wait-time=120s") scorecardOutputBytes, err := tc.Run(runScorecardCmd) Expect(err).NotTo(HaveOccurred()) err = json.Unmarshal(scorecardOutputBytes, &scorecardOutput) @@ -52,7 +52,7 @@ var _ = Describe("Testing Go Projects with Scorecard", func() { runScorecardCmd = exec.Command(tc.BinaryName, "scorecard", "bundle", "--selector=suite=custom", "--output=json", - "--wait-time=60s") + "--wait-time=120s") scorecardOutputBytes, err = tc.Run(runScorecardCmd) Expect(err).NotTo(HaveOccurred()) err = json.Unmarshal(scorecardOutputBytes, &scorecardOutput) @@ -63,7 +63,7 @@ var _ = Describe("Testing Go Projects with Scorecard", func() { runOLMScorecardCmd := exec.Command(tc.BinaryName, "scorecard", "bundle", "--selector=suite=olm", "--output=json", - "--wait-time=60s") + "--wait-time=120s") scorecardOutputBytes, err = tc.Run(runOLMScorecardCmd) Expect(err).To(HaveOccurred()) err = json.Unmarshal(scorecardOutputBytes, &scorecardOutput) diff --git a/test/e2e-helm/e2e_helm_scorecard_test.go b/test/e2e-helm/e2e_helm_scorecard_test.go index 01fb20fe91a..8412288c1f5 100644 --- a/test/e2e-helm/e2e_helm_scorecard_test.go +++ b/test/e2e-helm/e2e_helm_scorecard_test.go @@ -41,7 +41,7 @@ var _ = Describe("Testing Helm Projects with Scorecard", func() { runScorecardCmd := exec.Command(tc.BinaryName, "scorecard", "bundle", "--selector=suite=basic", "--output=json", - "--wait-time=60s") + "--wait-time=120s") scorecardOutputBytes, err := tc.Run(runScorecardCmd) Expect(err).NotTo(HaveOccurred()) err = json.Unmarshal(scorecardOutputBytes, &scorecardOutput) @@ -53,7 +53,7 @@ var _ = Describe("Testing Helm Projects with Scorecard", func() { runOLMScorecardCmd := exec.Command(tc.BinaryName, "scorecard", "bundle", "--selector=suite=olm", "--output=json", - "--wait-time=60s") + "--wait-time=120s") scorecardOutputBytes, err = tc.Run(runOLMScorecardCmd) Expect(err).To(HaveOccurred()) err = json.Unmarshal(scorecardOutputBytes, &scorecardOutput) From 7728ffd7a237045a64581e1782d545e86d9e48bd Mon Sep 17 00:00:00 2001 From: anmol372 Date: Wed, 11 Nov 2020 14:03:00 -0500 Subject: [PATCH 211/376] [docs] Improve Website Styling (#4004) 1. Increased the size of headings 2. Added styling to the left-nav bar 3. Corrected doc names and subsequent links to ensure correct generation of subsequent HTML pages 4. And corrected styling for Breadcrumb Navigation Signed-off-by: reinvantveer --- website/assets/scss/_breadcrumb.scss | 41 + website/assets/scss/_docs.scss | 2 +- website/assets/scss/_global.scss | 2 - website/assets/scss/_sidebar-tree.scss | 148 +++ website/assets/scss/_styles_project.scss | 4 +- website/assets/scss/_variables.scss | 2 +- website/content/en/build/_index.html | 10 +- .../en/docs/building-operators/_index.md | 1 - .../ansible/installation.md | 2 +- .../building-operators/ansible/quickstart.md | 2 +- .../building-operators/ansible/tutorial.md | 2 +- .../building-operators/golang/installation.md | 2 +- .../building-operators/golang/quickstart.md | 2 +- .../building-operators/helm/quickstart.md | 2 +- .../docs/building-operators/helm/tutorial.md | 2 +- .../docs/contribution-guidelines/releasing.md | 4 +- .../en/docs/faqs/{faqs.md => _index.md} | 2 +- .../{install-operator-sdk.md => _index.md} | 0 .../docs/overview/{_overview.md => _index.md} | 4 +- website/layouts/partials/section-index.html | 29 + website/package-lock.json | 909 +++++++----------- 21 files changed, 569 insertions(+), 603 deletions(-) create mode 100644 website/assets/scss/_breadcrumb.scss create mode 100644 website/assets/scss/_sidebar-tree.scss rename website/content/en/docs/faqs/{faqs.md => _index.md} (97%) rename website/content/en/docs/installation/{install-operator-sdk.md => _index.md} (100%) rename website/content/en/docs/overview/{_overview.md => _index.md} (98%) create mode 100644 website/layouts/partials/section-index.html diff --git a/website/assets/scss/_breadcrumb.scss b/website/assets/scss/_breadcrumb.scss new file mode 100644 index 00000000000..cad9fa0e9f4 --- /dev/null +++ b/website/assets/scss/_breadcrumb.scss @@ -0,0 +1,41 @@ +.breadcrumb { + display: flex; + flex-wrap: wrap; + padding-left: 0rem; + padding-top: 0.75rem; + + margin-bottom: $breadcrumb-margin-bottom; + list-style: none; + background-color: initial; + margin-left: 0px; + border-bottom-left-radius: 0rem; + border-top-left-radius: 0rem; + } + +.breadcrumb-item { + display: -ms-flexbox; + display: flex; +} + +.breadcrumb-item + .breadcrumb-item { + padding-left: 0.5rem; + } + +.breadcrumb-item + .breadcrumb-item::before { + display: inline-block; + padding-right: 0.5rem; + color: $breadcrumb-divider-color; + content: "/"; +} + +.breadcrumb-item + .breadcrumb-item:hover::before { + text-decoration: underline; +} + +.breadcrumb-item + .breadcrumb-item:hover::before { + text-decoration: none; +} + +.breadcrumb-item.active { + color: $breadcrumb-active-color;; +} \ No newline at end of file diff --git a/website/assets/scss/_docs.scss b/website/assets/scss/_docs.scss index 4002a849ffb..238f856a494 100644 --- a/website/assets/scss/_docs.scss +++ b/website/assets/scss/_docs.scss @@ -1,6 +1,5 @@ .td-sidebar-nav .td-sidebar-link__page { color: #222; - font-weight: normal; } .of-docs__wrapper { @@ -18,6 +17,7 @@ color: var(--of--Color--brand--200); font-weight: 800; letter-spacing: 2px; + margin: var(--of--spacer--md) 0 var(--of--spacer--sm); } h5, h6 { diff --git a/website/assets/scss/_global.scss b/website/assets/scss/_global.scss index 73eb61dc2f6..b74eed9c8a0 100644 --- a/website/assets/scss/_global.scss +++ b/website/assets/scss/_global.scss @@ -30,10 +30,8 @@ ol { li { counter-increment: ordered-list-counter; position: relative; - padding-left: var(--of--spacer--lg); } li::before { - content: counter(ordered-list-counter) ". "; position: absolute; left: 0; top: 0; diff --git a/website/assets/scss/_sidebar-tree.scss b/website/assets/scss/_sidebar-tree.scss new file mode 100644 index 00000000000..87161f11820 --- /dev/null +++ b/website/assets/scss/_sidebar-tree.scss @@ -0,0 +1,148 @@ +.td-sidebar-nav { + padding-right: 0.5rem; + margin-right: -15px; + margin-left: -15px; + + @include media-breakpoint-up(md) { + @supports (position: sticky) { + max-height: calc(100vh - 4rem); + overflow-y: auto; + } + } + + + @include media-breakpoint-up(md) { + display: block !important; + } + + + &__section { + li { + list-style: none; + } + + ul { + padding: 0; + margin: 0; + } + + @include media-breakpoint-up(md) { + & > ul { + padding-left: .5rem; + } + } + + + padding-left: 0; + } + + &__section-title { + display: block; + font-weight: 550; + + .active { + font-weight: 800; + color: $gray-900; + } + + a { + color: $gray-700; + } + } + + .td-sidebar-link { + display: block; + padding-bottom: 0.375rem; + + &__page { + color: $gray-600; + font-weight: $font-weight-light; + } + } + + a { + &:hover { + color: $blue; + text-decoration: none; + } + + &.active { + font-weight: 800; + color: $gray-800; + + } + } + + .dropdown { + a { + color: $gray-700; + } + + .nav-link { + padding: 0 0 1rem; + } + } +} + +.td-sidebar { + padding-top: 4rem; + margin-bottom: var(--of--spacer--md); + display:flex; + justify-content: center; + background: var(--of--color-white--200); + span { + margin-left: var(--of--spacer--md); + font-family: var(--of--font-family); + } + @include media-breakpoint-up(md) { + padding-top: var(--of--spacer--md); + padding-bottom: 4rem; + background-color: $td-sidebar-bg-color; + margin-bottom: 0; + padding-right: 1rem; + border-right: 1px solid $td-sidebar-border-color; + } + + &__toggle { + line-height: 1; + color: $gray-900; + margin: 1rem; + } + + &__search { + padding: 1rem 15px; + margin-right: -15px; + margin-left: -15px; + } + + &__inner { + order: 0; + + @include media-breakpoint-up(md) { + @supports (position: sticky) { + position: sticky; + top:71px; + z-index: 10; + height: calc(100vh - 6rem); + } + } + + + @include media-breakpoint-up(xl) { + flex: 0 1 320px; + } + + + .td-search-box { + width: 100%; + } + + &__heading { + padding: var(--of--spacer--md); + background: var(--of--color-brand--300); + color: var(--of--color-white--100); + margin-left: -15px; + margin-right: -15px; + } + } +} \ No newline at end of file diff --git a/website/assets/scss/_styles_project.scss b/website/assets/scss/_styles_project.scss index cde76fee1f8..e06d2d6c228 100644 --- a/website/assets/scss/_styles_project.scss +++ b/website/assets/scss/_styles_project.scss @@ -14,10 +14,8 @@ @import "../../themes/docsy/assets/scss/blog"; @import "../../themes/docsy/assets/scss/code"; @import "../../themes/docsy/assets/scss/nav"; -@import "../../themes/docsy/assets/scss/sidebar-tree"; @import "../../themes/docsy/assets/scss/sidebar-toc"; @import "../../themes/docsy/assets/scss/buttons"; -@import "../../themes/docsy/assets/scss/breadcrumb"; @import "../../themes/docsy/assets/scss/alerts"; @import "../../themes/docsy/assets/scss/content"; @import "../../themes/docsy/assets/scss/search"; @@ -61,6 +59,8 @@ footer { @import "variables"; @import "reset"; @import "type"; +@import "sidebar-tree"; +@import "breadcrumb"; //components @import "header"; diff --git a/website/assets/scss/_variables.scss b/website/assets/scss/_variables.scss index 2ba6fb84115..30d60c0b19b 100644 --- a/website/assets/scss/_variables.scss +++ b/website/assets/scss/_variables.scss @@ -74,5 +74,5 @@ $ov--breakpoint--md: 768px; $ov--breakpoint--lg: 992px; $ov--breakpoint--xl: 1200px; - $ov--breakpoint--2xl: 1450px; + $ov--breakpoint--2xl: 1450px; diff --git a/website/content/en/build/_index.html b/website/content/en/build/_index.html index 96626520b26..c1e67193a88 100644 --- a/website/content/en/build/_index.html +++ b/website/content/en/build/_index.html @@ -24,14 +24,14 @@

How can I write an Operator with Operator

Installing the SDK CLI

-

Follow the steps in the installation guide to learn how to install the Operator SDK CLI tool. If you are using a release version of the SDK, make sure to follow the documentation for that version. You make use any of the following installation processes:

+

Follow the steps in the installation guide to learn how to install the Operator SDK CLI tool. If you are using a release version of the SDK, make sure to follow the documentation for that version. You make use any of the following installation processes:

    -
  1. Install the Homebrew (macOS)
  2. -
  3. Install from GitHub release
  4. -
  5. Compile and install from master
  6. +
  7. Install the Homebrew (macOS)
  8. +
  9. Install from GitHub release
  10. +
  11. Compile and install from master
- Learn More + Learn More diff --git a/website/content/en/docs/building-operators/_index.md b/website/content/en/docs/building-operators/_index.md index 1ae03ed53b9..4069a0bcc38 100644 --- a/website/content/en/docs/building-operators/_index.md +++ b/website/content/en/docs/building-operators/_index.md @@ -1,4 +1,3 @@ - --- title: "Building Operators" linkTitle: "Building Operators" diff --git a/website/content/en/docs/building-operators/ansible/installation.md b/website/content/en/docs/building-operators/ansible/installation.md index 02a9ad17850..544cee7a77f 100644 --- a/website/content/en/docs/building-operators/ansible/installation.md +++ b/website/content/en/docs/building-operators/ansible/installation.md @@ -20,7 +20,7 @@ local Kubernetes cluster and [quay.io][quay-link] for the public registry. [ansible-tool]:https://docs.ansible.com/ansible/latest/index.html [ansible-runner-tool]:https://ansible-runner.readthedocs.io/en/latest/install.html [ansible-runner-http-plugin]:https://github.com/ansible/ansible-runner-http -[install-guide]: /docs/installation/install-operator-sdk +[install-guide]: /docs/installation/ [minikube-tool]:https://github.com/kubernetes/minikube#installation [quay-link]:https://quay.io [openshift-module]:https://pypi.org/project/openshift/ diff --git a/website/content/en/docs/building-operators/ansible/quickstart.md b/website/content/en/docs/building-operators/ansible/quickstart.md index 3dabe64a01e..ac64ab5f37c 100644 --- a/website/content/en/docs/building-operators/ansible/quickstart.md +++ b/website/content/en/docs/building-operators/ansible/quickstart.md @@ -85,7 +85,7 @@ make undeploy Read the [tutorial][tutorial] for an in-depth walkthough of building a Ansible operator. -[operator_install]: /docs/installation/install-operator-sdk +[operator_install]: /docs/installation/ [ansible-operator-install]: /docs/building-operators/ansible/installation [layout-doc]:../reference/scaffolding [tutorial]: /docs/building-operators/ansible/tutorial/ diff --git a/website/content/en/docs/building-operators/ansible/tutorial.md b/website/content/en/docs/building-operators/ansible/tutorial.md index 9aac13e5aed..e3b55838f45 100644 --- a/website/content/en/docs/building-operators/ansible/tutorial.md +++ b/website/content/en/docs/building-operators/ansible/tutorial.md @@ -232,4 +232,4 @@ OLM will manage creation of most if not all resources required to run your opera [docker-tool]:https://docs.docker.com/install/ [kubectl-tool]:https://kubernetes.io/docs/tasks/tools/install-kubectl/ [quickstart-bundle]: /docs/olm-integration/quickstart-bundle/ -[operator_install]: /docs/installation/install-operator-sdk +[operator_install]: /docs/installation/ diff --git a/website/content/en/docs/building-operators/golang/installation.md b/website/content/en/docs/building-operators/golang/installation.md index 506d915c668..323164ff4dd 100644 --- a/website/content/en/docs/building-operators/golang/installation.md +++ b/website/content/en/docs/building-operators/golang/installation.md @@ -20,5 +20,5 @@ Follow the steps in the [installation guide][install-guide] to learn how to inst [docker_tool]:https://docs.docker.com/install/ [mercurial_tool]:https://www.mercurial-scm.org/downloads [kubectl_tool]:https://kubernetes.io/docs/tasks/tools/install-kubectl/ -[install-guide]: /docs/installation/install-operator-sdk +[install-guide]: /docs/installation/ [quay-link]:https://quay.io diff --git a/website/content/en/docs/building-operators/golang/quickstart.md b/website/content/en/docs/building-operators/golang/quickstart.md index f21a79b5996..dd2e5d4a84c 100644 --- a/website/content/en/docs/building-operators/golang/quickstart.md +++ b/website/content/en/docs/building-operators/golang/quickstart.md @@ -87,6 +87,6 @@ Read the [tutorial][tutorial] for an in-depth walkthough of building a Go operat [go_tool]:https://golang.org/dl/ [docker_tool]:https://docs.docker.com/install/ [kubectl_tool]:https://kubernetes.io/docs/tasks/tools/install-kubectl/ -[operator_install]: /docs/installation/install-operator-sdk +[operator_install]: /docs/installation/ [tutorial]: /docs/building-operators/golang/tutorial/ diff --git a/website/content/en/docs/building-operators/helm/quickstart.md b/website/content/en/docs/building-operators/helm/quickstart.md index 6aa53395e14..a8b1dff5bb5 100644 --- a/website/content/en/docs/building-operators/helm/quickstart.md +++ b/website/content/en/docs/building-operators/helm/quickstart.md @@ -87,7 +87,7 @@ make undeploy Read the [tutorial][tutorial] for an in-depth walkthough of building a Helm operator. -[operator_install]: /docs/installation/install-operator-sdk +[operator_install]: /docs/installation/ [project_layout]: /docs/building-operators/helm/reference/project_layout/ [tutorial]: /docs/building-operators/helm/tutorial/ [helm-official]: https://helm.sh/docs/ diff --git a/website/content/en/docs/building-operators/helm/tutorial.md b/website/content/en/docs/building-operators/helm/tutorial.md index 02273bf636b..be6a4c250a7 100644 --- a/website/content/en/docs/building-operators/helm/tutorial.md +++ b/website/content/en/docs/building-operators/helm/tutorial.md @@ -315,4 +315,4 @@ todo(camilamacedo86): https://github.com/operator-framework/operator-sdk/issues/ [helm-charts]:https://helm.sh/docs/topics/charts/ [helm-values]:https://helm.sh/docs/intro/using_helm/#customizing-the-chart-before-installing [helm-official]:https://helm.sh/docs/ -[operator_install]: /docs/installation/install-operator-sdk +[operator_install]: /docs/installation/ diff --git a/website/content/en/docs/contribution-guidelines/releasing.md b/website/content/en/docs/contribution-guidelines/releasing.md index 3fb79158103..1770779901f 100644 --- a/website/content/en/docs/contribution-guidelines/releasing.md +++ b/website/content/en/docs/contribution-guidelines/releasing.md @@ -374,10 +374,10 @@ following release. You've now fully released a new version of the Operator SDK. Good work! -[install-guide]: /docs/installation/install-operator-sdk +[install-guide]: /docs/installation/ [doc-maintainers]: https://github.com/operator-framework/operator-sdk/blob/master/MAINTAINERS [doc-owners]: https://github.com/operator-framework/operator-sdk/blob/master/OWNERS -[doc-readme-prereqs]: /docs/installation/install-operator-sdk#prerequisites-for-compilation +[doc-readme-prereqs]: /docs/installation/#prerequisites-for-compilation [doc-git-default-key]:https://help.github.com/en/articles/telling-git-about-your-signing-key [doc-gpg-default-key]:https://lists.gnupg.org/pipermail/gnupg-users/2001-September/010163.html [link-github-gpg-key-upload]:https://github.com/settings/keys diff --git a/website/content/en/docs/faqs/faqs.md b/website/content/en/docs/faqs/_index.md similarity index 97% rename from website/content/en/docs/faqs/faqs.md rename to website/content/en/docs/faqs/_index.md index db93d3b8289..e65211f1ffe 100644 --- a/website/content/en/docs/faqs/faqs.md +++ b/website/content/en/docs/faqs/_index.md @@ -16,7 +16,7 @@ You should not have separate logic. Instead design your reconciler to be idempot Use a [finalizer]. -## I keep seeing the following intermittent warning in my Operator's logs: `The resourceVersion for the provided watch is too old.` What's wrong? +## I see the warning in my Operator's logs: `The resourceVersion for the provided watch is too old.` What's wrong? This is completely normal and expected behavior. diff --git a/website/content/en/docs/installation/install-operator-sdk.md b/website/content/en/docs/installation/_index.md similarity index 100% rename from website/content/en/docs/installation/install-operator-sdk.md rename to website/content/en/docs/installation/_index.md diff --git a/website/content/en/docs/overview/_overview.md b/website/content/en/docs/overview/_index.md similarity index 98% rename from website/content/en/docs/overview/_overview.md rename to website/content/en/docs/overview/_index.md index b17575b94fd..30d721e63e4 100644 --- a/website/content/en/docs/overview/_overview.md +++ b/website/content/en/docs/overview/_index.md @@ -83,11 +83,11 @@ Operator SDK is under Apache 2.0 license. See the [LICENSE][license_file] file f [capability_levels]: /docs/advanced-topics/operator-capabilities/operator-capabilities [contrib]: https://github.com/operator-framework/operator-sdk/blob/master/CONTRIBUTING.MD [controller_runtime]: https://github.com/kubernetes-sigs/controller-runtime -[faq]: /docs/faqs/faqs +[faq]: /docs/faqs/ [getting_started]: https://github.com/operator-framework/getting-started/blob/master/README.md [golang-guide]:/docs/building-operators/golang/quickstart/ [helm-guide]:/docs/building-operators/helm/quickstart/ -[install_guide]: /docs/installation/install-operator-sdk/ +[install_guide]: /docs/installation/ [license_file]:https://github.com/operator-framework/operator-sdk/blob/master/LICENSE [of-blog]: https://coreos.com/blog/introducing-operator-framework [of-home]: https://github.com/operator-framework diff --git a/website/layouts/partials/section-index.html b/website/layouts/partials/section-index.html new file mode 100644 index 00000000000..a903d26cf84 --- /dev/null +++ b/website/layouts/partials/section-index.html @@ -0,0 +1,29 @@ +
+ {{ $pages := (where .Site.Pages "Section" .Section).ByWeight }} + {{ $parent := .Page }} + {{ if $parent.Params.no_list }} + {{/* If no_list is true we don't show a list of subpages */}} + {{ else if $parent.Params.simple_list }} + {{/* If simple_list is true we show a bulleted list of subpages */}} + + {{ else }} + {{/* Otherwise we show a nice formatted list of subpages with page descriptions */}} +
+ {{ range $pages }} + {{ if eq .Parent $parent }} +
+

+ {{- .Title -}} +

+

{{ .Description | markdownify }}

+
+ {{ end }} + {{ end }} + {{ end }} +
diff --git a/website/package-lock.json b/website/package-lock.json index 4adfdf4505f..15838aa675c 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -2,11 +2,33 @@ "requires": true, "lockfileVersion": 1, "dependencies": { + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==" + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, "@nodelib/fs.scandir": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", "integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==", - "dev": true, "requires": { "@nodelib/fs.stat": "2.0.3", "run-parallel": "^1.1.9" @@ -15,228 +37,126 @@ "@nodelib/fs.stat": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz", - "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==", - "dev": true + "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==" }, "@nodelib/fs.walk": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz", "integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==", - "dev": true, "requires": { "@nodelib/fs.scandir": "2.1.3", "fastq": "^1.6.0" } }, - "@types/color-name": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", - "dev": true + "@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" }, "ansi-regex": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" }, "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" + "color-convert": "^1.9.0" } }, "anymatch": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", - "dev": true, "requires": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, "array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" }, "at-least-node": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" }, "autoprefixer": { - "version": "9.8.5", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.5.tgz", - "integrity": "sha512-C2p5KkumJlsTHoNv9w31NrBRgXhf6eCMteJuHZi2xhkgC+5Vm40MEtCKPhc0qdgAOhox0YPy1SQHTAky05UoKg==", + "version": "9.8.6", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.6.tgz", + "integrity": "sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg==", "requires": { "browserslist": "^4.12.0", - "caniuse-lite": "^1.0.30001097", - "colorette": "^1.2.0", + "caniuse-lite": "^1.0.30001109", + "colorette": "^1.2.1", "normalize-range": "^0.1.2", "num2fraction": "^1.2.2", "postcss": "^7.0.32", "postcss-value-parser": "^4.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "postcss": { - "version": "7.0.32", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.32.tgz", - "integrity": "sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==", - "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" - } - }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "requires": { - "has-flag": "^3.0.0" - } - } } }, "binary-extensions": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", - "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", - "dev": true + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==" }, "braces": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, "requires": { "fill-range": "^7.0.1" } }, "browserslist": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.13.0.tgz", - "integrity": "sha512-MINatJ5ZNrLnQ6blGvePd/QOz9Xtu+Ne+x29iQSCHfkU5BugKVJwZKn/iiL8UbpIpa3JhviKjz+XxMo0m2caFQ==", + "version": "4.14.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.5.tgz", + "integrity": "sha512-Z+vsCZIvCBvqLoYkBFTwEYH3v5MCQbsAjp50ERycpOjnPmolg1Gjy4+KaWWpm8QOJt9GHkhdqAl14NpCX73CWA==", "requires": { - "caniuse-lite": "^1.0.30001093", - "electron-to-chromium": "^1.3.488", - "escalade": "^3.0.1", - "node-releases": "^1.1.58" - } - }, - "caller-callsite": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", - "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", - "dev": true, - "requires": { - "callsites": "^2.0.0" - } - }, - "caller-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", - "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", - "dev": true, - "requires": { - "caller-callsite": "^2.0.0" + "caniuse-lite": "^1.0.30001135", + "electron-to-chromium": "^1.3.571", + "escalade": "^3.1.0", + "node-releases": "^1.1.61" } }, "callsites": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", - "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", - "dev": true - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" }, "caniuse-lite": { - "version": "1.0.30001109", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001109.tgz", - "integrity": "sha512-4JIXRodHzdS3HdK8nSgIqXYLExOvG+D2/EenSvcub2Kp3QEADjo2v2oUn5g0n0D+UNwG9BtwKOyGcSq2qvQXvQ==" + "version": "1.0.30001146", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001146.tgz", + "integrity": "sha512-VAy5RHDfTJhpxnDdp2n40GPPLp3KqNrXz1QqFv4J64HvArKs8nuNMOWkB3ICOaBTU/Aj4rYAo/ytdQDDFF/Pug==" }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } } }, "chokidar": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.1.tgz", - "integrity": "sha512-TQTJyr2stihpC4Sya9hs2Xh+O2wf+igjL36Y75xx2WdHuiICcn/XJza46Jwt0eT5hVpQOzo3FpY3cj3RVYLX0g==", - "dev": true, + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", + "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==", "requires": { "anymatch": "~3.1.1", "braces": "~3.0.2", @@ -249,30 +169,27 @@ } }, "cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "dev": true, + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.1.tgz", + "integrity": "sha512-rcvHOWyGyid6I1WjT/3NatKj2kDt9OdSHSXpyLXaMWFbKpGACNW8pRhhdPUq9MWUOdwn8Rz9AVETjF4105rZZQ==", "requires": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" + "wrap-ansi": "^7.0.0" } }, "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "requires": { - "color-name": "~1.1.4" + "color-name": "1.1.3" } }, "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "colorette": { "version": "1.2.1", @@ -280,79 +197,62 @@ "integrity": "sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==" }, "cosmiconfig": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", - "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", - "dev": true, + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz", + "integrity": "sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==", "requires": { - "import-fresh": "^2.0.0", - "is-directory": "^0.3.1", - "js-yaml": "^3.13.1", - "parse-json": "^4.0.0" + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" } }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, "dependency-graph": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.9.0.tgz", - "integrity": "sha512-9YLIBURXj4DJMFALxXw9K3Y3rwb5Fk0X5/8ipCzaN84+gKxoHK43tVKRNakCQbiEx07E8Uwhuq21BpUagFhZ8w==", - "dev": true + "integrity": "sha512-9YLIBURXj4DJMFALxXw9K3Y3rwb5Fk0X5/8ipCzaN84+gKxoHK43tVKRNakCQbiEx07E8Uwhuq21BpUagFhZ8w==" }, "dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, "requires": { "path-type": "^4.0.0" } }, "electron-to-chromium": { - "version": "1.3.514", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.514.tgz", - "integrity": "sha512-8vb8zKIeGlZigeDzNWWthmGeLzo5CC43Lc+CZshMs7UXFVMPNLtXJGa/txedpu3OJFrXXVheBwp9PqOJJlHQ8w==" + "version": "1.3.578", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.578.tgz", + "integrity": "sha512-z4gU6dA1CbBJsAErW5swTGAaU2TBzc2mPAonJb00zqW1rOraDo2zfBMDRvaz9cVic+0JEZiYbHWPw/fTaZlG2Q==" }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, "requires": { "is-arrayish": "^0.2.1" } }, "escalade": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.0.2.tgz", - "integrity": "sha512-gPYAU37hYCUhW5euPeR+Y74F7BL+IBsV93j5cvGriSaD1aG6MGsqsV1yamRdrWrb2j3aiZvb0X+UBOWpx3JWtQ==" + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.0.tgz", + "integrity": "sha512-mAk+hPSO8fLDkhV7V0dXazH5pDc6MrjBTPyD3VeKzxnVFjH1MIxbCdqGZB9O8+EwWakZs3ZCbDS4IpRt79V1ig==" }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, "fast-glob": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz", "integrity": "sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==", - "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -366,7 +266,6 @@ "version": "1.8.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.8.0.tgz", "integrity": "sha512-SMIZoZdLh/fgofivvIkmknUXyPnvxRE3DhtZ5Me3Mrsk5gyPL42F0xr51TdRXskBxHfMp+07bcYzfsYEsSQA9Q==", - "dev": true, "requires": { "reusify": "^1.0.4" } @@ -375,26 +274,14 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, "requires": { "to-regex-range": "^5.0.1" } }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, "fs-extra": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz", "integrity": "sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==", - "dev": true, "requires": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", @@ -406,26 +293,22 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", - "dev": true, "optional": true }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, "get-stdin": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-7.0.0.tgz", - "integrity": "sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==", - "dev": true + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", + "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==" }, "glob-parent": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", - "dev": true, "requires": { "is-glob": "^4.0.1" } @@ -434,7 +317,6 @@ "version": "11.0.1", "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.1.tgz", "integrity": "sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ==", - "dev": true, "requires": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -447,87 +329,77 @@ "graceful-fs": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" }, "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "ignore": { "version": "5.1.8", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", - "dev": true + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==" }, "import-cwd": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz", - "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=", - "dev": true, + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-3.0.0.tgz", + "integrity": "sha512-4pnzH16plW+hgvRECbDWpQl3cqtvSofHWh44met7ESfZ8UZOWWddm8hEyDTqREJ9RbYHY8gi8DqmaelApoOGMg==", "requires": { - "import-from": "^2.1.0" + "import-from": "^3.0.0" } }, "import-fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", - "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", - "dev": true, + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", + "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", "requires": { - "caller-path": "^2.0.0", - "resolve-from": "^3.0.0" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" } }, "import-from": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz", - "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=", - "dev": true, + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/import-from/-/import-from-3.0.0.tgz", + "integrity": "sha512-CiuXOFFSzkU5x/CR0+z7T91Iht4CXgfCxVOFRhh2Zyhg5wOpWvvDLQUsWl+gcN+QscYBjez8hDCt85O7RLDttQ==", "requires": { - "resolve-from": "^3.0.0" + "resolve-from": "^5.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==" + } } }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" }, "is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, "requires": { "binary-extensions": "^2.0.0" } }, - "is-directory": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", - "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", - "dev": true - }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" }, "is-glob": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, "requires": { "is-extglob": "^2.1.1" } @@ -535,107 +407,106 @@ "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "js-yaml": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", - "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, "jsonfile": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz", "integrity": "sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==", - "dev": true, "requires": { "graceful-fs": "^4.1.6", "universalify": "^1.0.0" } }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } + "lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=" + }, + "lodash.difference": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=" + }, + "lodash.forown": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.forown/-/lodash.forown-4.4.0.tgz", + "integrity": "sha1-hRFc8E9z75ZuztUlEdOJPMRmg68=" }, - "lodash": { - "version": "4.17.19", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", - "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", - "dev": true + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" + }, + "lodash.groupby": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.groupby/-/lodash.groupby-4.6.0.tgz", + "integrity": "sha1-Cwih3PaDl8OXhVwyOXg4Mt90A9E=" + }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" }, "log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "dev": true, + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", + "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", "requires": { - "chalk": "^2.0.1" + "chalk": "^4.0.0" }, "dependencies": { "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "requires": { - "color-convert": "^1.9.0" + "color-convert": "^2.0.1" } }, "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "requires": { - "color-name": "1.1.3" + "color-name": "~1.1.4" } }, "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "requires": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" } } } @@ -643,29 +514,26 @@ "merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" }, "micromatch": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", - "dev": true, "requires": { "braces": "^3.0.1", "picomatch": "^2.0.5" } }, "node-releases": { - "version": "1.1.60", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.60.tgz", - "integrity": "sha512-gsO4vjEdQaTusZAEebUWp2a5d7dF5DYoIpDG7WySnk7BuZDW+GPpHXoXXuYawRBr/9t5q54tirPz79kFIWg4dA==" + "version": "1.1.61", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.61.tgz", + "integrity": "sha512-DD5vebQLg8jLCOzwupn954fbIiZht05DAZs0k2u8NStSe6h9XdsuIQL8hSRKYiU8WUQRznmSDrKGbv3ObOmC7g==" }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" }, "normalize-range": { "version": "0.1.2", @@ -677,232 +545,136 @@ "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=" }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "requires": { - "p-limit": "^2.2.0" + "callsites": "^3.0.0" } }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz", + "integrity": "sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==", "requires": { + "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" } }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, "path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" }, "picomatch": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "dev": true + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==" }, "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" }, "postcss": { - "version": "7.0.32", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.32.tgz", - "integrity": "sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==", - "dev": true, + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", "supports-color": "^6.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } } }, "postcss-cli": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/postcss-cli/-/postcss-cli-7.1.1.tgz", - "integrity": "sha512-bYQy5ydAQJKCMSpvaMg0ThPBeGYqhQXumjbFOmWnL4u65CYXQ16RfS6afGQpit0dGv/fNzxbdDtx8dkqOhhIbg==", - "dev": true, + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/postcss-cli/-/postcss-cli-8.1.0.tgz", + "integrity": "sha512-FYuV5zyYX53X5RywInxjWLqHZ4oCBC3nDwrHYU3Z75mFqUo5IHfbeY593heWSagG90nPnXq3tXCck8+2CUl8EA==", "requires": { "chalk": "^4.0.0", "chokidar": "^3.3.0", "dependency-graph": "^0.9.0", "fs-extra": "^9.0.0", - "get-stdin": "^7.0.0", + "get-stdin": "^8.0.0", "globby": "^11.0.0", - "postcss": "^7.0.0", - "postcss-load-config": "^2.0.0", - "postcss-reporter": "^6.0.0", + "postcss-load-config": "^3.0.0", + "postcss-reporter": "^7.0.0", "pretty-hrtime": "^1.0.3", "read-cache": "^1.0.0", - "yargs": "^15.0.2" - } - }, - "postcss-load-config": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.1.0.tgz", - "integrity": "sha512-4pV3JJVPLd5+RueiVVB+gFOAa7GWc25XQcMp86Zexzke69mKf6Nx9LRcQywdz7yZI9n1udOxmLuAwTBypypF8Q==", - "dev": true, - "requires": { - "cosmiconfig": "^5.0.0", - "import-cwd": "^2.0.0" - } - }, - "postcss-reporter": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-6.0.1.tgz", - "integrity": "sha512-LpmQjfRWyabc+fRygxZjpRxfhRf9u/fdlKf4VHG4TSPbV2XNsuISzYW1KL+1aQzx53CAppa1bKG4APIB/DOXXw==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "lodash": "^4.17.11", - "log-symbols": "^2.2.0", - "postcss": "^7.0.7" + "yargs": "^16.0.0" }, "dependencies": { "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "requires": { - "color-convert": "^1.9.0" + "color-convert": "^2.0.1" } }, "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "requires": { - "color-name": "1.1.3" + "color-name": "~1.1.4" } }, "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "requires": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" } } } }, + "postcss-load-config": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.0.0.tgz", + "integrity": "sha512-lErrN8imuEF1cSiHBV8MiR7HeuzlDpCGNtaMyYHlOBuJHHOGw6S4xOMZp8BbXPr7AGQp14L6PZDlIOpfFJ6f7w==", + "requires": { + "cosmiconfig": "^7.0.0", + "import-cwd": "^3.0.0" + } + }, + "postcss-reporter": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-7.0.1.tgz", + "integrity": "sha512-R9AK80KIqqMb+lwGRBcRkXS7r96VCTxrZvvrfibyA/dWjqctwx7leHMCC05A9HbW8PnChwOWwrmISwp5HQu5wg==", + "requires": { + "colorette": "^1.2.1", + "lodash.difference": "^4.5.0", + "lodash.forown": "^4.4.0", + "lodash.get": "^4.4.2", + "lodash.groupby": "^4.6.0", + "lodash.sortby": "^4.7.0", + "log-symbols": "^4.0.0" + } + }, "postcss-value-parser": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", @@ -911,14 +683,12 @@ "pretty-hrtime": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", - "dev": true + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=" }, "read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", "integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=", - "dev": true, "requires": { "pify": "^2.3.0" } @@ -927,7 +697,6 @@ "version": "3.4.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", - "dev": true, "requires": { "picomatch": "^2.2.1" } @@ -935,61 +704,37 @@ "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" }, "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", - "dev": true + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" }, "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" }, "run-parallel": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", - "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==", - "dev": true - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true + "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==" }, "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, "string-width": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -1000,25 +745,22 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, "requires": { "ansi-regex": "^5.0.0" } }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "requires": { - "has-flag": "^4.0.0" + "has-flag": "^3.0.0" } }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "requires": { "is-number": "^7.0.0" } @@ -1026,60 +768,69 @@ "universalify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", - "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==", - "dev": true - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true + "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==" }, "wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "requires": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + } } }, "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.2.tgz", + "integrity": "sha512-CkwaeZw6dQgqgPGeTWKMXCRmMcBgETFlTml1+ZOO+q7kGst8NREJ+eWwFNPVUQ4QGdAaklbqCZHH6Zuep1RjiA==" + }, + "yaml": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.0.tgz", + "integrity": "sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==" }, "yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "dev": true, + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.0.3.tgz", + "integrity": "sha512-6+nLw8xa9uK1BOEOykaiYAJVh6/CjxWXK/q9b5FpRgNslt8s22F2xMBqVIKgCRjNgGvGPBy8Vog7WN7yh4amtA==", "requires": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", + "cliui": "^7.0.0", + "escalade": "^3.0.2", + "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" + "y18n": "^5.0.1", + "yargs-parser": "^20.0.0" } }, "yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } + "version": "20.2.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.1.tgz", + "integrity": "sha512-yYsjuSkjbLMBp16eaOt7/siKTjNVjMm3SoJnIg3sEh/JsvqVVDyjRKmaJV4cl+lNIgq6QEco2i3gDebJl7/vLA==" } } } From 5e6f0508e53f1b416225e424e190ff9f4af07d93 Mon Sep 17 00:00:00 2001 From: Camila Macedo Date: Wed, 11 Nov 2020 23:01:01 +0000 Subject: [PATCH 212/376] feat and bugfixes: update kb and add edit command to support multigroups (#4156) **Description of the change:** - Update kubebuilder dependency (See: https://github.com/kubernetes-sigs/kubebuilder/compare/36124ae2e027...9c02d557f01b) - Add edit command which allows multigroup support - Align SDK with Kubebuilder and address bug fixes **Motivation for the change:** - Solve tech-debt and keep both projects aligned - Close the issue: https://github.com/operator-framework/operator-sdk/issues/3678 and provide the same facility that has in upstream to change the layout to support multigroup - Close the issue: https://github.com/operator-framework/operator-sdk/issues/4157 Signed-off-by: reinvantveer --- ...-kb-from-36124ae2e027-to-9c02d557f01b.yaml | 16 ++++++++++ go.mod | 2 +- go.sum | 4 +-- internal/plugins/golang/v2/plugin.go | 5 +++ .../api/v1alpha1/groupversion_info.go | 2 +- .../api/v1alpha1/memcached_types.go | 2 +- .../api/v1alpha1/memcached_webhook.go | 3 +- .../api/v1alpha1/zz_generated.deepcopy.go | 2 +- .../controllers/memcached_controller.go | 2 +- .../controllers/suite_test.go | 2 +- .../hack/boilerplate.go.txt | 2 +- testdata/go/memcached-operator/main.go | 2 +- .../building-operators/golang/crds-scope.md | 3 +- .../building-operators/golang/migration.md | 13 ++------ .../building-operators/golang/tutorial.md | 6 ++-- website/content/en/docs/cli/operator-sdk.md | 1 + .../content/en/docs/cli/operator-sdk_edit.md | 32 +++++++++++++++++++ 17 files changed, 73 insertions(+), 26 deletions(-) create mode 100644 changelog/fragments/update-kb-from-36124ae2e027-to-9c02d557f01b.yaml create mode 100644 website/content/en/docs/cli/operator-sdk_edit.md diff --git a/changelog/fragments/update-kb-from-36124ae2e027-to-9c02d557f01b.yaml b/changelog/fragments/update-kb-from-36124ae2e027-to-9c02d557f01b.yaml new file mode 100644 index 00000000000..7e8c00506e6 --- /dev/null +++ b/changelog/fragments/update-kb-from-36124ae2e027-to-9c02d557f01b.yaml @@ -0,0 +1,16 @@ +# entries is a list of entries to include in +# release notes and/or the migration guide +entries: + - description: > + (go/v2) Added the command `òperator-sdk edit` which allows users edit the project layout to support [multi-group](https://book.kubebuilder.io/migration/multi-group.html) + kind: "addition" + breaking: false + - description: > + (go/v2) Removed unused import for defaulting webhooks scaffolded by `create webhook` ([kubebuilder#1718](https://github.com/kubernetes-sigs/kubebuilder/pull/1718)). + kind: "bugfix" + breaking: false + - description: > + (go/v2) Allow owner to not be specified in generated licenses ([kubebuilder#1749](https://github.com/kubernetes-sigs/kubebuilder/pull/1749)). + kind: "bugfix" + # Is this a breaking change? + breaking: false diff --git a/go.mod b/go.mod index b77db9dc392..31657778fdb 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( rsc.io/letsencrypt v0.0.3 // indirect sigs.k8s.io/controller-runtime v0.6.3 sigs.k8s.io/controller-tools v0.3.0 - sigs.k8s.io/kubebuilder v1.0.9-0.20201021204649-36124ae2e027 + sigs.k8s.io/kubebuilder v1.0.9-0.20201030182622-9c02d557f01b sigs.k8s.io/yaml v1.2.0 ) diff --git a/go.sum b/go.sum index 5bab10b2423..0ba2bd71f1f 100644 --- a/go.sum +++ b/go.sum @@ -1218,8 +1218,8 @@ sigs.k8s.io/controller-runtime v0.6.3 h1:SBbr+inLPEKhvlJtrvDcwIpm+uhDvp63Bl72xYJ sigs.k8s.io/controller-runtime v0.6.3/go.mod h1:WlZNXcM0++oyaQt4B7C2lEE5JYRs8vJUzRP4N4JpdAY= sigs.k8s.io/controller-tools v0.3.0 h1:y3YD99XOyWaXkiF1kd41uRvfp/64teWcrEZFuHxPhJ4= sigs.k8s.io/controller-tools v0.3.0/go.mod h1:enhtKGfxZD1GFEoMgP8Fdbu+uKQ/cq1/WGJhdVChfvI= -sigs.k8s.io/kubebuilder v1.0.9-0.20201021204649-36124ae2e027 h1:2ubws/tSma7ZSqzH7fYIsVl7CvA4jA79VE8YWn9AhH8= -sigs.k8s.io/kubebuilder v1.0.9-0.20201021204649-36124ae2e027/go.mod h1:NatUhFMh/ci8gR+qETvZBIlZ4RTQoNa+9uei7okpgcY= +sigs.k8s.io/kubebuilder v1.0.9-0.20201030182622-9c02d557f01b h1:IDxyhHz2vQ5DRRp0azVMPC5rtSWz3ziFDWWnjC+TH5Q= +sigs.k8s.io/kubebuilder v1.0.9-0.20201030182622-9c02d557f01b/go.mod h1:NatUhFMh/ci8gR+qETvZBIlZ4RTQoNa+9uei7okpgcY= sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0= sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU= sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= diff --git a/internal/plugins/golang/v2/plugin.go b/internal/plugins/golang/v2/plugin.go index ce836e74550..eb2792fc669 100644 --- a/internal/plugins/golang/v2/plugin.go +++ b/internal/plugins/golang/v2/plugin.go @@ -39,6 +39,7 @@ var ( _ plugin.InitPluginGetter = Plugin{} _ plugin.CreateAPIPluginGetter = Plugin{} _ plugin.CreateWebhookPluginGetter = Plugin{} + _ plugin.EditPluginGetter = Plugin{} ) // Plugin defines an Operator SDK Go scaffold and CLI plugin. Its current purpose is to @@ -66,3 +67,7 @@ func (p Plugin) GetCreateAPIPlugin() plugin.CreateAPI { func (p Plugin) GetCreateWebhookPlugin() plugin.CreateWebhook { return (kbgov2.Plugin{}).GetCreateWebhookPlugin() } + +func (p Plugin) GetEditPlugin() plugin.Edit { + return (kbgov2.Plugin{}).GetEditPlugin() +} diff --git a/testdata/go/memcached-operator/api/v1alpha1/groupversion_info.go b/testdata/go/memcached-operator/api/v1alpha1/groupversion_info.go index cac95280cd0..cd34e142a1d 100644 --- a/testdata/go/memcached-operator/api/v1alpha1/groupversion_info.go +++ b/testdata/go/memcached-operator/api/v1alpha1/groupversion_info.go @@ -1,5 +1,5 @@ /* - +Copyright 2020. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/testdata/go/memcached-operator/api/v1alpha1/memcached_types.go b/testdata/go/memcached-operator/api/v1alpha1/memcached_types.go index 1c7636092f5..f9a4c16774b 100644 --- a/testdata/go/memcached-operator/api/v1alpha1/memcached_types.go +++ b/testdata/go/memcached-operator/api/v1alpha1/memcached_types.go @@ -1,5 +1,5 @@ /* - +Copyright 2020. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/testdata/go/memcached-operator/api/v1alpha1/memcached_webhook.go b/testdata/go/memcached-operator/api/v1alpha1/memcached_webhook.go index f9441978484..cdf24233311 100644 --- a/testdata/go/memcached-operator/api/v1alpha1/memcached_webhook.go +++ b/testdata/go/memcached-operator/api/v1alpha1/memcached_webhook.go @@ -1,5 +1,5 @@ /* - +Copyright 2020. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -17,7 +17,6 @@ limitations under the License. package v1alpha1 import ("errors" - "k8s.io/apimachinery/pkg/runtime" ctrl "sigs.k8s.io/controller-runtime" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/webhook" diff --git a/testdata/go/memcached-operator/api/v1alpha1/zz_generated.deepcopy.go b/testdata/go/memcached-operator/api/v1alpha1/zz_generated.deepcopy.go index f720c7d1e27..5edd2767bb0 100644 --- a/testdata/go/memcached-operator/api/v1alpha1/zz_generated.deepcopy.go +++ b/testdata/go/memcached-operator/api/v1alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* - +Copyright 2020. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/testdata/go/memcached-operator/controllers/memcached_controller.go b/testdata/go/memcached-operator/controllers/memcached_controller.go index 846dba8510e..56b2340d0bd 100644 --- a/testdata/go/memcached-operator/controllers/memcached_controller.go +++ b/testdata/go/memcached-operator/controllers/memcached_controller.go @@ -1,5 +1,5 @@ /* - +Copyright 2020. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/testdata/go/memcached-operator/controllers/suite_test.go b/testdata/go/memcached-operator/controllers/suite_test.go index 7f88d0a358a..c8409b4e5a4 100644 --- a/testdata/go/memcached-operator/controllers/suite_test.go +++ b/testdata/go/memcached-operator/controllers/suite_test.go @@ -1,5 +1,5 @@ /* - +Copyright 2020. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/testdata/go/memcached-operator/hack/boilerplate.go.txt b/testdata/go/memcached-operator/hack/boilerplate.go.txt index 767efde9817..606681a693e 100644 --- a/testdata/go/memcached-operator/hack/boilerplate.go.txt +++ b/testdata/go/memcached-operator/hack/boilerplate.go.txt @@ -1,5 +1,5 @@ /* - +Copyright 2020. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/testdata/go/memcached-operator/main.go b/testdata/go/memcached-operator/main.go index 864331f99bf..c334f6d39cd 100644 --- a/testdata/go/memcached-operator/main.go +++ b/testdata/go/memcached-operator/main.go @@ -1,5 +1,5 @@ /* - +Copyright 2020. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/website/content/en/docs/building-operators/golang/crds-scope.md b/website/content/en/docs/building-operators/golang/crds-scope.md index 2dbe2f54fcd..fd4a5308347 100644 --- a/website/content/en/docs/building-operators/golang/crds-scope.md +++ b/website/content/en/docs/building-operators/golang/crds-scope.md @@ -15,7 +15,7 @@ should specify `spec.scope: Cluster`. To ensure that the CRD is always generated with `scope: Cluster`, add the marker `// +kubebuilder:resource:path=,scope=Cluster`, or if already present replace `scope={Namespaced -> Cluster}`, above the CRD's Go type definition in `api//_types.go` or `apis///_types.go` -if you are using the `multigroup` layout. Note that the `` +if you are using the [multigroup][multigroup-kubebuilder-doc] layout. Note that the `` element must be the same lower-case plural value of the CRD's Kind, `spec.names.plural`. **NOTE**: When a `Manager` instance is created in the `main.go` file, it receives the namespace(s) as Options. @@ -94,3 +94,4 @@ spec: [RBAC]: https://kubernetes.io/docs/reference/access-authn-authz/rbac/ [manager_user_guide]:/docs/building-operators/golang/tutorial/#manager [manager_options]: https://godoc.org/github.com/kubernetes-sigs/controller-runtime/pkg/manager#Options +[multigroup-kubebuilder-doc]: https://book.kubebuilder.io/migration/multi-group.html \ No newline at end of file diff --git a/website/content/en/docs/building-operators/golang/migration.md b/website/content/en/docs/building-operators/golang/migration.md index 5bd9e052ef7..ff3a47b44b9 100644 --- a/website/content/en/docs/building-operators/golang/migration.md +++ b/website/content/en/docs/building-operators/golang/migration.md @@ -68,18 +68,10 @@ operator-sdk init --domain example.com --repo github.com/example-inc/memcached-o ## Check if your project is multi-group -Before we start to create the APIs, check if your project has more than one group such as : `foo.example.com/v1` and `crew.example.com/v1`. If you intend to still working on with multiple groups in your project, then add the line -`multigroup: true` in the `PROJECT` file. The `PROJECT` file for the above example would look like: - -```YAML -domain: example.com -repo: github.com/example-inc/memcached-operator -multigroup: true -version: 2 -... -``` +Before we start to create the APIs, check if your project has more than one group such as : `foo.example.com/v1` and `crew.example.com/v1`. If you intend to work with multiple groups in your project, then to change the project's layout to support multi-group, run the command `operator-sdk edit --multigroup=true` **Note:** In multi-group projects, APIs are defined in `apis//` and controllers are defined in `controllers/`. +For further information see the [Single Group to Multi-Group][multigroup-kubebuilder-doc] ## Migrate APIs and Controllers @@ -358,3 +350,4 @@ E.g `kubectl logs deployment.apps/memcached-operator-controller-manager -n memca [ctrl-options]: https://godoc.org/sigs.k8s.io/controller-runtime/pkg/manager#Options [envtest]: https://godoc.org/sigs.k8s.io/controller-runtime/pkg/envtest [gomega]: https://onsi.github.io/gomega/ +[multigroup-kubebuilder-doc]: https://book.kubebuilder.io/migration/multi-group.html \ No newline at end of file diff --git a/website/content/en/docs/building-operators/golang/tutorial.md b/website/content/en/docs/building-operators/golang/tutorial.md index 3b5ef25d730..27a5ed6bd10 100644 --- a/website/content/en/docs/building-operators/golang/tutorial.md +++ b/website/content/en/docs/building-operators/golang/tutorial.md @@ -61,8 +61,7 @@ Read the [operator scope][operator_scope] documentation on how to run your opera ### Multi-Group APIs -Before creating an API and controller, consider if your operator's API requires multiple [groups][API-groups]. -If yes then add the line `multigroup: true` in the `PROJECT` file which should look like the following: +Before creating an API and controller, consider if your operator requires multiple API [groups][api-groups]. Then to change the layout of your project to support multi-group run the command `operator-sdk edit --multigroup=true`. It will update the `PROJECT` file which should look like the following: ```YAML domain: example.com @@ -70,7 +69,7 @@ layout: go.kubebuilder.io/v2 multigroup: true ... ``` -For multi-group projects, the API Go type files are created under `apis///` and the controllers under `controllers//`. +For multi-group projects, the API Go type files are created under `apis///` and the controllers under `controllers//` and then, the Dockerfile will be updated accordingly. For further information see the [multi-group migration doc][multigroup-kubebuilder-doc] This guide will cover the default case of a single group API. @@ -500,3 +499,4 @@ Also see the [advanced topics][advanced_topics] doc for more use cases and under [legacy_CLI]:https://v0-19-x.sdk.operatorframework.io/docs/cli/ [env-test-setup]: /docs/building-operators/golang/references/envtest-setup [role-based-access-control]: https://cloud.google.com/kubernetes-engine/docs/how-to/role-based-access-control#iam-rolebinding-bootstrap +[multigroup-kubebuilder-doc]: https://book.kubebuilder.io/migration/multi-group.html \ No newline at end of file diff --git a/website/content/en/docs/cli/operator-sdk.md b/website/content/en/docs/cli/operator-sdk.md index 92217d388d0..2a934bb72d3 100644 --- a/website/content/en/docs/cli/operator-sdk.md +++ b/website/content/en/docs/cli/operator-sdk.md @@ -70,6 +70,7 @@ operator-sdk [flags] * [operator-sdk cleanup](../operator-sdk_cleanup) - Clean up an Operator deployed with the 'run' subcommand * [operator-sdk completion](../operator-sdk_completion) - Generators for shell completions * [operator-sdk create](../operator-sdk_create) - Scaffold a Kubernetes API or webhook +* [operator-sdk edit](../operator-sdk_edit) - This command will edit the project configuration * [operator-sdk generate](../operator-sdk_generate) - Invokes a specific generator * [operator-sdk init](../operator-sdk_init) - Initialize a new project * [operator-sdk olm](../operator-sdk_olm) - Manage the Operator Lifecycle Manager installation in your cluster diff --git a/website/content/en/docs/cli/operator-sdk_edit.md b/website/content/en/docs/cli/operator-sdk_edit.md new file mode 100644 index 00000000000..4e6ed12e4a3 --- /dev/null +++ b/website/content/en/docs/cli/operator-sdk_edit.md @@ -0,0 +1,32 @@ +--- +title: "operator-sdk edit" +--- +## operator-sdk edit + +This command will edit the project configuration + +### Synopsis + +This command will edit the project configuration. You can have single or multi group project. +Note: unable to find configuration file, project must be initialized + +``` +operator-sdk edit [flags] +``` + +### Options + +``` + -h, --help help for edit +``` + +### Options inherited from parent commands + +``` + --verbose Enable verbose logging +``` + +### SEE ALSO + +* [operator-sdk](../operator-sdk) - Development kit for building Kubernetes extensions and tools. + From 17c4e8488d6aaf55ea2535cae5e9366c764fbcc6 Mon Sep 17 00:00:00 2001 From: Venkatramanan Srinivasan Date: Wed, 11 Nov 2020 21:19:25 -0700 Subject: [PATCH 213/376] Add tests for registry.go (#4091) * Add tests for registry.go Signed-off-by: reinvantveer --- .../registry/configmap/registry_test.go | 387 ++++++++++++++++++ 1 file changed, 387 insertions(+) create mode 100644 internal/olm/operator/registry/configmap/registry_test.go diff --git a/internal/olm/operator/registry/configmap/registry_test.go b/internal/olm/operator/registry/configmap/registry_test.go new file mode 100644 index 00000000000..4ee359efa22 --- /dev/null +++ b/internal/olm/operator/registry/configmap/registry_test.go @@ -0,0 +1,387 @@ +// Copyright 2020 The Operator-SDK 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. + +package configmap + +import ( + "context" + "fmt" + + "github.com/blang/semver" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "github.com/operator-framework/api/pkg/lib/version" + "github.com/operator-framework/api/pkg/manifests" + apimanifests "github.com/operator-framework/api/pkg/manifests" + "github.com/operator-framework/api/pkg/operators/v1alpha1" + "github.com/operator-framework/operator-sdk/internal/olm/client" + "github.com/operator-framework/operator-sdk/internal/util/k8sutil" + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client/fake" +) + +var _ = Describe("Registry", func() { + + Describe("makeRegistryLabels", func() { + It("should return the registry label", func() { + labels := map[string]string{ + "package-name": k8sutil.TrimDNS1123Label("pkgName"), + } + for k, v := range SDKLabels { + labels[k] = v + } + + Expect(makeRegistryLabels("pkgName")).Should(Equal(labels)) + }) + }) + + Describe("GetRegistryServiceAddr", func() { + It("should return a Service's DNS name + port for a given pkgName and namespace", func() { + name := fmt.Sprintf("%s.%s.svc.cluster.local:%d", getRegistryServerName("pkgName"), "testns", registryGRPCPort) + + Expect(GetRegistryServiceAddr("pkgName", "testns")).Should(Equal(name)) + }) + }) + + Describe("DeletePackageManifestsRegistry", func() { + It("should delete the package manifest registry", func() { + fakeclient := fake.NewFakeClient( + &corev1.ConfigMapList{ + Items: []corev1.ConfigMap{ + { + ObjectMeta: metav1.ObjectMeta{ + Namespace: "testns", + Labels: makeRegistryLabels("test"), + }, + }, + }, + }, + newRegistryDeployment("pkgName", "testns"), + newRegistryService("pkgName", "testns"), + ) + rr := RegistryResources{ + Pkg: &manifests.PackageManifest{ + PackageName: "pkgName", + Channels: []manifests.PackageChannel{ + manifests.PackageChannel{ + Name: "pkgChannelTest", + }, + }, + }, + Bundles: []*apimanifests.Bundle{ + { + Name: "testbundle", + Objects: []*unstructured.Unstructured{ + { + Object: map[string]interface{}{"val1": "val1"}, + }, + { + Object: map[string]interface{}{"val2": "va2"}, + }, + }, + CSV: &v1alpha1.ClusterServiceVersion{ + Spec: v1alpha1.ClusterServiceVersionSpec{ + Version: version.OperatorVersion{ + Version: semver.SpecVersion, + }, + }, + }, + }, + }, + Client: &client.Client{ + KubeClient: fakeclient, + }, + } + dep := appsv1.Deployment{} + err := rr.Client.KubeClient.Get(context.TODO(), types.NamespacedName{Name: getRegistryServerName("pkgName"), Namespace: "testns"}, &dep) + Expect(err).Should(BeNil()) + + err = rr.DeletePackageManifestsRegistry(context.TODO(), "testns") + Expect(err).Should(BeNil()) + + err = rr.Client.KubeClient.Get(context.TODO(), types.NamespacedName{Name: "pkgName-registry-server", Namespace: "testns"}, &dep) + Expect(apierrors.IsNotFound(err)).Should(BeTrue()) + }) + }) + + Describe("IsRegistryExist", func() { + var ( + testns string + rr RegistryResources + ) + BeforeEach(func() { + testns = "testns" + fakeclient := fake.NewFakeClient( + &corev1.ConfigMapList{ + Items: []corev1.ConfigMap{ + { + ObjectMeta: metav1.ObjectMeta{ + Namespace: testns, + Labels: makeRegistryLabels("test"), + }, + }, + }, + }, + newRegistryDeployment("pkgName", testns), + newRegistryService("pkgName", testns), + ) + rr = RegistryResources{ + Pkg: &manifests.PackageManifest{ + PackageName: "pkgName", + Channels: []manifests.PackageChannel{ + manifests.PackageChannel{ + Name: "pkgChannelTest", + }, + }, + }, + Bundles: []*apimanifests.Bundle{ + { + Name: "testbundle", + Objects: []*unstructured.Unstructured{ + { + Object: map[string]interface{}{"val1": "val1"}, + }, + { + Object: map[string]interface{}{"val2": "va2"}, + }, + }, + CSV: &v1alpha1.ClusterServiceVersion{ + Spec: v1alpha1.ClusterServiceVersionSpec{ + Version: version.OperatorVersion{ + Version: semver.SpecVersion, + }, + }, + }, + }, + }, + Client: &client.Client{ + KubeClient: fakeclient, + }, + } + }) + + It("should return true if a deployment exitsts in the registry", func() { + temp, err := rr.IsRegistryExist(context.TODO(), testns) + Expect(err).Should(BeNil()) + Expect(temp).Should(BeTrue()) + }) + + It("should return false if a deployment does not exitst in the registry", func() { + var ( + err error + temp bool + ) + + err = rr.DeletePackageManifestsRegistry(context.TODO(), testns) + Expect(err).Should(BeNil()) + + temp, err = rr.IsRegistryExist(context.TODO(), testns) + Expect(err).Should(BeNil()) + Expect(temp).Should(BeFalse()) + }) + }) + + Describe("IsRegistryDataStale", func() { + var ( + testns string + rr RegistryResources + ) + BeforeEach(func() { + testns = "testns" + fakeclient := fake.NewFakeClient( + &corev1.ConfigMapList{ + Items: []corev1.ConfigMap{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "config1", + Namespace: testns, + Labels: makeRegistryLabels("pkgName"), + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "config2", + Namespace: testns, + Labels: makeRegistryLabels("pkgName"), + }, + }, + }, + }, + newRegistryDeployment("pkgName", testns), + newRegistryService("pkgName", testns), + ) + rr = RegistryResources{ + Pkg: &manifests.PackageManifest{ + PackageName: "pkgName", + Channels: []manifests.PackageChannel{ + manifests.PackageChannel{ + Name: "pkgChannelTest", + }, + }, + }, + Bundles: []*apimanifests.Bundle{ + { + Package: "pkgName", + Name: "testbundle", + Objects: []*unstructured.Unstructured{ + { + Object: map[string]interface{}{"val1": "val1"}, + }, + { + Object: map[string]interface{}{"val2": "va2"}, + }, + }, + CSV: &v1alpha1.ClusterServiceVersion{ + Spec: v1alpha1.ClusterServiceVersionSpec{ + Version: version.OperatorVersion{ + Version: semver.SpecVersion, + }, + }, + }, + }, + }, + Client: &client.Client{ + KubeClient: fakeclient, + }, + } + }) + + It("should return true if there are no registry configmaps", func() { + rr.Client.KubeClient = fake.NewFakeClient() + temp, err := rr.IsRegistryDataStale(context.TODO(), testns) + + Expect(err).Should(BeNil()) + Expect(temp).Should(BeTrue()) + }) + + It("should return true if the configmap does not exist", func() { + temp, err := rr.IsRegistryDataStale(context.TODO(), testns) + + Expect(err).Should(BeNil()) + Expect(temp).Should(BeTrue()) + }) + + It("should return true if the number of files to be added to the registry don't match the numberof files currently in the registry", func() { + rr.Client.KubeClient = fake.NewFakeClient( + &corev1.ConfigMapList{ + Items: []corev1.ConfigMap{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: getRegistryConfigMapName("pkgName") + "-package", + Namespace: testns, + Labels: makeRegistryLabels("pkgName"), + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "config2", + Namespace: testns, + Labels: makeRegistryLabels("pkgName"), + }, + }, + }, + }, + newRegistryDeployment("pkgName", testns), + newRegistryService("pkgName", testns), + ) + temp, err := rr.IsRegistryDataStale(context.TODO(), testns) + + Expect(err).Should(BeNil()) + Expect(temp).Should(BeTrue()) + }) + + It("should return true if the binary data does not have a filekey", func() { + binarydata, _ := makeObjectBinaryData(struct { + val1 string + val2 string + }{ + val1: "val1", + val2: "val2", + }, "userInput") + rr.Client.KubeClient = fake.NewFakeClient( + &corev1.ConfigMapList{ + Items: []corev1.ConfigMap{ + { + BinaryData: binarydata, + ObjectMeta: metav1.ObjectMeta{ + Name: getRegistryConfigMapName("pkgName") + "-package", + Namespace: testns, + Labels: makeRegistryLabels("pkgName"), + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "config2", + Namespace: testns, + Labels: makeRegistryLabels("pkgName"), + }, + }, + }, + }, + newRegistryDeployment("pkgName", testns), + newRegistryService("pkgName", testns), + ) + temp, err := rr.IsRegistryDataStale(context.TODO(), testns) + + Expect(err).Should(BeNil()) + Expect(temp).Should(BeTrue()) + }) + + It("should return true if it fails in the next iteration", func() { + binarydata, _ := makeObjectBinaryData(&manifests.PackageManifest{ + PackageName: "pkgName", + Channels: []manifests.PackageChannel{ + manifests.PackageChannel{ + Name: "pkgChannelTest", + }, + }, + }) + rr.Client.KubeClient = fake.NewFakeClient( + &corev1.ConfigMapList{ + Items: []corev1.ConfigMap{ + { + BinaryData: binarydata, + ObjectMeta: metav1.ObjectMeta{ + Name: getRegistryConfigMapName("pkgName") + "-package", + Namespace: testns, + Labels: makeRegistryLabels("pkgName"), + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: getRegistryConfigMapName("pkgName2") + "-package", + Namespace: testns, + Labels: makeRegistryLabels("pkgName"), + }, + }, + }, + }, + newRegistryDeployment("pkgName", testns), + newRegistryService("pkgName", testns), + ) + temp, err := rr.IsRegistryDataStale(context.TODO(), testns) + + Expect(err).Should(BeNil()) + Expect(temp).Should(BeTrue()) + }) + }) + + // TODO: Test CreatePackageManifestsRegistry and Test to make IsRegistryDataStale to return false + +}) From 868f378176b2c80148c1e5290fb87ee62e550417 Mon Sep 17 00:00:00 2001 From: Varsha Date: Thu, 12 Nov 2020 14:05:37 -0800 Subject: [PATCH 214/376] [olm] Store multiple versions of olm manifests (#4043) * [olm] Store multiple versions of olm manifests This PR modifies the existing script to download multiple versions of olm manifests and generate bindata for all of them during release. * Modify changes to samples * change the number stored olm versions Signed-off-by: reinvantveer --- Makefile | 4 +- go.mod | 2 +- go.sum | 11 + hack/generate/olm_bindata.sh | 40 +-- internal/bindata/olm/manifests-0.15.1.go | 270 ------------------- internal/bindata/olm/manifests.go | 316 +++++++++++++++++++++++ internal/bindata/olm/versions.go | 3 +- internal/olm/installer/client.go | 12 +- 8 files changed, 361 insertions(+), 297 deletions(-) delete mode 100644 internal/bindata/olm/manifests-0.15.1.go create mode 100644 internal/bindata/olm/manifests.go diff --git a/Makefile b/Makefile index aaeaadc2e10..e5a0960891f 100644 --- a/Makefile +++ b/Makefile @@ -41,9 +41,9 @@ generate: build # Generate CLI docs and samples go run ./hack/generate/samples/generate_testdata.go .PHONY: bindata -OLM_VERSION=0.15.1 +OLM_VERSIONS = 0.16.1 0.15.1 bindata: ## Update project bindata - ./hack/generate/olm_bindata.sh $(OLM_VERSION) + ./hack/generate/olm_bindata.sh $(OLM_VERSIONS) .PHONY: fix fix: ## Fixup files in the repo. diff --git a/go.mod b/go.mod index 31657778fdb..129750c29a5 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.4.0 github.com/stretchr/testify v1.6.1 - golang.org/x/tools v0.0.0-20200403190813-44a64ad78b9b + golang.org/x/tools v0.0.0-20201014231627-1610a49f37af gomodules.xyz/jsonpatch/v3 v3.0.1 helm.sh/helm/v3 v3.3.4 k8s.io/api v0.18.8 diff --git a/go.sum b/go.sum index 0ba2bd71f1f..01a3237091e 100644 --- a/go.sum +++ b/go.sum @@ -829,6 +829,7 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1/go.mod h1:QcJo0QPSfTONNIgpN5RA8prR7fF8nkF6cTWTcNerRO8= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= github.com/yvasiyarov/go-metrics v0.0.0-20150112132944-c25f46c4b940 h1:p7OofyZ509h8DmPLh8Hn+EIIZm/xYhdZHJ9GnXHdr6U= github.com/yvasiyarov/go-metrics v0.0.0-20150112132944-c25f46c4b940/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= @@ -904,6 +905,8 @@ golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKG golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -937,6 +940,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -950,6 +955,8 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1026,10 +1033,14 @@ golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200403190813-44a64ad78b9b h1:AFZdJUT7jJYXQEC29hYH/WZkoV7+KhwxQGmdZ19yYoY= golang.org/x/tools v0.0.0-20200403190813-44a64ad78b9b/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20201014231627-1610a49f37af h1:VIUWFyOgzG3c0t9KYop5Ybp4m56LupfOnFYX7Ipnz+I= +golang.org/x/tools v0.0.0-20201014231627-1610a49f37af/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.0.1 h1:xyiBuvkD2g5n7cYzx6u2sxQvsAy4QJsZFCzGVdzOXZ0= gomodules.xyz/jsonpatch/v2 v2.0.1/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU= gomodules.xyz/jsonpatch/v3 v3.0.1 h1:Te7hKxV52TKCbNYq3t84tzKav3xhThdvSsSp/W89IyI= diff --git a/hack/generate/olm_bindata.sh b/hack/generate/olm_bindata.sh index 1eea414d9e5..4c7e7eb3e84 100755 --- a/hack/generate/olm_bindata.sh +++ b/hack/generate/olm_bindata.sh @@ -1,35 +1,41 @@ #!/usr/bin/env bash function get_olm_manifests() { - mkdir olm-manifests echo "downloading olm manifests for version ${1}" - wget -O olm-manifests/olm.yaml "https://github.com/operator-framework/operator-lifecycle-manager/releases/download/${1}/olm.yaml" - wget -O olm-manifests/crds.yaml "https://github.com/operator-framework/operator-lifecycle-manager/releases/download/${1}/crds.yaml" + wget -O olm-manifests/$1-olm.yaml "https://github.com/operator-framework/operator-lifecycle-manager/releases/download/${1}/olm.yaml" + wget -O olm-manifests/$1-crds.yaml "https://github.com/operator-framework/operator-lifecycle-manager/releases/download/${1}/crds.yaml" } function remove_olm_manifests { rm -rf olm-manifests } -# check for files starting with the name "olm-bindata" inside internal/olm folder +# check for files starting with the name "manifests" inside internal/bindata/olm folder function delete_old_olmbindata { echo "Deleting previous versions of olm-bindata files if they exist" - find internal/bindata/olm -maxdepth 1 -type f -name manifests-* -exec rm {} \; + find internal/bindata/olm -maxdepth 1 -type f -name manifests* -exec rm {} \; } -# TODO: -# 1. Modify this to accept multiple versions and download bindata. -# 2. Discuss on the number of olm versions of will be supported. -FILE=internal/bindata/olm/"manifests-"$1.go -if [ -f "$FILE" ]; then - delete_old_olmbindata - get_olm_manifests $1 - - go get -u github.com/go-bindata/go-bindata/... - $(go env GOPATH)/bin/go-bindata -o manifests-$1.go -pkg olm olm-manifests/ - mv manifests-$1.go internal/bindata/olm +function generate_bindata() { + $(go env GOPATH)/bin/go-bindata -o manifests.go -pkg olm olm-manifests/ + mv manifests.go internal/bindata/olm/ remove_olm_manifests -fi +} + +# delete bindata if it already exists +delete_old_olmbindata + +# get go-bindata tool +go get -u github.com/go-bindata/go-bindata/... + +mkdir olm-manifests +for v in $@; do + echo "processing version $v" + get_olm_manifests $v +done + +generate_bindata +remove_olm_manifests go mod tidy diff --git a/internal/bindata/olm/manifests-0.15.1.go b/internal/bindata/olm/manifests-0.15.1.go deleted file mode 100644 index 949f4ab785a..00000000000 --- a/internal/bindata/olm/manifests-0.15.1.go +++ /dev/null @@ -1,270 +0,0 @@ -// Code generated by go-bindata. (@generated) DO NOT EDIT. - -//Package olm generated by go-bindata.// sources: -// olm-manifests/crds.yaml -// olm-manifests/olm.yaml -package olm - -import ( - "bytes" - "compress/gzip" - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - "strings" - "time" -) - -func bindataRead(data []byte, name string) ([]byte, error) { - gz, err := gzip.NewReader(bytes.NewBuffer(data)) - if err != nil { - return nil, fmt.Errorf("read %q: %v", name, err) - } - - var buf bytes.Buffer - _, err = io.Copy(&buf, gz) - clErr := gz.Close() - - if err != nil { - return nil, fmt.Errorf("read %q: %v", name, err) - } - if clErr != nil { - return nil, err - } - - return buf.Bytes(), nil -} - -type asset struct { - bytes []byte - info os.FileInfo -} - -type bindataFileInfo struct { - name string - size int64 - mode os.FileMode - modTime time.Time -} - -// Name return file name -func (fi bindataFileInfo) Name() string { - return fi.name -} - -// Size return file size -func (fi bindataFileInfo) Size() int64 { - return fi.size -} - -// Mode return file mode -func (fi bindataFileInfo) Mode() os.FileMode { - return fi.mode -} - -// ModTime return file modify time -func (fi bindataFileInfo) ModTime() time.Time { - return fi.modTime -} - -// IsDir return file whether a directory -func (fi bindataFileInfo) IsDir() bool { - return fi.mode&os.ModeDir != 0 -} - -// Sys return file is sys mode -func (fi bindataFileInfo) Sys() interface{} { - return nil -} - -var _olmManifestsCrdsYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\xfd\x7d\x73\x23\xb9\x91\x27\x8e\xff\xef\x57\x91\xd1\xf6\x86\xa4\xb5\x48\x75\xdb\x6b\xff\x76\xfb\x7c\x37\xa1\xed\xee\x19\xeb\xe7\x7e\x50\xb4\x34\xe3\x73\x8c\x67\xe7\xc0\x2a\x90\xc4\xaa\x08\x94\x01\x14\xd5\xf4\xcd\xbd\xf7\x6f\x20\x81\x7a\x22\x8b\x22\x0b\x80\xdc\xea\x31\xd2\x11\x9e\x96\x44\x66\xa1\xf0\x90\x99\xc8\xfc\x64\xe6\x64\x32\xf9\x05\x29\xd9\x77\x54\x2a\x26\xf8\x4b\x20\x25\xa3\x9f\x34\xe5\xe6\x27\x35\xbd\xfb\x77\x35\x65\xe2\x62\xfd\xe2\x17\x77\x8c\xe7\x2f\xe1\x55\xa5\xb4\x58\x7d\xa4\x4a\x54\x32\xa3\xaf\xe9\x9c\x71\xa6\x99\xe0\xbf\x58\x51\x4d\x72\xa2\xc9\xcb\x5f\x00\x10\xce\x85\x26\xe6\xd7\xca\xfc\x08\x90\x09\xae\xa5\x28\x0a\x2a\x27\x0b\xca\xa7\x77\xd5\x8c\xce\x2a\x56\xe4\x54\x22\xf3\xfa\xd1\xeb\xe7\xd3\xdf\x4e\x9f\xff\x02\x20\x93\x14\xbf\x7e\xcb\x56\x54\x69\xb2\x2a\x5f\x02\xaf\x8a\xe2\x17\x00\x9c\xac\xe8\x4b\xc8\x88\x26\x85\x58\xd8\x41\xa8\xa9\x28\xa9\x24\x5a\x48\x35\xcd\x84\xa4\xc2\xfc\x67\xf5\x0b\x55\xd2\xcc\x3c\x7d\x21\x45\x55\xbe\x84\xc1\xcf\x58\x7e\xf5\x20\x89\xa6\x0b\x21\x59\xfd\xf3\x04\x44\xb1\xc2\x7f\xb9\x57\xb7\x0f\xbd\xc1\x87\xe2\xef\x0b\xa6\xf4\x9f\x76\xff\xf6\x96\x29\x8d\x7f\x2f\x8b\x4a\x92\x62\x7b\xb8\xf8\x27\xb5\x14\x52\xbf\x6f\x1f\x3e\x31\x1f\x52\x32\xb3\x7f\x64\x7c\x51\x15\x44\x6e\x7d\xf3\x17\x00\x2a\x13\x25\x7d\x09\xf8\xc5\x92\x64\x34\xff\x05\x80\x9b\x3e\x64\x34\x01\x92\xe7\xb8\x20\xa4\xb8\x96\x8c\x6b\x2a\x5f\x89\xa2\x5a\xf1\xe6\x31\x39\x55\x99\x64\xa5\xc6\x09\xbf\x5d\x52\x28\x25\xd5\x7a\x83\x13\x01\x62\x0e\x7a\x49\xeb\xa7\xe2\x37\x00\xfe\x5b\x09\x7e\x4d\xf4\xf2\x25\x4c\xcd\x9c\x4e\x73\xa6\xca\x82\x6c\xcc\x18\xdc\x27\xec\xa2\xbc\xb6\xbf\x77\xbf\xd3\x1b\x33\x50\xa5\x25\xe3\x8b\x7d\x8f\x36\x9f\x39\xee\x99\x76\x02\x6e\x37\x65\xff\x91\x9d\x5f\x1c\xf3\xbc\xb2\x9a\x15\x4c\x2d\xa9\x3c\xee\xa1\xcd\xc7\x7b\xcf\xbc\xde\xfa\xed\xc0\x83\x3b\x8c\xea\x63\x31\xdd\xd9\xd2\x3d\xa6\x97\x8b\xfe\x7b\xe4\x44\xdb\x5f\xd8\x3f\xaf\x5f\x90\xa2\x5c\x92\x17\x76\x77\x64\x4b\xba\x22\x2f\xdd\xe7\x45\x49\xf9\xe5\xf5\xd5\x77\xbf\xbd\xe9\xfd\x1a\xfa\x6f\xdf\xdb\x9f\xc0\x14\x10\x90\xb4\x14\x8a\x69\x21\x37\x66\x36\x5e\xdd\x7c\xa7\xce\xe1\xd5\xc7\xd7\xea\x1c\x08\xcf\x9b\xe3\x02\x25\xc9\xee\xc8\x82\xaa\x69\xc3\xd8\x8e\x50\xcc\xfe\x9b\x66\xba\xf9\xa5\xa4\x7f\xab\x98\xa4\x79\xfb\xfc\x09\xd4\xef\xde\xf9\x95\x99\xd7\xe6\xc7\x52\x9a\xa7\xe8\xe6\xc0\x59\xea\xc8\xa2\xce\x6f\xb7\xde\xe7\xc4\xbc\xb2\xfd\x14\xe4\x46\x08\x51\x85\x0b\xea\xce\x02\xcd\xdd\x2c\xd9\x85\x66\xca\xbc\xad\xa4\x8a\x72\x2b\x96\x7a\x8c\xc1\x7c\x88\x70\xf7\x46\x53\xb8\xa1\xd2\xb0\x31\x47\xb4\x2a\x72\x23\xbb\xd6\x54\x6a\x90\x34\x13\x0b\xce\xfe\xde\xf0\x56\xa0\x05\x3e\xb4\x20\x9a\x2a\xbd\xc5\x13\xcf\x1e\x27\x05\xac\x49\x51\x51\x3b\xa9\x2b\xb2\x01\x49\xcd\x53\xa0\xe2\x1d\x7e\xf8\x11\x35\x85\x77\x42\x52\x60\x7c\x2e\x5e\xc2\x52\xeb\x52\xbd\xbc\xb8\x58\x30\x5d\xcb\xe0\x4c\xac\x56\x15\x67\x7a\x73\x81\xe2\x94\xcd\x2a\x23\xce\x2e\x72\xba\xa6\xc5\x85\x62\x8b\x09\x91\xd9\x92\x69\x9a\xe9\x4a\xd2\x0b\x52\xb2\x09\x0e\x9d\xa3\x1c\x9e\xae\xf2\x5f\x4a\x27\xb5\xd5\x49\x6f\xac\x3b\x1b\xd8\x12\x0a\xbd\x07\x56\xc0\x08\x3e\xbb\x93\xec\x57\xed\x5b\xb4\x13\x6d\x7e\x65\x66\xe7\xe3\x9b\x9b\x5b\xa8\x1f\x8d\x8b\xb1\x3d\xfb\x38\xef\xed\x17\x55\xbb\x04\x66\xc2\x18\x9f\x53\x69\x17\x71\x2e\xc5\x0a\x79\x52\x9e\x97\x82\x71\x6d\x0f\x71\xc1\x28\xdf\x9e\x7e\x55\xcd\x56\x4c\x2b\xdc\x97\x54\x69\xb3\x56\x53\x78\x85\x8a\x09\x66\x14\xaa\xd2\x9c\xb0\x7c\x0a\x57\x1c\x5e\x91\x15\x2d\x5e\x11\x45\x1f\x7d\x01\xcc\x4c\xab\x89\x99\xd8\xe3\x96\xa0\xab\x53\xb7\x3f\xbc\x75\xfe\x00\x6a\x7d\x77\xf0\x83\x43\x87\x15\xec\xe9\xdc\x96\xb2\x96\x86\xcf\xa9\x21\x92\xe7\x92\xaa\x9d\x5f\xef\x1c\x56\xfb\x31\xbb\x5b\x96\x42\x99\x75\x23\x1a\x3e\xbc\x7d\x07\x19\xe1\x50\x29\x6a\x8e\x52\x26\x38\x37\x1b\x41\x0b\x20\x46\x2b\x4d\xe8\x27\xa6\x74\x7f\x46\xda\x37\x58\x30\xa5\xe5\x66\x0a\x5f\x0b\xb9\x22\xfa\x25\xfc\xa1\xfe\xd5\x04\x1f\x20\x24\xb0\xf2\x7f\xbd\xfc\x43\x29\xa4\xfe\x5f\xf0\x81\x17\x1b\xf3\x98\x1c\xee\x97\x94\xc3\xcd\xf0\x7b\x5a\xfa\x9f\x9d\x3f\x7f\x23\xcb\x6c\x0a\x57\x0b\x2e\x64\xfd\x5d\xb3\xe3\xae\x56\x64\x41\x61\xce\x68\x81\x27\x40\x51\x3d\x3d\xd9\xe1\xb4\x67\x4d\xc1\x9a\x43\x73\xb6\x78\x47\xca\x03\x13\xf7\xaa\xfe\x9c\x79\x8a\x79\x70\x57\x49\xb7\x7f\xd4\x02\xb7\xb4\x79\x3d\x2d\x06\xde\x68\x46\xb2\x3b\x20\xee\xa9\x2b\x52\x4e\x14\x1e\xaf\xce\x24\xee\x9d\x9f\xde\x6c\xbc\xaa\x19\x0c\x3c\x43\xc8\xce\x07\xaf\x9c\xec\x9b\x8e\x99\x94\xee\x9b\x8f\xfa\x5e\x6b\x8e\x1c\x98\xce\x77\xdb\xfa\xe8\x08\xee\x2c\xdb\x3f\x9c\x81\x93\x05\x7b\x4f\x17\xe0\x09\x9b\x11\x45\x7f\xff\x6f\x83\x83\x30\xfa\x32\x67\x44\x0f\xed\xca\xfd\x27\x10\x70\x7d\x6b\xa6\x43\x7f\x7d\xf0\xf5\x00\xa5\x8c\x7b\xec\xe8\x6f\x33\x73\x0e\x0e\x4c\xba\x3d\x2b\xe6\xe4\xf3\xc6\xa8\x98\xd4\x3b\x0f\x2f\x06\x84\x71\x2a\x2d\x2f\xb3\x95\x19\x57\x9a\x70\xcd\x6a\x0b\xa8\x4f\xa4\xd9\xb5\xf5\x2e\xbe\x67\x7a\x79\xec\x0e\xc6\xf3\x3c\xc0\xf5\x6a\x0e\x4e\xf9\x9c\xe3\xd9\x72\x72\xad\x3d\xe2\xcc\x8a\x80\x51\x1b\xba\x31\x1f\x47\x6d\x67\x45\x33\x49\xf5\x21\x91\x7a\x63\x3f\xd5\x2a\x4d\x23\x84\x8c\x64\x70\x5f\xb7\x02\xd6\x08\xd7\x07\x25\x03\xc9\x32\xf3\x9a\xa8\x45\x05\xd7\x46\xf9\x6e\x99\xc6\x53\xb8\xd2\x66\x02\x66\x54\xa1\x64\xbe\xa3\xb4\xb4\xca\xb8\x60\x3b\x36\x0f\x8e\x7f\x45\x8a\xe2\xdc\x5c\x61\x32\x0a\x94\x64\x4b\xb8\x67\x45\x01\x9c\xe2\x18\xcc\x70\xb4\x64\x34\x87\xb9\x90\x40\xd7\xd4\xec\x01\xfb\x24\xa0\xdc\xc8\xa2\x3d\x73\x45\xa4\x6c\xae\x16\x2d\x31\x4d\x57\x83\x47\xe2\xa1\x09\x6e\x76\xc3\xa1\x39\x6e\xf7\x90\x13\xbf\xf5\x7d\x45\xb5\x57\xc0\x23\x1f\x6a\xed\x8d\x1b\x2d\xcd\x1d\x73\x73\xe0\xc1\xdf\xf6\x3e\xdc\xd8\xb7\x4b\x71\x5f\xdb\x2d\xcd\x9c\x39\xab\x0a\x0f\xcf\xb6\x5d\x05\x78\xa7\xc5\x1d\x90\x33\x95\x89\x35\x35\x4a\xec\x95\xe0\x8a\x29\xbb\xce\x84\x5b\x33\x75\x4d\x0a\xbb\x61\xea\x47\x95\xa2\x28\x8c\xfd\x96\x57\x72\xc8\x5e\x36\x64\xec\x59\xc2\x81\xae\x66\x34\xcf\x8d\x4d\x5c\x0f\x77\x50\x80\x3d\x28\x30\x1f\x96\x6e\xf5\x79\xbf\x16\x45\xf1\x90\x84\xda\xc3\xfc\xf0\x03\xa0\xb6\xd6\xd7\x64\xcf\x03\x60\x47\xa8\xd5\xb3\xc6\x54\x7d\xba\x20\xa7\x9a\xca\x15\xe3\xd4\x6e\x15\xb6\xa2\x0d\xd7\xbd\x4c\x01\x66\x54\xdf\x53\xca\x21\x5b\xd2\xec\xae\x39\x7c\xf6\x46\xb1\xbd\xca\xee\x72\x33\x35\x77\xd9\x07\x58\xd6\xdf\x6a\xaf\x70\xa2\x28\xf0\xb2\xa2\x28\x05\x36\x07\x02\x9c\xde\xd7\xdc\x86\xaf\xc2\x43\xa4\xda\xcb\xe3\x9a\xb0\x82\xcc\x0a\x3a\x35\x92\xb3\xf9\xe9\xbc\x3b\x76\x56\xcb\xfd\xb2\x2a\x0a\xf4\x53\xec\x23\xb3\x93\x16\x1f\xaf\x5f\x81\x96\x64\x3e\x67\x99\xf9\x52\xce\x24\xcd\xb4\x9d\xd8\xbd\x13\x32\x24\xc9\x2d\xed\x39\x89\x4a\x13\x5d\xa9\x23\x8d\xe4\xfd\x9b\xa6\x31\xdf\x3e\xd2\x39\x95\x94\x67\x03\x92\xc4\xdb\x42\xe0\xad\x5b\x65\xfb\xd7\xe8\xf1\x19\x79\x7a\x0a\xa2\xb4\x95\x27\xb7\x6c\xc8\x40\x82\xc3\xf6\x01\x18\x59\x8d\x36\xb6\x61\x33\x31\x3b\x7b\xe0\x53\x7c\xd0\xfe\x3a\x82\x7d\xf3\x66\x5e\xdf\xae\x2f\x96\x83\x2e\x83\x23\x79\x54\x6c\x60\x25\x60\x47\x2a\x5f\xbd\xb6\x17\x18\xd4\x02\x28\x2e\x97\xa2\xc8\x15\x54\x9c\xfd\xad\xa2\x70\xf5\xda\xdd\xe3\xcf\x81\xf1\xac\xa8\xf2\x7d\xb3\x09\xf0\xed\xb7\x57\xaf\xd5\x14\xe0\x3f\x69\x46\xcc\xe5\xe7\x9e\x42\x2e\xf8\x89\x86\x0f\xef\xdf\xfe\x05\xaf\x43\xf8\x89\x73\xab\x68\xad\xed\x44\x0a\x86\x1e\x87\x3d\x2c\xed\xcb\x21\x4f\x23\xb8\xdd\x28\x33\x52\x9a\xbb\xa8\x42\x49\xc4\x35\x1e\xb5\x25\x2d\x4a\x73\xb3\xbe\xa3\xa0\x2a\x69\xdf\x64\xdf\x38\xaf\x5e\x2b\xfc\x0e\xae\x11\xe4\x02\xcc\xf5\x79\x41\x35\x1e\x81\x02\x6f\xd0\x63\x27\xdc\xdd\xf2\x98\xe0\x37\x9a\xe8\x98\x27\xc7\x6c\xf5\x0f\x33\xb4\x0a\x73\xe4\x3d\xf2\xa8\xec\xbd\xcc\x1e\x78\x23\x70\xc7\xec\x95\x7d\xb3\x47\x3c\x63\x3b\x6f\x38\xfa\x59\x56\x8e\xa2\x4d\xfe\xf1\x41\xbd\xba\xe3\x3b\x35\xcf\xb6\x5a\x0d\x2f\x9f\x7d\x7f\x22\xca\xfa\xc6\xa8\x5f\x12\x63\x2f\xd2\x21\xab\xc1\xa8\x22\x2b\xd5\x29\x77\xbb\x8f\xb6\xaa\xa2\x2a\x27\x5a\x4c\xf2\xa1\xa5\x7b\x70\xfe\x0e\xcd\xdd\x8a\x2a\x75\xf8\xa6\x72\x09\xcb\x6a\x45\x38\x48\x4a\x72\xa3\xce\xea\xaf\x01\xe3\x39\xcb\x08\x3a\xb4\x72\xaa\x09\x2b\x14\x90\x99\xa8\x34\xdc\x2f\x77\x4d\x52\x18\x9a\x1f\x73\x00\xed\x61\xce\x04\xb7\xfe\xf9\x51\x57\x09\x49\x89\x1a\x12\x6e\xbd\xf1\x7f\xc4\x0f\xd5\xb6\xaa\xfd\xca\xc0\x60\xee\x8d\x18\x91\x84\x2b\x1c\xc6\xa0\x66\x36\xb7\x30\xad\x20\xab\xa4\xc4\xab\x85\xd9\x6a\x23\xc7\x6b\xb7\xc2\x0d\x95\x6b\x36\x5a\x3d\x3e\x7c\x4c\xd1\x91\x4e\xf3\xcb\xc7\x3c\x68\xa5\x90\x7e\xec\x4b\x29\xb4\xc8\xc4\x83\x86\xea\xde\x2f\x2b\x3b\x5b\xc3\x9e\x8c\x71\xdf\x1f\xa3\x50\xad\x3c\x79\x09\x5a\x56\x76\x2e\x94\x16\xd2\x1c\x97\xce\x6f\xaa\x59\xe3\x3c\xae\xb9\x3a\x63\x0a\xfe\xef\xff\xfb\x45\x6b\x57\x99\x0b\x65\xa9\x69\xde\x89\x6c\xd9\xe0\xd9\xb3\x67\xf8\x43\x1d\x11\xc3\x1f\x9b\xb3\xa0\x5e\xc2\xf7\x3f\xfc\xc2\x3e\x98\xe6\xdf\xd5\xf1\x2c\xf3\xcb\x5f\x7c\x91\xe1\xc9\xa2\x52\x9a\x4a\xb7\x1e\x75\x7c\xee\x1f\x15\xa6\xb4\x0f\x77\x47\xcf\xcd\x1b\xfe\xbd\x13\xae\x1c\xfa\xcc\x6e\xd8\x72\xf0\x35\xec\x86\xd8\x0d\x5f\xaa\x75\xfb\x2f\xf7\xa1\x36\x8c\x39\xc4\xe9\x71\xc2\x99\x3d\x17\xe9\xcd\x77\x6e\xb3\x3e\x5e\x0c\x73\xeb\x1a\xb5\xff\x91\xeb\xce\x4a\xd4\x8f\xfb\xae\xf7\xbb\x63\x1e\x57\xbf\x1e\x31\x4f\xb2\x56\x28\xea\x15\xc1\x31\xf4\x52\x90\xac\xf1\x03\x6c\x0f\x60\xeb\xcf\x76\x04\x1f\xfb\xbf\x7c\x38\x98\x69\xcf\xf9\xb4\x5c\x12\xd5\x9f\xb6\xeb\xce\x6f\x76\x58\xc4\x0a\x61\x0e\xed\x59\x6b\x91\xdb\x53\x0f\xf5\xb1\xc7\xb5\x30\xe6\xef\xff\x19\xfc\xce\x4d\x49\xb3\xff\x93\xc2\x99\x29\x9c\x99\xc2\x99\x5f\x54\x38\xf3\xb0\x34\x30\x27\x1b\x72\x9a\x15\xc4\xba\x2d\x15\x68\x5a\x14\x18\x67\x5c\x8a\xfb\x26\xb8\x50\x6c\x3b\xe4\x3a\xa1\x89\xd6\x71\xbe\x22\xdc\x18\xff\xa4\x2c\x15\x3a\xab\x09\x2c\xd8\x9a\xf2\xc6\x0b\x77\x9c\x17\x69\x5f\xa8\x75\x57\x01\xd5\x7f\x19\x1a\xe2\x03\x11\xd8\x6d\x5b\x66\xef\x8c\x5d\xb6\x9f\x74\x2e\x85\x8a\x2b\x2d\x2b\x5c\xde\x1c\xee\xe8\xc6\x6d\xf9\x15\x29\x9d\x25\x86\xb1\x95\xa1\x9b\x72\xf7\x00\x10\x8d\xfb\x7a\x46\x31\x04\x31\xdb\x80\x31\xcf\x50\x54\x68\x21\x9c\xdf\xd1\x70\x43\x91\x21\xa9\x96\x8c\xae\x07\x23\x3b\x72\xc6\xb4\x24\x72\xd3\xec\x93\x7d\x57\x8e\x3d\xd7\x86\xae\xa9\xf0\xd0\x05\xe2\x01\x2b\x9a\x94\xcc\xd9\x28\x79\x63\x3a\x1e\x9c\xd7\xeb\x2b\xb7\x0b\x5b\x73\x53\xb9\x5d\x48\x15\x90\xa2\xa8\x6d\x83\xc6\x6e\xc5\xe7\x0c\x8c\xcc\x6e\xb9\x1c\x84\x6c\xf6\x8d\x99\xd0\xee\xf6\x9c\xa1\x7b\x47\x12\x6e\xfe\x30\x78\x08\x46\xce\xda\xc3\x97\x2d\x71\xcf\x87\x9c\x2d\x70\x20\x2e\x03\x0f\xc5\x66\x1e\x9c\xc1\xe6\xd7\x66\x60\x6b\x96\x53\xd5\xdc\xb9\xb5\xc0\x93\x8c\x57\xef\x3d\x6c\xed\x0a\xd6\x5f\xcd\x61\xcd\x08\x90\xc5\x42\xd2\xc5\xbe\x30\xc6\xc1\xf9\xb1\xb4\xdf\xef\x64\x69\x62\xed\xf7\xbd\x7f\x35\x42\x72\xef\x1f\x07\x5d\xbe\xf5\x1f\xfb\x66\xe3\x36\x1d\x8e\x6c\x98\x3b\x99\x79\xf7\x7a\x6a\x85\x7c\xe0\xa3\x87\x57\xd5\xd2\x83\x6b\x6b\xa9\xbf\xc2\x5b\x43\x70\x7f\x9d\x99\xf3\xd1\x0a\xec\x41\xb1\xb0\xfb\x26\xbd\xd8\x66\x49\xa5\xb9\xd0\x9b\x43\xc3\x81\x40\x66\x2d\xc1\x46\x3c\xd9\x60\xf2\x80\xd7\x7c\xf7\x9d\x1f\x5c\x7f\x4b\x87\x76\x81\xa5\x09\x94\x64\x50\x6c\xb6\x74\xcc\xb2\x59\x7a\x10\x15\xb1\x4d\x07\x7d\x1f\x1d\xbe\x0f\xa1\x26\x02\xf8\x9a\x57\x8f\xca\x10\x75\xd2\x61\x8e\x7d\x4f\x18\xb9\x7f\x57\xfb\xee\x10\xea\x48\xee\x81\xf2\x4c\x18\x91\xf0\xff\xbf\xf9\xf0\xde\x32\xdd\x1f\x3e\x6a\xe9\x4a\x03\x5b\x95\x05\x5d\x61\x68\xfc\x1d\x91\x6a\x49\x0a\x2a\x51\x97\x7d\xcb\x57\xbd\x9f\x33\xb2\xef\x94\x76\xa9\x8d\xc7\x43\x4e\x0b\xb2\xb1\x03\xca\x69\x26\x72\x23\xd9\x85\x84\xd2\x98\xd2\xab\xb2\xd2\x14\x08\xfe\xf5\x08\xae\xf8\x76\x8c\x2f\x0e\xbf\xd3\x88\xa9\x6f\x7d\x65\xb3\xcd\x20\x18\xa3\x4b\x9f\x26\xf9\x71\x12\xa6\x3b\x8c\x43\x72\xc6\xd2\x11\xd2\xa6\xcb\xf4\xc0\xbb\x35\x90\x93\xeb\xbd\x4e\xbe\x2e\x37\x73\xf1\x59\x34\x60\xdf\x21\xaa\x27\x89\x71\xfd\xdb\xdf\xec\xfd\x5c\x4e\xcb\x42\x6c\xcc\x3e\x3a\x74\xe6\x8e\x7a\x8b\x23\xe5\xc2\x71\xbc\x8e\x93\x05\x47\xf1\xb2\x6e\xac\x50\x2e\xbb\x97\x35\x0f\x26\xfb\x23\x92\x23\x98\xec\xb8\x3d\xf7\x73\x8a\xae\x34\xaf\xaf\x6a\x8f\x46\x13\x68\xb6\xf2\xec\x4f\xd5\x8c\x4a\x4e\x35\x55\xcd\xf8\x0e\x9c\x0e\x74\x87\xa0\xdc\x31\xf6\xe4\xb6\x9a\xfc\xc7\x6a\xc7\x07\x6c\xa1\xfa\x23\x0f\x58\x44\xf5\x47\x1e\xb6\x8b\x2c\x1d\xaf\x66\x0f\x6d\x38\x4b\x23\x64\xe7\xa1\xcd\x37\x9a\xe1\xfa\xa1\x00\xf7\x68\x9e\xe6\x76\xfd\x59\x2d\xc2\x9b\xde\x00\x7a\xf6\xa0\x03\xdd\x19\x73\xae\xe7\x5f\x1b\xa6\x59\x21\xb2\x3b\xe7\x11\xfd\xf8\x1a\x94\xe8\x63\x8b\x33\xc1\x55\xb5\xa2\xc0\x1e\xde\xbb\xc9\x04\x8c\xc7\x37\x99\x80\x07\x28\x99\x80\x9d\x61\x7c\x0e\x13\xd0\xc6\x31\x3e\xaf\xfc\xdb\x1a\xc2\x5e\x09\x88\x9f\x4b\x32\x30\xc9\xc0\x24\x03\x0f\x73\x4d\x32\x10\x8e\x7d\xb7\x23\xec\xc9\x83\xd0\xcb\x87\xc4\x40\x72\x0f\x77\x28\xb9\x87\xb7\x29\xb9\x87\x1f\xa0\xa4\x17\x93\x5e\x4c\x7a\x31\xb9\x87\xfd\xdf\x22\xb9\x87\x93\x7b\x38\xb9\x87\x93\x7b\xd8\x93\x67\x72\x0f\x0f\xbd\x64\x32\x01\x63\xf0\x4d\x26\xe0\x01\x4a\x26\x60\x67\x18\xc9\x3d\x9c\xdc\xc3\x49\x06\x26\x19\x98\x64\xe0\xa1\xcf\x3e\x25\xf7\xb0\xbd\x40\xd4\xf7\x87\xe3\xb1\xd4\xcf\xf6\xe5\xef\x0d\x03\xaa\x5f\x7d\x7c\xad\x6a\xd0\xf4\xc0\x40\xc3\x60\xd4\xf0\xd7\xa1\x8d\x7a\xd5\x3c\x19\x6b\x5b\xb8\xe2\x3b\xcc\x26\xda\x7e\xb8\xe7\x34\xc7\x34\xbb\x73\x60\x58\x36\xc7\x1c\x0b\x96\x31\x5d\x6c\x9a\xa1\x4c\x9f\xed\xb0\x7d\xea\x00\xed\x57\x1f\x5f\x1f\xed\x7a\x37\x13\xb1\x77\xd3\x98\x05\xdb\xf3\xc7\x28\x5e\xf6\xe4\x47\x4f\x7e\xf4\x0e\x25\x03\x22\x19\x10\xc9\x80\xf8\x3c\x06\xc4\x53\xf5\x40\x27\xdf\x71\xf2\x1d\x27\xdf\x71\x8f\x92\xef\x78\x98\x92\xdf\xa4\x47\xc9\xec\x49\x66\xcf\xa1\x4f\xfe\xd3\x9b\x3d\xc9\x77\xbc\xff\x45\x93\x0c\x8c\xc1\x37\xc9\xc0\x03\x94\x64\x60\x67\x18\x5f\x9e\xef\x18\xfe\x81\xd0\xe2\xe4\xd8\x4c\x8e\xcd\xe4\xd8\x6c\x28\x69\xb7\xa4\xdd\x0e\x7d\xf2\x9f\x5e\xbb\x25\xc7\x66\x72\x6c\x26\xc7\x66\x72\x6c\x26\xc7\x66\x32\x7b\xa2\xf1\x4d\x66\xcf\x01\x4a\x66\x4f\x67\x18\xc9\xb1\x99\x1c\x9b\x49\x06\x26\x19\x98\x64\xe0\xa1\xcf\x3e\x25\xc7\xe6\xa3\x34\x38\x7d\xe0\x7b\x0f\xb5\x2e\xf5\x6a\xa7\xb8\x57\xcc\x3d\x24\xdc\x1e\xec\x79\xfa\x70\xd7\xd3\xc3\xc2\xee\x50\xe7\xd3\x23\xd6\xf5\x40\xf7\xd3\x87\x67\xd8\x96\xea\x3e\x00\x6a\x36\x0b\x97\x5f\xd9\x8f\x36\x4d\x1d\xdb\xf2\xf0\x88\x1c\x6e\xb5\x11\x7f\xa0\x81\x47\x9f\x1a\x27\xe5\xfd\x92\xd6\x9d\x94\xec\x53\xda\x66\x8c\x4c\xe1\x7d\x80\xcd\xd9\xfe\xe6\xa5\x1e\xad\xb6\x6a\xfe\x3b\x7f\x7a\x78\xc1\x76\x6b\xba\x0f\x4e\x58\x3d\x49\xaf\xad\x17\xfe\x75\x93\x1a\xbd\x3d\x6b\x25\x91\x46\x1e\x3a\x6f\xfd\x9e\xf5\x43\x15\xdf\xe1\xb1\xb5\x12\x0f\x35\x30\x7b\x40\xaf\x3f\xac\xcf\x27\x9d\x7c\xee\xe1\x71\x1d\x56\xe3\xae\x67\xca\x35\x95\x2b\xa6\xd4\x30\x78\xbe\x3f\xdc\x87\x45\xe2\x41\x51\xb8\x67\x0d\xea\xf7\xe8\x0c\xa4\x31\xbc\x1e\x8c\x89\x18\x92\x33\x92\x81\xac\x0a\x6a\xfb\xc8\xb9\xe2\xea\x40\xb2\x4c\x54\x5c\x63\x57\x58\xeb\x5f\x19\xda\xbd\x07\xc5\xec\x41\xbb\xeb\x18\xab\x6b\x62\xc7\xf7\xe0\x27\xdc\xb8\x2f\xed\xb0\x77\x8a\xf6\xf7\xe9\x58\x0b\x0d\x1f\x7b\x48\x37\x1d\xaf\xec\x8e\x54\x75\xbd\x55\xbe\x16\x05\xcb\x36\x1f\xab\x82\xba\x5e\x86\x8c\x5b\xbd\xdd\x84\x49\x1a\x13\xfb\x08\x1d\x4a\xa0\x44\x7e\xf8\x66\xe7\x30\xab\x34\xe4\x82\x2a\x6c\x1a\xe8\xca\x2a\x74\x1f\x70\x0c\x47\xd7\x66\xcd\x36\x26\x31\x6c\x81\x94\x65\xc1\x28\x86\xe6\x84\x84\xfb\x25\xcb\x96\x0f\x34\xc7\xdc\xa5\x01\x46\xc7\x5a\x3e\x47\x98\xf9\x70\xb4\xa9\x0f\xb5\x47\x6e\x76\x78\x6a\x8f\xb7\xf9\xc1\xd6\x38\xfa\x46\x8a\xaa\x3c\xea\xc3\xbb\xfe\x53\xfb\xdd\xa1\x8e\xf3\xf5\x1f\x8f\x62\x0b\x2e\xcc\x66\xd7\xbd\xee\x49\xe7\x1c\xc3\x53\x4c\xa4\x59\x55\x85\x66\x65\x81\x8c\x8f\xe4\xb9\xb0\x83\x23\x92\xb6\x7a\xed\x1c\x08\xdf\xd4\xb1\x3d\xd7\x20\x85\xe6\x40\x16\xe6\xb9\x87\x97\xcb\x92\xe0\xcd\x6b\x52\x5e\xad\xa8\xc4\x36\xcb\xcd\x80\xf1\x62\xc9\x37\x66\xa4\x0f\x96\x72\xda\x26\xec\x7d\x3d\xa3\x40\x8a\x42\xdc\xef\xeb\x96\xb9\x4d\x63\x0c\x5c\x18\x63\xe4\xc2\x58\x23\x1e\x80\x0b\x5e\x3b\xd4\xbf\xfd\xf8\xd6\x67\x4b\xbd\xef\x73\x70\x3d\x76\x6c\xb7\xf2\x92\x48\xcd\x1e\xec\x8f\xdc\xa5\x4a\x16\xae\xb1\x39\x31\x17\x21\x59\xb7\x34\x5a\x92\x35\x6d\x5a\x99\x8b\x29\xc0\xbf\x1e\x23\xad\x00\x7b\x8e\x34\x4b\x63\xe5\x95\xe0\xc5\x06\x88\xdd\xad\xf3\xaa\x28\xce\x61\xce\x38\x31\x2a\x89\x1e\xbb\xe4\x2e\x17\xcc\xdc\x66\xe1\x06\xbb\xa0\x73\xc1\x27\x8d\xb1\x86\x73\x60\x9e\xcb\xc5\xb1\x7b\xb3\x11\x6f\xb9\xeb\x08\xdb\xb4\xa5\xb7\xc3\x35\x82\x2c\xc3\x8e\x95\x73\xf1\x50\x25\x9a\x2e\x39\x23\xf3\xa3\x28\x30\x20\xe2\x42\x25\xb9\xed\x49\x44\xba\x7f\xfe\x4f\xc6\x8f\xbb\x1e\x5a\xfa\x88\xca\x3e\x23\x1c\x28\xd3\x4b\x73\xbf\x2d\xcb\x62\x63\xc4\xb5\x39\x3b\xed\x81\x3a\x55\x55\xf6\xb0\xa7\xa3\x25\xa2\xe0\x59\x29\x72\xf5\xcc\x88\xfc\x67\xae\xc5\xfd\xb3\x33\xf3\xd3\xf6\xdc\x1e\xc9\xd1\xac\x8e\x1b\x03\x72\xbf\x20\x25\x7b\x76\x76\x0e\xb8\x09\xb0\xa9\x92\xd0\xcb\x2f\xef\xb4\xd6\x33\xd1\xe9\xcc\x77\x88\xb6\x5a\x88\x76\xbe\xef\xba\x04\x89\xd2\x36\xd5\x31\xba\xf6\xe0\x55\xbe\xa6\x82\x29\x3c\xe0\xb6\x71\xb0\x6b\x53\xb7\xab\x78\x01\x2e\x8f\x31\x03\x0c\xd1\x55\xa9\x37\x28\x37\x56\x94\x70\xc7\x93\xae\xa9\xdc\xe8\x25\xe3\x0b\x1c\xec\x97\x2a\x64\x8f\x0a\x98\xb6\x34\xb8\x64\x4e\xb0\xd6\x13\xdf\xb0\x3c\x5a\x59\x33\x35\xb0\x3c\x35\xf7\xcb\xa2\xe8\x5c\xbe\x8e\x3d\xb6\xf8\xa5\x5a\xe5\x7f\x71\xab\x82\xb6\x99\xc7\x8a\x7c\x67\xbe\xd7\x5f\x0d\xfb\x2b\xab\xba\x8c\x38\x3c\x76\xc0\x02\x2e\xdf\xbe\xb5\x6d\xe7\xdc\x3c\xfe\x89\xf1\xdc\xde\xa5\x2e\xb5\xed\xd9\x46\x3f\x52\xf3\x4a\x68\xfe\x1c\xbb\x32\x75\x91\xb3\xbc\xe9\x4b\x6c\x96\x7e\x0a\x38\x50\xef\xb5\xc6\x4e\x70\x5f\xd2\x3a\xef\x5e\xeb\x8e\xbb\x8e\x3d\xc8\xba\x73\xf3\xff\xbc\x17\x76\xec\x86\xd7\xb3\xbf\xd1\x98\x27\x07\x90\x04\xc6\xae\xc6\x86\x77\xe6\x1b\xed\xcb\xc0\xe5\xdb\x77\x4d\x0f\x49\x6c\xc1\xfc\x8f\xba\x9e\x1f\x00\x36\x4c\x0e\x45\xbc\x8f\xbd\x3d\x1d\x03\x3f\x38\x7e\x6b\xed\x75\x75\xb5\xd4\x5b\xbf\xad\x75\x73\xd7\x2f\x77\xc9\xc9\xec\x8d\x5c\xcc\x0f\xdf\x54\x71\xd1\x94\xad\x79\x40\x97\x64\xcd\x84\xac\x2f\x36\xed\x23\x0e\x1d\xd2\x11\xf7\xdd\x63\x6f\xbb\x13\x50\xb4\xa0\x99\x3e\x68\xa1\x4e\x40\xd3\x55\x59\x3c\xbc\xc1\x60\xe4\xad\x78\xc5\xf8\x47\x4a\xf2\xcd\x0d\xcd\x04\xcf\x8f\x92\x24\xbd\xd5\x79\xc7\x38\x5b\x55\x2b\xe0\xd5\x6a\x46\x71\x42\x95\xe5\x84\x27\x05\xbd\x10\x47\x09\x27\x02\x9c\xde\x17\x9b\xba\x89\x39\x94\x22\xaf\x0f\xd5\x0c\x7b\xb6\xe7\x1b\x6c\xba\x28\x2a\x6d\xee\x9b\x47\xf1\x14\x73\xdb\xad\xbd\x2e\x5c\x09\x99\x24\xca\xd8\x44\xe7\x38\x38\xa6\x8d\x1e\x99\x51\x0c\x69\xb2\x9c\xca\xc1\x5a\x19\x03\x43\x5d\x13\x56\x98\x5b\xc5\x14\x5e\xd3\x39\xa9\x0a\xec\x3a\x0a\xcf\xe1\xd4\x0c\xba\xbe\xd8\xfa\x32\x35\x56\xb7\x12\x82\x9b\xff\xda\x52\x19\xf8\xf2\x67\x47\x87\x6a\x0e\x17\xde\xac\xe9\xb8\x02\x9c\x35\x95\xa4\x52\xc7\xf8\x6e\xb6\x36\xc8\x15\xcf\xcd\x29\xed\x1a\xbb\x1d\xd9\xc9\x94\xe3\x7b\x8c\x76\xb4\xef\x37\x13\xa2\xa0\x47\x84\x05\x4b\x29\x16\x92\x2a\xf5\x9a\x92\xbc\x60\x9c\xfa\xee\xf0\xdb\x25\x85\x15\xf9\x84\xbb\x5c\xb3\x15\x35\x96\x41\x77\x8f\x93\xce\xfb\x1c\xa7\xe2\x05\xac\xc8\x1d\x6d\x06\x08\x33\x3a\xc7\x7e\xb4\x38\x1d\xed\xbe\xb1\xbb\xf3\x28\x96\x73\xc2\x0a\x9a\x4f\x71\xac\x9d\xd9\x6d\xdb\xb7\xdb\x6d\x69\x7e\x66\xbc\x3a\x8e\xa7\x16\x66\x84\xe8\x3b\xb0\xec\xbb\x0a\x1c\x0d\x2d\xd2\x36\xaa\x3f\x8a\xa3\x39\xbf\x40\xe0\x7a\x6b\x61\xde\x7c\xca\xac\xb7\x5b\x52\xa2\x04\xaf\x4f\xd0\x51\x2c\x55\x25\xe7\xe6\xfe\x5f\x3b\x17\x3a\x2f\xef\x7a\x72\xc3\x7b\xa1\x5d\x37\xd6\x7a\xc2\x8f\x1c\x6c\x51\x80\xeb\x22\x4c\x95\x66\x2b\x14\x4b\x79\x25\xeb\x7e\xc7\xb8\x17\x46\x2f\x7e\xbb\xe1\x7b\xc2\xe3\xf7\xcf\x9f\x1f\x65\x20\x3e\xee\x11\x97\x14\x1d\x26\xe3\xcf\xc8\xfb\x46\xfa\xd7\x2a\xb6\x14\xb9\x32\xfb\x91\x39\x83\x1f\xdb\x38\x1f\x35\x64\xdc\x79\x39\x53\x9a\xf1\x45\xc5\xd4\x12\x66\x54\xdf\x53\xca\x81\x7e\xb2\x25\x83\xe0\xef\x54\x0a\xdc\x80\x66\x79\x1e\x88\xe2\x0d\x51\x77\xd2\x5f\x3c\x85\x19\x5f\x33\xc5\x04\xff\x23\x53\x5a\xc8\xcd\x5b\xb6\x62\x0f\xd6\x56\xae\x69\xb7\xfd\x7d\xb3\x02\xa2\xc8\xb1\x79\x3d\xcb\xc8\x0d\xb5\x2f\x2a\xa9\x51\x80\xc7\xce\x3d\x7a\x0b\xc0\xc8\x8d\x19\xc9\xee\x06\x16\x71\x6b\x81\x8e\xe2\x7b\xec\x22\x36\x0b\x74\xec\x68\x5f\x3c\xff\xfc\xab\x58\x1b\x70\xa3\x57\xee\x2d\x99\xd1\xa2\xf9\x3a\xaa\x13\x7b\x70\xde\x7c\xb2\xf3\xdb\x5d\xc9\xe3\xc4\xd6\x52\x28\x8a\x4c\x6c\x2c\x00\x59\xd7\x91\x44\xa6\x1a\xf3\xc4\x48\x30\xc1\x8f\xf4\x82\x90\xf9\xbc\xcf\xa5\x15\x7a\x53\xb8\xd2\xb0\xaa\x94\x86\x15\xd1\xd9\xf2\x60\xdc\xb3\x26\x63\x2a\xd5\xe6\xec\x89\x82\xc2\x4c\xc4\x08\x09\x78\x64\xc4\x69\x6c\x84\x08\xec\x5b\xbc\xf9\x64\x2e\xf9\x07\x42\xcb\x7d\xea\x2d\xeb\x36\x93\xbe\xcf\x03\xdf\xf5\x48\xb6\xed\xde\xaa\xef\x13\x2b\xdb\x39\xff\x16\xa3\x46\xed\x6f\xcc\x6a\x1f\xcd\xf3\xf2\xfd\xeb\x63\xe5\xe5\x78\x8f\xc4\x48\x9f\xc4\x76\x9c\xcd\x4e\xcf\xe0\x6b\x1f\xcd\x11\xea\x58\x8a\xe3\xd1\x0f\xb8\x21\x50\x4d\x9d\x03\x81\x3b\xba\x39\x1f\xc1\x14\x6d\x9e\xed\x8e\xf8\x92\x16\xce\xba\xa5\xd8\x2a\xfe\x90\x17\xa1\x4f\x76\x2c\xc7\x2e\xc5\xe8\xdd\x6f\xe9\xf8\xb8\x6b\x4d\x13\xf3\x2a\x23\x3e\x5d\x4f\xc9\xd1\x5f\x19\x7b\x2c\x2d\xdd\xd1\xcd\x98\x8f\x6f\x6d\x2d\xb3\x3a\xce\x7b\x60\xf7\x98\xf9\x85\x59\xc3\x51\x2c\xad\x27\xa1\xd9\x5a\x63\x82\xe5\x3d\x26\xe3\x5c\xae\x35\xd5\x13\x1d\x30\x0d\xcd\xf6\xed\x60\x86\xf0\x28\x9c\x1c\xeb\xd2\xac\x09\xb7\xbe\x91\x6f\x4b\x56\xa2\xe1\x50\x47\x2f\xdd\xae\x86\xef\x48\xc1\xc6\x9c\x86\xee\x1b\x5a\xfd\x75\xc5\xcf\x8d\x01\x6f\xfe\x83\x2a\x51\x8d\x3c\x5f\x86\x5e\x0b\xaa\xde\x0b\x8d\xdf\xff\x87\x2c\x92\x7d\xfd\x80\x25\xb2\x0c\x5c\x98\x09\x25\x2f\x3a\x56\xc6\x8e\xa3\x1d\xcb\xb4\x2e\xcf\xd9\x2c\x3e\x53\x70\xc5\x41\x48\x37\xbb\x1e\x47\xc0\x0d\xd2\x0e\x0f\x2d\x80\x99\x8d\xe8\x62\x40\x6a\xdc\x44\xc3\xd0\xf8\xdc\x82\x0b\xd9\x5b\xc1\x68\x43\xb5\xc3\x44\xeb\x76\x24\x4b\xcb\x07\x3d\x33\x65\x81\xb7\x4f\x77\x2d\x24\x35\x42\x8b\x1d\x4a\x34\xda\xa6\x15\x95\x0b\x0c\x8d\x67\x47\x06\x57\x9b\xd7\x1b\xad\x9d\x2d\x8d\xd4\xd1\xdd\x87\x8d\xd8\x87\x68\x08\xa1\x91\x1b\x60\x48\xd9\xef\x5b\x95\xbe\x22\xa5\x39\x0a\xff\xd7\x68\x6e\x5c\xd5\xff\x77\xbc\xca\x21\x4c\xaa\x29\x5c\x82\x62\x7c\x51\xd0\x2e\x8f\xda\x7b\xd0\x79\xdc\xd1\x6c\xcd\x88\x98\x02\xa3\x62\xd7\xa4\xa0\x1c\x9d\x8a\x84\x03\xb5\x00\x77\x33\xda\x6d\x73\xf0\xf8\x2d\x6c\xad\x79\xa3\xa7\x1a\x64\xc3\xb3\x3b\xba\x79\x76\xbe\x7d\x58\x8e\xe6\xf8\xec\x8a\x3f\x3b\x47\x4b\x66\xe7\x60\x34\x06\x12\x82\x27\x9e\xe1\xdf\x9e\x1d\xbf\x1b\x87\x2c\x52\x1f\x4b\x73\x94\x71\x43\x72\xeb\x7f\x22\xc5\xb5\x87\x45\x31\x6a\x3f\xd7\xe0\x4b\xaf\xeb\x79\xcf\x2f\xe5\x20\xc8\x5a\x40\xa5\xa8\xbd\x9f\xa3\x1c\x39\x6a\xdc\xb4\xbe\x19\xe2\x1d\x0f\x5d\x6a\x9c\xde\xe3\x5d\xee\x09\x5c\x9f\xa4\x28\x0a\xc6\x17\xdf\x96\x39\xd1\x47\x64\x98\x58\xea\xcd\xd6\xc9\x47\xcb\x02\x2a\xe4\x61\x76\xe5\x9c\x2d\xa0\x24\x92\xac\x46\x18\xca\xd7\xae\x00\x35\xee\x65\x36\xef\x46\x91\xdc\xfc\xdf\x6e\x4a\x0a\xff\x13\x3e\x76\x47\x7c\x3c\xff\xc9\x64\x02\xb7\x1f\x5e\x7f\x78\x09\xf6\x9b\xf6\x5e\xac\x05\xcc\x05\xba\x4f\x44\x25\xcd\xd0\xd7\x94\x1f\xed\x1e\x05\xeb\x77\x30\x4b\xf9\x61\x7e\x0e\xf7\x4b\xa2\xe9\x9a\x4a\xb8\x37\xdb\x27\x63\x39\x6d\x22\x16\xd3\x93\xc7\x3b\x51\x3e\x96\xf9\x8a\x7c\xba\xa9\xe4\xe2\xe8\x05\x87\x9d\x45\xef\x3a\xd9\x5b\x57\x96\xd9\xe2\xe3\xb4\x61\xa7\x80\x89\xca\x96\x34\xaf\x0a\x9a\x03\x99\x89\x35\xed\x06\x00\x47\xf1\xec\x0f\x07\x8d\xda\x8a\xd6\x0f\x31\xf6\xd9\x4c\x89\xa2\x3a\x1a\x00\xd4\x63\x7a\x4a\x3f\xbd\x84\xdf\x21\x5e\x8b\x40\x49\x65\x46\xb9\x26\x0b\xda\x71\xa4\x8e\xe2\x8a\x22\x01\x79\xbe\x78\xfe\x2f\x67\xce\x73\x67\x46\xea\xfc\xd8\xcf\xcd\x49\x78\x47\x3e\x7d\xcb\x9b\x70\xd3\x38\xa3\x41\xc1\xf3\x29\x5c\xba\x17\xae\x5f\x02\x9f\x51\x64\x55\x81\x1e\xf2\xb9\x14\xab\x71\x83\x6e\x5f\x7b\xb6\x01\x29\x2a\x44\xd5\x41\x55\xf6\x3c\xe4\xa3\x58\xfe\xe6\x77\xff\x32\x85\x37\x9f\xc8\xaa\x2c\xe8\x4b\xb8\x5f\x52\x87\xe5\x60\x0a\x6f\x28\x5a\xc0\x6f\x9f\xff\xcb\x38\x43\x12\x51\x02\xf4\xbe\xe3\x8f\x6b\xf7\x19\x31\x9b\xac\x2a\x81\xad\x6c\xce\x0c\x3d\x1a\xc7\x62\xc9\x0d\x90\xd6\xd2\xb3\x16\x7d\x4a\x13\xa9\xd5\x39\x20\x18\x6f\xf4\x45\x15\x63\x14\x42\x93\x62\xcb\x37\x8c\x3e\x57\x7a\x6f\x37\x4b\x3e\x6e\x62\xcd\x3e\xa2\x18\xae\x81\x17\xbf\x7d\xfe\x2f\xbb\x0e\xff\x0f\x87\x4a\x02\x6d\x93\x19\x11\x8e\x04\xb1\xaa\x33\x4a\x39\xdc\xb1\xa2\xa0\xf9\xf9\xd6\x74\x8f\xe2\xba\xb3\x34\xf3\x4a\xea\x25\x95\xe7\x40\xb9\xaa\x43\x38\x63\xe7\x73\x6b\x2e\x71\xd4\xb2\xe2\x1c\x2d\x7f\x8c\x4a\x63\x4c\x68\xdc\xb5\xaf\x8d\x27\xb9\x45\x37\x66\xae\x86\x95\x50\x7a\x7b\x8a\x47\x8b\x82\xa3\xd5\x04\xa0\x73\x6b\xf3\x61\x3e\x46\x80\x4f\x46\x3b\xd5\xb7\xbf\x39\xfa\x42\xfb\x69\x72\xd7\x14\x2b\x99\x30\xae\x27\x42\x4e\x2c\x93\x97\xa0\xe5\x91\x71\x4d\xb0\x0a\xab\x23\x03\x9f\x94\xda\xaa\xda\x71\xed\xee\x8e\x71\x77\xc3\x7d\x9a\x6a\x4b\xfb\x8c\x3b\xaf\x7b\x35\xd5\xb6\xf6\x19\xc5\xf6\xb0\x4e\xe9\x3c\x74\x14\xe7\xae\x4e\xc9\xc5\x3d\x1f\xd6\x8a\xa3\x58\xbe\x73\xe6\x8e\xd3\x87\xdd\x90\x62\x4f\xf3\xf8\x28\x81\x1d\x2d\x65\x6f\x7a\xbd\x98\x5e\x80\x28\x34\x33\x60\x38\xff\xff\x76\x85\xf7\x38\x4b\xa0\x55\x75\x07\xd4\xd7\xb8\x7d\xf0\x01\xd3\x02\x6a\xed\x64\x6e\x90\x88\x7e\x39\x8f\x3c\x03\x8d\x3a\xb0\xd6\x3a\x46\xb6\x46\xf1\x34\xcc\xec\xab\x0e\x58\x06\xad\x96\x19\x2f\x05\x86\xb4\xb6\x9d\x0b\x2f\x8b\xcd\xe8\xa5\xa2\x40\xbd\xa4\xf6\x2a\x9b\x82\x92\xa3\xd3\x81\x2c\x0d\x6c\x9f\xa4\x6c\x86\xe8\xa1\xfc\xe9\x6d\xea\x3b\x0d\xcc\xed\x14\xa7\xb8\x8d\xb4\xbe\xb2\x1b\xf9\xd9\x47\x6a\x51\x72\xbb\xfd\x92\xf6\x91\x90\xf0\xac\x77\xd1\x7d\xd6\x88\x2d\xb3\x07\xbc\xee\xc0\xa3\xa6\xb5\x0e\xf5\x8e\x77\x9e\xb8\x2f\x76\x4a\x9a\x60\x12\x91\x39\x12\x78\x60\xee\x59\x71\x5c\x30\x75\x46\x6b\x70\xe1\x13\xf0\x93\xac\xa8\x26\x0f\x65\xe7\x6f\x53\xdf\xec\xb8\xd1\x84\xe7\x44\xe6\x6e\x7c\x27\x27\xaa\x61\x38\x85\x77\x62\x44\x24\x98\xf1\xb9\x78\x09\x4b\xad\x4b\xf5\xf2\xe2\x62\xc1\xf4\xf4\xee\xdf\xd5\x94\x89\x8b\x4c\xac\x56\x15\x67\x7a\x73\x81\x20\x32\x36\xab\xb4\x90\xea\x22\xa7\x6b\x5a\x5c\x28\xb6\x98\x10\x99\x2d\x99\xa6\x99\xae\x24\xbd\x20\x25\x9b\xb4\xde\x0e\x35\x5d\xe5\xbf\xac\x07\xf4\x88\xae\x8a\xde\x09\xc5\x58\x96\x5c\xd3\x49\xc5\xef\xb8\xb8\xe7\x13\xf4\x98\xaa\x11\x67\xf5\x18\x64\x72\x4d\x5b\xeb\xb1\x05\x46\x1e\x04\x1b\x1f\x7f\x58\xe7\xf5\x16\xb7\x8b\xf9\x88\x8b\x64\x5e\x79\x42\x78\x3e\xb1\x60\xb9\x47\x5c\xab\xb1\x31\xe8\x49\x0b\xdb\x3d\xd6\x32\xf1\xf1\x5c\x91\x4c\xb3\x35\xf5\x80\x88\xd6\xd4\xdb\x08\x1f\xea\x8c\xb0\xbc\x92\x76\x2f\xb4\x58\xd1\xd1\x77\xf7\x52\xe4\xb0\x22\x1b\xb4\xdd\x71\x94\x20\xac\x99\xc5\x45\x4e\x5d\xec\xf5\x60\x61\xdf\x2d\xb6\x02\x6e\x8c\x51\x76\xcb\x56\xb4\x46\x9d\x62\x34\x7b\xa3\x34\x5d\x59\x6c\x90\x7d\xd6\x48\x0f\x86\x96\x1b\x0b\x6b\x95\x77\xc0\x74\x8d\x17\x25\x3c\xc7\xcb\x3c\x10\xa5\x44\x66\xac\xc5\x71\x77\xd8\x76\x07\xd4\x5e\xb7\x3a\x76\x47\xa0\x14\x8a\xe1\xa4\x38\x8b\x60\x8c\x99\xe9\x6b\x4a\x74\x40\x61\xbf\xff\xb7\xe3\xb7\xd8\x1c\x7b\x35\x8e\x42\x2e\xf4\x11\xd4\xf3\x6e\x4a\xb7\xdb\x1a\x27\xaa\x76\x70\x8e\x35\x33\x33\xc1\x95\x96\x84\x1d\x9f\xc2\x04\xbe\xc0\x13\x5f\x9c\x07\xe0\x1e\xbf\xf4\x98\x38\xd8\xcd\x1e\xa9\xcd\x06\x3c\x36\xf5\x62\x8c\x64\x09\x9d\xc9\x76\x55\x3b\xea\x44\x20\x23\xa6\xbd\xc2\xa8\xa3\xe7\x12\x02\xe6\xd3\x7e\x97\xce\xa9\x94\x34\x7f\x8d\xf7\x80\x9b\xe6\x8d\xae\x16\x5c\x34\xbf\x7e\xf3\x89\x66\xd5\x71\xa5\xd1\x76\x69\x27\xee\x55\x3b\xe1\xe5\xf1\x76\xda\xf0\xb0\x8d\x78\xa9\x99\x39\xeb\x4f\xe0\x92\x8e\x0d\xde\x5b\x42\xd3\x51\x11\xcd\xd4\xdc\x96\x58\xa9\x37\x06\xd0\x36\x4e\xeb\xc5\xb9\x39\xaa\x0d\x58\x12\x0d\x11\x9b\x45\x7f\xa0\x68\xde\x3e\x32\x6a\x20\x5b\x0a\xa1\x8c\xe4\xc3\x7d\x8c\xe3\x5f\x33\x81\xd8\x33\x2f\x9e\x58\xd7\x41\xc2\xca\xe8\x80\xba\xbe\x43\xfb\xea\x63\xb7\xb4\xa5\xdb\x5a\x3b\xe1\xf0\x98\xb2\x6e\xcc\x66\xdf\x79\xf1\x74\x88\x2d\x33\x5c\x0c\x76\x9a\x1f\x16\x68\xc7\x2b\x0d\xaa\x1a\x17\x6b\xa8\x49\xcc\xe1\x9e\xb2\xc5\x52\xab\x73\x60\x53\x3a\xc5\xd3\x4c\x49\xb6\xc4\xe1\xfb\xef\xa8\x15\xa5\xba\xd7\x88\xd7\x53\x46\xd7\xd4\x8b\xa7\x9f\x36\xe9\xfc\xae\x96\xc7\x58\x28\x4c\x8f\xe7\x8e\x14\xf0\x97\x8d\x80\x61\xe9\x16\xde\x00\x54\x67\xd3\xb3\x73\x68\x2a\xee\xf9\x1d\xa4\x6a\x65\x8e\x10\xd3\xd4\xd8\x52\xe8\xb7\x90\xa2\x5a\xd8\x1d\xe0\xd0\x15\x9e\x5b\x7f\xde\xad\x16\x81\xa8\xce\x1c\xfd\x83\xcf\xec\xa6\x38\xfe\x5e\xdd\x25\x6d\x6b\xf1\x98\x61\xb3\x79\x6b\xa8\x21\xf8\xc3\x5b\x4a\x51\xc8\x84\x94\x54\x95\xc2\x7a\x30\xb7\xa1\x24\xff\xc3\x9b\xaf\x19\xdc\xa9\x3a\x6b\x0f\xd5\x92\x2d\x96\x21\x67\x8a\x38\x63\xb2\x7f\xe6\x7d\x04\x89\x2f\xa6\xc9\x92\x17\xb2\xc9\x52\x1f\x89\xcc\x5d\x69\x85\x30\xf9\xd5\x33\x1d\x34\x95\xab\x7a\x47\x18\x31\xe1\xc9\xd1\x9a\x0e\x0e\xfd\x51\x77\xd2\x76\x12\xcd\x93\xe5\x73\x38\x45\x41\xc8\xf4\x89\x42\x25\x33\x11\xe5\xd9\x14\x2e\x81\x57\xde\xc3\x6c\x26\x6e\xdf\x14\x78\xf2\xe5\xa2\x99\x01\x37\x68\x33\x99\x4a\xb4\xe3\xf6\x3b\x15\xfe\x66\x99\xa5\xf1\x38\xeb\x2e\x4d\xdc\x7c\xd1\xb1\x21\xd4\x96\x41\xc0\x0e\x08\x31\x2c\x6b\x0e\xf5\xe8\x7d\x39\xec\xa4\x02\xa0\x00\x3d\x32\x3b\xfa\x21\x32\x7b\xee\xbc\x73\x0b\x6d\x84\x5e\x00\xcf\xbe\x5c\xb6\x33\xef\xb7\xef\x20\xc6\xde\x83\x28\x6b\x08\x01\x19\x30\xc3\xb4\x9d\xdc\x61\x73\x60\x82\x58\x42\x7f\x5f\xf4\x8c\xa4\x40\xc6\xb3\x0d\xf2\x1e\x95\x90\xb4\x9f\xc2\xf4\x58\x4b\x01\x1a\xad\xa5\x81\xa3\x15\xc8\x71\x38\x37\x29\x98\xe9\x6e\xea\x4e\x30\xcb\xdd\xd4\x9f\x60\x96\x77\x74\x73\xbe\x9d\x10\x14\xcc\x74\x28\xa1\x28\x98\xa9\x19\xe4\xd8\x34\xa3\x3d\xc3\x8b\x21\xa4\x2c\x85\xa9\xca\x96\xc6\x25\x2a\xed\xe3\x11\x69\x01\xe3\xc8\x5f\x4b\xa3\x53\x9d\x86\x69\xdb\x21\x13\x81\x25\x84\x65\x4f\x0d\xd3\x50\x4e\x55\x1c\xc6\x23\xf3\xb2\xf6\x70\xf1\x0b\x21\x0f\x93\x5f\x0e\xd7\x30\x6d\x55\x3c\x1b\x59\x9b\xea\x61\x72\x49\x61\xbd\x34\xaf\x48\x6b\xb2\x93\x2a\x16\x85\x2f\xa6\x9b\xb5\x09\x64\x71\x26\xa1\x97\x84\x16\x85\xa5\xcd\x6b\x3a\x0f\xc8\x4b\xdb\x47\xdf\x68\xab\x93\xde\x46\xe1\x17\x75\xd3\xfb\xe4\xc4\x0d\xd3\xd6\x25\x3d\xd2\x2a\x87\xe4\xd8\x0d\x53\x3f\xf3\x2e\x0a\xcb\x7e\xf6\x5e\x1c\x96\x75\x06\x60\xb4\x41\xee\x24\xdb\x45\xe1\x1a\x92\x5b\x38\x4c\x5b\x19\x87\x51\x78\x46\xcb\x5a\x1c\xa6\xed\x94\xad\x28\x4c\xfb\xf9\x90\x4f\x79\x6a\xbf\xd1\x66\x5a\xdf\xea\xa7\xbe\x57\x6d\xd9\x65\x97\x67\x18\x85\xa3\x73\x77\x9f\x8f\x28\xa8\x76\x88\xea\x42\x20\x58\xd1\xa5\x94\x74\x6c\x70\x7e\x1f\x11\x4c\x5a\xf6\x88\xca\xef\x27\x04\xec\xd6\x49\xb7\x51\x38\x6e\x25\xee\x46\x32\x97\x9a\xe4\x5f\x9b\xce\x1b\x85\xab\x47\x4a\xf0\x30\xc5\x72\x46\x58\x8a\xe2\x92\xe8\x0e\x2c\x58\xf1\xa2\xdb\xea\x6b\x8b\xf9\xfa\xa7\xf4\x58\x59\xbc\x5b\xf2\x58\x3d\x48\xc9\x63\x95\x3c\x56\x7e\x94\x3c\x56\x07\x28\x79\xac\x92\xc7\xea\x08\x4a\x1e\xab\x0e\x25\x8f\x55\xf2\x58\xf9\x51\xf2\x58\x3d\x75\x2f\x40\xf2\x58\x25\x8f\x55\xf2\x58\x25\x8f\x55\xf2\x58\x79\xd2\xcf\xd9\x63\x65\xf1\x62\x91\x80\x72\x7f\x46\x66\xbe\x59\x56\x5b\x03\x63\x7a\x69\x7d\x69\x75\xaa\x78\x0f\xe8\x16\xc0\x99\x8b\x9c\xde\xb8\x0b\xd3\x2d\x02\xf2\x6c\xd5\xbd\x00\x96\x92\xf0\x05\x85\x17\x93\x17\xcf\x8f\x2a\x02\x3e\x4c\xbe\xd9\x60\x7d\x1a\x57\x30\x7c\x9b\xf6\x61\xf2\x1f\x29\x33\xc7\x69\xbb\x26\xe7\x25\xd8\x1f\xb9\x27\xe9\x65\x64\x3b\xc7\x3e\xad\xa8\x06\xa2\x7b\xd0\x61\xb6\xa2\x4d\x02\x9c\x17\xcf\x6e\x53\x87\xb6\x3e\x98\xe0\x16\xbb\xef\xc5\xd2\x6c\xeb\xe9\x3f\x6e\x46\x33\x4a\x94\x67\x82\x0a\xf6\xba\xa9\x67\x55\xac\xa8\x2d\xe7\x1f\xa2\x50\x4a\x91\x03\xad\x77\x25\x9c\xd2\xe9\x62\x0a\x79\x45\x6d\x05\x4c\x2f\x8e\xb6\x2e\xc5\xd9\x79\x37\x2d\x75\x65\x2e\x3a\xd2\xfc\xc7\x73\x81\x74\x9d\x9f\x4a\xd7\x94\xeb\x8a\x14\xc5\x06\xe8\x9a\x65\xda\x7b\xd1\xcd\x8b\x63\x51\x1a\xa6\x6d\x62\xa1\x7f\x9a\x83\xb7\x73\x32\xc4\x21\x39\xd9\x91\xc6\x3e\xbb\x34\xd4\x7b\xb8\x33\x06\x5f\x7d\xb8\xe5\x53\xb2\xf3\x32\x75\xc1\x1b\x6f\x91\x2e\xe6\x5b\x61\x1b\x6d\xc6\x38\x0d\x72\x4a\x22\x0b\x14\x8b\x1f\x3e\xfa\x25\xc7\x40\x14\xcb\x28\xd0\x1a\xda\x0e\xcd\x54\x45\x61\x8e\x28\x5e\xc8\x02\x4d\x84\xfe\x74\x07\x66\x8a\x40\x2f\x5b\x64\xb7\x6b\x42\x00\x5b\x9b\xe0\xb7\xea\x54\xb9\x45\xee\xb7\xa2\x14\x85\x58\x6c\xba\xfb\x3a\xe0\x29\x66\xa5\x31\xc3\xa7\xae\xa9\x0b\xaa\x9a\xa9\x91\x05\x90\x86\x06\x0e\xef\xb7\x0e\x5f\xca\x5d\xd8\xa1\x2f\x35\x12\x9c\x72\x17\x8e\xa0\x14\x09\x4e\x91\x60\x3f\x4a\x91\xe0\x03\x94\x22\xc1\x29\x12\x7c\x04\xa5\x48\x70\x87\x52\x24\x38\x45\x82\xfd\x28\x45\x82\x9f\x7a\x74\x2d\x45\x82\x53\x24\x38\x45\x82\x53\x24\x38\x45\x82\x3d\xe9\xe7\x1c\x09\x86\x94\xbb\x90\x72\x17\x8e\xa2\xe4\xb1\x4a\x1e\x2b\x3f\x4a\x1e\xab\x03\x94\x3c\x56\xc9\x63\x75\x04\x25\x8f\x55\x87\x92\xc7\x2a\x79\xac\xfc\x28\x79\xac\x9e\xba\x17\x20\x79\xac\x92\xc7\x2a\x79\xac\x92\xc7\x2a\x79\xac\x3c\xe9\xe7\xe7\xb1\x2a\x45\x1e\xb9\x21\x47\x29\xf2\x88\xfd\x38\x2c\xfa\x38\x13\x93\x42\x64\x75\x3f\xee\xd1\x5c\xcd\x90\x6c\x56\x02\x28\xb2\xb2\x45\xd2\xcf\xe1\xef\x82\x53\x5b\xd4\x1e\xc8\x78\x9e\x08\xb5\x16\x7a\x49\xa5\x61\x7f\xaa\xce\x46\x97\xa7\x4e\xfd\x42\xc6\x0f\x3b\xf5\x0b\x49\xfd\x42\x52\xbf\x90\xd4\x2f\xe4\x8b\xeb\x17\xb2\x24\x6a\x7c\x3b\xde\x9a\xd0\x60\x6d\x1a\x4c\xc4\xc9\xde\xeb\x28\xfe\x5b\x2a\x57\xff\x63\xa7\x7b\x88\xe7\xf6\xef\x75\x1c\xf9\xd9\x75\x0f\x31\xa2\xcd\x89\x0c\xb3\x7f\x02\x7a\x7d\xd8\xbd\x61\xd7\x34\x77\xb9\x9e\x34\xbf\xee\xaf\x8a\x27\x73\x1b\x77\xc3\xc9\x27\x79\x4e\x73\x28\xa9\x9c\x58\x89\x2c\xbc\x59\xf2\x7c\x60\x25\xeb\x1d\xe3\xb7\x59\x3e\x7b\x67\x8e\x08\xb3\xfd\xb9\xdb\x73\xf4\x5f\x21\x52\xee\x4f\x37\xd9\xca\x37\x29\xd3\x52\x63\x50\x6d\x37\xeb\x08\xe0\xd9\x18\x00\x4f\xb0\x59\x47\x78\x4c\x6e\x02\xda\x25\x1b\xfd\x29\x20\x2a\x17\x27\x8c\x86\x41\xaa\x3a\x9d\x28\x2e\x86\x01\xc3\x5f\x7f\xab\xa8\x0c\xbd\x49\x8b\x35\x95\x6d\x28\xa4\x36\x8e\x54\xa8\xb3\x90\xb9\xb6\xfd\x19\x51\xf6\xa6\x11\x03\xc6\x10\x21\xec\x1b\x2f\x3e\x1a\x37\xab\x0a\xb6\xd7\x78\x9b\x7d\x0c\x87\x89\x02\x52\xa3\x5f\xec\x0e\x8a\xc0\x74\x10\x02\x13\xc3\x59\x14\x31\x2b\xb1\xa6\x36\x2b\x31\x1c\x26\x11\xd1\x95\x15\xcd\x91\x35\x24\x24\xa2\xf8\xc7\x1e\x05\x64\x03\xdb\x40\x9b\x48\xf1\x09\xa2\x1b\xb0\x4d\x44\x07\xfd\xb9\x8d\x45\xc7\x09\xa2\xc4\x06\xed\xc0\x00\x70\x27\x0a\xd3\x3b\xba\x89\x08\xde\x81\xb8\x00\x1e\x88\x08\xe2\x81\x48\x40\x1e\x88\x09\xe6\x81\xc8\x80\x1e\x88\x07\xea\x81\x6d\x71\x13\x67\xea\x2c\x39\x6f\x55\x3c\xf9\x05\x6e\x2b\xe3\x19\x89\x75\x36\xa0\x2b\x18\x63\xe2\x85\x20\x1a\x66\x08\x62\x43\x28\x20\x32\x76\x08\xb6\xb7\x51\x54\x91\x08\x36\xcc\x16\x13\x90\x04\x8f\x09\x4a\x82\x3e\x30\x29\x1a\xcf\x1a\x06\x82\xe0\xa4\x68\x5c\xe3\x82\x9c\xe0\x71\x80\x4e\xd0\x80\x9d\x8c\x1e\x8b\xc6\x32\x3e\x6e\xea\x11\x0e\x6a\x3c\xbc\x13\x6c\x1f\x53\xcb\x3a\xa6\xc0\x27\x3c\x22\x9e\x04\xac\x8b\x30\xe2\x5c\x42\x0f\x4d\x15\xef\xb4\xc7\x86\xa8\x80\x9d\xcd\x2b\xde\xa2\xaa\xa2\x0e\x36\xf2\xc2\x47\x46\xbd\xc0\xa3\xa0\xb4\xe0\x91\xe0\x44\xd0\x45\x6b\xc5\xdb\xf7\x8f\x81\xfa\x82\x2f\x69\xf9\x23\x2f\x7d\x0b\xfd\x89\xb9\xea\x35\xfc\x27\x1a\x4f\x0b\x23\xea\x42\x80\xa2\xb1\x46\x28\x51\x3c\x18\x10\x44\x87\x02\x41\x5c\x38\x10\xc4\xd5\xc6\xe8\xca\x7b\x8b\xe5\x87\x1e\xc3\x49\x68\x39\xc7\xf2\x0f\xae\x48\x69\x54\xe7\xff\xbd\xa3\x9b\x73\x3c\xed\xff\x2f\xc6\x25\x96\x30\xa9\xa6\x70\x19\x0f\x8f\xd8\x19\x5f\x78\xc5\xd4\x9a\x3a\xd3\x69\xe6\x21\xce\x94\xd2\xbf\x55\x6c\x4d\x0a\xca\xb5\x7f\xf8\xb0\x4b\x84\xd7\x71\x7b\xb3\x4e\xdb\x6e\xe2\x18\xe2\xfe\x7e\x29\x14\xe6\x7d\xd9\x48\x68\x9c\x69\x78\x76\x47\x37\xcf\xce\x63\x2b\x51\xc3\xf8\x8a\x3f\xb3\x29\x07\x71\x36\x41\x0f\x8f\x1b\xd1\x91\x28\x78\xb1\x81\x67\xc8\xfd\x59\x58\xb9\xc4\x96\x7a\xc8\x16\x22\x63\xb0\x8c\xea\x1f\x8f\xe4\xe6\x23\x79\xce\x8c\xc0\x23\xc5\x75\x54\x6f\x58\x24\x19\xcf\xc9\x8a\xaa\x92\x64\xa1\x83\xea\x89\xf6\x96\x69\xe0\x8b\xd6\x50\x3a\xe5\x70\x30\xd1\x18\x37\x2e\xba\x9b\xb8\x4e\x30\x2d\xe0\xb4\x06\xeb\x90\x85\x39\x7d\xfa\xec\x7f\x04\xf2\xec\xd5\xe2\xb4\x31\xb0\x15\x25\xc1\xe7\xfa\x19\xc6\x38\x4b\x91\x9f\xa8\x76\x5e\xfd\x80\x4f\x35\x3d\xa9\x84\xed\x48\x07\xa4\x13\x91\x8f\x78\x42\x6e\xdd\xdc\x87\x9e\x8f\xa5\xa8\x8a\xdc\xdc\x1b\x1a\x98\x74\x28\xcb\xd3\x1a\xb6\x71\x66\xf6\x1c\x17\x3a\x26\x6b\xae\xd9\xa4\xe5\xef\x0d\x35\x6b\xc9\x95\x0e\x57\xbd\x02\xf7\x81\x3c\xfb\x72\x21\x8a\x81\xd6\x42\x82\x5b\x09\x16\x6a\xed\xdc\x2f\xa9\xec\xae\x7b\x78\x6e\x47\x4e\xe7\x8c\xd3\x1c\x88\x02\x59\x71\x6e\x66\x53\x84\x66\xc9\x39\xb4\xb2\x35\xcb\xd0\x80\x08\x77\x0e\x37\xc2\xdb\xc2\x81\x30\x38\x12\x01\x37\x63\xa9\x85\x5a\x12\x34\x52\x09\x0f\xe5\x88\x13\x20\xb8\x53\x61\x84\x6f\xe2\xcc\x80\x0d\xdf\xd0\xdc\xee\xff\xe0\xc5\x77\x2b\x3e\x85\x37\xa8\x66\xe2\x4d\x28\x53\x28\x45\x48\x51\x88\xfb\x50\xeb\xec\xa9\xf5\xe9\xb8\xff\x22\xfa\x74\x6c\x01\x05\x53\x9b\x8e\x96\x52\x9b\x8e\x5d\x4a\x6d\x3a\xbe\xe8\x36\x1d\xde\x6b\x64\x55\xea\x9e\x7e\x1d\x5e\x1c\x6d\x8f\x8f\x87\xfa\x75\xf8\x4d\xa8\xdd\x88\x5b\xfd\x3a\xe0\xcf\x4b\x8a\x72\xcd\xd3\x95\x60\x8e\xcc\xaa\x2a\x34\x2b\x8b\x36\xbb\xc4\x4e\x43\xe1\x1d\xe4\x70\x1d\x27\xd4\x16\x5e\xd9\xcc\x04\xf1\x4c\x44\xde\x92\xe6\x38\x6e\x4c\x42\x56\x68\x0e\xf8\x99\x95\x98\x02\x45\x8a\xc2\xb5\xb3\xa8\x73\xda\x6d\x7e\x1c\xfb\x92\xd3\x36\x5e\xa3\x51\xab\x42\x81\x09\x68\x64\x9d\x1a\xeb\xbd\x30\x62\xc1\x58\xb3\xb5\xae\xf6\xe4\xb8\xeb\x82\xb0\x98\x8c\x75\x40\xaa\x06\xa6\xc6\xb1\x35\xe5\xed\x3d\xe3\x54\x9d\x9d\x85\xd4\x19\xaa\xbd\x04\x31\xef\x9a\x8f\x70\xc7\x1c\xba\x5b\x9e\xdb\x3b\x92\x27\xc7\xde\xcd\x6a\xe0\x6e\xe4\xc9\x56\xf0\xe1\x3b\x51\x80\x45\xb6\x75\x17\xfa\x43\xc7\x76\xff\x5f\x9e\x2c\x07\x6e\x41\xf5\x3d\xc6\xd7\xee\xb6\xb7\x1f\xdc\x4a\x75\x6a\xa4\xc5\xed\x7b\xe7\xc6\xd9\x58\x64\xc0\x6a\x7c\xf6\x2c\xa4\xd0\x5b\x56\x38\xc0\x32\x52\x9a\xc7\xa3\xa4\x78\x3c\x42\x7a\x47\xc4\xd4\x8e\x7f\x8e\x26\x39\x91\x53\x39\x76\xd3\x38\x62\x21\xe8\x7b\x29\x1c\xb1\x13\x30\x22\x25\x5f\x3c\x29\xff\xf8\xa3\x24\x5c\xa4\x8a\xa6\xa9\xa2\xa9\x1f\xa5\x8a\xa6\x07\xe8\x31\x2a\x9a\xc6\x4a\x7c\xe8\x26\x3d\x44\x63\x5a\x27\x3c\xc4\xcd\xb1\x72\x71\xde\x7f\xaa\xc2\xa6\x51\x91\x9f\x6d\x52\x42\x9d\x4c\x10\x89\x6d\x9b\x90\x10\x07\x6c\x04\xa9\x4a\x2a\x26\x0e\x44\x07\xfc\x7f\x09\x85\x4d\x23\x82\x7d\x3b\x00\xff\x58\x89\x2d\x76\xee\xa2\x6e\xcb\x47\xaa\x19\x19\x1d\x8c\xff\xa8\x35\x38\x53\x89\xd3\x2f\xa5\xc4\x69\xaa\x49\x19\x4d\x10\xff\x9c\x6a\x52\xf6\x29\x1a\xf8\xfc\x91\x80\xe7\x8f\x03\x3a\xdf\x02\x9c\x47\xe4\xec\x0a\x61\xc6\x85\x8a\x6f\xc3\xc4\x81\x84\x62\x86\x1e\x11\x22\xbe\x05\x0f\x6f\xc1\xdd\x11\x00\x39\xdd\xea\xe2\x08\xec\x0e\x75\x3a\xb9\xb2\x5b\x11\xc5\x79\xe3\xf6\xe8\x01\xba\x03\x99\x6e\xfb\xda\x22\x80\xb9\xa3\xf9\xda\x22\xb8\x26\x1e\x03\xc0\x1d\x41\x3e\xc6\x00\x6e\xef\x01\x6d\xb7\xb0\xeb\x10\x38\xd3\x16\x60\x7b\x37\xde\x19\xc0\xbc\xbd\xc4\xc7\x85\x5b\x3f\x02\xd4\x3a\x32\xcc\x3a\x86\xca\x0f\x56\xf4\x11\xb6\x6f\x14\x58\xf5\x20\xa4\xda\x05\xaa\x03\x5e\xaf\x17\xe2\xee\x04\xab\x43\x42\x59\xdb\x61\xee\xed\x80\x75\x28\x70\x30\x36\x10\x7a\x08\x04\xdd\x62\xa3\x42\x8e\x58\x0b\x80\xde\x81\x30\x87\x04\xf6\x86\x42\xf4\x61\xf0\xe5\xd8\x61\x7a\xd8\x0d\xd5\xc7\x41\xd9\xee\x0b\xd6\x87\xec\xd7\x3e\x5c\xb9\x07\x38\x0e\x60\xeb\xa0\xca\x8f\x03\x36\x8e\x05\x34\x0e\x2a\xa8\xcf\x35\x7b\x8c\xa2\xfa\x5d\x59\x31\xfa\xc5\xf6\x54\xd6\x27\x6b\xc1\x72\x28\x2b\xad\x7d\xc4\x78\x83\x0b\x7a\xa8\xba\xfe\x68\xae\x44\xa5\xea\xfa\x0f\xd0\x17\x5c\x5d\x3f\x68\x07\x43\xbf\xbe\xf8\x2e\x48\xd7\x8b\x63\xaf\x2c\xff\x6e\x89\x7d\xff\x17\xaf\xcb\xf2\x0f\x94\xd8\x0f\x7d\xf5\xe9\x4e\x89\x7d\x2f\x8e\x5b\xa5\x9c\xb7\x4a\xec\x7b\xbe\x79\xbf\x2c\xff\x4e\x89\x7d\xbf\x35\xea\x96\xe5\xdf\x2d\xb1\xef\x3d\xd2\xae\x4c\x1c\x2c\xb1\xef\x8d\x07\xa3\x4a\x9f\xef\xcd\x2b\xf0\xe2\xda\x3b\x3b\x43\x75\xf6\xbd\xb8\x36\xb5\xf9\xf7\xd6\xd9\xf7\x9e\xdc\x1a\x3d\xbd\x5b\x67\xdf\xef\xfd\xfb\xb5\xf9\xfb\x75\xf6\xbd\x07\xd9\xab\xcd\xdf\xaf\xb3\xef\xcd\xb3\x8f\xf2\xde\xae\xb3\x1f\x34\xd4\xba\x36\xff\x76\x9d\x7d\xbf\x19\x4d\xb5\xf9\x87\x29\xd5\xe6\x7f\x02\xa8\xd8\x54\x9b\xbf\xa5\x54\x9b\x3f\xd5\xe6\xdf\xa1\x54\x9b\x3f\xd5\xe6\x1f\x41\xa9\x36\x7f\x97\x52\x6d\xfe\xd1\x94\x6a\xf3\xa7\xda\xfc\xa9\x36\xbf\x37\xa5\xda\xfc\xe3\x28\xd5\xe6\x4f\xb5\xf9\x23\x50\xaa\xcd\xdf\xa5\x54\x9b\x3f\xd5\xe6\x4f\xb5\xf9\x23\x50\xaa\xcd\x9f\x6a\xf3\xa7\xda\xfc\xa9\x36\x7f\x30\xa5\xda\xfc\xa9\x36\x7f\x10\xa5\xda\xfc\xa9\x36\x7f\xaa\xcd\x9f\x6a\xf3\xa7\xda\xfc\x9e\x94\x6a\xf3\x07\x50\xaa\xcd\x9f\x6a\xf3\x87\x0d\x26\xd5\xe6\x1f\x49\xa9\x36\x7f\xaa\xcd\x9f\x6a\xf3\xa7\xda\xfc\xa9\x36\xff\x30\xa5\xda\xfc\xa9\x36\xff\x18\x1a\xac\xcd\x1f\x9c\xa8\xd2\xbb\x3c\x45\xcc\x54\xa9\x8b\xfa\xef\x16\xe8\xf7\xe2\xd9\x2b\xea\x3f\x5c\xa0\xdf\x8b\x6f\x5d\xd4\x7f\xab\x40\xff\xd3\x9d\x56\xac\xec\xbf\x5b\xa5\xdf\x8b\x63\xb7\xb2\xff\x50\x95\x7e\x2f\xa6\xdd\xca\xfe\x03\x55\xfa\xbd\x78\xb6\x95\xfd\x1f\xac\xd2\xef\xc5\x1b\x2b\xfb\x3f\x54\xa5\xdf\x6f\xbf\xa2\x4d\xb5\xbf\x4a\xbf\x17\xd3\xc2\x56\x62\xda\x57\xa5\xdf\xef\xf5\x49\xb6\x4c\x55\xfa\x0f\x52\xaa\xd2\x9f\xaa\xf4\xa7\x2a\xfd\xa9\x4a\xff\x41\xfa\xec\xf9\x48\xa9\x4a\xff\x43\x94\xaa\xf4\x1f\x49\xa9\x4a\x7f\xaa\xd2\x3f\x9a\x52\x95\xfe\x54\xa5\x3f\x55\xe9\xdf\xc3\x23\x55\xe9\x1f\x45\xa9\x4a\x7f\xaa\xd2\x1f\xcc\x36\x55\xe9\x4f\x55\xfa\x43\x28\x55\xe9\x4f\x55\xfa\x53\x95\xfe\x54\xa5\x3f\x55\xe9\xf7\xa3\x54\xa5\x7f\x2c\xa5\x2a\xfd\xa9\x4a\xbf\xa5\x54\xa5\x3f\x55\xe9\x1f\x3d\xb8\x54\xa5\xdf\x97\x52\x95\xfe\x54\xa5\x3f\x55\xe9\x77\x94\xaa\xf4\xa7\x2a\xfd\xa9\x4a\xff\x67\xae\xd2\x4f\x2a\x2d\x56\xa2\xe2\xfa\x86\xca\x35\xcb\xe8\x65\x96\x99\x9f\x6e\xc5\x1d\x1d\x05\x20\xed\x47\xe5\x1e\x60\x3a\xea\xf5\x18\xcf\x59\x86\x31\xa4\xfb\x25\xc5\x02\xf8\x04\x94\xe5\x09\xc4\x32\x05\x3d\x9a\x6b\x8b\x08\xc2\xb7\x27\x9a\x65\xa4\x28\x36\x80\x43\x1e\xb7\x02\x76\xce\x67\x42\x14\x74\xc4\xf5\xc1\x99\xb3\x54\x8e\xd2\x66\xbd\x29\x7e\xeb\x62\xd1\x2d\x2b\x98\xd1\x42\xf0\xc5\x58\xd5\xe6\xa0\xa9\xa5\xc8\xa7\xf0\xaa\x65\x96\x11\x8e\x82\xbf\x92\x92\x72\x3d\x12\xf6\x38\xab\xcb\xf9\x62\x40\x75\x25\xd6\x34\xc7\xd0\x36\x22\x15\xad\x4b\x66\x64\x2c\xb4\xa0\xc4\xbc\x2f\xa7\xed\x0b\x1b\xe1\x4e\xe0\x1a\xc7\x6d\x07\x3b\x1b\x27\x39\x2c\x62\xd4\x63\xb9\xc7\x5a\x31\x1e\x76\xcb\x56\x90\xdb\xdd\xa8\xd1\x7c\xcc\x30\xdc\xd0\xce\xc3\x48\x79\x81\xc2\x76\x23\x2a\xb8\x27\xf6\xda\x2b\x2b\x8e\x82\x1d\xa7\xd3\x6c\x83\x71\xdb\xc7\xf7\xba\xe2\x17\x37\x9d\xa0\x1e\x1e\xf5\x15\xff\x58\x26\x91\x0b\x0f\x73\xb3\xb7\x74\x27\x97\x72\x51\xd9\xdb\xa5\x3b\x68\x94\x6b\xb9\x41\x50\xb4\x8f\xa4\x37\x77\xd6\x5c\x64\x77\x66\xfb\xaf\xc8\x82\x9e\x9c\x28\x78\xf5\xee\xb5\xd1\x21\x95\xf2\x52\x71\xcc\x15\xa4\x77\x5a\xa8\x94\x62\xcd\x72\x73\x5e\xbf\x23\x92\x91\x99\x57\x09\x01\x2c\xba\x4d\xb9\xb9\x3d\xfd\xea\xf4\xbb\xcb\x8f\x3f\xbe\xbf\x7c\xf7\xe6\x0c\xa3\x45\xf4\x53\x49\x78\xee\x35\xd2\x4a\xb5\xa9\x26\x6e\xef\x9b\xd7\xa7\x7c\xcd\xa4\xe0\x66\x92\x7d\x66\xf4\x6a\x0e\x04\xd6\xee\x5d\x6b\xb1\x37\xa3\x08\xdb\x2a\xd6\x7e\xb8\x64\x8d\x9e\x05\x37\x07\xb5\x11\xca\x78\x59\x69\xff\xcb\x07\xa6\x23\xcc\x28\x54\x3c\x5b\x12\xbe\x70\x12\xb5\x3b\xbf\x1e\x4c\xd5\x86\x6b\xf2\xc9\xbc\x35\xba\xc9\x55\x46\x4a\x9a\x5b\x33\x8f\x40\x2e\x2a\xbf\xe5\xff\xd5\xaf\xce\x81\xd1\x97\xf0\xab\xce\xe0\xa6\xf0\xc6\x71\x6f\x37\x87\xef\x2c\x70\xba\xa6\x12\x07\xec\x36\xd3\x39\x48\xba\x20\x32\x2f\xa8\xf2\x61\x2a\xe6\x8d\x79\x61\xfd\x56\x6e\x33\xd0\x3a\xde\xe1\xc1\x93\x0b\xdd\xd1\x4b\x8d\xae\x81\x77\x02\x61\xef\x73\xe1\x73\x7b\x5c\x6a\x5d\xaa\x97\x17\x17\x77\xd5\x8c\x4a\x4e\x35\x55\x53\x26\x2e\x72\x91\xa9\x0b\x4d\xd4\x9d\xba\x60\xdc\xc8\xe1\x49\x4e\x34\x99\x74\x94\xc5\x85\xbd\x62\x4c\x32\xb1\x5a\x11\x9e\x4f\x88\x13\x4a\x93\xe6\x20\x5d\xfc\xd2\x99\xb6\x13\xd2\x7c\x8a\xf1\x09\x99\xa8\x25\x2d\x8a\x93\xd1\x63\x0d\xb9\xee\x7b\x5f\xf3\x03\xae\xf7\xee\x9d\x43\xa5\xfd\x9b\x46\xb8\xdb\x77\x9f\xc2\x7b\xe1\xe3\xc5\xb3\x39\x32\xee\x28\xa2\x62\xc6\x75\x98\x76\xe4\xbf\x8f\xa8\xaf\x35\xc6\x9b\xf7\xb7\x1f\xff\x72\xfd\xe1\xea\xfd\x6d\xad\x38\x6a\x35\xe0\xc3\x75\x9f\xe2\x08\x3b\xe9\xfb\x14\x47\xab\x06\x3c\x98\xee\x55\x1c\x7d\x35\xe0\xc3\x79\x57\x71\xf4\xd5\x80\xcf\xcc\xee\x2a\x8e\x01\x35\xe0\x69\x45\x74\xe7\x77\x50\x0d\x78\x49\xe7\x8e\xe2\x18\x56\x03\x1e\x5c\x77\x15\x47\x5f\x0d\x78\x9d\xaf\x5d\xc5\xd1\x51\x03\x9e\x2a\x7f\x57\x71\x74\xd5\x80\x07\xd3\x61\xc5\x91\xd4\xc0\x31\x0f\xf5\x52\x03\x94\xaf\x03\x55\x40\x7d\x2f\xef\x08\x97\x66\x5f\xf8\x88\x41\x2d\x10\x0b\xe6\x44\x41\xb3\x50\x71\x36\xd5\x97\xb1\x9e\xbd\xf9\x7d\xc3\xd7\xdf\x11\xd9\x03\xf3\xf9\xf9\x4a\x87\x16\x08\x1c\x53\x60\x7e\x3c\x49\xeb\x41\xf1\x4f\x3c\xf4\x0e\xfd\x85\x20\x91\x3d\xee\xd5\x96\x42\x91\xc2\xe6\xb1\xbe\x81\x94\xde\xc6\x78\x4f\x56\xb5\x9f\xbb\xbb\xb6\xde\xde\xd4\x7a\x4f\x4c\xe1\x5d\xed\xb2\x82\x57\x3f\x5e\xbd\x7e\xf3\xfe\xf6\xea\xeb\xab\x37\x1f\x7d\xfd\xb4\xc1\x31\x28\xf4\xe8\x47\x99\xb2\x93\x38\x96\x9a\xa5\x87\xed\x35\x7f\xa7\xf6\x12\x4f\xe5\x9a\x89\xaa\x8d\x94\xc4\x5c\x5f\xb5\x23\x5b\xbd\x59\xda\x24\x8a\x4d\xe3\xa1\x8e\x3a\xcc\xe9\xa0\xa7\xc2\x9b\x6f\x54\x43\xd5\xd2\x03\xe6\xaa\x37\xcf\xa8\xde\x0e\x4b\xfb\x7d\x1e\xfe\x0b\x1f\xdb\xe4\xb5\xf4\xa0\xe1\x1b\xb2\xf2\x7b\xcc\x5f\x6f\x96\x0f\x78\x4f\xbc\x79\xd6\xc6\xf3\x6b\x3a\x27\x55\x61\xfd\xa7\xcf\x9e\x4d\xc7\xdb\xa0\x96\xe2\x88\xdd\xaf\xa5\xf0\xee\x5c\xd7\x13\xbd\x37\x98\x12\x8a\xbd\x5c\x43\x02\xb3\x43\x46\xcc\x89\x4b\x0e\xf3\xdf\x77\x1d\xb7\x95\x73\x0d\xd8\x28\x72\x00\xe0\xd5\xf0\x0b\x42\xe1\x46\x80\x45\xc5\x48\x6a\xca\x04\x9f\xb3\xc5\x3b\x52\xfe\x89\x6e\x3e\xd2\x79\x08\x18\xa5\xbf\x1f\x30\x46\xed\x32\x53\x82\x40\x5a\x62\x6e\xcd\x50\x3b\xcc\x10\x2c\x5a\x24\x24\x5a\x8c\x04\xb9\xd0\xe4\xb8\x58\xf9\x6c\x11\x72\xd9\x76\xba\xb4\xc6\x48\x3b\xc3\x5b\xa2\xd9\x41\x71\x12\x23\x23\xa4\xc8\x84\xd8\xf5\x35\xf5\x8d\x55\x67\xe0\x87\xcf\x55\x6b\xec\x68\xeb\x56\x09\x66\x79\xd0\x2d\x93\x09\x9e\xd1\x52\xab\x0b\xb1\x36\xb6\x21\xbd\xbf\xb8\x17\xf2\x8e\xf1\xc5\xc4\xd8\x1d\x13\x7b\xc6\xd4\x05\x62\x8c\x2e\x7e\x89\xff\x09\x1e\xd4\xed\x87\xd7\x1f\x5e\xc2\x65\x9e\x83\x40\xe5\x5c\x29\x3a\xaf\xc2\x33\xa5\x6d\xcb\xde\x29\x90\x92\x7d\x47\xa5\x62\x22\x42\x7e\xcd\x1d\xe3\xf9\x39\x54\x2c\xff\xca\x57\xbd\xd7\x14\x6d\xff\x8a\xd2\x62\x67\xa3\xee\xe1\x1b\xc4\xa1\x85\x1f\xf7\xae\xbd\xd5\x88\xfa\x60\xae\x42\x62\x51\xaa\x3b\xba\xa9\x51\x1a\xc1\x2c\xdd\x85\x2d\xca\xa2\x8e\x05\xd9\x6c\x13\x6e\xdc\x98\x3a\xfb\xa4\x51\xda\x41\xef\x67\x01\xfd\xce\x73\x51\x8a\xfc\x25\xa8\xaa\x2c\x85\x0c\x2c\xfe\xb0\xa2\x9a\xe4\x44\x93\xa9\x91\x26\xe7\xfd\x1f\x11\xc7\x18\x76\x6c\x1b\x7e\x88\x0c\x54\x9d\x07\xa0\xf1\x68\x53\x62\xc3\x1e\xa1\x4a\x9a\x4d\xb9\xc8\xe9\x7b\x7c\x03\xfc\x51\xf5\x00\x65\xf8\x87\xb0\x67\x68\xa2\x2b\x35\x5d\x0a\xa5\xaf\xae\xcf\xeb\x1f\x4b\x91\x5f\x5d\x47\x61\x8c\x9c\x94\xf7\xad\x05\x9e\x9a\x19\x86\x9b\xf5\x9a\x04\x55\x42\x8e\x65\x8c\xb5\x1a\x28\xaa\x90\x76\x3c\xc3\xc5\xa9\x43\x9f\x66\x4b\xba\x22\x51\x3a\x26\x7c\x5d\x4f\x3e\x30\x05\xf7\x92\x69\xed\x59\x38\xb0\x4b\x8c\xbb\xda\x79\x62\x7e\x6e\xe4\x35\x5e\xb6\x63\x18\xa4\xcf\xd6\x2f\x82\x53\x74\xa2\xa9\xf3\x66\xdf\x46\xdd\x2a\xb8\x16\x91\x4c\x52\xab\x06\x1a\x43\x3e\xca\xba\x76\xa1\xef\x70\x79\x7d\x15\xcc\x74\x6d\xcf\xc6\x93\x58\xd6\xba\xae\xd6\xd7\x4f\x54\xaf\xd7\xe3\xab\x05\x41\xe3\x5f\x0e\xdb\x82\x98\x01\xd7\xd4\x14\x83\x82\xad\x58\xe0\x79\x25\x3c\x47\xed\x40\x95\x56\x70\x6a\x19\x4e\xb3\xb2\x0a\x53\x80\x8e\xcf\x8a\xae\x84\xdc\x9c\xd7\x3f\xd2\x72\x49\x57\x54\x92\x62\xa2\xb4\x90\x64\x11\xa8\xbe\xeb\x61\xe3\x70\xdb\x9f\xec\x43\xa3\x4d\xca\xee\xa8\x43\xd2\x5e\x6c\xd5\x8c\x06\x58\x5d\x5b\x7b\x34\xff\xf9\x58\x09\xf5\xf6\x7c\x02\x46\x42\x73\xea\xde\x47\x77\x48\xbc\x0a\x0e\x18\xd5\x84\xce\x92\x66\xee\x61\x1e\xa1\x64\xc3\x5a\x14\xd5\x8a\xaa\xf3\xe6\x22\x1b\x7e\xf1\x17\x12\x28\x5f\xc3\x9a\x48\xf5\x64\xae\xe9\x39\x5b\x33\x15\x5e\x79\x68\xe0\x96\x1e\xa3\xc5\x34\x66\x57\x57\xba\xac\xb4\x2b\xfc\x1e\xcb\xa8\xa4\x9f\x4a\xa1\x30\x32\x14\xa1\xb6\xa4\xa5\xbc\x1b\x67\x79\x11\xd6\x59\x07\x4b\x45\x68\x2a\xf9\x4b\xf8\xaf\xd3\xbf\xfe\xfa\xa7\xc9\xd9\x57\xa7\xa7\xdf\x3f\x9f\xfc\xc7\x0f\xbf\x3e\xfd\xeb\x14\xff\xf1\xaf\x67\x5f\x9d\xfd\x54\xff\xf0\xeb\xb3\xb3\xd3\xd3\xef\xff\xf4\xee\x9b\xdb\xeb\x37\x3f\xb0\xb3\x9f\xbe\xe7\xd5\xea\xce\xfe\xf4\xd3\xe9\xf7\xf4\xcd\x0f\x47\x32\x39\x3b\xfb\xea\x57\x81\x03\x27\x7c\xf3\x21\xc8\x94\x00\x5b\x20\x35\x4a\xb7\x80\x3e\xb7\x28\x85\x8b\x3e\x4d\x5a\xf7\xe4\x84\x71\x3d\x11\x72\x62\x19\xbf\x04\x2d\xab\xb0\x4b\x4a\xbd\x1d\xe3\xca\xd9\x8f\x91\x2a\xec\x75\x4c\xb2\xc6\xcc\x7e\x12\x82\x4c\xd1\x4c\x52\xfd\xb4\x23\x4a\x76\x8c\xf5\xad\x02\xd3\xc2\x83\xe3\x03\xe8\x86\xfa\xb9\xd8\x3c\x29\x40\xf5\x10\x35\xa9\xb8\xb8\x8b\xe2\xdd\x72\xe7\x52\xac\xa6\xd0\x81\x68\xad\xa3\x34\xde\x77\xe3\xbc\xa3\xc1\x55\xa3\x52\x40\xcd\x87\x52\x40\x2d\x8c\x52\x40\x6d\x1c\x75\x03\x6a\x37\x78\xf6\x53\x34\x6d\x88\x28\x5f\xfb\x41\xa0\x06\x31\xf2\xb5\x0f\x4b\x0b\x28\x45\x59\x15\x44\x7b\xe5\x72\x0c\x21\xed\x77\x01\xf3\x1e\x9c\x9d\xf2\x6b\x71\xa7\x6d\x36\x96\xaf\x7b\x63\x35\x8c\x25\x86\xcb\xa2\x00\xc6\x7d\x95\x17\x0e\xb2\xce\x0c\x92\xd4\xba\x93\x80\x60\xfd\x4f\xec\x5c\xe4\xc1\xf3\x7e\x49\xb7\xa6\x10\x98\x02\xa5\x89\xd4\x8c\x7b\xb5\x6d\xfa\xb3\xe1\x88\xe6\x68\x9d\x20\xc3\x78\xdb\xb9\x28\xe0\x22\xdb\x14\x1b\xeb\xb4\xb6\x6b\xab\xcb\x14\x44\xf9\xbc\xbf\xbb\x29\xe0\xac\x6a\x72\x87\x28\xe4\x8c\xe6\x94\x67\x74\x0a\xdf\xf9\x56\x69\xad\x77\xd2\x6c\x63\xd6\xe6\x0d\x5f\x37\x39\x53\x95\x4d\xd3\xf1\xd9\x54\x66\x46\x87\xc7\xf9\xcf\x9b\x24\x62\xc4\x94\x03\x59\xb6\xb9\x22\x5e\x92\x13\xed\xd6\xc6\x93\xdf\x94\x66\x6e\x70\x17\x5e\x59\x3d\x61\x37\x97\xd0\xdb\x42\x83\x62\x0c\xb8\x70\xee\x5c\x13\x9a\x09\x09\xa9\x82\x6d\xaf\x05\x68\xd6\x7b\xf2\x78\x22\x40\xd1\x50\x73\x7d\xd0\x54\x0f\x8e\x22\xf7\xcd\xf4\xa7\x67\x66\x3f\x82\x89\x3d\x60\x5e\x5b\xf3\x38\x88\x6b\xa8\x69\x1d\xc5\xac\x8e\x61\x52\x0f\x99\xd3\x01\x69\xb0\x2d\xf5\xb0\x69\x51\x4c\xe0\x70\xf3\x37\x1c\x48\x56\x4a\x3a\x67\x9f\xa2\xc8\xcc\x4b\xde\x2c\x20\xb0\x9c\x72\xcd\xe6\x2c\x60\xce\x8d\x11\x2d\x69\x49\x39\x82\x08\xb0\xe3\xa2\xb1\x0b\x3c\x33\x19\x61\x7b\x05\x9f\x5c\x1a\x9c\x75\xd1\xc4\x54\x60\x37\xb1\x9c\x53\x49\x7b\x25\xed\x95\xb4\xd7\x21\x7a\xf2\xda\xcb\xc9\x83\xfa\xca\xfe\x79\xd5\x0f\xd6\x6e\x09\x2d\x4f\xf3\xba\x53\x39\x0c\xcf\xb8\xb7\xbb\xf6\xf8\xb3\xd7\x16\x28\xbc\xc0\xe7\xfa\x1c\x31\x2c\x91\xdb\x14\x3e\x6f\xb4\xa6\x16\xb6\x68\xa6\x07\xc7\x25\x5b\x98\x13\x5a\xd0\x35\x2d\xdc\x75\x08\x56\x84\x93\x85\xad\xe0\xee\x75\x83\x71\x11\x74\x10\x12\x3b\x40\x4a\x96\xf7\x9c\x27\xbe\x2f\xcf\x38\x18\xb1\x55\x08\x92\x23\x3b\x29\x8a\x82\x4a\x05\x05\xbb\xa3\xf0\x9a\x96\x85\xd8\xf8\xb6\x0a\x24\x3c\x87\x1b\x4d\xb4\x11\x53\x37\x54\xfb\xe0\x94\x03\x44\x01\xce\xc8\x75\x55\x14\xd7\xa2\x60\x99\x47\xdc\xaa\xbf\xb9\xaf\x70\x57\x97\x55\x51\x40\x89\x0c\xa7\xf0\x81\xfb\xec\x6d\x31\x87\xcb\xe2\x9e\x6c\xd4\x39\xbc\xa7\x6b\x2a\xcf\xe1\x6a\xfe\x5e\xe8\x6b\xeb\x44\xf0\x31\x78\xba\x39\xac\x96\x35\xb0\x39\xbc\xc4\xee\x78\x1a\x34\xf1\x11\xa2\xac\xd3\xf2\xfd\xdc\xec\xb9\xee\x20\xad\x02\xba\x67\xca\x2b\x0b\xf4\xc1\xb2\x65\x7e\x87\xfe\x97\xc8\xc9\xa8\x5e\xfb\xf3\x3f\x74\xa3\x15\x6c\x4e\xb3\x4d\x56\x84\xca\xcf\xcb\x0c\xb3\x1a\xda\x06\x6f\xad\xc4\xf0\x71\x30\xda\x7e\xf3\xae\x18\x2d\xba\xee\x18\x07\xdb\x6c\x5d\x79\xf6\xd2\x6e\xc5\x4d\xf3\xce\xd6\x01\xac\x3e\xab\x2f\xd0\xd3\x9e\x0d\xb3\x64\x4b\xa1\xf4\x8d\x26\x52\x47\x68\xc6\x7e\x72\x5d\x33\x03\x6c\xc2\x5b\x14\xde\x86\x00\x5b\xad\x68\xce\x88\xa6\xc5\x06\xc8\x5c\x63\x49\xe3\xd0\xd2\x13\x66\x4c\x92\xda\x93\xea\x7a\x3f\x2d\x09\xcf\x0b\x2a\x61\x4e\x58\xe1\x8d\x0e\xdb\x71\xff\x6b\x2a\x57\x8c\x07\x94\x3c\xb7\xb0\x5a\x8c\x22\xd0\x1c\x4b\x38\xcb\x1c\xcb\xb9\x09\xf0\x87\x31\x3b\x86\xad\xd8\x47\xeb\x3b\xe8\x70\x42\x8b\x59\x68\x27\x60\x56\x88\xec\x4e\x41\xc5\x35\xf3\xb5\xea\x71\x69\x84\xb8\x83\x4c\xac\xca\x02\x85\x67\x58\x49\x48\x78\xb8\x2c\xe4\x90\x44\x6e\xfe\x39\x69\x84\xc4\xc4\x8c\x49\x5d\xfc\xb2\xfd\x13\xfe\xc2\xef\x8e\x10\x7c\x87\x0d\xbf\xc1\xd2\x4f\x34\x8b\xd4\x9e\xe1\x03\xa7\xb8\x6b\x05\x1f\x59\x04\xbb\x4f\x82\x37\x89\x00\x73\x61\x8c\x56\xb3\xeb\x63\x74\x7c\x68\x8c\x80\x29\xbc\xf9\x44\xb3\x28\x3d\x50\xcc\x28\x09\x2a\x3b\xac\x5a\x4c\xee\x02\x8a\x49\x3c\xa1\x76\xe3\xde\x45\x3e\xbb\xd4\xdb\x1c\xaf\x2c\xc7\xf0\x56\x70\x56\xd0\x58\x66\x05\xe3\x9e\xea\xbf\x4b\xae\x84\x28\x30\xae\xcc\x45\xa4\x27\xc9\x62\x74\x8d\x72\xae\x14\xc8\x99\xc4\x5e\x1b\xa1\x20\x0c\x57\x0a\xa5\x99\x85\xf0\x39\x95\x42\x68\x38\x3d\xb9\x38\x39\xdb\x41\x03\x04\xf7\x7e\x9d\xb3\x82\x5a\x03\xce\x16\x26\x72\xa3\x0e\xe4\x6a\x6c\x7a\xb6\x2a\x8b\x0d\xae\xde\x49\x7e\x0e\x2c\x14\x88\xe2\xaa\xb3\xca\x8a\xd7\x3b\x21\xb4\x63\x38\x96\x82\x3c\x07\x25\x40\x4b\x52\xb7\x98\x8a\xc1\xd3\x0c\x50\xcb\xca\x19\xd9\xa7\x27\x3f\x9d\x84\xee\x53\xaa\xb3\x33\xb8\x17\xfc\x44\xe3\x76\x9d\xc2\x6d\xe8\xa9\xaa\x14\xad\x8b\xf1\x9e\x63\x15\x7d\x4e\xc3\x01\x39\x02\xe8\xa7\xb2\x60\x19\xd3\xc5\x06\x8d\x4b\x10\x55\xe8\xba\x63\xb5\x79\xa2\xeb\xba\xc1\x6f\x3e\x05\xef\x24\x9b\xd1\x6c\x94\xd8\x73\x34\x05\xad\xc1\x19\xc8\x94\x28\x28\xd8\x9a\x5e\x2c\x29\x29\xf4\x72\x03\xe1\x67\x88\x0b\x3e\xf9\x3b\x95\x02\x2b\x1b\x73\xc7\x37\x46\x4b\xb6\xf0\x3e\x76\x51\x1a\x55\x46\xf0\xbd\x1a\x7b\xf1\x1b\xea\x79\x2f\x82\x6d\x1d\xf8\xc7\xdb\xdb\xeb\x6f\xa8\x8e\x66\x78\x98\xd1\xd5\xa9\x77\x18\xd5\xa2\x72\x2e\xe4\xea\x33\x5b\x20\xe1\x20\xf1\x09\x94\x42\x7e\x6e\x13\x68\x29\x54\xc0\xba\xc3\xce\xda\x0b\xa5\x7d\x2b\x87\x76\x49\x0b\xa3\x9b\x39\xcd\xcc\x8a\x47\x4b\x43\x6f\x5b\xdb\xc0\xd5\xf5\x14\xfe\x22\x2a\x33\x8b\x33\x32\x0b\xb2\xe4\x0d\xd5\xbd\x53\x14\xd5\xf0\xcc\x4c\xc2\xb3\x90\x40\xab\x25\xb3\xef\xff\x48\x49\x4e\xa5\x42\x4d\x48\x49\x94\x4e\x92\xc1\xd0\xdd\xce\xb8\x62\x5a\xce\x95\xd2\x62\x05\x4b\xcb\x38\x7c\xa1\x3b\x45\x92\x9d\xec\x08\x45\xee\x1b\xb9\x66\xe3\x0b\x0a\x24\x2d\x63\x68\x3b\xf7\xb6\x3f\x23\x6d\xb4\xa3\x09\xec\x4e\x09\xe4\x5a\xf3\x9d\x51\x05\x04\x32\xdc\x2a\xc1\x2c\xed\xe4\x9b\xbd\xe2\x0a\x1b\x06\x73\x64\xdc\x6e\x12\x23\x54\x82\xf3\x0b\xa2\xf5\x7d\x8d\x93\xd0\x04\x21\x45\xa1\xfb\x4c\x10\x9a\x1b\xc8\x25\x56\x7e\x14\x44\xca\xa4\x81\x01\x00\x49\x04\x96\xcd\x2e\xb5\xc1\xce\x08\xd3\x0f\x31\x73\x38\x20\xb4\xfc\x74\x97\x1e\x7f\xfa\x62\x6c\x3c\x88\x37\x7f\x65\x70\xf9\x99\xdd\xe2\x33\x5a\x00\xc9\x32\xbf\xb6\x47\x5d\x12\x56\x75\xa2\x38\x53\x54\xae\xfd\x12\x26\x5a\x8a\x35\x65\xc2\x37\x7c\x53\xd3\x40\x8d\x78\x09\xbc\x5a\xcd\x82\x95\x54\x53\xb1\x4d\xea\xd8\xcb\xd0\x69\xf3\xf0\x3e\xc6\x50\x6b\x08\x4b\x6d\x20\x11\xbe\x08\x3d\x17\x2f\xcc\x3b\xff\xfe\x77\xbf\xfb\xed\xef\xa6\x76\x5a\xcd\x33\x02\x79\xce\x28\x10\x0e\x57\x97\xef\x2f\x7f\xbc\xf9\xee\x15\x56\xcf\x0e\xdb\x85\x11\x92\xf9\x63\xa6\xf2\x47\x4c\xe4\x7f\xc4\x34\x7e\x2c\x58\x16\x28\xe1\xfb\xb8\x2c\x64\x18\xee\xd1\xae\x94\x2d\x98\xed\x6e\x8a\x36\x6c\x18\xc1\x93\x6d\xee\xc4\xbd\x3a\xe3\x11\x2e\x0e\x9f\x5d\x7a\xea\xac\xbc\x11\xd9\x5d\x34\x2f\xcf\xc9\xed\xab\x6b\xcb\x30\x8a\xa3\x87\xf0\x3a\xc0\xc4\xf8\x5a\x14\x6b\xb3\x98\x04\x6e\x5f\x5d\x07\x2a\x8b\xa9\xe1\x81\x11\x56\xeb\xf7\xde\x04\x65\x72\x36\xa5\x99\x1c\xb4\x93\xad\xca\x22\x24\xa2\x0c\xd8\x2b\x40\x52\x52\x30\xa5\x59\x86\x63\x6d\x62\xb0\x41\x5e\x1d\x71\xe7\x8f\xe7\x4c\xfe\xb1\x96\x22\xfb\xc7\x4e\x3e\x44\xca\x7a\x6e\x1c\x6d\x1d\x57\x59\xb0\xd3\xe4\xbc\x57\xf4\x27\xbc\x42\xa5\x73\xb4\x85\xa5\x9c\x3f\x51\xcb\x11\xcd\x30\xbf\x56\xa0\x5d\xe2\x9d\x2e\x45\xce\x72\x0c\x8d\xa0\xa0\xdd\xb9\x6b\x39\x06\xb2\x75\x2f\xdc\xb7\x1c\x43\xfd\x12\xc6\xee\xdc\xb1\x1c\x23\xd9\xb6\xc9\x72\x3c\x8e\x1e\xc1\x72\x2c\x25\xbd\xd1\xa2\x8c\x82\xb3\xb3\xac\xa2\xa2\xec\x66\x74\x2e\x24\x8d\x03\xb3\x6b\x01\x70\x90\x57\x28\x8c\x09\x0f\xa8\xac\x5a\x87\xb9\x44\x17\xae\xe6\x9d\xb2\x0f\x68\xb2\x64\xcb\x3a\xaa\xca\xa9\x52\x17\x08\x8d\xab\x4a\xeb\xa4\xf4\x64\x3a\x27\xac\xa8\x24\x3d\x37\x2b\x4d\x57\xb8\x56\xe7\xa1\x45\x1e\xcd\x62\x50\x6e\x59\x51\x9d\x59\x18\x85\x43\x2d\xfa\xaf\x8f\xb1\xf9\xec\xc6\xb1\x1d\x6d\xc3\xdb\x7a\x65\x92\xa8\x25\xc5\x66\x9e\xf4\x13\xd3\xca\x0e\x54\x52\xa2\xbc\x6b\x44\x23\xd4\xc5\x6d\x24\x34\x81\x15\x94\x44\x29\x9a\xfb\x6b\x83\x0e\xe4\xd3\x0e\xf0\x5a\xe4\x27\x27\xaa\xfb\x18\x4f\xce\x0b\x49\x32\x0a\x25\x95\x4c\xe4\x80\x55\xd7\x73\x71\xcf\x61\x46\x17\x8c\xfb\xde\x00\xdc\x89\x34\x83\xae\x0f\xbc\x31\x61\x69\x00\x90\xaa\xee\x98\x3c\x85\x8f\xbd\x8e\xae\xfe\x5a\x4b\x54\x3a\x13\xad\xb6\x76\xb3\x7b\x1e\xc0\xb1\x45\x92\x62\xb5\x06\x3c\xe6\x15\x29\x8a\x4d\x2b\x56\x3c\x39\xbb\xc2\x24\xfa\xb1\x16\xfe\x0b\xc3\xd4\x9a\xc3\x1a\xca\xb1\x7b\x40\xbb\x53\xe1\x2f\x9b\x24\x25\xd9\x32\x2c\x99\x22\x41\x77\x0f\x50\x82\xee\x26\xe8\xee\x5e\x4a\xd0\xdd\x04\xdd\x4d\xd0\xdd\x04\xdd\x4d\xd0\xdd\x04\xdd\x1d\x49\x09\xba\x7b\x88\x12\x74\x77\x2f\x3d\xc9\xd0\x44\x82\xee\x26\xe8\xee\xd1\x94\xa0\xbb\x09\xba\x3b\x8e\x6f\x82\xee\x7a\x51\x82\xee\x3e\x48\x09\xba\x1b\x42\x09\xba\xeb\x4b\x09\xba\x3b\x9a\x12\x74\x37\x41\x77\x03\x28\x01\x30\x3c\x28\x41\x77\x23\x5c\x1c\x3e\xbb\xf4\x4c\xd0\xdd\x04\xdd\x3d\x92\x92\x7f\xac\xa5\x04\xdd\x0d\xa0\x04\xdd\x3d\x48\x09\xba\x9b\xa0\xbb\x01\xbc\x9e\x9e\xe5\x58\x43\x44\xaf\xa5\x98\x05\x97\x96\xbe\x46\x70\x14\xcb\xac\x47\xcd\x9c\x93\x10\xe0\x65\x3d\xb4\x29\xbc\xea\x63\xe6\xb0\xbf\x95\x2b\x1f\xe9\xc1\xd7\x61\x42\xed\x18\xb1\x34\xe6\x74\xa0\xda\xad\x07\xe3\x91\x90\xae\xba\xa0\xb3\xba\x28\x85\xfd\xbf\x16\xd0\xd5\x41\x72\x59\xef\xa4\x6f\xad\xdc\xcf\x52\x75\xd5\x1f\xbe\xb5\x17\xba\x05\xc2\xab\x8c\x33\xb4\x17\xfd\x6d\xd8\x56\x1f\x7c\xe5\xc9\xbb\x0f\xd9\xea\x03\xaf\x7c\x2d\x7f\x6f\xb8\xd6\x13\x00\xee\x05\x43\xb4\xf6\xc0\xb3\x02\xb5\xd7\x16\x34\xab\x06\x57\x05\x70\x1c\x84\x65\x05\x8e\x72\x07\x92\x55\x83\xaa\x22\xbc\x39\x62\x4f\xbb\x80\xaa\xc0\x28\x7f\x07\x8a\xd5\x05\x53\x05\x70\xed\xc0\xb0\x76\x81\x54\x21\x2b\xa5\x87\x40\x54\x0e\x03\x14\x72\xb9\xec\x01\xa8\x06\x20\x50\x01\xbc\x11\x3c\x15\x19\xfe\x34\x08\x7d\x0a\xb3\x5f\x07\x60\x4f\x35\x70\x29\x64\x62\x5b\xc8\x53\x17\xb4\x14\xb2\x05\x1a\xb8\xd3\x36\x60\x29\xc8\x05\x92\xc7\x06\x2b\xc5\x08\x0d\x07\x87\x85\x03\x2d\x55\x97\x26\x74\xbb\x94\x54\x2d\x45\xe1\xa9\x0a\x7a\x6a\xe0\x1d\xe3\x6c\x55\xad\x8c\xcc\x51\x46\x6e\xb3\x75\x60\x0e\x93\x6a\xd0\xaa\xd6\x08\xc4\x98\xb2\xb7\xc6\x43\x89\x22\x69\x8e\xdc\xcd\x16\xc3\x82\xee\x4b\xb2\xf6\x37\xf5\x55\x95\x65\x94\xe6\x34\xef\xf9\x35\xe1\xb7\xd3\x7a\x2e\x3c\xf9\xda\x06\xa9\x4c\xc1\x8b\x10\x0b\x23\xe4\x46\x34\x17\x72\x45\x34\xf2\xf8\xed\x6f\x3c\x38\x04\x61\xdf\x1e\x05\xf7\x16\x1d\xf3\x16\x6c\xc6\x85\xf9\xf2\x02\xfc\x78\xe1\xf6\x63\x98\xff\x6e\x18\xdb\x16\xa6\xe3\x86\x70\x6d\x61\x1c\x1f\x01\xd3\x36\x88\x67\xeb\x22\xbf\xc2\x2c\xdd\x30\x2c\x5b\x24\xc4\x6b\x30\x86\xed\x71\xf0\x6b\xc3\xd8\x35\x94\x2e\x21\xc6\x45\x1f\xb7\x16\x8e\x3c\x7b\x12\xa6\xc5\x63\xa0\xcd\x76\x91\x66\x6e\xb2\xc2\xbc\xd8\x0d\xca\x2c\x1e\x4a\x2c\x12\x42\x2c\x06\x3a\x2c\x18\x19\x16\x8e\x0a\x8b\x85\x08\x8b\x81\x06\xdb\xe9\x02\x1a\x61\x07\x41\xdd\xb8\x31\x0a\xbe\x3a\x96\xf7\x38\x0a\xfa\xeb\x71\xa7\x2b\x06\xea\x2b\xc2\x7c\x85\xa1\xbd\x1e\x07\xe9\x15\x13\xe5\x15\x63\x8a\x82\x62\x74\x8f\x83\xec\x1a\x44\x75\x81\x77\xfe\x3b\x6c\xbb\xbb\xa6\xdd\xc8\x5a\x00\xd3\x2d\x34\x57\x37\xaa\x16\xc0\xb5\x41\x72\xc5\x8d\xa8\x05\x46\xd3\x62\x45\xd2\x22\x45\xd1\x1e\x09\x7b\x15\x8a\xbb\x1a\xc6\x5c\x19\x1b\x24\x60\x43\xec\xe0\xad\x5a\xc4\x54\x00\xd7\xae\x4f\x22\x0c\x2d\x15\xb8\xa0\x8c\x33\xcd\x48\xf1\x9a\x16\x64\x73\x43\x33\xc1\x73\x4f\x6b\x62\xab\x57\xb5\x43\x0b\xcc\x41\x59\xa6\x9e\xef\x67\x3d\x41\xfd\x5a\x17\x4b\xa2\xc0\x3f\x76\x09\x6d\xe1\x94\x3a\x3c\xea\x0c\x53\x20\x18\x7c\x34\xf3\xe1\x19\xbe\x84\x27\x17\xc2\x84\x27\xe1\x72\xb2\x25\x3f\xe2\x6d\xaf\x3f\x8a\x7b\x10\x73\x4d\x39\x9c\x32\x5e\xef\xb0\x33\x5f\xef\x53\xe3\x6c\x6a\xfd\x99\x8d\xd3\xd0\x9f\xe7\x8b\xe7\xf5\xc0\x1a\x97\x63\x90\x61\xf6\x25\xbb\x1c\xd1\x19\xab\xd4\xd3\xf4\x68\xbb\xc1\x3d\x96\x4b\xdb\xb1\x9f\x57\x85\x15\x66\xbe\xfe\x1b\x74\x86\x3b\x07\x79\xdf\xa7\xed\xb9\x2d\x00\xde\x39\x33\xe7\x05\xbe\x79\x23\x0d\x09\xcf\xc1\x95\x3b\xf3\xe6\xdc\xdd\xf0\x5f\xf4\xd6\x0d\x44\x11\x3f\x16\x82\x78\x2f\x7a\xd8\x62\x80\x3d\xb9\xee\x20\x87\x5b\xfc\xaf\x2f\xc7\x3e\x6a\xb8\x8b\xfd\x0d\x18\x63\xdb\x95\xd9\x1f\xf7\x9b\x62\x04\x7e\xdf\xdd\x8b\xef\xc5\x70\x41\x80\x49\xbc\x85\xed\x8d\x95\x06\xdf\x4f\x81\x0f\xc5\x88\x3f\x99\xdb\x7e\x8d\xc6\x0d\xf5\x8d\xa5\xdb\x7e\xba\xed\x1f\xa0\x47\xb8\xed\x6b\xb6\xa2\xa2\xd2\x4f\xf6\xc2\x79\xbf\x64\xd9\xb2\x6b\x0b\xb2\x95\xb7\xaa\x16\x95\xde\xb2\xd7\xdc\x10\x23\x42\x11\xd2\xad\x73\x8b\xfc\x62\x1a\x03\x0e\xd5\xf0\xea\xb7\x0d\x42\x16\x88\x02\x02\xaf\xdf\xdf\xfc\xf8\xf6\xf2\x3f\xdf\xbc\x9d\xc2\x1b\x92\x2d\x83\x58\x33\x0e\x04\x35\x1b\x8a\xb0\x25\x59\x53\x20\x50\x71\xf6\xb7\x8a\xfa\xea\x85\xd3\x66\x7c\x67\x51\x30\xdd\x01\x12\xc8\xe8\x24\x0f\xd9\xd0\x5b\xc4\xb7\x4c\x69\xb3\x88\xc8\xcb\xd5\x19\x13\x5e\xfe\xc0\xb9\x14\xab\x6d\xd5\xf6\xc6\x30\xb3\xa6\xb7\xa7\x35\xb7\xa4\x92\xc2\x82\xad\x1d\xf2\xd9\x62\x40\x81\xe4\x01\x55\xe5\x8c\x14\x30\x07\xc7\x5c\x0e\xc8\x0c\x01\x85\x4b\x0a\x9c\x6a\x73\xe8\x1b\x57\xa6\x1f\xba\xb2\x53\xfc\x1b\x2a\x45\xd5\x39\xcc\x2a\x04\x87\x96\x92\xad\x88\x64\x5e\x10\x8c\xce\x80\x49\x31\x85\xf7\xa2\xbe\x1e\x6d\x70\x6a\x7d\xfc\x4d\xc6\x9a\xc1\xa9\x7d\xfd\xe1\xcd\x0d\xbc\xff\x70\x0b\xa5\xc4\x3a\xc1\xbe\xc8\x4a\xe4\x88\x5b\x60\x46\xcd\xa8\xec\x36\xca\xa7\x70\xc9\x37\xbe\x6b\x6f\x95\x0c\x53\x60\xee\x43\x94\x1b\xb6\x2e\x3c\x95\x7b\x3b\x9f\x9e\x3d\x9f\xe2\xff\x9e\x99\x3d\x24\x8d\x29\xd7\xc0\x75\x43\x04\x4d\x9d\x34\x62\xcd\x43\x36\x2b\x68\x7b\x1e\xdc\xce\xf2\xb1\x96\xa2\xc9\x17\x3f\x54\x86\x37\x1a\x63\x0b\x62\xef\xe6\xf5\xda\xec\x11\x49\x4b\x49\x15\xe5\x9e\x77\x16\xd2\x1c\x54\xdc\x71\x28\xe0\x8d\x84\x29\x02\x13\xdb\x02\x6f\xbb\x21\x77\xdd\x49\x3b\xf2\x6b\xbf\x83\x12\x7a\xe1\xed\x3d\xdf\xd7\x2c\x1f\xbc\x7e\xcd\xc3\x32\x76\x1b\x7d\x54\x1f\xfc\x52\xe4\x27\x0a\xae\xfc\x71\x4f\xee\xd4\x4f\xe1\x76\xc9\x54\x7b\xb3\x31\xb6\x22\xf3\x2f\xf7\x84\x7b\xd1\x06\x96\xcf\xe1\x39\xfc\x01\x3e\xc1\x1f\xf0\xf2\xf5\x7b\xdf\x3b\x52\x8c\x0b\x4e\xa8\x6b\xcf\xfa\x41\xae\xae\xa3\xec\x88\x3f\x2f\x89\x46\x7e\x70\x75\x1d\x02\x6e\x9c\x31\x9e\xe3\x56\xa0\x9f\x34\x95\x9c\x14\xf5\xd5\x3c\x6c\xa6\x03\xae\x80\xe6\xa5\x9e\xfc\xc1\xb1\x15\x2c\xae\xe6\xde\x1c\x1b\x2b\xfd\x1c\x74\xef\xe8\x78\x73\xc4\x23\x37\x78\x74\xbc\x59\xda\x23\x07\x57\x73\xf4\xb5\xbd\x77\x9a\x82\xa9\xce\xe8\xfd\xa7\xb4\x79\xeb\x15\xd1\xd9\xb2\xaf\xd6\xfc\x5d\x21\xef\xcc\x91\x68\x4b\xef\x43\x2e\xd0\xb7\x1c\x54\x34\xd8\x0c\xf5\xcb\x16\x3c\x21\x90\xbb\xde\x79\xba\x9a\x6f\xef\x5c\xef\x59\xdd\xe7\x06\x0b\xaa\x48\xec\x2e\xa3\x9d\xc6\x1a\xa5\xc8\xed\xcd\xd7\x9b\xa7\x99\xbc\xbc\x63\x1f\xf5\x2e\xc0\xfe\x9a\xb3\x7b\x71\x76\x15\x9d\x42\x93\x07\xad\xe8\x36\x9a\x21\x23\xdc\x26\x5d\xcf\xa9\x94\x21\x5b\x5f\xc0\x6c\x83\xc8\x35\x96\xd1\xc0\x43\x10\xa0\x13\x4a\x29\xb4\xc8\x84\x77\x51\x8f\x3e\xb8\xcf\x31\xc3\xe9\x0e\x09\x5f\xb5\x11\xcd\x6f\x5f\x5f\x9f\xc3\xed\xab\xeb\x73\x10\x12\x6e\x5e\x85\xe0\x6b\xba\x9e\xbb\x67\xb7\xaf\xae\x9f\x7d\xb6\x49\x87\xfa\x5e\xf8\xd2\xab\x4c\x50\xcf\x8d\x6b\xae\x9c\x93\x15\x29\x27\x77\x74\xe3\x61\x55\x87\xda\xf4\x93\x66\x07\x45\x78\x0d\x3b\xb1\x2b\x52\x8e\xe4\x25\x29\xc9\xd9\x13\xad\xdc\xe0\x4e\x78\x3b\xc6\xed\x12\x0e\x1e\x3c\x51\xfe\xac\xc4\x9a\xe6\xf6\xf2\x5e\x3f\x83\xf2\xbc\x14\xcc\xef\xc6\x9a\x2a\x41\x1c\xa6\x54\x09\xe2\x38\x4a\x95\x20\xfa\x94\x2a\x41\x04\xf0\x4c\x95\x20\x52\x25\x08\x4b\xa9\x12\x44\xaa\x04\xe1\x49\xa9\x12\xc4\xe1\xc1\xa5\x4a\x10\x5f\x2c\xb6\x35\x55\x82\x38\x4c\x09\xe5\x99\x2a\x41\xa4\x4a\x10\x3b\x94\x2a\x41\x7c\x6e\xd3\x22\x55\x82\x48\x95\x20\x6a\x4a\x95\x20\x46\x50\xaa\x04\x31\x8e\x52\x25\x88\x83\xf4\xc4\x72\x43\x52\x25\x88\x94\x1b\x72\x2c\x9f\xa7\x97\x1b\x02\xa9\x12\x84\x1f\xa5\x4a\x10\xe3\x29\x55\x82\x18\x47\xa9\x12\xc4\x78\x9e\xa9\x12\x44\x4b\xa9\x12\x44\xaa\x04\xf1\x85\x6e\xdd\x54\x09\x22\x55\x82\x18\xa6\x14\x23\x48\x95\x20\xc6\x51\xaa\x04\xe1\xcf\x34\xdd\xf6\xfd\xf9\x3c\xbd\xdb\x7e\xaa\x04\x91\x2a\x41\x1c\xa4\x10\xd3\x4d\x52\x25\x2a\x99\xf9\xa8\xc8\xfe\xbe\x7a\x25\x56\x65\xa5\x29\x7c\xac\x19\x36\x7a\xdf\xe3\x9d\x66\x1b\x9b\x70\xd5\x91\x8e\x9f\x03\x36\x9d\x09\x3e\x67\x8b\x4a\x62\xf2\xfd\xc5\x8a\x70\xb2\xa0\x93\xcc\xbe\xe8\xa4\x99\xb9\x49\x33\xca\x8b\x2f\x0a\x3a\x5d\xb0\x15\xf3\xa9\x20\x01\x3b\x6b\xff\x16\x39\xb5\xf1\xd1\x00\x78\xcb\x8a\x7c\xc2\x0b\x11\x59\x89\x8a\x6b\x9b\x27\x80\xf3\xed\xc9\xb3\x59\x25\x1b\xe7\x36\x57\xc2\x76\x13\x04\x40\x04\x9e\xc0\xd6\x81\x18\xc6\x79\x5b\x4b\xe3\x3a\xd8\x5a\x2e\x89\xd6\x54\xf2\x97\xf0\x5f\xa7\x7f\xfd\xf5\x4f\x93\xb3\xaf\x4e\x4f\xbf\x7f\x3e\xf9\x8f\x1f\x7e\x7d\xfa\xd7\x29\xfe\xe3\x5f\xcf\xbe\x3a\xfb\xa9\xfe\xe1\xd7\x67\x67\xa7\xa7\xdf\xff\xe9\xdd\x37\xb7\xd7\x6f\x7e\x60\x67\x3f\x7d\xcf\xab\xd5\x9d\xfd\xe9\xa7\xd3\xef\xe9\x9b\x1f\x8e\x64\x72\x76\xf6\xd5\xaf\xbc\x2f\x87\x01\xe6\x47\x1c\xe3\x23\x8a\xe9\xf1\x08\x86\x87\x43\x97\x44\x11\x0f\x1f\x1d\xaf\x38\x02\xc2\x79\x4c\xe2\x0b\x88\x5a\x5f\x61\x06\x71\x3d\x66\x7f\x27\xa4\x58\x31\xad\x69\x8e\x2e\xa3\x4e\x79\x11\x5f\x1c\x38\xd3\xbd\x66\xdc\x4e\xe4\x62\x82\x91\x37\x04\x9a\xa9\x2e\xae\xba\x93\x29\x2b\xf4\x92\xca\x7b\xe6\x1d\x0f\x32\x17\x24\xde\x7a\x33\x50\x08\x4e\x72\x3a\x67\xdc\xdb\x41\x82\x46\xdc\x68\xfb\x2d\x89\xe1\x24\x86\xc7\x70\x79\x4a\x62\x58\xd1\xac\x92\x4c\x6f\x5e\x09\xae\xe9\x27\x0f\x87\x48\x5f\x0a\xdf\x38\x76\x20\xf0\x37\xbe\x79\x4e\xa5\xc8\xeb\xac\x36\x59\x71\x4c\x5d\x0f\x34\xa9\x8e\x39\xc7\xa5\x28\x58\xb6\xb9\xa8\xa7\x04\x0f\x2c\xfd\xa4\x2f\x1e\xed\x0e\xa0\x89\xba\x6b\xc5\x07\x9d\x98\x9b\x5f\x2b\x25\x76\xc6\xf1\x45\x19\xfe\x68\x09\x5f\x4b\xb6\x66\x05\x5d\xd0\x37\x2a\x23\x05\xca\xc7\x18\xba\xfe\x72\x0f\x6f\xff\xf8\x90\x96\xa2\x50\x70\xbf\xa4\x46\x27\x01\x31\xef\x8e\xae\xb7\x8c\xf8\x32\x5d\x10\xc6\x61\x65\xb6\x41\x59\x0f\xd4\x9c\x06\xa3\xb1\xbc\x15\x7e\x49\x24\xe5\xba\x1e\x9c\x2b\x30\x34\x13\xa2\x70\x29\x76\xde\x98\xeb\x66\x06\x5c\x2e\x31\x17\x3f\x72\x7a\xff\xa3\x19\xb9\xef\x58\xe7\x05\x59\x34\x35\xcb\x14\xd5\x35\xd8\x2b\x24\x23\x1b\xec\xae\xb4\x2f\x1f\x79\x13\x60\x4e\x55\x45\x81\x14\xf7\x64\x83\x5b\x21\xce\x78\x99\x7a\x09\x2f\xce\x50\x8c\x11\x05\xcd\x78\x73\xf8\x8d\x6f\x88\x7c\x49\x14\xbc\xba\xbc\xfe\xf1\xe6\x2f\x37\x3f\x5e\xbe\x7e\x77\xf5\x3e\xc4\x9c\x30\xbb\x87\x7a\x6d\xf2\x8c\x94\x64\xc6\x0a\xe6\x6f\x45\xec\xe0\x2e\xbb\x2c\x03\x8c\xc2\x3c\xbf\xc8\xa5\x28\xed\x1a\xca\x8a\x63\x59\xbf\xb6\xfe\x8d\xaf\x27\xb9\xeb\x35\xec\x54\x08\x34\x9b\xdb\xd7\x19\x39\xef\xbd\x32\x2c\x24\xe1\xc6\x9a\x47\xcf\x54\x40\xb4\xdb\x41\x73\x64\xc5\x35\x5b\x7d\xb9\xc9\xd7\x24\x8f\x95\x78\x7d\x99\xe7\x34\x8f\xb1\xbd\x9e\x62\xe2\xc1\xab\xfa\xb5\x42\x32\x6e\xa0\xad\x9a\x08\xd7\x1f\x6e\xae\xfe\x77\x9c\xd9\x02\x37\x63\x21\x01\xac\x08\x35\x5b\xa4\x28\x23\xed\xa4\x8f\xae\x7a\x47\xda\x4b\x0f\xd1\xcf\x74\x2f\x35\x96\x5c\x0c\xcc\xd4\xc7\x8a\x77\x64\xb5\x77\x01\x83\x76\x4c\xb0\x12\x39\x9d\xc2\xb5\x35\x90\xa8\x8a\xc2\xb3\x53\x36\x8e\x48\x0a\x86\x31\xd7\x8c\x14\xde\xa6\x26\xfd\x5b\xc5\xd6\xa4\xa0\x36\xc1\x0f\x4b\x38\x74\xeb\x07\x46\xd0\xcd\x73\x52\xa8\x20\xa5\xe7\x6f\x13\x19\xe3\xf4\x9d\xa8\x78\x0c\x7c\x52\xc3\x0b\x72\xca\x85\x0e\xf2\x67\x9a\xf7\xc2\x82\x8f\x52\x64\x60\x7d\x9a\x41\x50\xec\x1a\x9b\xd7\x31\xaa\xd0\x80\xf3\x2f\x9a\x0c\xd6\x04\x77\xeb\x78\xdd\xbc\xbb\x8d\xfd\x56\x2a\xe8\xf5\x77\x4c\xa2\x50\x28\x8b\x79\x7f\x49\x49\x8e\x95\x7c\x4a\xa2\x97\x16\xa7\xb7\x22\xea\xce\xdb\xf7\x88\x6c\xdc\x9d\xce\x79\x89\x6d\x01\x9e\x66\x32\x6e\xfd\x85\xdf\x9c\x12\x5d\x49\x6a\x6f\x65\x36\x19\x90\x72\x32\x2b\x7c\x91\xd5\x81\x82\xd4\xcc\xdd\x07\x5e\x6c\x3e\x0a\xa1\xbf\x6e\xaa\xad\x44\x38\x34\x7f\x76\x37\xf8\x7e\x60\x37\xe0\xa2\x85\x10\xb9\x7c\x82\x0b\x8d\xc2\x2a\xbc\x38\x8c\xdb\xe3\x66\xbb\x7f\x46\x51\x25\x2b\x7e\xa9\xbe\x91\xa2\xf2\xb4\x8c\x76\x2e\x6f\xdf\x5c\xbd\x46\x89\x5e\xf1\x80\xcb\x0b\xe5\x5a\x6e\xb0\x12\x5a\x8c\xb6\x0f\xd0\xf5\x17\x7c\x6b\x54\xe2\xd6\xf9\xf7\x15\x54\x73\xa8\xb8\xa2\x7a\x0a\xef\xc8\x06\x48\xa1\x44\xed\xe4\xf0\x56\xb9\xd7\x88\xc8\xef\xba\x62\xa7\x80\x95\x45\xbd\x2f\x97\x8c\xc3\x4c\xe8\x25\x6c\xb1\x0d\x28\x25\xba\x3b\x46\xac\x10\x15\x04\xa4\x6f\x3b\x73\x30\xbe\x3d\x54\x5f\x89\x4f\xee\xa8\x82\x52\xd2\x8c\xe6\x94\x67\x41\xe7\x2b\x12\x62\xe6\xf7\xff\xe6\x7b\x42\xdf\x0b\x6e\x84\x64\x84\x33\x7a\xc5\x73\x96\x11\x6d\xbd\x90\x3a\x8a\x83\x01\xb1\x7a\xce\xb3\x45\xb0\x78\x90\x11\x91\x9e\x6c\x2b\x45\x25\x46\x45\xb5\xac\xa8\xdd\x58\x7f\xaa\x66\xb4\xa0\xda\xb7\xd8\x22\xd4\x15\xa0\x89\xb6\x95\xcd\xd8\x8a\x2c\x28\x10\x5d\x8b\x01\x7f\x1f\x13\xe5\xca\xa8\x53\x9c\x49\xa6\x21\x17\xb4\x29\xc9\xe5\xeb\xec\x50\xf0\xed\xd5\x6b\x78\x0e\xa7\x66\x0e\xcf\xd0\x9e\x98\x13\x56\xf8\xd7\xe6\xc0\xac\x81\x2d\xfb\x87\xcd\xeb\xe1\xfa\x6a\xaf\x2b\x27\xfb\x40\x48\xab\xbe\xce\x81\x0b\x50\x55\xb6\xac\xe7\xda\xdf\x07\x5b\xbb\x8b\x5d\x06\x10\xe2\x68\x9c\x80\xf5\xe4\xd8\x88\xe5\x7d\x02\xd6\x77\x6e\x2d\xd3\x21\x01\xeb\x1d\x9f\xcc\xf7\x09\xd8\x20\x44\xe2\x13\x17\xb0\x81\x06\xcc\xb7\x8a\xca\x48\xf6\xcb\xb7\x4f\xdc\x7e\xe9\x5e\x71\x8d\xac\x6c\x57\xd6\xdf\x40\xb0\x02\x71\x45\x35\xc9\x89\x26\xce\xae\x09\xad\x21\xba\x6b\x13\xa5\xc3\xf7\x34\x0f\xdf\xe7\xb4\x6e\x14\x7d\xcb\x78\xf5\xc9\x26\xac\xc4\x0a\x20\xdd\xbc\x41\xa6\x90\x85\x4d\x31\x6e\x5d\x52\x96\x05\xc3\x8a\x92\x5b\x39\x14\x41\x8a\xb3\xdb\x28\x20\x5c\x38\xd4\xd7\x19\x54\x9c\xa4\x28\x84\x31\xf0\xcc\x9d\x95\xf0\x5c\xf8\x22\xd9\xb7\x26\x11\x9d\x1d\xb4\xd7\x26\x6f\x8a\x87\xdc\xf7\xac\x25\xd1\xf0\x05\x88\x86\xcf\x1a\xf8\x2b\xe8\x9a\x7a\xf7\x35\xd8\xee\x3e\x68\x78\x01\x53\xf5\xb6\x0e\x88\x1e\xe0\xb0\xa0\x20\x33\x5a\x58\xcb\xdf\x8a\x88\x08\xf9\x70\xc1\xc2\x25\x4a\x98\x4c\x8a\x22\x56\xbd\x8f\x8f\xa2\xc0\x64\x18\x12\x61\xda\xcd\xb0\x7e\xc6\xb3\x8e\x2c\xe2\xcc\xfa\xed\xa6\x8c\x36\xeb\x18\x32\xf8\xf9\xce\x7a\xe5\x7d\x71\x80\xed\x59\x37\x77\x90\x58\xb3\x8e\x86\xfd\xcf\x73\xd6\xef\x19\xcf\xc5\xbd\x8a\x6b\xf0\xfd\xd9\x32\xad\xb5\xa9\x6f\x1a\xbb\xa2\x5a\x33\xbe\x50\x5d\xa3\x8f\x14\x45\x04\xd0\xd0\x90\xd5\xe7\xb0\xb1\xbe\xa1\x9c\xba\xe9\xe7\xae\x55\x12\xe8\x76\xa9\x94\xcb\x4b\xe8\x58\x51\xbe\x36\xe4\xae\xd3\x79\xc8\x8a\x0a\x88\xe9\x25\x2b\xea\x10\x2d\x56\x8a\xbc\x92\xe6\x25\x34\x23\xc5\x4d\xe9\xdb\xc3\x04\xb6\x0f\xde\x37\xef\x6e\x2e\xfb\x8c\x03\xe4\x13\x43\xac\xa5\xb4\x0e\x5a\xc3\x19\x48\xbe\x62\x4a\xf9\x7b\x11\x0d\xdd\xd3\xd9\x52\x88\x3b\x38\xad\xd1\xd7\x0b\xa6\x97\xd5\x6c\x9a\x89\x55\x07\x88\x3d\x51\x6c\xa1\x2e\x9c\x60\x9a\x98\xf9\xf2\xc5\x64\xe2\x9b\xf0\x82\x71\x17\xb3\xc5\xbb\x13\xd7\x0a\x84\x7f\x3b\x44\x68\xa7\x24\x6b\x66\x1b\x77\x7c\x00\x4b\xdb\xb8\xcd\x02\x0c\x07\x16\xf2\x7d\x58\xfd\x02\xac\x78\xf9\x59\xf5\xfa\xee\xa6\x7f\x1f\x54\x50\xf5\xc0\xc6\x0f\x9c\x2f\xdb\x08\xc6\x16\xdb\x70\xfe\x42\xf3\x8c\x00\x8e\x5b\x3b\xc5\x39\x0b\x3f\xef\xb5\xa2\x76\xd4\x46\x5c\x09\x74\xd8\x3a\x96\x41\x47\xb6\xb1\x20\x5a\xd7\x6f\xc7\x89\x1b\xc0\x7a\xdb\xfd\xdb\x38\x72\x03\x78\x6e\x23\x90\xa3\xb8\x81\xe1\x11\x5d\xc1\x70\xb4\x3b\x38\xe0\x01\x7d\x83\x25\x92\x15\x00\xfb\x5d\x3f\x81\x02\xfd\xd1\x0c\x17\x88\x66\xbc\x40\xd8\xc1\x77\xe5\xca\xa2\xb4\xf4\xbb\xe9\xf0\x02\x56\x87\xb0\x3d\xde\xaa\x0e\x7a\x9b\x15\xb5\x45\x2b\x9b\x52\x70\xc5\xa6\x2e\xbc\xc9\xfe\xee\xb7\xd7\xfb\x2d\x60\xb9\xb0\xb9\xad\x9d\x4a\x96\x1e\x3c\x5d\x4f\xaf\x1c\x2a\xae\x59\x51\x23\x9a\x56\x65\x61\x2c\x97\xde\xe8\x3d\x47\x8c\x1c\x3b\x5d\x03\xcf\x9b\xe9\x09\x69\x6e\xe8\x6a\x81\x9e\xc3\x7f\x57\x4a\x03\x69\x52\x8a\xea\x82\x76\xb8\x92\x1e\xcc\xeb\x5a\x7b\x88\x8f\x73\xad\x5c\xb1\x9e\xbd\x16\xe6\x25\xd6\x2c\xf7\xe1\x9a\xb3\xf9\x9c\xd6\x49\x55\x33\x0a\x25\x91\x64\x45\x35\xc2\x5d\x7d\x31\x12\x33\xba\x60\x36\xe7\x44\xcc\x81\x98\x09\x3d\x39\x51\x6d\x95\x34\x1f\xf9\x81\x99\x2c\x4c\xc3\x8a\x2d\x96\x1a\x0f\x39\x10\x28\x04\x5f\x60\x2d\x1c\x3f\x88\x40\x21\x48\x0e\x28\xeb\x85\x84\x7b\x22\x57\x40\x20\x23\xd9\x12\xb1\x17\x5e\x11\xd9\xbc\x92\xd8\x8e\x50\x53\x92\x6f\x26\x4a\x13\x6d\xee\xba\xd4\xe6\x45\xdb\x95\xf3\xe0\x9a\xed\xd4\x64\xb1\x7b\x00\x3d\x2e\x33\xaa\x7d\xba\x83\xd7\x70\x48\x87\x81\xac\xed\xe1\xae\xb0\x09\xe0\x3a\x2f\xc8\xe2\xa9\x15\x01\x4a\xdd\x33\x1d\xa5\xee\x99\xc7\x52\xea\x9e\x79\x34\xa5\xee\x99\xa9\x7b\x66\xea\x9e\x99\xba\x67\xa6\xee\x99\x5b\x94\xba\x67\xa6\xee\x99\x0f\x50\xea\x9e\x79\x98\x61\xaa\x8c\xed\x49\xa9\x7b\x66\xea\x9e\xb9\x9f\x52\xf7\xcc\xcf\x6d\x5a\xa4\xee\x99\xa9\x7b\x66\x4d\xa9\x7b\xe6\x08\x4a\xdd\x33\xc7\x51\xea\x9e\x79\x90\x9e\x58\x3f\x8d\xd4\x3d\x33\xf5\xd3\x38\x96\xcf\xd3\xeb\xa7\x01\xa9\x7b\xa6\x1f\xa5\xee\x99\xe3\x29\x75\xcf\x1c\x47\xa9\x7b\xe6\x78\x9e\xa9\x7b\x66\x4b\xa9\x7b\x66\xea\x9e\xf9\x85\x6e\xdd\xd4\x3d\x33\x75\xcf\x1c\xa6\x14\x23\x48\xdd\x33\xc7\x51\xea\x9e\xe9\xcf\x34\xdd\xf6\xfd\xf9\x3c\xbd\xdb\x7e\xea\x9e\x99\xba\x67\x1e\xa4\x10\xd3\x4d\xe9\x9c\x79\xb4\x4d\x79\x9c\xba\xa8\x0e\x2d\xdb\xa9\x35\x33\xab\xe6\x73\x2a\xd1\xec\xc6\x91\x7a\x39\x6e\x86\xcb\xf4\x4e\xeb\x34\x05\x1f\x9e\xd6\xf0\x53\x54\x9f\x63\x09\x57\x65\x13\xa7\x71\x88\x7e\x80\xc7\xfe\x10\x5d\xc9\x1d\x6c\x16\x22\xa9\xf2\xbb\x5f\x33\x0e\x6f\x3e\x7c\x3d\x8d\x50\x12\x36\xa4\x9a\x1a\xce\xc9\x07\x9e\x85\x26\xeb\xb4\x9b\x2c\xac\xb2\x51\x5d\xd5\xc8\xed\xb5\xac\x10\xca\x62\x6b\xed\xe2\x65\x4b\xc2\x39\xf5\x49\x50\xb1\x02\x91\x69\x74\xbb\xcd\x28\xe5\x20\x4a\xca\x2d\xfe\x9f\x80\x62\x7c\x51\xf8\x68\x00\xa2\x35\xc9\x96\x53\xf3\xfe\xbc\xde\x60\xae\x9b\x4c\x33\x6a\x9f\xa3\xa6\x25\x25\x2b\xbb\xd1\x24\x5d\x11\x66\x87\x0b\x24\x93\x42\x29\x58\x55\x85\x66\x65\xc0\x80\x41\x51\x4c\xb3\x56\x36\xe7\xbf\xde\x04\xe0\x75\xdc\x14\xb5\x60\x4f\xac\xdd\xd9\xcc\x81\x9b\x5e\x2f\x13\xac\x3d\x6a\x78\x81\x3f\xc7\x46\x82\xab\x52\x6f\x6c\x42\x94\xe7\x01\x9e\x33\xa9\x34\x64\x05\xc3\x1b\x1c\xce\x03\x45\x4d\x86\x63\xf6\x41\x00\x13\x9e\x1b\xce\xdc\xad\x91\x72\x8b\xc4\x73\x34\x40\x4b\x2f\x83\x1f\xd3\x72\xea\xbc\x2f\x5a\x0f\x37\x67\xca\x5d\x28\x94\xd7\x40\xeb\x6a\xea\xf6\x70\xd5\x6b\x84\xc7\x2b\xf7\x2c\x0b\x5c\xbf\xb3\x63\xd2\x19\x72\xc0\xf9\xc7\x02\xe8\xce\x2b\xde\xa8\x00\x5b\xba\xbc\x16\x90\x5e\xef\xbf\x9b\x8c\x5b\x17\xc3\x45\x05\xe1\xc1\xb2\xa3\x52\xf0\x98\x72\xba\x36\xda\x8b\x66\x94\xad\x8d\x11\xee\xc1\x72\x50\x1f\xfc\x43\xd5\x81\xa6\x72\xc5\x38\x26\x6d\xbd\xa3\x4a\x91\x05\xbd\xf6\x8a\x7e\xef\xbb\x5b\x63\x00\xbc\xde\x8c\xde\xc7\xb8\xc0\x0b\x76\x6b\xdc\xb6\x29\x08\x27\x5e\xe9\xa1\xed\x4b\xc3\xca\xbe\x75\x53\x17\xe5\x5e\x32\xad\xa9\x97\x61\xa3\x6c\xb7\x05\x04\x0e\x6d\x57\xe2\xf1\x1b\x68\x27\xbd\x02\xde\xd5\x03\xb5\x03\x34\x8f\x33\x46\x2a\xcf\xbd\x7c\x5c\x16\xe5\x34\x93\x8c\xce\x61\xce\x30\x8b\x01\xf1\xf6\xe7\xb6\xba\x2f\xf1\x19\x2d\xe1\x40\x94\xa2\x12\xe7\xd5\xe1\xad\xeb\xf9\x9d\xc2\x9f\xbd\xf3\x4c\xb5\xac\x78\x46\xda\x5e\x59\xc0\x45\x4e\x81\xcd\x61\x81\xc8\x7e\x1f\xa9\x83\xbd\xf9\xfe\xed\xf9\x7f\xfc\x1e\x66\x1b\x73\xd1\x40\x2c\x8b\x16\x9a\x14\xf5\x80\x3d\x98\x16\x94\x2f\xcc\x6e\xb7\x2a\xbb\x5f\x52\x28\x20\xcd\x16\xbb\xaa\xdb\xdc\xd7\x17\xbf\xb9\x9b\xf5\xee\x64\x1e\x1c\x2f\x72\xba\xbe\xe8\x9c\x80\x49\x21\x16\x9d\x66\xf8\x1e\x1c\xeb\x54\x4d\xdf\x44\x45\xaf\x6b\xfe\x80\xe0\xc2\x8e\x9e\x81\xa2\xab\x2e\x9c\x0e\x4b\x71\x6f\xbb\xa9\xb4\xcf\xf1\x98\x9a\x5a\xba\xb4\x79\x87\xa5\x28\xab\xc2\x66\xb6\x7e\xcd\xbc\x0c\x3a\x94\x54\x95\xa2\xdb\xb5\x67\xf6\xc8\x72\x3f\xe1\x50\x0f\x73\xeb\x22\x64\x85\x44\xc0\x44\x08\x57\xb8\xc1\x45\x97\x9a\xca\xe7\x95\xf4\xca\x7c\xfc\x9a\x14\xc5\x8c\x64\x77\xb7\xe2\xad\x58\xa8\x0f\xfc\x8d\x94\x42\xf6\x66\xc8\xe7\x1c\x13\x63\x35\x2e\x2b\x7e\x67\x9b\x81\xd7\x2f\x5f\x88\x05\x88\x4a\x97\x95\xd7\xed\x6f\xbe\xbd\x9d\x9a\x39\x99\xfb\xed\x83\xc6\x44\x76\x46\x69\x67\xa4\xf4\x13\xf3\x0b\x7d\xdc\x33\x23\xc0\x38\x50\x33\x8f\x56\x2a\xb6\x6f\xed\x77\x59\xe8\x88\xaf\xdf\x3c\xff\xb7\x7f\xb7\x02\x17\x84\x84\x7f\x7f\x8e\x49\x99\x5e\xe6\x2d\x9a\x02\x68\x7f\x31\x05\x6a\x45\x8a\x82\xca\x50\xc1\x68\x8e\x63\x47\x10\x36\x62\xed\x1f\x2a\xd5\x74\xa8\x00\x7b\x44\xe7\xcf\xed\xed\x5f\xd0\xf3\xc3\xb4\xa2\xc5\xdc\xcb\x2a\x2f\x94\x68\xfb\x1d\x9d\xa0\x31\x7d\xe2\x6c\x11\x73\x9b\xf4\x11\x01\x9f\xd7\x9d\xb2\x16\x45\xb5\xa2\xaf\xe9\x9a\x65\x3e\x61\xad\xde\xd2\xf5\x78\xf9\x67\x3e\x17\x4c\x61\x41\xfa\x59\x21\xb2\x3b\xc8\x1d\xbb\x16\xd6\xee\x63\x85\x6c\x42\xeb\x4a\x86\x24\x21\x78\x27\x1f\xec\x9d\xdd\x36\x75\xc0\xcb\xc1\x4b\x60\x45\xca\xb2\x29\xfa\x21\xc9\x7d\x6f\xb2\xbd\x78\x1a\xc9\xcb\x78\xf7\xde\xea\x73\x18\x02\x83\xc3\x21\xa1\xe1\x89\x7b\x7b\x4f\x9b\xc3\x3b\x2f\x21\x34\xaa\xdc\x8e\xda\x37\xf0\xd5\xdb\x66\x2d\xbb\xd0\xda\x05\x25\xf2\xb0\x49\xeb\x91\xfa\x4b\x74\x2a\x23\xd9\x71\x36\xd7\x5e\xb3\xa1\x03\xaa\x8a\x69\xe1\x1b\x74\x0c\x8e\xf4\x85\x64\x81\xf4\x56\x8e\x37\x31\xd5\x15\xd1\x5e\xce\x0a\x4b\xdd\x22\x7f\x04\x4a\x2a\x15\x53\xc6\x46\xff\x0e\x05\xd0\xab\x82\x30\xdf\xc0\x59\x13\x3c\x29\x85\xef\x52\x05\x4c\xb7\x15\xa0\xd8\x9c\x30\x54\xd3\x5d\x8b\xdc\xb1\x43\xc5\x84\x6e\x13\xaf\x88\xca\x8e\x9b\x25\xb4\x24\x45\x34\xf3\xef\x73\xaa\xba\xef\xda\x95\x0a\xd7\x74\x86\x4b\xa3\xea\x2c\x67\xa7\xac\x3c\x39\x7e\xb9\x0a\x0e\xe7\xe2\x4b\xd3\x6f\xcd\xa0\xa3\x08\x49\x54\x6c\xce\x56\x09\x51\x6e\xed\x5d\xb5\x8d\x54\x2c\xa9\x13\x0a\xde\x5c\x5b\x37\x8b\xf3\xc4\x4e\x1d\x58\x94\x7b\x77\xaa\x6b\x86\x0a\x27\x2f\x4f\x3e\x9b\x92\xb3\x8b\x28\x45\x49\x16\xe8\x3b\x88\xb2\x96\xdb\x4c\x03\x10\x5e\xd6\xad\x41\x15\xba\xcd\x90\xaf\x6f\x25\x44\x4b\xa5\x1b\x15\xcd\xdb\x12\xe8\x4b\x81\x15\x16\x62\x6c\x39\xe7\x30\xb1\x85\x1b\xef\x03\xf2\xa2\x89\x14\x15\xcf\x5d\x34\xb8\x81\x20\xbc\xdb\x9a\xd8\xf7\xfe\x15\xcc\xd0\xcd\x63\x6b\xb5\x63\x21\x3c\x9b\x28\xc9\x94\x6f\x31\x3c\xc7\x93\xc3\x8b\xe9\x8b\xe7\x5f\xbe\xcd\x86\x73\x12\xc9\x66\x7b\xdf\xd8\x6c\x56\xcb\x7d\xb6\xd9\xa9\x1b\x26\x47\x99\xa1\x77\x2e\x24\xd5\x74\x36\xf6\xdf\x34\x75\xb7\x4e\x64\x75\x2f\x99\x76\x27\xe8\x9e\x05\x24\xaa\x9d\xa2\xd3\x06\x84\xec\x96\x20\x3e\x6b\x7d\x79\x01\x57\x92\x90\x8e\xcb\xe1\x2d\x0b\x01\x54\x35\x7b\x72\x7a\xd7\x2a\x58\x2b\x54\x87\xe2\xa9\xfe\xf3\xed\x38\xef\xaa\x60\x6f\x8e\x5d\xec\xe1\xb3\x67\x70\x6a\x9f\x70\x62\xab\xd9\x9d\x7d\xb6\xe3\xe9\x96\xf5\xcd\xa7\xd2\xbb\xa9\x4c\x6f\x69\xdf\x7c\x2a\x09\xcf\x69\x6e\x2f\xfc\x01\xa6\x35\xd4\x45\xa7\x87\xd6\x38\x5c\x6d\x9e\xa8\xfe\x1a\x7b\x73\xec\x9a\x67\xff\x49\x97\x64\x4d\xb1\xe6\x1f\x2b\x88\x0c\x10\x4f\x5a\xc0\x8d\x5d\x19\x98\x55\x1a\x28\x5f\x33\x29\xf8\x8a\x06\x14\x76\x5f\x13\xc9\xc8\xac\xa0\x20\x29\x16\x0e\xce\xa8\x82\x5f\x9d\x7e\x77\xf9\x11\x61\xd6\xfe\xed\x23\x88\xa4\x40\xeb\x55\xaf\x14\xa6\xe7\x46\x3a\x85\x9d\xd7\x9e\x6e\x1d\x20\x7f\x11\xbd\x75\xf0\xea\x79\x36\x27\xc0\x7f\x0e\x78\xde\xac\x97\x99\x8f\x55\xa5\x2b\x52\x60\xd9\xc7\xac\xa8\x14\x5b\x7f\x0e\xfd\xeb\xca\x70\xbe\x66\x1e\x27\x7b\xab\x7c\x69\x7b\x68\x76\x6a\x7b\x7a\x96\xf0\x46\xf3\x32\x5e\x4b\x49\x07\xbc\x3c\x51\x75\xb2\x4a\xaf\x35\x90\x77\x50\xce\x95\xad\x9e\xe1\xe0\xe6\x6c\x51\x49\x5b\x48\xc7\x4f\x04\x75\x9a\x59\xaf\x10\x45\xf2\xb9\xc2\x73\x39\x57\xaf\xf0\x7d\xc6\x6c\x8c\x7e\x5e\x7f\xaf\x54\xf0\xeb\xf7\x37\x9d\xfa\xe3\xa3\xde\xc1\xba\x15\x45\x3e\x85\xeb\xb6\x80\x79\xdb\x62\x00\xfb\xeb\x8c\x46\x9b\x18\x99\x4c\xe5\xa2\x6d\x81\xba\xa0\x9c\x4a\xbc\x80\x99\xa1\xd6\x6b\x39\xfe\x9e\x38\x23\x0a\x41\xa1\x86\x8d\x45\x68\x8c\x59\x31\x4f\x77\x8f\xaf\xcf\xc4\xdc\x4b\x6c\x75\x95\xd1\xce\x96\xde\x5a\x5f\x36\x41\x38\x33\x79\xe8\x0c\xb6\x6c\x47\x6f\xd6\xab\x6b\x20\x79\x2e\x11\xbe\xe8\xae\x80\xf5\x31\x25\x65\xe9\x87\xfe\x72\x2b\x6c\x56\xa6\xfb\xc6\xed\x92\x8f\xe6\x88\xa6\x46\xbb\xc0\xf0\xba\x2a\x0b\x66\x21\x5b\x9d\x07\x8c\x66\x5b\xbf\xa9\xa4\x2b\xb1\x1e\x7f\xd4\xfd\x1d\xb1\x9e\x6e\x58\x6f\xcd\x23\xfc\xfa\xe4\x3d\xb0\xe7\x24\x55\xa2\xf0\xd9\x70\x6e\x28\x5b\x7b\xcd\xc9\x06\x63\x9c\x8e\x9f\x95\x7a\xaf\x39\xd6\x1d\xd1\xb2\xb5\x6f\x46\xb3\xee\xec\x33\xca\xb5\x34\xc2\x35\x70\xcf\x00\x7c\x34\x33\x57\x21\x40\xa7\x19\x30\x5b\x53\x6e\x94\xd8\x07\xcf\x66\x7e\x38\x28\xb1\xa6\x52\xda\xca\xe1\x36\xc7\xc1\xb6\x7c\xa4\x44\xfa\xa4\xa8\x34\xb3\xea\x3d\x7d\xff\xf0\xe3\xb1\x1d\x02\x7a\xfd\xfe\xc6\xea\x54\x3b\xad\xc6\x0e\x61\xdc\x2b\x50\xd1\xdd\xf1\xcd\xaa\x35\x7a\xd2\xf3\x1c\x7f\x96\xfe\x09\xfe\x9e\xb1\x7e\x4b\x5e\x17\xe7\x08\xa9\x5e\xe0\x7d\x45\x0e\xa8\x34\xe7\xfd\x64\x45\x89\xcc\x96\xe3\xe7\xfc\x01\x11\x6a\x59\x42\x2e\x30\xeb\x61\xbc\x4e\x14\x12\x5d\xd6\x13\x54\xff\x85\x10\x77\x55\xd9\x97\xaa\xa3\x59\xd6\x1a\xbf\xa7\xc1\xdd\x30\x4b\xa2\x97\xe3\x07\xb9\x57\x14\x77\x44\xeb\x68\xa6\xdd\x11\xfd\x73\xe8\xf0\x9c\xab\xf1\xe8\xe3\xfe\xed\x80\x6a\x7b\x27\x40\x36\x6d\x45\x97\xb1\xe2\xab\x77\xe5\x7f\x55\x54\x4a\x53\xf9\x35\x93\x4a\x3f\x9b\xc2\x77\xa4\x60\xae\xc8\xe2\xb8\x9d\x62\xee\xe7\x27\x5d\x66\x7f\x66\x7a\xf9\x47\xa1\xf4\x7b\xaa\x4f\xce\xfb\x7f\x3a\x19\x77\x73\x3c\x71\x03\x3e\x01\x21\xe1\xe4\xbd\xe0\xf4\x64\xba\x75\x39\xb2\xea\x77\x14\x57\x86\xd7\x0d\xab\x5c\x86\x6c\x18\x37\xb7\x66\xaa\x47\x4a\x99\x82\x66\xba\x66\xd2\x39\x2d\xb7\x02\x96\x64\x6d\xaf\x75\x3e\x1d\x7f\x15\xd5\x40\xb0\xc7\x13\x72\x5e\xda\xb9\xbd\x17\xf2\xce\x36\x6c\x40\xe6\x23\x63\x5f\xf6\x4a\xb8\xe9\x6e\xab\x4e\xd7\x06\x2d\xf6\x2f\xe9\xf8\x1b\xda\xc8\xf3\x62\x5b\x31\xdd\x50\xb9\x66\x19\x7d\xcb\xf8\xdd\xa8\x83\xda\xcf\x35\x7a\xb3\xc3\xcb\xb3\x75\xdc\xbd\x43\xce\x32\x6e\x13\xb8\x8d\x49\x42\x66\xa2\xd2\x78\x77\x43\x10\xa5\x87\xe3\x13\xeb\x3f\xfc\xb7\xdd\x35\x88\x57\x29\x6d\x8b\xb0\x8e\xa3\xae\xf1\x33\x8e\x84\x42\x63\xc8\xab\x76\x1e\xaa\x0d\xd7\xe4\x13\xea\x2e\x91\xdd\x51\x09\x85\x99\x8a\x29\x34\xa9\x58\xde\x62\x04\x81\xb9\x63\x72\x3b\xfc\x22\x27\xb4\x5c\xd2\x15\x95\xa4\x68\x7c\x67\xfe\x9b\xe2\xad\x53\xe3\x0d\xcf\x4e\x26\xce\xa8\x79\xb0\x7d\x63\x5c\xf7\x3c\x91\x4f\xe1\x4d\x28\xc7\x15\xd9\xa0\x3a\xb4\x8c\x09\x07\xfa\x89\x29\x04\xd8\x94\x22\xef\xd4\x74\x1b\xc5\xb4\x52\x54\x4e\x9a\x0a\x80\xae\xc2\x92\xaa\x53\xb9\x20\xa7\xb3\x6a\xb1\x60\x7c\x31\x4e\x97\xa0\xad\x82\x16\x51\xdb\x96\xad\xf5\x33\x61\x9b\xba\x4c\x52\xa2\xc7\xda\x6a\x68\x95\x9f\xa3\x07\x98\x75\x79\xaf\x44\x6e\x59\xcf\x36\xd6\xbb\x37\x96\x71\x5d\x2f\xc7\x0c\x72\x0a\x57\x1c\x84\xcc\xa9\xc4\xf2\x30\x79\x8e\x73\x5d\xaf\xde\x28\xb6\xad\x13\xd2\x70\xea\xaf\xd8\xb9\x57\x9e\x89\x91\x01\xaa\x1d\x4d\x27\x4d\x4c\x55\x33\x73\x91\xa9\xe4\xd8\x76\x9e\x7d\x74\x00\x29\xca\x25\x99\x14\x74\x4d\x0b\x70\x5d\x95\x46\xc7\x7e\x97\x82\x0b\x69\x57\xa3\xf6\x10\xe1\x9d\xd5\x0a\x6f\x9c\xec\x37\xbb\x67\x76\xd4\x23\x5c\x13\xbd\xf1\xfa\x66\xac\x41\xe8\x61\x0c\xf6\x6f\x06\x7c\xe0\x5d\xc7\xe7\xc3\x74\xb3\x92\x71\x2e\x9d\x34\x20\x39\x5a\xf5\x74\x55\x0a\x49\x24\x1b\x1d\x05\xdb\xdd\x97\x68\x41\xf6\xc5\xc2\xd8\xb1\x66\x9a\xad\x99\xb9\xc7\x0e\xc8\x91\x76\x36\x46\x72\xed\x6c\x75\xb4\x69\xb8\x80\x7a\xbf\x1b\x0b\x50\x65\x4b\x9a\x57\xc5\xf8\x7b\xe7\xa2\x22\x92\x70\x4d\xa9\x3a\xaf\xe1\x3d\x1b\x97\xa6\x6d\x85\x4b\x93\x64\x3e\x36\x24\x64\xc4\x1c\x72\xa3\x9f\x98\xc6\xf6\x99\xe6\x37\x28\xc3\x6c\xf2\x3a\xde\x6b\x46\x72\x15\x72\x2b\xeb\xbd\x2b\x9c\xbc\xc3\x3a\x19\xa9\x14\x76\x43\x70\xaa\x84\x7e\xca\xa8\x31\x3b\xb4\x6a\x26\x79\xec\x26\xb0\xd9\x3f\x4c\xf0\xf3\x46\xba\xba\x3d\x4b\xd7\x2c\xf3\x88\xbf\x0c\x29\x50\x64\xe9\xd6\x09\x8f\xc2\x48\x9e\xb3\x8d\x0b\xae\x15\xad\xe2\xd8\x52\x06\xb7\x4b\x3a\xf6\x50\x35\xe5\xb5\xf0\x70\xae\x19\xa9\x59\x0e\x8b\xee\x91\xdc\x3b\x82\x7e\x7b\xc7\xfa\x3a\x05\xbb\x6f\x0c\x82\x67\x6e\xe8\x9d\x16\xaa\x63\x39\xa2\x1a\xd9\xd7\x40\x35\x54\xf8\x6f\xf5\x50\x1d\xa7\xe9\x7d\x3d\x74\x7e\x00\x60\x0f\xf0\xae\xbf\x1b\x90\xc8\x45\xa8\x73\xf5\xe4\x52\x2e\xaa\x15\xe6\x05\x3b\x57\x51\xdb\xe6\xde\xc7\x25\x78\xbb\xa4\x90\xdb\x6b\x05\xc6\x61\xcd\x05\xe6\xd5\xbb\xd7\x35\x36\xd1\x83\x23\x73\x85\x3e\x5c\xe5\x26\xd7\xd4\x39\x9f\xc2\x77\xee\x2e\xe4\x13\xd1\x1e\x44\x69\xf4\xd0\x16\x1e\x5c\x87\xf0\x19\xfd\xfb\x9b\x67\x3c\x9f\xb4\xf8\x92\xd6\x06\x76\x5e\x6c\xaf\xf8\xbb\xed\x42\xe4\xe6\xa0\x4e\x15\x61\xbc\x34\x37\x58\x5f\x5f\x6e\x83\x09\xe0\xd9\x92\xf0\x85\x95\x26\x34\x10\x05\xe3\xee\xaa\xae\xb1\x37\x55\x19\x29\x6b\x9f\x0a\x81\x5c\x54\x7e\xcb\xff\xab\x5f\x9d\x03\xa3\x2f\xe1\x57\x9d\xc1\x4d\xe1\x8d\xe3\xde\x6e\x0e\xdf\x59\xb0\xf5\x5e\x66\xed\x66\x3a\x07\x49\x17\x44\xe6\x85\x5f\x6b\x0f\x31\x6f\x5c\x0e\x88\xda\xaa\x37\x03\x9a\x71\x0a\x84\x0f\xa8\x83\x0b\x3d\x84\x91\xe8\x94\xd9\xf3\x60\xfa\x40\x61\x3e\x4d\xd4\x9d\xba\xb0\x0e\x8e\x49\x4e\x34\x99\x90\xd2\xfa\x8d\x99\xe0\x17\x36\xa0\x33\x71\xad\x5d\x27\xc4\x09\xa5\x49\x73\x90\x2e\x7e\x29\x2b\xec\x9e\x3e\x21\xcd\xa7\x18\x9f\x90\x09\x36\x02\xf5\xad\x27\xf1\x0f\x4e\xbd\x09\x88\x96\x78\xf7\x4c\xde\x76\x81\xd5\xc2\xdd\xbe\xfb\x14\xde\x7b\xe5\x3b\xb8\xde\xc8\x79\x9b\x8c\xea\x1a\xb2\xb6\xf2\xdf\x47\xd4\xd7\x1a\xe3\xcd\xfb\xdb\x8f\x7f\xb9\xfe\x70\xf5\xfe\xb6\x56\x1c\xb5\x1a\xf0\xe1\xba\x4f\x71\x84\x9d\xf4\x7d\x8a\xa3\x55\x03\x21\x28\xa6\x6d\xc5\xd1\x57\x03\x3e\x9c\x77\x15\x47\x5f\x0d\xf8\xcc\xec\xae\xe2\x18\x50\x03\x9e\x56\x44\x77\x7e\x07\xd5\x80\x97\x74\xee\x28\x8e\x61\x35\xe0\xc1\x75\x57\x71\xf4\xd5\x80\xd7\xf9\xda\x55\x1c\x1d\x35\xe0\xa9\xf2\x77\x15\x47\x57\x0d\x78\x30\x1d\x56\x1c\x49\x0d\x1c\xf3\x50\x2f\x35\x40\xf9\x3a\x50\x05\x34\x0e\xef\xa1\xa8\x82\xcf\xcb\xf4\x5a\x5b\x76\x8a\x62\xc7\xd8\x54\x5f\xc6\x7a\xf6\x31\xfa\x7c\xfd\x1d\x91\x20\x69\x29\xa9\xc2\x7b\x95\x67\x4e\xc8\xd0\x02\x81\x63\xea\xdb\x9a\x9f\xb4\x70\xe3\x2f\x2e\xa5\xf6\x33\x25\xc5\x46\x4b\x40\xab\x93\xc6\xec\x1d\x3b\x5e\xca\xc1\xb4\x69\x72\x42\xe0\xd5\x8f\x57\xaf\xdf\xbc\xbf\xbd\xfa\xfa\xea\xcd\xc7\xcf\x96\xf5\x12\xd4\x3e\xb2\x6f\xae\xc6\xb1\xd4\x2c\x3d\x6c\xaf\x79\xb3\xb5\x15\xd4\xe9\x9a\x89\x4a\x39\x5c\x5a\x1e\x75\x7d\xd5\x8e\x6c\xf5\x66\x89\xd5\x67\xf9\xa6\x8e\x52\xc7\x1d\xe6\x74\xd0\x53\xe1\xcd\x37\xaa\xa1\x6a\xe9\x01\x73\xd5\x9b\x67\x54\x6f\x87\xa5\xfd\x3e\x0f\xff\x85\x8f\x6d\xf2\x5a\x7a\xd0\xf0\x0d\x59\xf9\x3d\xe6\xaf\x37\xcb\x07\xbc\x27\xde\x3c\x6b\xe3\xb9\x9f\x3a\xe5\xdd\x7e\x25\x8e\xd8\xfd\x5a\x8a\x55\x14\xd1\x7b\x63\x03\x6d\x0e\x5d\xe6\x3d\x49\x43\x46\xcc\x89\xb2\x63\xf5\xdf\x77\x1d\xb7\x95\x73\x0d\xd4\x8d\x22\xbc\x59\x1a\x7e\x58\x23\x31\x4c\x6d\x06\x35\xee\x8e\xd1\xed\xda\xa6\xdf\xbc\x23\xe5\x9f\xe8\xe6\x23\x0d\xe8\xd0\xb2\x83\x3a\x2c\x68\x66\x8c\x59\xb8\x1b\x1d\x1e\xeb\x13\x82\xad\x5f\xd5\xc3\x0c\x69\x6d\xf3\xa4\x7a\xa5\x87\x4d\x4b\xac\x46\xe7\x77\xd4\xbb\x16\x40\x4d\x3b\x8d\xbb\x43\x17\x1c\xea\x5b\xa2\xd9\x41\x21\xeb\x0d\x31\x9b\x9c\x47\x6f\x09\x7f\xe2\x0c\xfc\xf0\xb9\x6a\x8d\x1d\x6d\xdd\x2a\xc1\x2c\x8f\x6f\x9b\x23\xd6\xc6\x36\xa4\xf7\x17\x2e\x17\x75\x62\xec\x8e\x89\x3d\x63\xea\x02\x53\xb4\x2e\x7e\x89\xff\x09\x1e\x94\x6d\x9c\x77\x99\xe7\xae\xba\x4a\xa5\xe8\xbc\xf2\xa9\x7c\xdd\x27\x44\x36\xa9\x29\x90\x92\x7d\x47\xa5\x62\xc2\xab\x7d\x43\x9f\xee\x18\xcf\xcf\xa1\x62\xf9\x57\xfe\xdd\xd5\x2c\x45\xdb\xbf\xc2\x0b\xad\xb9\x4b\x03\x99\xa7\xe1\xc7\xbd\x6b\x6f\x35\xa2\x3e\x98\xab\x2d\x28\x6b\xe4\x51\x8d\xb8\x08\x66\xe9\x2e\x6c\x51\x16\x35\xa4\x00\x08\xd4\x1b\x37\xa6\xce\x3e\x69\x94\x76\xd0\xfb\x59\xa8\x60\xd3\x45\x2f\x7f\x59\xb7\xcc\x0c\x13\x01\x2b\xaa\x49\x4e\x34\x99\x1a\x69\x72\xde\xff\x51\x95\x24\xf3\x6a\xe6\x31\xc0\xbe\x20\x33\x5a\xa8\xce\x03\xd0\x78\x44\x7f\xb3\x57\x41\xe9\x96\x10\x2f\xc4\x45\x4e\xdf\xe3\x1b\xe0\x8f\xee\x6a\x7d\x99\x65\xa2\xe2\x1a\xff\x10\xf6\x0c\x2c\xa3\x3e\x5d\x0a\xa5\xaf\xae\xcf\xeb\x1f\x4b\x91\x5f\x5d\x47\x61\x8c\x9c\x54\x40\xd3\xc8\x27\x66\x86\xe1\x66\xf5\x2c\xbc\x57\x53\x2c\x63\xac\xd5\x40\x51\x85\xb4\xe3\x19\x2e\x4e\xed\x89\x56\xd9\x92\xae\x48\xd0\x2d\xaf\xa6\xaf\xeb\xc9\x07\xa6\x02\xda\xa3\xf4\x89\x71\x2c\x85\x6f\xee\xff\x51\xba\xa5\x5a\x32\x97\xf5\xf5\x8b\x67\x4f\xc6\x1c\x6d\xf6\x6d\xd4\xad\x82\x6b\x11\xc9\x24\xb5\x6a\xa0\x31\xe4\xa3\xac\xeb\xb2\x9b\x26\x70\x79\x7d\x15\xcc\x74\x6d\xcf\xc6\x93\x58\xd6\x1a\xb4\xf9\xf5\x13\xd5\xeb\x2d\x9a\x7a\xab\x64\x74\xd8\x16\x14\xbc\xd8\x34\xbc\x95\x6d\xea\x10\x76\x5e\x09\xcf\x51\x3b\x50\xa5\x15\x9c\x5a\x86\xd3\xac\xac\xc2\x14\xa0\xe3\xb3\xa2\x2b\x21\x37\xe7\xf5\x8f\x0d\x5c\x77\xa2\xb4\x90\x64\x11\xa8\xbe\xeb\x61\xe3\x70\xdb\x9f\xec\x43\xa3\x4d\xca\xee\xa8\xfd\xbd\xcf\xe0\xb2\x38\xb3\x4a\x9a\x0b\x68\xb1\x69\x1b\xa4\xff\x7c\xac\x04\x4f\x8c\x7b\x97\x62\x19\x09\xcd\xa9\x7b\x1f\xdd\x21\xf1\x2a\x38\x60\x54\x13\x3a\x4b\x9a\xb9\x87\xb9\x17\xe2\xb0\x4f\xae\xa8\xf7\x79\x73\x91\x0d\xbf\xf8\x0b\x09\x94\xaf\x61\x4d\xa4\x67\x43\xdf\x96\xa2\xe9\xf5\x9c\xad\x99\x12\x81\x22\x75\x5f\x7d\xa8\x28\x7a\xdd\x75\xec\xb1\x99\xac\xb1\x8c\x4a\xfa\xa9\xc4\xce\x8f\x8d\x1e\x08\xf7\xc1\xe4\xdd\x38\xcb\x0b\xff\x1a\x75\x96\x4a\xa2\x35\x95\xfc\x25\xfc\xd7\xe9\x5f\x7f\xfd\xd3\xe4\xec\xab\xd3\xd3\xef\x9f\x4f\xfe\xe3\x87\x5f\x9f\xfe\x75\x8a\xff\xf8\xd7\xb3\xaf\xce\x7e\xaa\x7f\xf8\xf5\xd9\xd9\xe9\xe9\xf7\x7f\x7a\xf7\xcd\xed\xf5\x9b\x1f\xd8\xd9\x4f\xdf\xf3\x6a\x75\x67\x7f\xfa\xe9\xf4\x7b\xfa\xe6\x87\x23\x99\x9c\x9d\x7d\xf5\xab\xc0\x81\x07\x36\x5e\xb7\x14\xab\xfd\x7a\x9f\x5b\x84\xe3\xf2\x28\xad\xd8\x5b\xaa\xb7\x63\x5c\x39\xfb\x31\x82\x4e\xea\x8f\xaf\x35\xb3\x9f\x84\x20\x53\x34\x93\x54\x3f\xed\x88\x92\x1d\x63\xa7\xed\x45\x40\x69\x4c\xa8\x0b\xbc\x95\x24\xc8\x46\x78\x52\x36\x4f\x0a\x50\x3d\x44\xb5\x33\xc4\xee\xa2\x78\xb7\xdc\xb9\x14\xab\xba\xb5\x00\x42\xb4\xd6\xa4\x60\xa1\xfe\xe6\xfa\x44\x9a\x37\x7f\x12\x57\x5d\x48\x01\xb5\x14\x50\x1b\x43\x29\xa0\x36\x8e\xba\x01\xb5\x1b\x3c\xfb\x29\x9a\x36\x44\x94\xaf\xfd\x20\x50\x83\x18\xf9\xda\x87\xd5\xe9\x72\xeb\xf1\x6e\x83\x48\xfb\x5d\xc0\xbc\x07\x67\xa7\xfc\x5a\xdc\x69\x9b\x8d\xe5\xeb\xde\x58\x0d\x63\x89\xe1\xb2\x28\x80\x71\x5f\xe5\x85\x83\x6c\xeb\xbb\x59\x77\x12\x10\x85\xc5\x0c\xd6\x7e\xf0\xd3\xba\xdc\x42\xb7\xf2\xb3\x02\xac\x94\x30\xba\x7e\x8d\xa5\x3f\xdb\x72\x0d\x77\xb6\x82\x83\xd2\xb8\x48\xab\xaa\xd0\xac\x2c\x28\x04\x5c\x64\x2d\xec\xb0\xa8\x28\x10\xa5\x44\x66\x4b\xef\x34\xd5\xc5\x0a\xa2\x7c\xde\xdf\xdd\x14\x70\x56\x35\xb9\x43\x14\x72\x46\x73\xca\x33\x8a\x05\xdc\xc6\x96\x6e\xb3\x54\xef\xa4\xd9\xc6\xac\xcd\x1b\xbe\x6e\x72\xa6\xea\x2a\x7f\x7e\xcb\xbf\x67\x9c\xff\xbc\x49\x22\x46\x4c\x39\x90\x65\x9b\x2b\xe2\x25\x39\xd1\x6e\x6d\x3c\xf9\x04\xd3\x71\xc4\xbc\xc5\x5d\x78\x65\xf5\x84\xdd\x5c\x42\x6f\x0b\x0d\x8a\x31\xe0\xc2\xb9\x73\x4d\x68\x26\x24\xa4\x35\x94\xbd\x16\xa0\x59\xef\xc9\xe3\x89\x00\x45\x43\xcd\xf5\x41\x53\x3d\x38\x8a\xdc\x37\xd3\x9f\x9e\x99\xfd\x08\x26\xf6\x80\x79\x6d\xcd\xe3\x20\xae\xa1\xa6\x75\x14\xb3\x3a\x86\x49\x3d\x64\x4e\x07\xa4\xc1\xb6\xd4\xc3\xa6\x45\x31\x81\xc3\xcd\xdf\x70\x20\x59\x29\xe9\x9c\x7d\x8a\x22\x33\x2f\x79\xb3\x80\xc0\x72\xca\x35\x9b\xb3\x90\x7e\xc2\xc2\x0c\xae\xa4\xdc\x16\x9c\x22\xd9\x12\xed\x82\xc0\x0e\x46\x2d\x90\xfc\xa9\xa5\xc1\x59\x17\x4d\x4c\x05\x76\x13\xcb\x39\x95\xb4\x57\xd2\x5e\x49\x7b\x1d\xa2\x27\xaf\xbd\x9c\x3c\xa8\xaf\xec\x9f\x57\xfd\x60\xed\x96\xd0\xf2\x34\xaf\x3b\x95\xc3\xf0\x8c\x7b\xbb\x6b\x8f\x3f\x7b\x6d\x5d\xbe\x0b\x7c\xae\x07\x76\x20\x60\xbb\xe1\x23\xaf\xab\xa2\x18\x5f\x15\xde\x52\x7f\x02\xaf\x70\xe6\xca\xaa\x28\x5c\x21\xef\x29\x7c\xf0\xea\x28\x2b\xe6\x70\x59\xdc\x93\x8d\x3a\x87\xf7\x74\x4d\xe5\x39\x5c\xcd\xdf\x0b\x7d\x6d\x2f\xaa\x3e\x4a\xb5\x9b\x27\x69\x59\x03\x9b\xc3\xcb\x82\x68\xaa\x34\x68\xe2\x73\x50\x99\xea\xf6\x39\x13\xb2\x37\xc8\xb6\xe5\x68\x9c\xf6\xee\x63\x85\xfa\xce\xc6\xfa\x65\x5d\x71\x72\xf2\x19\x36\x5a\xc1\xe6\x34\xdb\x64\x45\xe8\x19\x7d\x5b\xf3\xa9\xeb\x2a\x91\xa2\x10\xf7\x5e\x62\x07\x01\x3b\x03\x45\x3e\xbf\xa8\x36\x2c\xa5\x50\xfa\x46\x13\xa9\x23\xf4\x62\x39\xb9\xae\x99\x99\xc9\xcd\x48\x51\x78\x8b\x73\xb6\x5a\xd1\x9c\x11\x4d\x8b\x0d\x90\xb9\xa6\xb2\x5b\x51\xd8\x97\xa7\xb2\x55\xbc\x5d\x21\x5a\xec\xb4\x4d\x78\x5e\x50\x09\x73\xc2\x0a\x6f\x8c\xcf\x8e\x13\xd7\xf6\x08\xf7\xea\x28\x62\xc9\x82\x23\x5d\xd5\x5c\x20\x59\x26\x64\x8e\x45\xb9\x04\xf8\x83\x51\x1d\xc3\x56\xb0\xa2\x0d\xb5\x22\x9c\x2c\x68\x40\x09\x85\x6d\xf4\x2d\xcc\x0a\x91\xdd\x29\xa8\xb8\x66\xbe\xb6\x99\x6d\x82\x2e\xee\x20\x13\xab\xb2\x40\xf1\x14\x56\xd8\x0f\x1e\x2e\xee\x37\x24\xf3\x9a\x7f\x4e\x1a\xd1\x33\x31\x63\x52\x17\xbf\x6c\xff\x84\xbf\xf0\xb3\xf4\x82\x6f\x22\xe1\xf7\x10\xfa\x89\x66\xfe\xd6\x61\xef\xe8\x7f\xe0\x14\x77\x6d\x50\xdf\x6d\x00\xc1\x1b\x38\xf7\x5c\x18\xc1\x6c\x76\x7d\x60\x13\x5e\xe8\x55\xf3\x9f\xc2\x9b\x4f\x34\x6b\x7e\x0e\xb9\x90\x98\x51\xda\x06\x04\x58\x7b\x96\xdc\x05\x94\x04\x88\x02\xb5\x89\x03\x72\xf1\x2e\xd5\xd8\xa5\xad\x1e\xb1\xc8\x31\xa4\xbe\x81\x25\x2b\x68\x2c\xb3\x82\xf1\xd1\x8d\x62\x76\xc9\x15\x82\x04\xc6\x95\x6d\x58\xd7\x91\x64\xa1\x30\x01\xc3\x6c\xa7\x25\x6e\x20\xcf\xba\x5d\x52\x3d\x0b\xe1\x73\x2a\x85\xd0\x70\x7a\x72\x71\x72\xb6\x13\xd3\x0d\x84\xa0\x99\xdb\x75\x41\xd5\x46\x69\xba\xb2\xe5\x65\xdc\xa8\x03\xb9\x32\x6c\xa2\x5d\x62\x07\x65\x9a\x9d\xe4\xe7\xc0\x42\xe1\x04\xce\x16\xb4\xbd\x4a\x70\x27\x84\xe5\xa6\x80\xad\x27\x7a\x0e\x4a\x80\x96\x24\x67\x51\x30\xe2\xc8\xd3\x0c\x50\xcb\xca\x35\x3e\x39\x3d\xf9\x69\x64\x1f\xaa\x5d\xa2\x3a\x3b\x83\x7b\xc1\x4f\x34\x6e\xd7\x29\xdc\x86\x9e\xaa\x4a\xd1\xba\xa4\xaa\xed\xea\xc4\x69\x38\xac\x42\x74\x9b\x3a\x19\xe3\x12\x44\x15\xba\xee\x58\x33\x9c\xe8\xba\xfa\xeb\x9b\x4f\xc1\x3b\xc9\xe6\xa5\x1a\x25\xf6\x1c\x4d\x41\x6b\x70\x06\x32\x25\x0a\x0a\xb6\xa6\x17\x4b\x4a\x0a\xbd\xdc\x40\xf8\x19\xe2\x82\x4f\xfe\x4e\xa5\xc0\xfa\xb4\xdc\xf1\x0d\xc3\xe2\x85\x84\xa5\xbb\xe4\x1d\xa2\xde\x1d\x4c\x90\x07\xcd\xd8\x8b\xdf\x50\xcf\x7b\x11\x6c\xeb\xc0\x3f\xde\xde\x5e\x7f\x43\x75\x34\xc3\xc3\x8c\xae\x4e\xa0\xea\x34\x53\xfa\xcc\x16\x48\x38\xd4\x77\x02\xa5\x90\x9f\xdb\x04\x5a\x0a\x15\xb0\xee\xb0\xb3\xf6\x42\x69\xdf\xfa\x8f\x5d\xd2\xc2\xe8\x66\x4e\x33\xb3\xe2\xd1\x92\x89\x5d\xdf\x84\x52\xe4\x70\x75\x3d\x85\xbf\x88\xca\xcc\xe2\x8c\xcc\x82\x2c\x79\x43\xf7\x84\xeb\xba\xc0\xea\x33\x33\x09\xcf\x42\xc2\x65\x96\xcc\xbe\xff\x23\x25\x39\x95\x0a\x35\x21\x25\x9e\xad\x5f\x6b\x8a\x04\xc0\xec\x8c\x2b\xa6\xe5\x5c\x29\x2d\x56\xb0\xb4\x8c\xc3\x17\xba\x53\xea\xd6\xc9\x8e\x50\xfc\xb5\x91\x6b\xd6\x87\xa6\x40\xd2\x32\x86\xb6\x73\x6f\xfb\x33\xd2\x46\x3b\x9a\xc0\xee\x94\x40\xae\x35\xdf\x19\x76\x42\xca\x70\xab\x04\xb3\xb4\x93\x6f\xf6\x8a\x2b\x4f\x17\xcc\x91\x71\xbb\x49\x8c\x50\x09\x46\x89\x47\x4a\x49\x81\x48\x69\x29\x10\x52\xda\xb7\xcf\x04\x01\x96\x81\x5c\x62\x65\xb9\x40\xa4\x7c\x08\x18\x80\x01\x44\x60\xd9\xec\x52\x5b\xd3\x21\xc2\xf4\x43\x4c\x24\x3e\x84\x16\x11\xee\xd2\xe3\x4f\x5f\x8c\x8d\x07\xf1\xe6\xaf\x0c\x2e\x22\xb2\x5b\x42\x44\x0b\x20\x59\xe6\xd7\xbc\xa6\x4b\xc2\xaa\x4e\x14\x67\xb6\x53\xe4\x93\xb0\x3d\x8c\xc5\x1c\x71\xca\x2c\x9c\x44\x02\xaf\x56\xb3\x60\x25\xd5\xd4\xdd\x92\x3a\xf6\x32\x74\x8a\xf5\xbf\x8f\x31\xd4\x1a\x88\x50\x1b\x48\x84\x2f\x42\xcf\xc5\x0b\xf3\xce\xbf\xff\xdd\xef\x7e\xfb\xbb\xa9\x9d\x56\xf3\x8c\x40\x9e\x33\x0a\x84\xc3\xd5\xe5\xfb\xcb\x1f\x6f\xbe\x7b\x85\x35\x90\xc3\x76\x61\x84\x94\xec\x98\x09\xd9\x11\xd3\xb1\x1f\x31\x19\x1b\xcb\x4e\x05\x4a\xf8\x3e\xba\x06\x19\x86\x7b\xb4\x2b\x65\xcb\x1e\xbb\x9b\xa2\x0d\x1b\x46\xf0\x64\x9b\x3b\x71\xaf\x5a\x74\x84\x8b\xc3\x67\x97\x9e\x3a\x2b\x6f\x44\x76\x17\xcd\xcb\x73\x72\xfb\xea\xda\x32\x8c\xe2\xe8\x21\xbc\x0e\x30\x31\xbe\x16\xc5\xda\x2c\x26\x81\xdb\x57\xd7\x81\xca\x62\x6a\x78\x60\x84\xd5\xfa\xbd\x37\x41\xf9\x78\x4d\x81\x1d\x07\xd0\x63\xab\xb2\x08\x89\x28\x03\x56\x7c\x97\x94\x14\x4c\x69\x96\xe1\x58\x9b\x18\x6c\x90\x57\x47\xdc\xf9\xa3\xf2\x92\x7f\xac\xa5\xc8\xfe\xb1\x13\xbf\xd6\xfd\xbb\xd4\x38\xda\x3a\xae\xb2\x60\xa7\xc9\x79\xaf\x74\x4b\x78\x9d\x41\xe7\x68\x0b\x4b\x1c\x7e\xa2\x96\x23\x9a\x61\x7e\x0d\x1d\xbb\xc4\x3b\xbd\x66\x9c\xe5\x18\x1a\x41\x41\xbb\x73\xd7\x72\x0c\x64\xeb\x5e\xb8\x6f\x39\x86\xfa\x25\x8c\xdd\xb9\x63\x39\x46\xb2\x6d\x93\xe5\x78\x1c\x3d\x82\xe5\x58\x4a\x7a\xa3\x45\x19\x05\x67\x67\x59\x45\x45\xd9\xcd\xe8\x5c\x48\x1a\x07\x66\xd7\x02\xe0\x20\xaf\xa8\x6b\xda\xef\x5f\x1f\xb3\x0e\x73\x89\x2e\x5c\xcd\x3b\xf1\x1a\xd0\x64\xb1\x7d\xfe\x0b\xb6\xa6\x9c\x2a\x75\x81\xd0\xb8\xaa\xb4\x4e\x4a\x4f\xa6\x73\xc2\x8a\x4a\xd2\x73\xb3\xd2\x74\x55\xda\x5e\xf2\x81\xa5\xfa\xcc\x62\x50\x6e\x59\x51\x6d\xdb\xbb\xd7\xa8\x45\xff\xf5\x31\x36\x9f\xdd\x38\xb6\x2f\x69\x78\x73\xa6\x4c\x12\xb5\xa4\xd8\x92\x91\x7e\x62\x5a\xd9\x81\x4a\x4a\x94\x77\xa5\x5f\x84\xba\xb8\x8d\x84\x26\xb0\x82\x92\x28\x45\x73\x7f\x6d\xd0\x81\x7c\xda\x01\x5e\x8b\xfc\xe4\x44\x75\x1f\xe3\xc9\x79\x21\x49\x46\xa1\xa4\x92\x89\x1c\xb0\x76\x76\x2e\xee\x39\xcc\xe8\x82\x71\xdf\x1b\x80\x3b\x91\x66\xd0\xf5\x81\x37\x26\x2c\x0d\x00\x52\xd5\x7d\x6f\xa7\xf0\xb1\xd7\x97\xd3\x5f\x6b\x89\x4a\x67\xa2\xd5\xd6\x6e\x76\xcf\x03\x38\xb6\x48\x52\xcc\xb9\xc7\x63\x5e\x91\xa2\xd8\xb4\x62\xc5\x93\xb3\x2b\x2f\xa1\x1f\x6b\xe1\xbf\x30\x4c\xad\x39\xac\xa1\x1c\xbb\x07\xb4\x3b\x15\xfe\xb2\x49\x52\x92\x2d\xc3\xd2\x15\x12\x74\xf7\x00\x25\xe8\x6e\x82\xee\xee\xa5\x04\xdd\x4d\xd0\xdd\x04\xdd\x4d\xd0\xdd\x04\xdd\x4d\xd0\xdd\x91\x94\xa0\xbb\x87\x28\x41\x77\xf7\xd2\x93\x0c\x4d\x24\xe8\x6e\x82\xee\x1e\x4d\x09\xba\x9b\xa0\xbb\xe3\xf8\x26\xe8\xae\x17\x25\xe8\xee\x83\x94\xa0\xbb\x21\x94\xa0\xbb\xbe\x94\xa0\xbb\xa3\x29\x41\x77\x13\x74\x37\x80\x12\x00\xc3\x83\x12\x74\x37\xc2\xc5\xe1\xb3\x4b\xcf\x04\xdd\x4d\xd0\xdd\x23\x29\xf9\xc7\x5a\x4a\xd0\xdd\x00\x4a\xd0\xdd\x83\x94\xa0\xbb\x09\xba\x1b\xc0\xeb\xe9\x59\x8e\x35\x44\xf4\x5a\x8a\x59\x68\xf1\x51\xe4\xa1\xb0\x3f\x75\x2a\x3d\x1a\x80\x61\xda\x8b\x5f\x02\xe1\x55\x2d\x18\xda\xdb\xee\x36\x76\xa9\x8f\x40\xf2\xe4\xdd\xc7\x2d\xf5\xd1\x47\xbe\xe6\xaf\x37\x66\xe9\x09\xa0\xd7\x82\x71\x4a\x7b\x30\x4a\x81\x22\x7c\x0b\x9f\x54\x23\x8c\x02\x38\x0e\x62\x93\x02\x47\xb9\x83\x4b\xaa\x91\x45\x11\xde\x1c\x01\x98\x5d\x54\x51\x60\xa8\xbb\x83\x47\xea\x22\x8a\x02\xb8\x76\xb0\x48\xbb\x68\xa2\x90\x95\xd2\x43\x48\x22\x07\x84\x09\xb9\x61\xf5\x50\x44\x03\x38\xa0\x00\xde\x88\x20\x8a\x8c\x01\x1a\xc4\xff\x84\x19\x71\x03\xd8\x9f\x1a\xbd\x13\x32\xb1\x2d\xee\xa7\x8b\xdc\x09\xd9\x02\x0d\xe6\x67\x1b\xb5\x13\xe4\x07\xc8\x63\x23\x76\x62\xc4\x47\x83\x63\xa3\x81\xe6\x9a\xcb\x95\xb9\x5d\x4a\xaa\x96\xa2\xf0\x54\x05\x3d\x35\xf0\x8e\x71\xb6\xaa\x56\x46\xe6\x28\x23\xb7\xd9\x3a\x30\x91\x47\x35\x90\x4d\x8c\x7f\xda\xc0\xaa\xb7\xc6\x43\x89\x22\x69\x8e\xdc\xcd\x16\xc3\xaa\xe6\x4b\xb2\xf6\xb7\x77\x55\x95\x65\x94\xe6\x34\xef\x39\xf7\xe0\xb7\xd3\x7a\x2e\x3c\xf9\xda\x5e\x8f\x4c\xc1\x8b\x10\x0b\x23\xe4\x5a\x30\x17\x72\x45\x34\xf2\xf8\xed\x6f\x3c\x38\x04\x01\xc0\x1e\x05\xfc\x15\x1d\xf8\x15\x6c\xc6\x85\x39\xb4\x02\x9c\x59\xe1\xf6\x63\x98\x13\x6b\x18\xe0\x15\xa6\xe3\x86\xc0\x5d\x61\x1c\x1f\x01\xd8\x35\x08\xea\xea\xc2\x9f\xc2\x2c\xdd\x30\x40\x57\x24\xd8\x67\x30\x90\xeb\x71\x40\x5c\xc3\x00\x2e\x94\x2e\x21\xc6\x45\x1f\xbc\x15\x0e\xbf\x7a\x12\xa6\xc5\x63\x40\xae\x76\xe1\x56\x6e\xb2\xc2\x5c\xb9\x0d\xd4\x2a\x1e\x54\x2a\x12\x4c\x2a\x06\x44\x2a\x18\x1e\x15\x0e\x8d\x8a\x05\x8b\x8a\x01\x89\xda\x69\x68\x18\x61\x07\x41\xdd\x83\x2e\x0a\xc8\x38\x96\x0b\x35\x0a\x04\xea\x71\xa7\x2b\x06\xf4\x29\xc2\x7c\x85\x41\x9e\x1e\x07\xee\x14\x13\xea\x14\x63\x8a\x82\x02\x55\x8f\x03\x6f\x1a\x84\x36\x81\x77\x12\x38\x6c\xbb\xbb\xa6\xdd\xf0\x52\x00\xd3\x2d\x48\x53\x37\xb4\x14\xc0\xb5\x81\x33\xc5\x0d\x2b\x05\x86\x94\x62\x85\x93\x22\x85\x92\x1e\x09\x80\x14\x0a\x3e\x1a\x06\x1e\x19\x1b\x24\x60\x43\xec\x80\x8e\x5a\xd8\x50\x00\xd7\xae\x4f\x22\x0c\x32\x14\xb8\xa0\x8c\x33\xcd\x48\xf1\x9a\x16\x64\x73\x43\x33\xc1\x73\x4f\x6b\x62\xab\xed\xae\x0b\x99\xcf\x41\x59\xa6\x9e\xef\x67\x3d\x41\xfd\x82\x0f\x4b\xa2\xc0\xf5\x7f\xf3\xe4\xea\xaa\x87\xd4\xe1\x4b\x67\x98\x62\xec\xd1\xce\x87\xf6\x8f\x67\x8d\x2c\xcd\x70\x2f\xe4\x5d\x21\x48\xae\x2e\x4a\x61\xff\xaf\x2d\xcc\xd0\xa9\xc8\x60\x47\x18\x52\x92\xe1\x73\xba\x9c\x6c\xdd\x8b\x78\xdb\xeb\x8f\xe2\x1e\xc4\x5c\x53\x0e\xa7\x8c\xd7\x3b\xec\xcc\xd7\xfb\xd4\x38\x9b\x5a\x7f\x66\xe3\x34\xf4\xe7\xf9\xe2\x79\x3d\xb0\xc6\xe5\x18\x64\x98\x7d\xc9\x2e\x47\x74\xc6\x2a\xf5\x34\x3d\xda\x6e\x70\x8f\xe5\xd2\x76\xec\xe7\x55\x61\x85\x99\xaf\xff\x06\x9d\xe1\xce\x41\xde\xf7\x69\x7b\x6e\x0b\x68\xba\xea\xbf\xc0\x37\x6f\xa4\x21\xe1\x39\xb8\x9a\x5f\xde\x9c\xbb\x1b\xfe\x8b\xde\xba\x81\x50\xda\xc7\x82\xd1\xee\x85\xd0\x5a\x20\xac\x27\xd7\x1d\xf8\x6c\x0b\x82\xf5\xe5\xd8\x87\xce\x76\x01\xb0\x01\x63\x6c\x34\x64\x00\xf8\x35\xc5\x08\xfc\xbe\xbb\x17\xe4\x8a\xe1\x82\x00\x93\x78\x0b\xe0\x1a\x2b\x17\xbc\x9f\x07\x1e\x0a\x94\x7e\x32\xb7\xfd\x1a\x92\x1a\xea\x1b\x4b\xb7\xfd\x74\xdb\x3f\x40\x8f\x70\xdb\xd7\x6c\x45\x45\xa5\x9f\xec\x85\xf3\x7e\xc9\xb2\x65\xd7\x16\x64\x2b\x6f\x55\x2d\x2a\xbd\x65\xaf\xb9\x21\x46\x84\x22\xa4\x5b\xe7\x16\xf9\xc5\x34\x06\x1c\xaa\x56\x3c\x36\x78\x62\x8f\x17\x69\x1d\x17\x0d\x56\x16\x88\x02\x02\xaf\xdf\xdf\xfc\xf8\xf6\xf2\x3f\xdf\xbc\xf5\x11\x34\xb7\x4b\xa6\xac\xca\xac\xc5\x57\xc5\xd9\xdf\x2a\x0a\x64\x25\x8c\x2d\x58\x04\x0d\x55\x9d\xa3\x23\xa4\xf3\x0b\xcf\xe2\x4c\x31\x81\xd8\x5e\x62\xcc\x28\x36\x0f\x01\xd3\x8f\x3e\x18\x1e\x4f\x10\x99\xee\x17\x8b\xf6\x8e\x41\x6f\x01\x8b\xdd\xe8\xcd\xe4\x80\xa4\xa5\xa4\x8a\x72\x4f\x4b\x8d\x00\xa7\xda\xc8\x24\x6b\x87\x30\x0e\x04\x14\xe3\x8b\x22\x30\xa7\x25\xd0\xc6\x0f\xb1\xf0\x27\xed\xc8\xaf\xfd\x0c\xfd\x50\x33\xbf\xf7\x7c\x5f\x63\x64\xd0\xe8\x9c\x87\x25\xeb\xd9\x92\x77\x42\xd1\x3a\x1a\x57\x8a\xfc\x44\xc1\x95\x3f\xda\x83\xe4\xb9\xa4\x0a\x0b\x6b\x33\xd5\xda\x73\x46\x43\x32\xff\x4a\x2f\xb8\x17\x6d\x38\xed\x1c\x9e\xc3\x1f\xe0\x13\xfc\x01\x4d\xce\xdf\xfb\x5a\x86\x31\xcc\xba\x50\x87\x86\xbd\xfd\x5d\x5d\x47\xd9\x11\x7f\x5e\x12\x8d\xfc\xe0\xea\x3a\x04\xd2\x35\x63\x3c\xb7\x8a\xf6\x93\xa6\x92\x93\xa2\xbe\x90\x84\xcd\x74\x80\xe1\x6b\x5e\xea\xc9\x1f\x1c\x9b\xbc\x7e\x35\xf7\xe6\xd8\x58\x24\xe7\xa0\x7b\x47\xc7\x9b\x23\x1e\xb9\xc1\xa3\xe3\xcd\xd2\x1e\x39\xb8\x9a\xa3\x87\xe1\xbd\xd3\x14\x4c\x75\x46\xef\x3f\xa5\xcd\x5b\xaf\x88\xce\x96\x7d\xb5\xe6\x7f\x01\x7c\x67\x8e\x44\xc7\x78\xca\x05\x9a\x0e\x41\xf5\x42\xcd\x50\xbf\x6c\xc1\x13\x02\x34\xea\x9d\xa7\xab\xf9\xf6\xce\xf5\x9e\xd5\x7d\x97\xff\xa0\x62\xa4\xce\x14\xef\xd4\xd4\x2f\x45\x3e\x85\x37\x24\x5b\x7a\xf3\x34\x93\x97\x77\xec\xa3\x52\xe4\x76\xf0\x4b\xe2\x1d\xfa\x30\x96\x97\x1b\xab\x61\xef\x8a\xb9\x84\xa6\x4c\x59\xd1\x6d\x34\x43\x46\xb8\x99\x5b\x49\xe7\x54\xca\x90\xad\x2f\x60\xb6\x41\xbc\x0e\xcb\x68\xe0\x21\x08\xd0\x09\xa5\x14\x5a\x64\xc2\x3b\x9f\x7f\x3b\xdf\x15\x99\xe1\x74\x87\x38\xed\xdb\x38\xce\xb7\xaf\xaf\xcf\xe1\xf6\xd5\xf5\x39\x08\x09\x37\xaf\x42\x50\x05\x5d\x7f\xc5\xb3\xdb\x57\xd7\xcf\x3e\xc3\xa4\x4b\x4a\x72\x96\xd2\x8b\x87\x29\xa5\x17\x1f\x47\x29\xbd\xb8\x4f\x29\xbd\x38\x80\x67\x4a\x2f\x4e\xe9\xc5\x96\x52\x7a\x71\x4a\x2f\xf6\xa4\x94\x5e\x7c\x78\x70\x29\xbd\xf8\x8b\x05\x4c\xa5\xf4\xe2\xc3\x94\xa0\x43\x29\xbd\x38\xa5\x17\xef\x50\x4a\x2f\xfe\xdc\xa6\x45\x4a\x2f\x4e\xe9\xc5\x35\xa5\xf4\xe2\x11\x94\xd2\x8b\xc7\x51\x4a\x2f\x3e\x48\x4f\x0c\x70\x9c\xd2\x8b\x13\xe0\xf8\x58\x3e\x4f\x0f\x70\x0c\x29\xbd\xd8\x8f\x52\x7a\xf1\x78\x4a\xe9\xc5\xe3\x28\xa5\x17\x8f\xe7\x99\xd2\x8b\x5b\x4a\xe9\xc5\x29\xbd\xf8\x0b\xdd\xba\x29\xbd\x38\xa5\x17\x0f\x53\x8a\x11\xa4\xf4\xe2\x71\x94\xd2\x8b\xfd\x99\xa6\xdb\xbe\x3f\x9f\xa7\x77\xdb\x4f\xe9\xc5\x29\xbd\xf8\x20\x85\x98\x6e\x92\x2a\x51\xc9\xcc\x47\x45\xf6\xf6\xd5\xc7\x9a\xcf\x63\x02\x93\xe1\x4d\x8c\xec\x65\x85\xf8\x34\x55\x9a\x81\xca\x76\xd8\x85\xa4\x24\xf7\x89\x58\x9a\x17\xcd\x30\x74\xda\xaa\xd0\x2f\x0a\x43\x5d\xb0\x15\xf3\x49\x2d\x86\x1d\xe1\xf2\x16\x39\xb5\x81\xd2\x00\x9c\xcb\x8a\x7c\xc2\x9b\x11\x59\x89\x8a\x6b\x23\xaf\x32\xb1\x2a\xfd\x91\xb4\xdd\x95\xc6\x8d\xd9\x95\x05\x01\x58\x81\x43\x12\x24\x13\x7c\xce\x16\x95\x24\x66\x8a\x2e\x56\x84\x93\x05\x9d\xb8\x57\x99\x34\x83\x9a\x34\xbb\xf3\xe2\x33\x59\xe9\x24\xaf\xf1\xa5\xd7\xc1\x66\x73\x49\xb4\xa6\x92\xbf\x84\xff\x3a\xfd\xeb\xaf\x7f\x9a\x9c\x7d\x75\x7a\xfa\xfd\xf3\xc9\x7f\xfc\xf0\xeb\xd3\xbf\x4e\xf1\x1f\xff\x7a\xf6\xd5\xd9\x4f\xf5\x0f\xbf\x3e\x3b\x3b\x3d\xfd\xfe\x4f\xef\xbe\xb9\xbd\x7e\xf3\x03\x3b\xfb\xe9\x7b\x5e\xad\xee\xec\x4f\x3f\x9d\x7e\x4f\xdf\xfc\x70\x24\x93\xb3\xb3\xaf\x7e\xe5\x7d\x4b\x0c\xb0\x43\xe2\x58\x21\x51\x6c\x90\x47\xb0\x40\x1c\xcc\x24\x8a\x78\xf8\xe8\x78\xc5\x11\x10\xce\x75\x12\x5f\x40\xd4\x17\x56\xcc\xd4\xac\xc7\xec\xef\x8d\x14\x2b\xa6\x8d\x76\x30\x6a\x8d\x74\x20\xfc\xbe\x1c\x75\xaf\xdf\xa9\x13\xb9\x6c\x1e\x82\x85\x66\xaa\x0b\xb0\xee\x64\x24\x0a\xbd\xa4\xf2\x9e\x79\x07\x86\xcc\x4d\x89\xb7\x6e\x0d\x14\x82\x93\x9c\xce\x19\xf7\xf6\x94\xa0\x35\x37\xda\x90\x4b\x62\x38\x89\xe1\x31\x5c\x9e\x92\x18\x56\x34\xab\x24\xd3\x9b\x57\x82\x6b\xfa\xc9\xc3\x33\xd2\x8f\xf7\xf6\xb9\xb9\x8c\x15\x4f\xbb\xf7\xde\xc9\xb5\x2f\x3e\x8f\x10\x5f\xe6\x5a\xb2\x35\x2b\xe8\x82\xbe\x51\x19\x29\x50\x54\xc4\x50\x7b\x97\x7b\x78\xfb\xc7\x4c\xb4\x14\x85\x82\xfb\x25\x35\xe2\x19\x88\x79\x77\x74\x47\x65\xc4\x97\xe9\x82\x30\x0e\x2b\x23\x53\xcb\x7a\xa0\xca\x68\x14\x0e\xcc\x5b\xf7\x99\x1b\x16\xd7\xf5\xe0\x5c\x4d\x93\x99\x10\x85\x4b\x3b\xf3\xc6\x21\x37\x33\xc0\xac\x53\x8e\x8b\x1f\x39\xbd\xff\xd1\x8c\xdc\x77\xac\xf3\x82\x2c\xe0\x9e\x15\x05\xe6\x6a\x52\xbd\xd3\x89\xda\x77\x0e\xea\x97\x8f\xbc\x09\x30\xcf\xa8\xa2\x40\x8a\x7b\xb2\xc1\xad\x10\x67\xbc\x4c\xbd\x84\x17\x67\x98\xbf\x46\x14\x34\xe3\xcd\xe1\x37\xbe\x61\xe3\x25\x51\xf0\xea\xf2\xfa\xc7\x9b\xbf\xdc\xfc\x78\xf9\xfa\xdd\xd5\xfb\x10\xcd\x6a\x76\x0f\xf5\xda\xe4\x19\x29\xc9\x8c\x15\xcc\x5f\xa1\xee\x60\x11\xbb\x2c\x03\xec\xa3\x3c\xbf\xc8\xa5\x28\xed\x1a\xca\x8a\x73\xc6\x17\x41\x62\xd4\xd2\xeb\x7e\x53\xfc\xda\x68\x34\x9b\xdb\xd7\x41\x37\xef\xbd\x32\x2c\x24\xe1\xc6\xb0\x9d\x6d\x02\x32\x47\x5b\xb8\x8a\xac\xb8\x66\xab\x2f\x37\x21\x99\xe4\xb1\x92\x91\x2f\xf3\x9c\xe6\x31\xb6\xd7\x53\x04\xe3\xbf\xaa\x5f\x2b\x24\x0b\x05\xda\x42\x6d\x70\xfd\xe1\xe6\xea\x7f\xc7\x99\x2d\x70\x33\x16\x12\xd4\x09\x37\x1f\x8d\x34\x88\xb4\x93\x3e\xd2\x95\x58\xa7\xbd\x74\x80\x7e\xa6\x7b\xa9\xb1\xe4\x62\xe0\x88\x3e\x56\xbc\x23\xab\xbd\x93\xfa\xdb\x31\xc1\x4a\xe4\x74\x0a\xd7\xd6\x40\xa2\x2a\x0a\xcf\x6e\x99\x4f\x49\xc1\x30\xe6\x9a\x91\xc2\xdb\xd4\xa4\x7f\xab\xd8\x9a\x14\xd4\x26\xbd\x61\x59\x83\x6e\xc9\xb2\x08\xba\x79\x4e\x0a\x15\xa4\xf4\xfc\x6d\x22\x63\x9c\xbe\x13\x15\x8f\x81\xd9\x69\x78\x41\x4e\xb9\xd0\x41\xae\x3d\xf3\x5e\x58\x63\x4e\x8a\x0c\xac\x7b\x2f\x08\x9e\x5c\xe3\xd5\xba\xa1\xa4\xdb\xd6\x24\xf2\x37\xc1\xdd\x3a\x5e\x37\xef\x6e\xe3\xa1\x95\x0a\x7a\xfd\x1d\x93\x28\x14\xde\x61\xde\x5f\x52\x92\x63\x75\x9b\x92\xe8\xa5\xc5\xae\xad\x88\xba\xf3\x76\xc3\x21\x1b\x77\xa7\x73\x0e\x53\x5b\x94\xa6\x99\x8c\x5b\x7f\xe1\x37\xa7\x44\x57\x92\xda\x5b\x99\x4d\x90\xa3\x9c\xcc\x0a\x5f\xb4\x71\xa0\x20\x35\x73\xf7\x81\x17\x9b\x8f\x42\xe8\xaf\x9b\x0a\x24\x11\x0e\xcd\x9f\xdd\x0d\x1e\x8b\xf7\x85\x5e\xdd\x96\x58\x8b\xd9\x8c\x75\x82\x0b\x8d\xc2\x2a\xbc\x60\x8a\xdb\xe3\x66\xbb\x7f\x46\x51\x25\x2b\x7e\xa9\xbe\x91\xa2\xf2\xb4\x8c\x76\x2e\x6f\xdf\x5c\xbd\x46\x89\x5e\xf1\x80\xcb\x0b\xe5\x5a\x6e\x4a\xc1\x6c\xfc\x21\xaa\xbf\xe0\x5b\xa3\x12\xb7\xce\xbf\xaf\xa0\x9a\x43\xc5\x15\xd5\x53\x78\x47\x36\x40\x0a\x25\x6a\x27\x87\xb7\xca\xbd\x46\x94\x7a\xd7\x8f\x38\x05\x2c\x66\xe8\x7d\xb9\x64\x1c\x66\x42\x2f\x77\xdc\x93\xfe\xd5\x0b\x77\xc7\x88\x55\x93\x82\xc0\xe5\x6d\xe1\x73\xc6\xb7\x87\xea\x2b\xf1\xc9\x1d\x55\x50\x4a\x9a\xd1\x9c\xf2\x2c\xe8\x7c\x45\x42\x91\xfc\xfe\xdf\xfe\x3f\xf6\xde\x85\x39\x8e\xdb\x5a\x17\xfd\x2b\x28\x26\xa7\x48\xc6\x9c\xa1\xe4\xe4\xe4\xa1\x93\x8a\x8b\x21\x29\x87\x15\x8b\xe2\x15\x25\xfb\xee\xeb\x78\xa7\x30\xdd\x98\x19\x6c\x76\x03\x1d\x00\x3d\xe4\xe4\xea\xfe\xf7\x5b\x58\x00\xfa\x31\x33\xb4\xd4\x0b\xa0\x48\x3a\x8d\x53\x75\x6c\x29\xdb\x6b\xd0\x78\xac\x17\xbe\xf5\x2d\xec\x0d\xbd\x94\xc2\x2a\xc9\x04\x77\xf4\x42\xe4\x3c\xa3\xc6\x65\x21\x4d\x92\x04\x03\xe0\xd7\x7c\x66\x8b\x02\xa1\x8e\x55\x91\x48\xb1\xb5\x66\x0a\x1e\x08\x8d\xaa\x99\x3b\x58\x7f\xaf\x67\xac\x60\x06\xd2\x88\xf8\xc7\x2d\x9e\x53\xe3\xd8\xbe\x78\x49\x17\x8c\x50\x13\xd4\x00\x3e\xc7\xc4\x84\xb6\xe6\x14\x56\x92\x1b\x92\x4b\xd6\xd0\x54\x61\x93\x1d\x9a\x7c\xb8\x38\x23\x2f\xc8\x81\x5d\xc3\x43\xf0\x27\xe6\x94\x17\x78\xbe\x0a\x40\xd2\x6f\xf8\x3f\x7c\x1e\xa6\x8b\xb5\x5e\x17\x5e\xf7\x11\xa9\x9c\xf9\x3a\x22\x42\x12\x5d\x67\xcb\xb0\xd6\xf8\x1c\x6c\x48\x17\xfb\xaa\x18\x80\x94\x78\x05\x8b\x94\xd8\xa8\xe5\xfb\x14\x2c\x76\x6d\x9d\xd0\x5d\x0a\x16\xfd\x54\x97\xdf\xa7\x60\xa3\x50\x7a\x4f\x5c\xc1\x46\x3a\x30\x1f\x34\x53\x89\xfc\x97\x0f\x4f\xdc\x7f\xe9\x86\xb8\x56\x57\xb6\x3b\x8b\x77\x10\x9c\x42\x2c\x99\xa1\x39\x35\xd4\xfb\x35\xb1\xbc\x9a\xdb\x3e\xd1\x78\xf9\x9e\xe6\xe5\x7b\x4c\xef\x46\xb3\xef\xb8\xa8\xef\x5c\x11\x47\xaa\x07\xa4\xeb\x73\x10\x0a\x97\x2e\x62\x89\xe1\xe8\xd2\xaa\x2a\x78\x8b\x41\x8d\xea\x36\x42\x1a\xc3\xd9\xe5\x26\x8f\x57\x0e\x21\x9c\x01\xc3\x19\x60\xb3\x36\x66\xa5\x22\x97\x58\x74\xf7\xc6\x22\x3a\x38\x02\xcd\x96\xdd\xd2\x0a\x7b\xc9\xb1\x77\x6d\x54\x0d\xcf\x40\x35\x3c\xea\xc3\x5f\xc1\x56\x0c\x4d\xa5\xbe\xa1\x16\xbe\xb3\xb2\x08\xd7\xe1\x58\x47\xbc\x1e\xc0\xb4\x48\x41\x67\xac\x70\x9e\xbf\x53\x11\x09\x6a\xc4\xa2\x95\x4b\x92\x67\x32\x25\x8b\x54\x1c\x18\xef\x64\x01\x05\x22\x34\xc1\xb2\xdb\x69\xfd\x82\x57\x1d\x44\xa4\x59\xf5\xf7\xeb\x2a\xd9\xaa\xc3\x93\xc1\x2f\x77\xd5\x6b\x74\xe0\x40\x36\x57\xdd\xc6\x20\xa9\x56\x1d\x1c\xfb\x5f\xe6\xaa\xdf\x72\x91\xcb\x5b\x9d\xd6\xe1\xfb\xc1\x09\x0d\xd6\x14\x5b\xda\xad\x99\x31\x5c\x2c\x74\xd7\xe9\xa3\x45\x1c\xf6\xd2\x8d\x5d\x5e\x9f\xac\x62\x38\xc6\xe7\x4a\x3a\xbe\x90\x6d\xaf\x24\x32\xed\x52\x6b\x0f\xd1\xef\x78\x51\x58\x1f\x72\x3b\xe9\xbc\xcb\x8b\x8a\x78\xd3\x1b\xbd\xa8\x4f\x8d\x45\xa9\xe9\xa9\xb2\x1f\x61\x38\x2d\xae\x2b\x6c\x5f\x0f\xb2\x79\xf1\xbe\x7d\x73\x7d\xd2\x17\x1c\xa1\x9f\x38\x60\x2d\x95\x4b\xd0\x5a\xc9\x84\xe6\x25\xd7\x1a\x9f\x45\xb4\xe3\x96\xcd\x96\x52\xde\x90\x83\x50\xca\xb0\xe0\x66\x59\xcf\xa6\x99\x2c\x3b\x55\x0d\x13\xcd\x17\xfa\xd8\x2b\xa6\x89\x5d\x2f\x2c\x26\x13\xbe\x44\x14\x5c\xf8\x37\x5b\x88\x9d\x84\xd1\x44\xe2\x3b\xb0\x91\x76\x49\xb2\x66\xb5\xe1\xc4\x47\x88\x74\xbd\xa2\x1c\xc0\x70\xc7\x46\x5e\xc6\xd5\xf4\x03\x0b\xe4\xa3\xda\xf5\xed\x43\x7f\x19\x45\x32\xfa\x89\x83\x1f\xb9\x5e\xae\x39\x8a\x23\xa0\xf0\xf9\x42\xfb\x1b\x11\x12\x37\x4e\x8a\x4f\x16\x3e\x6e\x58\x11\x12\xb5\x09\x77\x02\x12\xb6\x5e\x64\xd4\x95\x6d\x3c\x88\x36\xf5\xdb\x49\xe2\x46\x88\xde\x4c\xff\x36\x89\xdc\x08\x99\x9b\x08\xe4\x24\x69\x60\xf2\x80\xa9\x60\xf2\xd9\xe9\xe0\x88\x1f\xe8\x3b\x2c\x89\xbc\x00\x72\x7f\xea\x27\x52\xa1\x3f\x98\xe3\x42\x92\x39\x2f\x24\xee\xe2\x7b\x0a\xaf\xb1\x37\xdb\xf6\x18\x7b\xb3\x7d\xde\x18\x7b\xb3\xf5\xc7\xd8\x9b\x2d\x26\x18\x18\x7b\xb3\x8d\xbd\xd9\x60\x8c\xbd\xd9\xc6\xde\x6c\xc8\x31\xf6\x66\xfb\xf4\xe4\xc6\xde\x6c\xcf\x96\x6d\x76\xec\xcd\xf6\xe9\x31\xf2\xae\x8e\xbd\xd9\xc6\xde\x6c\x5b\x63\xec\xcd\xf6\xd8\xae\xc5\xd8\x9b\x6d\xec\xcd\x16\xc6\xd8\x9b\x6d\xc0\x18\x7b\xb3\x0d\x1b\x63\x6f\xb6\x4f\x8e\x27\xc6\xd6\x3e\xf6\x66\x1b\xd9\xda\x3f\x57\xce\xd3\x63\x6b\x27\x63\x6f\x36\xdc\x18\x7b\xb3\x0d\x1f\x63\x6f\xb6\x61\x63\xec\xcd\x36\x5c\xe6\xd8\x9b\xad\x1d\x63\x6f\xb6\xb1\x37\xdb\x33\x3d\xba\x63\x6f\xb6\xb1\x37\xdb\xee\x31\xbe\x11\x8c\xbd\xd9\x86\x8d\xb1\x37\x1b\x5e\xe8\x18\xed\xe3\xe5\x3c\xbd\x68\x7f\xec\xcd\x36\xf6\x66\xfb\xe4\x88\x71\xdd\xb4\xc9\x39\xa2\x01\xc1\xc3\x30\x0c\x7a\xb4\x6c\x87\xb5\x61\x56\xcf\xe7\x4c\x81\xdb\x0d\x33\x45\x25\x6e\x76\x13\x5e\x3a\x62\xad\x25\xc7\x1c\x57\x8f\xf2\xd3\xcc\x1c\x01\x19\xa2\x76\x25\x88\x30\x45\x1c\xe0\xb1\x3f\x45\x4f\x5e\x01\xb4\xfb\x8a\x69\x5c\x7c\xcd\x05\x39\x7f\xfb\x7a\x9a\x80\x5c\x31\x86\x97\x08\xd6\xe4\xad\xc8\x62\x61\xef\xed\x21\x8b\xe3\x08\x09\xfc\x20\xfe\xac\x65\x85\xd4\x0e\x5b\xeb\x36\x2f\x5b\x52\x21\x18\x86\x5a\xcd\x29\x44\x6e\x20\xed\x36\x63\x4c\x10\x59\x31\xe1\x2a\xcb\x28\xd1\x5c\x2c\x0a\x8c\x05\xa0\xc6\xd0\x6c\x39\xb5\xdf\x2f\xc2\x01\xf3\x7d\x19\x9a\x59\x63\xae\x9a\x51\x8c\x96\xee\xa0\x29\x56\x52\xee\xa6\x4b\x68\xa6\xa4\xd6\xa4\xac\x0b\xc3\xab\x88\x09\x13\xcd\xa0\x60\x51\xbb\xea\xd9\x70\x08\x08\xea\xba\x69\xe6\xc0\x9e\xc0\x82\xd7\xac\x81\x5f\x5e\x94\x0b\xd6\x5e\x35\x08\xe0\x8f\xa0\x3b\x55\x59\x99\x35\xb1\xc7\x03\xb3\xfd\x80\xfb\xe7\x4a\x1b\x92\x15\x1c\x22\x38\x58\x07\x06\x96\x0c\xe6\x8c\x41\x00\x53\x91\x5b\xc9\xc2\xef\x91\xf6\x9b\x24\x72\x70\x40\x2b\x94\xc3\x0f\xc5\x4c\xf0\x99\xee\x32\xb9\xe9\xe6\x5c\xfb\x80\x42\xa3\x26\x1a\x78\x89\xdd\xe5\x0a\x7b\x04\xd7\x2b\x47\x12\x6c\x86\x6f\xf6\x42\x3a\x53\x8e\xb8\xff\x40\x25\xec\xb3\xe2\x8d\x09\x70\x24\xc0\x41\x41\xa2\xbe\x7f\xbb\xac\x2d\xd0\x4a\x82\x81\x40\x88\xec\x98\x14\xb8\xa6\x82\xad\xac\xf5\x62\x19\xe3\x2b\xeb\x84\x23\x44\xee\xb4\x07\x5f\xd4\x1c\x18\xaa\x16\xcc\x9c\x86\xb5\xc2\xd5\x3f\xf6\x49\x3c\xe7\xce\x0e\x6f\x54\x8d\x46\x29\x05\x58\xfa\x2b\x99\x5f\x43\xbd\xa8\xe3\x06\x45\x69\xae\x1d\xf5\x55\x7e\x09\x1c\x3d\x78\x22\x91\x81\xae\x00\xc7\xb5\xe9\x3d\x24\xbb\x78\xba\xa2\x19\xd3\xe4\xe0\xe2\xea\xf4\x88\x5c\x5d\x9c\xb9\xca\x00\x84\x4c\x39\xdf\x70\x07\xe1\xae\x79\xa7\x09\x54\x1a\x52\xc7\xee\xfa\x7c\xae\x7d\xc1\x05\x42\xe6\xed\x92\x1a\xb8\x58\x9d\xcf\xa7\xca\xfa\x07\x54\xb9\xc6\x63\xc8\x89\x56\x32\x9f\x92\x4b\x69\x58\x43\x2e\x9b\xc4\x6f\x81\x20\xdc\x67\x1b\xbd\xee\x72\x44\xe6\x58\xb7\x0e\x15\xf4\x1a\xa6\x4a\x2e\x80\xd8\xf4\x0d\xd3\x9a\x2e\xd8\x15\x0a\xc4\x72\x5f\x8a\x0c\x70\x2c\xc1\xa6\xa0\xad\x71\x01\x79\xb2\x36\x46\x6d\x2b\x89\xf6\x31\x97\xb9\xf3\xd1\xa4\x74\x5f\xdd\xdc\xbc\x5b\xc5\x8d\x41\x1d\x6a\xae\x5d\xfb\x01\xc0\xff\x6d\x52\xd3\xe0\x26\xda\xa9\x92\x22\x6f\xc2\x44\xdd\x04\xed\xcf\xd9\x58\x53\xe4\xa8\x54\xb5\x03\x2b\xce\x14\x67\x73\x32\xe7\x50\x8c\x04\x65\x33\x47\x8e\xee\x96\x62\x66\x4b\x05\xa1\x5a\x33\x05\xeb\xea\xcb\x26\xc2\xfa\x4e\xc9\x0f\x38\xa2\xe3\x19\xb3\xee\xa2\x70\x3d\xb3\x3d\xb7\x83\x90\x39\x23\x7c\x4e\x16\x50\xa0\x83\xbb\xd7\x54\x90\xdf\xbd\xf8\xd3\xef\xc9\x6c\x6d\x98\xef\xf0\x60\xa4\xa1\x45\x98\x30\x42\x68\xc1\xc4\xc2\x9e\x76\xe7\x79\xf7\x39\x76\xb0\x3c\xcf\x33\xe6\x3a\x6e\x3b\xde\x9e\x97\x5f\xdf\xcc\x7a\xa9\x15\x84\xc4\xe3\x9c\xad\x8e\x3b\x37\x60\x52\xc8\xc5\x94\x9c\x52\x61\x75\x3a\xea\xfd\xaf\xae\x72\xc0\x0f\x0c\x4f\x9b\xa4\x55\x5c\xb2\xe0\xd9\x3a\xd6\x09\xf1\x4c\xe2\x64\x29\x6f\x5d\x7b\x91\xf6\x77\x10\x4b\x13\xb4\x4b\x5b\x3e\x5c\xc9\xaa\x2e\x60\xb9\xc8\x6b\x8e\x8a\xcb\x40\x53\xd5\x9a\x6d\x92\xb1\xdc\xa3\xcb\x71\xca\x21\x4c\x73\x23\x9f\xe1\x94\x44\xc4\x42\x48\xcf\x64\xe0\x1f\x89\x1b\x2a\x70\x94\xdd\x23\xe4\x35\x2d\x8a\x19\xcd\x6e\xde\xcb\xef\xe4\x42\xbf\x15\xe7\x4a\x49\xd5\x5b\x21\xcc\x3d\xa6\x36\xf8\x5b\xd6\xe2\xc6\x35\x8a\x0e\x1f\x5f\xc8\x05\x91\xb5\xa9\x6a\x54\x12\x67\xbe\x79\x9c\x9a\x35\x99\xe3\xce\x41\x13\xe9\xfa\xd8\xb2\x33\x53\x76\xc7\x71\x2f\x98\xb7\xdc\x2a\x30\x41\x98\x5d\x47\xa7\x15\xdb\xaf\xc6\xc5\xfc\x1d\xf5\xf5\xf5\x8b\xdf\xfd\xd1\x29\x5c\x22\x15\xf9\xe3\x0b\xa8\xad\x46\x45\xa9\xe0\x0a\x80\xb7\xc7\x35\xd1\x25\x2d\x0a\xeb\x98\xc6\x29\x46\x7b\x1d\x3b\x8a\xb0\x51\x6b\x5f\x54\xab\x99\x58\x05\xf6\x80\x39\xdc\xf7\xef\xff\x0b\x12\xb8\xdc\x68\x56\xcc\x51\xc1\x75\xa1\x65\xdb\x00\x68\x1f\x62\xe2\x7d\xef\x8b\x18\x55\xa3\x54\xc0\xe3\x66\x45\x57\xb2\xa8\x4b\x76\xc6\x56\x3c\xc3\xbc\x4e\xf7\xb6\xae\x27\x0b\x4f\x60\x50\x70\x0d\x0c\xed\xb3\x42\x66\x37\x24\xf7\xe2\xda\xea\x14\x8c\x17\xb2\x8e\x25\x5a\x8c\xa9\x25\x42\xd7\x10\xdd\xbb\xba\x6d\x05\x10\xea\x9d\x86\x92\x92\x56\x15\x17\x0b\xbb\xcc\x94\x28\x7a\xdb\x5b\x6c\x94\x4c\xab\x79\xb9\xe8\xa6\x9f\x30\x97\x21\x12\xe3\x11\x83\xf0\x98\xf8\xaf\x47\xfa\x1c\xe8\xf2\xa2\x58\x70\x48\x3b\x6b\xec\xfb\x75\xef\x98\xb5\xe2\x62\x29\x48\x2a\x90\xe1\xb8\x27\x12\x35\x5c\x20\x6d\x0a\xc3\xcd\xb3\x09\x7b\xed\x81\x8e\xa0\xd9\x32\x12\x8b\x1d\x88\x7e\xb0\x8f\x29\xe6\xea\xed\x9c\x68\xa0\x11\x25\x35\xa8\x64\x85\x1b\xdd\xfc\x25\x25\x15\x53\x9a\x6b\xeb\xa3\x7f\x0f\x0a\xe8\xb4\xa0\x1c\xfb\xfe\xdd\x64\xf8\x2a\x89\xdd\xaa\x88\xe5\x76\x0a\x14\xba\xf5\xc5\x5a\xba\x2b\x99\x7b\x71\x60\x98\x20\x6d\x82\xca\x77\x6e\xa5\x59\x62\x99\x65\x92\xb9\x7f\x8f\x69\xea\xbe\x6f\x77\x2a\xde\xd2\x59\x29\x8d\xa9\x73\x92\xbd\xb1\x42\x4a\x7c\xbe\x06\x0e\xd6\xe2\xb9\xd9\xb7\x66\xd2\x49\x94\x24\x18\x36\xef\xab\xc4\x18\xb7\x36\x56\x6d\x1f\x1c\x97\xcc\x2b\x05\xb4\xd4\x36\xcd\xe2\x33\xb1\x53\x8f\xf9\x16\xe8\xd6\x6d\xcd\x54\xc9\xfe\xab\xfd\x47\x33\x72\x6e\x13\x95\xac\xe8\x02\x72\x07\x49\xf6\x72\x53\x28\x7a\x85\x72\xe6\xd2\x1a\x4c\x43\xda\x0c\xe4\xc2\xe3\x0b\xde\xf7\xf1\xb3\x62\x79\xcb\x09\xbe\x94\x40\x94\x92\xe2\xc8\xf9\x84\x89\x84\x48\xf9\x36\x82\xde\x80\x2a\x59\x8b\xdc\x83\x3a\x1a\x24\xd1\x9b\x8d\x85\xbd\xc4\x13\x11\x42\x9a\xc7\x91\x97\x43\xf7\x5c\x57\xef\xcc\x35\x99\x31\x43\x63\xdc\x88\x97\xd3\x97\x2f\x9e\xbf\xcf\x06\x6b\x92\xc8\x67\xbb\x6c\x7c\x36\x67\xe5\x1e\x6d\x75\x42\x07\xe1\x24\x2b\xf4\xc6\x3f\x49\x35\xad\x7e\xf1\x87\x26\xb4\xaf\x04\x51\xb7\x8a\x1b\x7f\x83\x6e\x79\x44\xbd\xe9\x01\x24\x6d\x88\x54\x5d\x4e\xde\xc3\x36\x97\x17\x11\x92\xc4\xb4\x20\x8e\xef\xe1\x47\x88\xae\x67\x4f\xce\xee\x3a\x03\xeb\x94\xea\xae\xf7\x54\xfc\x7a\x7b\xc9\xdb\x26\x18\x2d\xb1\x0b\x21\xde\xdb\x23\x07\xee\x17\xf6\x1d\x29\xe5\xe1\xa3\x5d\x4f\xbf\xad\xe7\x77\x15\xba\xcb\x4a\x6f\x6b\xcf\xef\x2a\x2a\x72\x96\xbb\x80\x3f\xc2\xb5\x26\x81\x85\x79\xd7\x1e\xc7\x9b\xcd\x7d\xdd\xdf\x63\xb4\xc4\xae\x7b\xf6\x57\xb6\xa4\x2b\x06\xd4\x9d\xbc\xa0\x2a\x42\x3d\x19\x49\xae\xdd\xce\x90\x59\x6d\x08\x13\x2b\xae\xa4\x28\x59\x04\xd3\xf9\x8a\x2a\x4e\x67\x05\x23\x8a\xcd\x99\x62\x22\x63\x9a\xfc\xfa\xe0\xfb\x93\x77\x50\x2d\x81\xef\xa7\x40\x15\x23\x2c\xec\x7a\xad\xa1\xca\x3e\xd1\x2d\xec\x7c\xf6\x74\xe3\x02\xe1\x55\xf4\xc6\xc5\x0b\xeb\x6c\x6f\x00\x7e\x0d\x44\xde\xec\x97\x5d\x8f\xb2\x36\x35\x2d\x80\xbd\x35\x2b\x6a\xcd\x57\x8f\x61\x7f\x3d\x9b\xee\x19\x47\xdc\xec\x0d\x16\xe2\xf6\xd2\x6c\x51\xf4\x62\x3e\x2c\x60\xae\xd2\xf5\x58\xf4\x38\xa4\x7d\x1d\x6a\xce\x7a\xbd\x72\xd0\x8f\x72\xa4\xe4\x8b\x25\x24\x50\x32\x29\xe6\x7c\x51\x2b\xc7\x87\x15\x8b\xe4\x03\x0e\xff\xc7\x7b\x9e\xb3\xc1\xc7\x49\xc1\xa9\x1e\x16\x86\x6f\xb1\x0b\x7a\x19\xd0\x53\x4b\xf8\x6e\x49\x74\x18\x30\x24\xbc\xef\xd8\x29\xb9\x07\xf4\x8b\x2b\x8f\x50\x0d\x3b\xc8\xc5\xff\xb0\x6c\xe8\x0b\x70\x93\x4d\xab\x64\xbe\xaf\xbd\x78\xc0\x5e\xf1\x39\x96\xf5\x1c\xfc\x73\xae\x1d\x1d\x3b\xf4\xd0\x86\x17\x44\x21\xc5\xc4\xca\xbf\x64\xc6\xde\x8e\x41\x22\x2b\x99\x0f\xe2\xb4\xc3\xa5\xe3\x10\x89\xb8\xdd\x7b\x4d\x96\xb2\xc8\x1d\xcb\xbb\x7f\x34\x1a\x78\x60\x67\xcc\xdc\x32\x26\xc8\xc5\x15\xec\xb5\x5d\x36\x40\x38\xf6\x76\x7c\xa0\xcc\x70\x3e\xa0\xb9\xbd\x70\x4d\x41\x3a\xb9\xe5\xb0\xfb\x03\xa5\xda\xb3\x32\xec\x78\xa0\xb3\x79\xf8\xa4\x58\xb3\x7e\x91\x1a\xfe\x6f\xcd\x3e\x04\x12\x05\x3a\x93\x28\x4a\x06\xbb\xb1\x79\xae\x50\xfd\x53\x1e\x25\xd7\x1c\x61\x60\x79\x15\x8b\xcf\x6a\x16\x2b\xbc\x89\x2d\x71\x45\xd8\xa0\xd8\xe0\xe0\x7f\x41\x0b\x72\x71\x75\x8a\xb6\x1e\xfb\x1f\x3c\xe4\xcb\x0a\xda\xdf\xd7\x84\x57\x59\x8b\x75\x1e\xf6\x11\x2d\x3e\x37\xa0\x27\x9a\x68\x79\x08\x88\x0f\x17\x22\x77\x14\x7f\x94\x29\x25\xc2\x09\xb1\xbe\x95\xe7\x50\x45\xe0\xbc\x01\x27\x03\x10\xef\xde\xfa\xea\x20\x1d\xbb\xc4\xa1\x20\xc5\x99\x78\x80\x29\x85\xe2\x86\x4a\x2a\xa3\x87\x33\xde\x77\xdd\xb3\xa6\x84\xbb\xb5\xcb\x28\x02\x1f\x4c\x92\x04\xbf\xeb\x57\x17\x67\xe9\x8e\x7f\xc5\xf3\x67\x7b\xfc\x87\xe6\x3f\xfb\x3c\x6f\xbd\xd6\x31\x41\x1c\xa6\x5a\xe6\x4a\xe6\xf7\x04\x16\xad\x13\x30\xf8\xd5\x2a\x1c\x53\x5f\xeb\x47\x89\x7b\x8c\x9d\xe4\x6c\xce\x05\xf3\x5c\x9d\xc3\xcf\xdb\x40\x6d\x0b\xe1\xc2\x55\x5d\x14\xd7\x2c\x53\x6c\xd8\x83\x75\xff\xdc\x5d\x6c\x48\x4a\xe1\xba\x77\xf2\x09\xc0\x05\xed\x05\x3b\x07\x4c\x0f\x5d\xf1\xe6\x16\x78\xee\x3f\xf0\x48\xaa\xba\x28\x80\x23\x47\xac\x31\x47\x03\xd6\xcf\xbd\x3c\x38\xf4\x17\xd7\xa1\x8e\xca\x15\x82\x36\xe7\x65\xa0\xb6\x65\x9a\x35\x1f\x1c\x8e\x4a\x45\xb5\x76\x08\x51\x2e\x72\xbe\xe2\x79\x3d\x70\x5d\xed\xc7\x42\x8c\xe8\x59\x77\xe0\xd5\xa5\xf1\xcc\x4a\x54\xa7\xc0\xd7\x52\x11\x76\x47\xad\xc8\xa3\xa6\xf6\x9c\x6a\xb8\x68\xb9\xcc\x6e\x98\x3a\x22\x83\xf3\xe9\x67\xf0\x1f\x9e\x42\x64\xec\xda\x50\x87\xb5\xa0\xca\xde\x65\x21\xd5\xd0\x10\x6b\x20\x11\x42\x5b\x92\x70\xec\xf6\xf8\x57\x6e\x2b\xd7\x5c\x2c\x26\xf0\x37\x76\x31\xfd\xac\x26\x52\x4c\xe8\xc4\x2a\x83\x27\x1f\x70\x7d\x27\x33\x5a\xbc\x85\x48\xe2\x5d\xb8\x5d\x21\x7d\x30\x34\x90\x61\x42\xd6\x8b\x25\x2c\xaa\x2a\xa9\x6f\xcd\x45\x0a\x66\xa0\x07\x8e\xc3\xc3\x0e\x14\xe9\x88\xde\xfd\xbc\x72\x1f\xf2\x74\x3b\x42\x0d\xbe\xf5\x04\x6b\xfd\x1e\x21\xe8\xc2\xbd\xf7\x6d\xf0\x9d\x74\x1a\x89\xfa\x95\x44\xd1\x7e\x0d\xbc\x2f\x72\xc5\xd4\x8a\xb3\xdb\x63\xef\x6a\x4e\x6e\xb9\x59\x4e\xdc\xea\xe9\x63\xd8\x82\xe3\x5f\xc1\x3f\x10\x73\x71\x64\x61\x27\x79\xee\x9f\xa2\x6b\xcd\xe6\x75\xe1\x1e\x79\xf5\x94\xd0\x8a\x7f\xcf\x94\xe6\x12\x55\x72\x7e\xc3\x45\x7e\x44\x6a\x9e\x7f\xf3\x85\x0a\x73\xb8\xe0\x6d\x41\x70\x84\xc5\xfd\xce\x5b\x49\xcf\xd4\xca\xff\xed\xae\x60\xab\xb9\x06\x7d\xce\x8c\x15\x52\x2c\x3a\x4c\xb6\xe0\xec\x5f\x08\x6e\xb0\x12\x5d\xfa\x1e\xba\xc1\x41\x6a\x53\xaa\x1c\x8a\xc5\xb9\x35\x37\x12\x3f\x4f\xe8\x33\xd8\x29\x68\xb7\xa6\x9b\xf7\xe6\x09\xa5\x32\x03\x0b\x26\x02\x17\x98\x2b\x07\x08\x24\x8d\x46\x92\x25\x5d\xb1\xa6\xff\xd0\xc0\xba\x7e\xae\xc9\x92\x8a\x1c\xfe\xd3\x2c\x93\x2a\xf7\xeb\xcb\x4d\x53\x95\xef\xca\xb1\x86\xa6\x0b\x3d\x74\xd2\x5a\x6e\x2a\x36\xbf\x1e\x32\x87\xaa\x1c\xe8\x1c\xb4\xff\x7d\x08\x9a\x6a\xc1\xff\x55\x33\x42\x4b\x69\x1d\xa4\x88\x5e\xf8\x1b\xa7\x88\x94\x74\x0d\xde\x34\x2c\xed\x77\x81\x5f\x68\xd8\xe1\x72\x8d\xe0\x8e\xc8\x3b\x46\x73\xde\x21\xeb\x3d\x22\xdf\xf5\xd9\x7b\x87\x1d\x03\xa9\xc8\xb5\xa3\xb8\xf4\xff\xb9\xab\xee\x51\x4c\xcb\x5a\x65\xec\x9d\x03\xc6\x59\xe7\x69\xd8\xb1\x95\xf3\x1d\x1b\x65\x6f\x88\xa1\x37\x4c\xb8\xa4\xb2\x3d\x22\x43\x11\x9e\x79\xad\xe0\x3e\x64\x4b\x96\xd7\xe0\xc9\xce\xd6\x64\x6e\xfd\x43\xff\x5a\xb6\xe4\x8b\x25\x1b\x98\xfa\xf1\x69\x82\x63\xa8\x49\x72\x7d\x53\x69\xb6\x6c\x16\x01\xd4\xde\xb0\x65\x6d\x78\x3d\xda\x67\xbc\x92\xde\xd9\x55\x01\x53\x45\x0d\x82\x02\xd7\xe7\x13\x75\x5d\x06\x7b\xe7\x4e\x7d\xf7\x98\x92\xef\xec\x27\x0c\xd7\x5b\xb4\xaa\x0a\x1e\x7c\xed\xfe\xe1\x85\xea\x03\xff\x0e\x3b\x48\xee\x9c\xea\x25\x97\x62\x4b\xa9\x92\xcc\x3d\xd6\x64\xb5\xb2\xc6\x7a\xa0\xab\x3c\x63\x84\xe6\xb9\xf5\x95\x14\x51\xac\x94\x2b\xab\x15\x23\x9f\x7f\xe2\x48\xc3\xec\x82\x4d\x3a\xfe\xf3\xd3\x77\x8a\x4f\x3c\x5d\x91\xdb\xf6\x6c\xc3\x8e\x0e\x76\x61\xa9\x73\x80\x43\xe7\x28\x55\x8b\xb6\x6c\xc5\x5a\xd5\x2f\xe3\x86\xe2\x30\xbc\x08\xfc\x2d\xde\xdf\xa5\x6a\x11\xfb\xbe\xb0\x7f\xa2\x16\x35\xa8\xe3\xe0\xb7\xb4\xad\xdb\x31\x6e\xaf\x55\xf6\x2e\x6c\x75\xb1\xfd\xfe\xbe\x26\xa7\x6f\xce\x02\xbc\x10\x21\x91\xfb\x0c\xa7\xe7\x50\xab\x94\x5c\x71\x68\x3f\xf8\xbd\x87\x4d\x60\x1e\xa5\x77\x02\x2d\x7a\x80\x09\x84\xd4\x5d\x10\x8b\x7d\xdd\xc3\x4a\xe0\x9e\xe4\x69\x0b\x11\xc9\x1a\xcd\x64\xad\x49\xb1\xc2\x3d\xa1\xf7\xc2\xc4\x90\x75\xe0\xa2\xaa\x0d\x1e\xb1\xd4\xe4\x8d\x45\xb6\xa4\x62\xe1\xa0\xa4\x2c\x12\xc8\xa2\xd7\xc2\xd0\x3b\xfb\xd5\x56\x34\xd3\x19\xad\x58\xee\xcb\x87\x49\x2e\x6b\xdc\xf6\xff\xfa\xd7\x47\x84\xb3\x57\xe4\xd7\x9d\xc9\x4d\xc9\xb9\x97\xde\x1e\x0e\xec\x2a\x38\xe6\xa5\x59\x7b\x98\x8e\x88\x62\x0b\xaa\xf2\x02\xd7\x64\x47\xce\xc9\x6d\x87\xce\xae\x39\x0c\xec\x8e\x6b\xa3\x09\x8a\x72\x46\x48\xb3\xcb\xce\x75\x6c\x17\x42\xe8\xcf\x58\x3b\x43\xf5\x8d\xb5\x6d\x56\x0f\x4f\x72\x6a\xe8\xa4\x63\x2c\x8e\x5d\xd6\x76\xe2\x9b\x2c\x4f\xa8\x57\x4a\xad\x19\x3c\xfe\x95\xaa\x85\xb0\x81\x31\x6d\xfe\xaf\xb8\x98\xd0\x09\xb4\xe4\xc5\x46\x9e\xcf\xe7\x45\x13\xdd\xbd\xbc\xaf\xed\xcf\x1b\xe5\xee\xbe\x1d\x18\x87\x10\x5f\xd2\xc4\xa5\x8d\x61\xf6\xad\x91\x5b\xfd\x8f\x51\xf5\xc1\x62\x9c\x5f\xbe\x7f\xf7\x5f\x57\x6f\x2f\x2e\xdf\x07\xc3\x11\xcc\x00\x46\xea\x7d\x86\x23\xee\xa6\xdf\x67\x38\x5a\x33\x10\x03\x44\xda\x34\x1c\x7d\x33\x80\x91\xbc\x6d\x38\xfa\x66\x00\xb3\xb2\xdb\x86\x63\x87\x19\x40\x7a\x11\xdd\xf5\xdd\x69\x06\x50\xda\xb9\x63\x38\x76\x9b\x01\x84\xd4\x6d\xc3\xd1\x37\x03\xa8\xfb\xb5\x6d\x38\x3a\x66\x00\x69\xf2\xb7\x0d\x47\xd7\x0c\x20\x84\xee\x36\x1c\xa3\x19\xf8\x9c\x1f\x45\x99\x01\x26\x56\x91\x26\x20\x64\x3d\x3b\xca\xa5\x39\x17\x28\x92\xb3\x5e\x93\xd9\x0e\x7d\x5f\x8a\x43\xf5\x3c\xf6\xb3\x0f\xb3\x17\xab\xef\xa9\x22\x8a\x55\x8a\x69\x88\xab\x90\x65\x1d\xbb\x36\x88\x78\xa1\x38\xea\x42\x42\x68\x8b\x18\x7e\x76\x55\xb1\x8f\x54\xd7\x9a\xac\x86\xac\xfb\xb0\x94\xb2\x6a\x60\xda\xb4\x1b\xa2\xe4\xf4\x9f\x17\x67\xe7\x97\xef\x2f\x5e\x5f\x9c\xbf\x7b\xb4\xc2\x95\xa8\x46\xae\x7d\x77\x35\x8d\xa7\xe6\xc6\xcf\xfb\x6b\x68\xb1\xae\x97\x01\x5b\x71\x59\x03\xc4\x1d\xc0\x27\x29\xf7\x57\x6f\xe9\x56\xb4\x48\xe0\x81\x16\x6b\x68\xd0\xca\xb3\xb4\xc7\x50\x4f\x77\x66\x2a\xd0\x72\x93\x3a\xaa\x6e\xfc\x8c\xbb\x8a\x96\x99\x34\xdb\xe1\xc6\xfd\x39\x0f\xfc\xc6\xa7\x76\x79\xdd\xf8\x59\xc7\x37\x66\xe7\xef\x71\x7f\xd1\x22\x7f\x26\x7b\x82\x96\x19\x9c\xe7\x7e\xf5\x13\xba\x11\x52\x1a\xb5\xfb\x5a\xc9\x32\x89\xea\xbd\x76\x2f\x55\x1e\xda\x84\x5e\xa4\x5d\x4e\xcc\xbe\x1e\x0e\xce\xeb\x8f\x4e\xda\xca\xa7\x06\x42\xcb\x16\xb4\x48\x2b\x0f\x68\x0e\xe3\xcc\x66\x54\x0b\xfd\x14\x7d\xe7\x5d\x35\xd4\x1b\x5a\xfd\x9d\xad\xdf\xb1\x88\x5e\x49\x9b\xe7\x81\x15\x2c\xb3\xce\x2c\xb9\x61\xf8\xe2\x49\xe2\x5f\x72\xc9\x69\x98\x66\x4c\x93\xa9\x04\x4b\x4e\xa2\xfb\xcd\xb9\x31\x89\x5c\x96\x14\x5b\x6f\xc7\x0d\x43\x97\xf3\x87\xb1\xd5\x42\x3f\x76\xc3\x49\x88\x12\xed\x09\x8a\xd9\x6f\x92\xa6\x5b\x9c\x1b\x31\x7e\x7d\x18\x3b\x91\x63\xf1\x6b\xd5\x45\x9e\x41\x5a\x25\x5a\xe4\x13\xc1\xa1\xf5\xc7\x6e\x54\x5a\xb4\xd8\x34\xa8\xb6\xfe\x88\xc1\xb8\xf5\x47\xb2\xf3\x1b\x80\xe1\x49\xcf\xb0\xc3\xfc\xc7\x5f\xf7\xae\xbf\xd5\xa8\xfa\x68\xa9\x8e\x13\xd6\xea\xa3\x00\xb1\x8a\x16\xe9\x03\xb6\x24\x9b\x1a\xc3\xe1\x41\xc2\xc1\x4d\x69\xb3\xf7\x1b\xa3\x1d\xf5\x7d\x8e\x0b\xa8\xe9\x67\x99\xbf\x0a\xed\x24\xe2\x54\x40\xc9\x0c\xcd\xa9\xa1\x53\xab\x4d\x8e\xfa\x7f\x04\xb8\x71\xdc\xb5\x6d\xe4\x15\x74\xc6\x0a\xdd\xf9\x01\x70\x1e\x1d\x74\x3f\xee\x27\x74\xc5\xb2\xa9\x90\x39\xbb\x84\x2f\x80\x3f\xfa\xd0\xfa\xc4\x41\xd1\xe0\x7f\x88\xfb\x0d\x60\x42\x9f\xba\xaa\xbe\xa3\xf0\xc7\x4a\xe6\x17\x57\x49\x04\x83\x24\x1d\xd1\xbe\xf5\x89\xb9\x61\x70\x58\x91\xdc\x79\x61\xa4\x72\xc6\x5a\x0b\x94\x54\x49\x7b\x99\xf1\xea\xd4\xdd\x68\x9d\x2d\x59\x49\xa3\xa2\xbc\x30\x5e\x87\xc5\x27\x5c\x47\x74\x38\xe9\x0f\x2e\x80\xcd\xde\xc6\xff\x49\xfa\x16\xbb\x61\x83\xf5\xd5\xcb\xbd\x27\xe3\x8e\x36\xe7\x36\xe9\x51\x81\xbd\x48\xe4\x92\x3a\x33\xd0\x38\xf2\x49\xf6\x75\xd9\xa9\x2c\x25\x27\x57\x17\xd1\x42\x57\xee\x6e\x3c\x89\x6d\x0d\x70\xdf\xd7\x4f\xd4\xae\x37\x70\xe4\x4d\xd6\xe7\xb8\x23\x08\x1c\x1c\x41\xb6\x76\x7d\x19\xe2\xee\x2b\x15\x79\x80\x54\x6b\x72\xe0\x04\x4e\xb3\xaa\x8e\x33\x80\x5e\x4e\xc9\x4a\xa9\xd6\x47\xe1\x8f\x4d\xbb\xb0\x89\x36\x52\xd1\x45\xa4\xf9\x0e\xd3\x86\xe9\xb6\x7f\x72\x3f\x9a\x6c\x51\xb6\x67\x8d\xcf\x3e\x13\x8f\xe0\x6e\xd0\xd4\xc1\xdb\x43\x75\xde\x69\xc7\x93\xf2\x12\xc2\xf1\x7c\x02\x4e\x42\x16\xd7\xda\xb0\x3f\xfa\x6a\xe2\x34\xfa\xc1\x28\x0c\x48\x96\x34\x6b\x8f\x6c\x72\xd7\x1f\x9e\x97\xfb\x08\x57\xe1\xbc\x6b\x40\x9d\x85\x58\x91\x15\x55\xc8\xd6\xda\xed\x48\x66\xd7\x73\xbe\xe2\x5a\x46\xaa\xd4\xfb\x2a\xf3\x93\xd8\x75\xdf\x74\xc7\xd5\xa0\xa6\x72\x2a\xd9\x5d\x05\x3d\x58\x1b\x3b\x10\x9f\x83\xc9\xbb\xef\x2c\x2f\xf1\x34\x73\x6e\x54\xd4\x18\xa6\xc4\x2b\xf2\xdf\x07\xff\xf8\xea\xe3\xe4\xf0\x9b\x83\x83\x1f\x5f\x4c\xfe\xf4\xd3\x57\x07\xff\x98\xc2\xbf\xfc\xe6\xf0\x9b\xc3\x8f\xe1\x0f\x5f\x1d\x1e\x1e\x1c\xfc\xf8\xf7\x37\xdf\xbe\xbf\x3a\xff\x89\x1f\x7e\xfc\x51\xd4\xe5\x8d\xfb\xd3\xc7\x83\x1f\xd9\xf9\x4f\x9f\x29\xe4\xf0\xf0\x9b\x5f\x47\x4e\x9c\x8a\xf5\xdb\x28\x57\x82\x80\x06\x8c\xef\x22\xbf\x2d\x2d\xc1\x75\x21\xe4\x6e\xd2\xa6\x27\x27\x5c\x98\x89\x54\x13\x27\xf8\x15\xf0\xc2\x26\x71\x79\xd2\xea\xd9\x77\x09\x6c\x52\x7f\x7e\xad\x9b\xfd\x24\x14\x99\x2b\xd3\x7f\xda\x2f\x4a\x6e\x8e\x3d\x76\xb1\xe8\xf7\x01\x48\x43\xfd\x52\x7c\x9e\xf1\x81\xea\xe7\x46\x48\x86\xb8\x53\x94\x2e\xca\x9d\x2b\x59\x86\xee\x00\x00\xd1\x02\x76\xc2\x68\xb1\x7e\x9e\x37\x0c\xfd\x5e\x1d\xc6\xf8\xa0\x86\x19\xe3\x83\x5a\xdc\x18\x1f\xd4\x86\x8d\xee\x83\x9a\x23\x88\x1a\x5f\xd3\x76\x0d\x26\x56\x38\x08\xd4\x4e\x8c\x7c\xc8\x61\x75\x1a\xd5\x22\xbe\x6d\x27\xd2\x7e\x1b\x30\x8f\x90\xec\x8d\x5f\x8b\x3b\x6d\xab\xb1\xb0\xe9\x8d\x72\x37\x96\x98\x9c\x14\x05\xe1\x02\x6b\xbc\x60\x92\xa1\x32\x48\x31\x97\x4e\x0a\xac\xb0\x2b\x1c\xfc\xf4\x76\xc9\x36\x96\x10\xd8\x0f\x0d\x55\x86\x8b\x05\x66\x39\xa1\xbb\x0a\xb8\xa3\xa1\x40\x86\x0b\x52\xd6\x85\xe1\x55\xc1\x48\x44\x20\xeb\x60\x87\x45\xcd\x08\xd5\x5a\x66\x9c\x86\xca\x39\xf8\x5f\x0a\x8a\x62\x16\xf5\x91\x02\xac\xaa\xa1\x37\x80\x42\xce\x58\xce\x44\xc6\xa6\xe4\x7b\xfb\x6b\x18\x8b\x12\x4e\xd2\x6c\x6d\xf7\xe6\x5c\xac\x9a\x9a\xa9\xda\x95\xe9\x60\x0e\x95\x5d\xd1\xdd\xf3\xfc\xcf\x2d\x12\xb1\x6a\xca\x83\x2c\xdb\x5a\x11\x94\xe6\x04\xbf\xb5\xc9\xe4\x53\x28\xc7\x91\xf3\x16\x77\x81\xaa\xea\x89\x8b\x5c\x62\xa3\x85\x06\xc5\x18\x11\x70\x6e\x85\x09\xcd\x82\xc4\x74\x77\x72\x61\x01\xb8\xf5\x48\x19\x4f\x04\x28\x1a\xeb\xae\xdf\xcb\x9a\x16\x99\xa0\xe9\xba\xe9\x4f\xcf\xcd\x7e\x00\x17\x7b\x87\x7b\xed\xdc\xe3\x28\xa9\xb1\xae\x75\x12\xb7\x3a\x85\x4b\xbd\xcb\x9d\x8e\x28\x83\x6d\x47\x0f\x9b\x96\xc4\x05\x8e\x77\x7f\xe3\x81\x64\x95\x62\x73\x7e\x97\x44\x67\x9e\xb4\xec\xb3\x84\xe7\x4c\x18\x3e\xe7\x31\x2d\x81\xa5\x9d\x5c\xc5\x04\x80\x08\x80\x10\xcb\xfa\x05\x91\x4d\x88\x5a\x20\xf9\x53\x2b\x83\x73\x29\x9a\x94\x06\xec\x3a\x55\x72\x6a\xb4\x5e\xa3\xf5\x1a\xad\xd7\xa7\xc6\x93\xb7\x5e\x5e\x1f\x84\x90\xfd\x71\xcd\x0f\x70\xb7\xc4\xd2\xd3\x9c\x75\x98\xc3\xe0\x8e\xa3\xd3\xb5\x11\x4c\xd5\xa8\x44\x4c\xb7\x67\x6a\x63\x35\x8d\x24\xb4\x28\xe4\x2d\x42\x22\xd0\x4e\x2a\x52\xb0\x15\x2b\x7c\x38\x44\x4a\x2a\xe8\x02\xb8\x33\x71\x11\x4c\x68\xc0\x25\x15\xb1\x0a\x47\xf1\x9c\x6d\x76\xbe\x42\xf1\xeb\x08\x12\x18\x0c\x41\x9c\x92\x45\xc1\x94\x26\x05\xbf\x61\xe4\x8c\x55\x85\x5c\x0f\xe7\xfb\x74\x03\xba\xb7\x19\x6a\xac\x9a\xba\x66\x06\x83\x53\x8e\xe9\x22\x13\x28\xf9\x1d\xc7\x6c\xec\xe1\x06\x86\x7f\xe0\x90\x27\x95\x23\xad\x25\x6f\x51\x0d\x7b\xe5\x9c\x9c\x14\xb7\x74\xad\x8f\xc8\x25\x5b\x31\x75\x44\x2e\xe6\x97\xd2\x5c\xb9\x24\x02\xc6\xe1\xe9\xd6\xb0\x3a\xd1\x84\xcf\xc9\xab\x82\x1a\xa6\x0d\x31\x14\xa3\x44\xb9\xee\x76\x7b\x90\xaa\x37\xc9\xb6\xa3\x6b\x9a\xee\xf9\xf1\xf4\xf4\x20\xa9\x21\xa7\x47\x00\x88\x22\x0e\x5a\x11\x28\x7c\x23\x8f\xd8\x89\x23\xf5\x75\x14\x9a\x8e\x23\x36\x68\x0c\x4c\x82\x11\x1a\x6a\x84\x4e\xab\x90\xba\xe3\x82\x28\xa6\x2b\x29\x34\xc3\xa9\xa0\x56\xdd\x34\xdf\xec\x12\xc0\xfa\x51\x73\x81\x48\x7f\x36\xce\x93\xad\xa4\x36\xc0\x95\x8c\x73\x30\xfa\xca\xe5\x2a\x08\x03\x02\x6e\x5a\x14\x68\x47\x80\x97\x25\xcb\x39\x35\xac\x58\x13\x3a\x37\x4c\x11\x1a\x4d\x3d\x61\xe7\xa4\x18\x0d\x8c\xe3\xc0\xab\x0c\xbc\xde\x28\xaa\xf1\x76\x6c\xa5\xff\x5d\x83\x78\x3a\xb4\x27\x61\x3b\x1c\xac\xd6\xd3\xa3\x6f\x91\x8e\x23\x85\x7a\x81\xad\xda\x07\xef\x3b\xea\x72\x92\x16\xb3\xd0\x2e\xc0\xac\x90\xd9\x8d\x26\xb5\x30\x1c\xeb\xd5\xbb\x5e\x3f\xf2\x86\x64\xb2\xac\x0a\x50\x9e\x71\x94\x90\xe4\xe7\x69\x21\x77\x69\xe4\xe6\x5f\x27\x8d\x92\x98\xd8\x39\xe9\xe3\x5f\xb5\xff\x13\xfc\x05\x2e\x46\x88\x8e\x61\xe3\x23\x58\x76\xc7\x32\x7c\x5c\xd1\xbb\xfa\x6f\x05\x83\x53\x1b\xd5\x74\x9d\x10\x29\x9a\x42\x80\xb9\xb4\x4e\x2b\xd0\xa2\xc7\x75\x60\x26\x1b\xad\xc3\xce\xef\x58\xd6\xfc\x39\x26\x94\x85\x3e\x88\x59\xe8\x98\x62\x4d\x13\x1e\x06\x93\x04\xa4\x95\x06\x1e\x85\x26\xf9\xec\x8e\x8d\x06\xc1\x20\x31\x86\x19\xc3\x0d\xa7\x68\x9c\xb0\x82\x0b\xa4\xf9\xef\x0e\x4f\x21\xda\x6d\x4e\xd3\xdc\xee\x58\x80\x89\x15\xb6\xd5\x0f\x39\x52\x66\xe8\xbf\x19\x56\x21\x7e\x4d\x95\x94\x86\x1c\xec\x1f\xef\x1f\x6e\xa1\x01\x22\xc1\x8b\xae\xef\xa4\x73\xe0\x1c\x31\x91\x9f\x75\xa4\x54\x0e\x1d\xd4\x2b\x68\x9f\xcd\xb2\xfd\xfc\x88\xf0\x58\x20\x8a\x67\x67\x55\xb5\x08\x27\x21\xae\xaa\x89\x38\x26\xda\x23\xa2\x25\x31\x8a\xe6\x3c\x49\x75\x01\xc8\xb4\x13\x34\xaa\xf6\x4e\xf6\xc1\xfe\xc7\xfd\xd8\x73\xca\x4c\x76\x48\x6e\xa5\xd8\x37\x70\x5c\xa7\xe4\x7d\xec\xad\xaa\x35\x0b\x64\xbc\x47\xc0\xa2\x2f\x58\x3c\x20\x47\x12\x76\x57\x15\x3c\xe3\xa6\x58\x83\x73\x49\x64\x1d\xbb\xef\xc0\x36\x4f\x4d\xe0\x0d\x3e\xbf\x8b\x3e\x49\xae\xa2\xd9\x1a\xb1\x17\xe0\x0a\x3a\x87\x33\x52\x28\xd5\xa4\xe0\x2b\x76\xbc\x64\xb4\x30\xcb\xf5\xe0\x0e\x36\xdb\x43\x48\x31\xf9\x37\x53\x12\x98\x8d\x85\x97\x1b\x87\xe2\x8c\x01\x34\x74\x07\x1a\xdc\xb0\x3d\x99\xa8\xdc\xab\xf5\x17\xbf\x65\xc8\xb8\x88\x6c\x35\x71\x7d\xff\xfe\xea\x5b\x66\x92\x39\x1e\x76\x76\xa1\xf4\x0e\x5e\xb5\x98\x9a\x4b\x55\x3e\xb2\x07\x12\x0f\x12\x9f\x40\xc7\xd8\x47\x76\x81\x96\x52\x47\xec\x3b\xd9\xdd\xc0\x17\xc7\x1c\xda\x1d\xae\xdf\x96\x60\x99\xdd\xf1\x64\x65\xe8\x6d\xa7\x30\x72\x71\x35\x25\xff\x25\x6b\x68\x9a\x44\x67\x51\x9e\xbc\x1d\xa1\x77\x8a\x66\x86\xec\xd9\x45\xd8\x8b\x79\x68\x75\xc3\x9e\xfb\xbf\x31\x9a\xbb\x26\x3e\xda\x30\x8a\xe2\xf6\x6e\x47\x22\xe8\x6e\x67\x5e\x29\x3d\xe7\x5a\x1b\x59\x92\xa5\x13\x1c\xbf\xd1\x1d\x92\x64\xaf\x3b\x62\x91\xfb\x56\xaf\xb9\xf7\x05\x4d\x14\xab\x52\x58\x3b\xff\xb5\xbf\x20\x6b\xb4\x65\x09\xdc\x49\x89\x94\x1a\xe4\xce\x98\x26\x94\x64\x70\x54\xa2\x45\xba\xc5\xb7\x67\xc5\x13\x1b\x46\x4b\xe4\xc2\x1d\x12\xd7\x89\x2d\x89\x5d\x8f\x2e\x66\x22\x89\x0a\x9a\x48\x0c\x29\x74\x5f\xc8\xf0\xd6\x69\xdb\x23\x55\x7d\x14\x49\x54\x49\x43\x76\x00\x48\x12\x88\x6c\x4e\xa9\x7b\xec\x4c\xb0\xfc\x24\x65\x0d\x07\x89\xa5\x9f\xee\x8e\x87\x5f\xbe\x14\x07\x8f\xa4\x5b\xbf\x2a\x9a\x7e\x66\x9b\x7c\xc6\xb5\x65\xc4\xb5\x3d\xea\x0e\xe9\x4c\x27\xa8\x33\xcd\xd4\x0a\x57\x30\xd1\x8e\x54\x4b\x26\xb1\xcf\x37\x61\xec\xe0\x88\x57\x44\xd4\xe5\x2c\xda\x48\x35\x8c\x6d\xca\xa4\xde\x86\x4e\x9b\x87\xcb\x14\x53\x0d\x10\x96\xe0\x20\x51\xb1\x88\xbd\x17\x2f\xed\x37\xff\xfe\x7f\xff\xef\xdf\xfe\xef\xa9\x5b\x56\xfb\x1b\x91\x32\x67\x8c\x50\x41\x2e\x4e\x2e\x4f\xfe\x79\xfd\xfd\x29\xb0\x67\xc7\x9d\xc2\x04\xc5\xfc\x29\x4b\xf9\x13\x16\xf2\x3f\x60\x19\x3f\x10\x96\x45\x6a\xf8\x3e\x2e\x0b\x04\xc6\x67\xb4\x6b\xed\x08\xb3\x7d\xa4\xe8\x9e\x0d\x13\x64\xb2\x6d\x4c\xdc\xe3\x19\x4f\x10\x38\x3c\xba\xf6\x34\x59\x75\x2d\xb3\x9b\x64\x59\x9e\xfd\xf7\xa7\x57\x4e\x60\x92\x44\x0f\x15\xe1\x81\x89\x8b\x95\x2c\x56\x76\x33\x29\x79\x7f\x7a\x15\x69\x2c\xa6\x56\x06\xbc\xb0\xba\xbc\xf7\x3a\xaa\x92\xb3\xa1\x66\xf2\xd0\x4e\x5e\x56\x45\xcc\x8b\x32\x81\x5e\x01\x8a\xd1\x82\x6b\xc3\x33\x98\x6b\x81\xea\x2f\xdd\x1f\xf6\x7b\xf1\x78\xce\x31\x3f\xd6\x8e\xc4\xf9\xb1\xfd\xb7\x89\xaa\x9e\x9b\x44\x5b\x27\x55\x16\x9d\x34\x39\xea\x91\xfe\xc4\x33\x54\xfa\x44\x5b\x5c\xc9\xf9\x13\xf5\x1c\xc1\x0d\xc3\xb5\x02\xed\x0e\xd1\xe9\x52\xe4\x3d\xc7\xd8\x17\x14\xf0\x3b\xb7\x3d\xc7\x48\xb1\xfe\x83\xfb\x9e\x63\x6c\x5e\xc2\xfa\x9d\x5b\x9e\x63\x22\xdf\x76\xf4\x1c\x3f\x6f\x3c\x80\xe7\x58\x29\x76\x6d\x64\x95\x04\x67\xe7\x44\x25\x45\xd9\xcd\xd8\x5c\x2a\x96\x06\x66\xd7\x02\xe0\x48\x5e\x83\x32\xa6\x22\x82\x59\x35\x3c\x73\xc9\x2e\x5c\x0d\x5d\xb2\x4f\xc0\x65\xc9\x96\xe1\x55\x55\x30\xad\x8f\x01\x1a\x57\x57\x2e\x49\x89\x14\x3a\xa7\xbc\xa8\x15\x3b\xb2\x3b\xcd\x4a\xd8\xab\xa3\x58\x92\x47\xbb\x19\x4c\x38\x51\xcc\x64\x0e\x46\xe1\x51\x8b\xf8\xfd\xb1\x3e\x9f\x3b\x38\xae\xa3\x6d\x7c\x5b\xaf\x4c\x51\xbd\x64\xd0\xcc\x93\xdd\x71\xa3\xdd\x44\x15\xa3\x1a\xcd\x11\x0d\x50\x17\x7f\x90\xc0\x05\xd6\xa4\xa2\x5a\xb3\x1c\x6f\x0d\x3a\x90\x4f\x37\xc1\x2b\x99\xef\xef\xeb\xee\xcf\x20\x25\x2f\x14\xcd\x18\xa9\x98\xe2\x32\x27\xc0\xba\x9e\xcb\x5b\x41\x66\x6c\xc1\x05\x36\x02\xf0\x37\xd2\x4e\x3a\x5c\x78\xeb\xc2\xb2\x08\x20\x55\xe8\x98\x3c\x25\xef\x7a\x1d\x5d\xf1\x56\x4b\xd6\x26\x93\xad\xb5\xf6\xab\x7b\x14\x21\xb1\x45\x92\x02\x5b\x03\x5c\xf3\x9a\x16\xc5\xba\x55\x2b\x48\xc9\x9e\x98\xc4\x3c\xd4\xc6\x3f\x33\x4c\xad\xbd\xac\xb1\x12\xbb\x17\xb4\xbb\x14\x78\xdd\xa4\x18\xcd\x96\x71\xc5\x14\x23\x74\xf7\x13\x63\x84\xee\x8e\xd0\xdd\x7b\xc7\x08\xdd\x1d\xa1\xbb\x23\x74\x77\x84\xee\x8e\xd0\xdd\x11\xba\x3b\x70\x8c\xd0\xdd\x4f\x8d\x11\xba\x7b\xef\x78\x92\x4f\x13\x23\x74\x77\x84\xee\x7e\xf6\x18\xa1\xbb\x23\x74\x77\x98\xdc\x11\xba\x8b\x1a\x23\x74\xf7\x67\xc7\x08\xdd\x8d\x19\x23\x74\x17\x3b\x46\xe8\xee\xe0\x31\x42\x77\x47\xe8\x6e\xc4\x18\x01\x18\x88\x31\x42\x77\x13\x04\x0e\x8f\xae\x3d\x47\xe8\xee\x08\xdd\xfd\xcc\x31\xe6\xc7\xda\x31\x42\x77\x23\xc6\x08\xdd\xfd\xe4\x18\xa1\xbb\x23\x74\x37\x42\xd6\xd3\xf3\x1c\x03\x44\xf4\x4a\xc9\x59\x34\xb5\xf4\x15\x80\xa3\x78\xe6\x32\x6a\xf6\x9e\xc4\x00\x2f\xc3\xd4\xa6\xe4\xb4\x8f\x99\x83\xfe\x56\x9e\x3e\x12\x21\xd7\x63\x42\xdd\x1c\x81\x1a\x73\xba\x83\xed\x16\x21\x78\x20\xa4\x2b\x10\x3a\xeb\xe3\x4a\xba\xff\xaf\x05\x74\x75\x90\x5c\x2e\x3b\x89\xe5\xca\x7d\x14\xd6\x55\x3c\x7c\xeb\x5e\xe8\x16\x91\x28\x1a\x67\xd2\x06\xfa\x9b\xb0\xad\x3e\xf8\x0a\x29\xbb\x0f\xd9\xea\x03\xaf\xb0\x9e\x3f\x1a\xae\xf5\x04\x80\x7b\xd1\x10\xad\x7b\xe0\x59\x91\xd6\x6b\x03\x9a\x15\xc0\x55\x11\x12\x77\xc2\xb2\x22\x67\xb9\x05\xc9\x0a\xa0\xaa\x04\x5f\x0e\xd8\xd3\x2e\xa0\x2a\xf2\x95\xbf\x03\xc5\xea\x82\xa9\x22\xa4\x76\x60\x58\xdb\x40\xaa\x98\x9d\x32\xbb\x40\x54\x1e\x03\x14\x13\x5c\xf6\x00\x54\x3b\x20\x50\x11\xb2\x01\x3c\x95\x18\xfe\xb4\x13\xfa\x14\xe7\xbf\xee\x80\x3d\x05\xe0\x52\xcc\xc2\xb6\x90\xa7\x2e\x68\x29\xe6\x08\x34\x70\xa7\x4d\xc0\x52\x54\x0a\x24\x4f\x0d\x56\x4a\xf1\x34\x1c\xfd\x2c\x1c\xe9\xa9\xfa\x32\xa1\xf7\x4b\xc5\xf4\x52\x16\x48\x53\xd0\x33\x03\x6f\xb8\xe0\x65\x5d\x5a\x9d\xa3\xad\xde\xe6\xab\xc8\x1a\x26\xdd\xa0\x55\x9d\x13\x08\x6f\xca\x68\x8b\x07\x1a\x45\xb1\x1c\xa4\xdb\x23\x06\x84\xee\x4b\xba\xc2\xbb\xfa\xba\xce\x32\xc6\x72\x96\xf7\xf2\x9a\xe4\xb7\xd3\xb0\x16\x48\xb9\xae\x41\x2a\xd7\xe4\x65\x8c\x87\x11\x13\x11\xcd\xa5\x2a\xa9\x01\x19\xbf\xfd\x1a\x21\x21\x0a\xfb\xf6\x20\xb8\xb7\xe4\x98\xb7\x68\x37\x2e\x2e\x97\x17\x91\xc7\x8b\xf7\x1f\xe3\xf2\x77\xbb\xb1\x6d\x71\x36\x6e\x17\xae\x2d\x4e\xe2\x03\x60\xda\x76\xe2\xd9\xba\xc8\xaf\x38\x4f\x37\x0e\xcb\x96\x08\xf1\x1a\x8d\x61\x7b\x18\xfc\xda\x6e\xec\x1a\x68\x97\x18\xe7\xa2\x8f\x5b\x8b\x47\x9e\x3d\x09\xd7\xe2\x21\xd0\x66\xdb\x48\x33\xbf\x58\x71\x59\xec\x06\x65\x96\x0e\x25\x96\x08\x21\x96\x02\x1d\x16\x8d\x0c\x8b\x47\x85\xa5\x42\x84\xa5\x40\x83\x6d\x75\x01\x4d\x70\x82\x48\x68\xdc\x98\x04\x5f\x9d\x2a\x7b\x9c\x04\xfd\xf5\xb0\xcb\x95\x02\xf5\x95\x60\xbd\xe2\xd0\x5e\x0f\x83\xf4\x4a\x89\xf2\x4a\xb1\x44\x51\x6f\x74\x0f\x83\xec\xda\x89\xea\x22\xe8\xfa\x77\xb2\x99\xee\x9a\x76\x5f\xd6\x22\x84\x6e\xa0\xb9\xba\xaf\x6a\x11\x52\x1b\x24\x57\xda\x17\xb5\xc8\xd7\xb4\x54\x2f\x69\x89\x5e\xd1\x1e\x08\x7b\x15\x8b\xbb\xda\x8d\xb9\xb2\x3e\x48\xc4\x81\xd8\xc2\x5b\xb5\x88\xa9\x08\xa9\xdd\x9c\x44\x1c\x5a\x2a\x72\x43\xb9\xe0\x86\xd3\xe2\x8c\x15\x74\x7d\xcd\x32\x29\x72\xa4\x37\xb1\xd1\xab\xda\xa3\x05\xe6\x44\x3b\xa1\xc8\xef\x73\x99\xa0\x3e\xd7\xc5\x92\x6a\x82\x7f\xbb\x24\x2d\x71\x4a\x78\x1e\xf5\x8e\x29\xa1\xf0\xf8\x68\xd7\x03\xf9\x7c\x49\x9e\xdc\x13\x26\x79\x12\x29\x27\x47\xf9\x91\xee\x78\xfd\x4d\xde\x12\x39\x37\x4c\x90\x03\x2e\xc2\x09\x3b\xc4\x66\x9f\x9a\x64\x53\x9b\xcf\x6c\x92\x86\x78\x99\x2f\x5f\x84\x89\x35\x29\xc7\x28\xc7\xec\x39\xa7\x1c\x21\x19\xab\xf5\xd3\xcc\x68\xfb\xc9\x3d\x54\x4a\xdb\x8b\x9f\xd7\x85\x53\x66\xd8\xfc\x0d\x24\xc3\x7d\x82\xbc\x9f\xd3\x46\x1e\x0b\x42\xde\x78\x37\xe7\x25\x7c\x79\xa3\x0d\xa9\xc8\x89\xa7\x3b\x43\x4b\xee\x1e\xf8\x67\x7d\x74\x23\x51\xc4\x0f\x85\x20\xbe\x17\x3d\xec\x30\xc0\x48\xa9\x5b\xc8\xe1\x16\xff\x8b\x95\xd8\x47\x0d\x77\xb1\xbf\x11\x73\x6c\xbb\x32\xe3\x71\xbf\xe3\x1b\x01\xee\xbf\xbd\x17\xdf\x0b\xcf\x05\x11\x2e\xf1\x06\xb6\x37\x55\x19\x7c\xbf\x04\x3e\x16\x23\xfe\x64\xa2\xfd\x80\xc6\x8d\xcd\x8d\x8d\xd1\xfe\x18\xed\x7f\x62\x3c\x40\xb4\x6f\x78\xc9\x64\x6d\x9e\x6c\xc0\x79\xbb\xe4\xd9\xb2\xeb\x0b\xf2\x12\x6d\xaa\x65\x6d\x36\xfc\x35\x3f\xc5\x84\x50\x84\x31\xea\xdc\x18\xb8\x37\x8d\x1d\x09\xd5\x78\xf6\xdb\x06\x21\x4b\xa8\x26\x94\x9c\x5d\x5e\xff\xf3\xbb\x93\xbf\x9e\x7f\x37\x25\xe7\x34\x5b\x46\x89\xe6\x82\x50\xb0\x6c\xa0\xc2\x96\x74\xc5\x08\x25\xb5\xe0\xff\xaa\x19\xd6\x2e\x1c\x34\xf3\x3b\x4c\x82\xe9\x8e\xd0\x40\xd6\x26\x21\x74\x43\x6f\x13\xbf\xe3\xda\xd8\x4d\x04\x59\x9e\x67\x4c\xa2\xf2\x81\x73\x25\xcb\x4d\xd3\x76\x6e\x85\x39\xd7\x1b\xe9\xcd\x2d\x99\x62\x64\xc1\x57\x1e\xf9\xec\x30\xa0\x84\xe6\x11\xac\x72\x56\x0b\xd8\x8b\x63\x83\x03\x3a\x03\x40\xe1\x92\x11\xc1\x8c\xbd\xf4\x4d\x2a\x13\x87\xae\xec\x90\x7f\x93\x5a\x33\x7d\x44\x66\x35\x80\x43\x2b\xc5\x4b\xaa\x38\x0a\x82\xd1\x99\x30\x2d\xa6\xe4\x52\x86\xf0\x68\x0d\x4b\x8b\xc9\x37\x59\x6f\x06\x96\xf6\xec\xed\xf9\x35\xb9\x7c\xfb\x9e\x54\x0a\x78\x82\xb1\xc8\x4a\x90\x08\x47\x60\xc6\xec\xac\xdc\x31\xca\xa7\xe4\x44\xac\xb1\x7b\xef\x8c\x0c\xd7\xc4\xc6\x43\x4c\x58\xb1\xfe\x79\x2a\x47\x27\x9f\xf6\x5e\x4c\xe1\xff\xed\xd9\x33\xa4\xac\x2b\xd7\xc0\x75\x63\x14\x4d\x28\x1a\x71\xee\x21\x9f\x15\xac\xbd\x0f\xfe\x64\x61\xbc\xa5\x64\xfa\x05\x87\xca\x40\xa3\x31\x36\x20\xf6\x7e\x5d\xaf\xec\x19\x51\xac\x52\x4c\x33\x81\x8c\x59\x68\x73\x51\xe1\xc4\x81\x82\xb7\x1a\xa6\x88\x2c\x6c\x8b\x8c\x76\x63\x62\xdd\x49\x3b\xf3\x2b\xdc\x45\x89\x0d\x78\x7b\xbf\x8f\x75\xcb\x77\x86\x5f\xf3\xb8\x8a\xdd\xc6\x1e\x85\x8b\x5f\xc9\x7c\x5f\x93\x0b\x3c\xee\xc9\xdf\xfa\x29\x79\xbf\xe4\xba\x8d\x6c\xac\xaf\xc8\xf1\x74\x4f\x70\x16\xdd\xc3\xf2\x11\x79\x41\xfe\x4c\xee\xc8\x9f\x21\xf8\xfa\x3d\x36\x46\x4a\x11\xe0\xc4\xa6\xf6\x5c\x1e\xe4\xe2\x2a\xc9\x89\xf8\x61\x49\x0d\xc8\x23\x17\x57\x31\xe0\xc6\x19\x17\x39\x1c\x05\x76\x67\x98\x12\xb4\x08\xa1\x79\xdc\x4a\x47\x84\x80\xf6\xa3\x9e\xfc\xc5\x71\x0c\x16\x17\x73\xb4\xc4\xc6\x4b\x3f\x22\xa6\x77\x75\xd0\x12\xe1\xca\xed\xbc\x3a\x68\x91\xee\xca\x91\x8b\x39\xe4\xda\x2e\xbd\xa5\xe0\xba\x33\x7b\xfc\x92\x36\x5f\x5d\x52\x93\x2d\xfb\x66\x0d\x9f\x0a\x79\x63\xaf\x44\x4b\xbd\x4f\x72\x09\xb9\xe5\x28\xd2\x60\x3b\xd5\xe7\xad\x78\x62\x20\x77\xbd\xfb\x74\x31\xdf\x3c\xb9\xe8\x55\xbd\x2f\x0d\x16\xc5\x48\xec\x83\xd1\x4e\x63\x8d\x4a\xe6\x2e\xf2\x45\xcb\xb4\x8b\x97\x77\xfc\xa3\x5e\x00\x8c\xb7\x9c\xdd\xc0\xd9\x33\x3a\xc5\x16\x0f\x3a\xd5\x6d\x2d\x43\x46\x85\x2b\xba\x9e\x33\xa5\x62\x8e\xbe\x24\xb3\x35\x20\xd7\x78\xc6\x22\x2f\x41\x84\x4d\xa8\x94\x34\x32\x93\x68\x52\x8f\x3e\xb8\xcf\x0b\x83\xe5\x8e\x79\xbe\x6a\x5f\x34\x3f\x9c\x5d\x1d\x91\xf7\xa7\x57\x47\x44\x2a\x72\x7d\x1a\x83\xaf\xe9\x66\xee\xf6\xde\x9f\x5e\xed\x3d\xda\xa2\x93\x10\x17\xbe\x42\xd1\x04\xf5\xd2\xb8\x36\xe4\x9c\x94\xb4\x9a\xdc\xb0\x35\xc2\xab\x8e\xf5\xe9\x27\xcd\x09\x4a\xf0\x19\x6e\x61\x4b\x5a\x0d\x94\xa5\x18\xcd\xf9\x13\x65\x6e\xf0\x37\xbc\x9d\xe3\x26\x85\x03\x42\x26\xe8\x9f\x52\xae\x58\xee\x82\xf7\xf0\x1b\x4c\xe4\x95\xe4\xb8\x88\x75\x64\x82\xf8\xf4\x18\x99\x20\x3e\x6f\x8c\x4c\x10\xfd\x31\x32\x41\x44\xc8\x1c\x99\x20\x46\x26\x08\x37\x46\x26\x88\x91\x09\x02\x39\x46\x26\x88\x4f\x4f\x6e\x64\x82\x78\xb6\xd8\xd6\x91\x09\xe2\xd3\x63\x44\x79\x8e\x4c\x10\x23\x13\xc4\xd6\x18\x99\x20\x1e\xdb\xb5\x18\x99\x20\x46\x26\x88\x30\x46\x26\x88\x01\x63\x64\x82\x18\x36\x46\x26\x88\x4f\x8e\x27\x56\x1b\x32\x32\x41\x8c\xb5\x21\x9f\x2b\xe7\xe9\xd5\x86\x90\x91\x09\x02\x37\x46\x26\x88\xe1\x63\x64\x82\x18\x36\x46\x26\x88\xe1\x32\x47\x26\x88\x76\x8c\x4c\x10\x23\x13\xc4\x33\x3d\xba\x23\x13\xc4\xc8\x04\xb1\x7b\x8c\x6f\x04\x23\x13\xc4\xb0\x31\x32\x41\xe0\x85\x8e\xd1\x3e\x5e\xce\xd3\x8b\xf6\x47\x26\x88\x91\x09\xe2\x93\x23\xc6\x75\x53\x4c\xcb\x5a\x65\x18\x13\xd9\x3f\x57\xa7\xb2\xac\x6a\xc3\xc8\xbb\x20\xb0\xb1\xfb\x88\x6f\x9a\xad\x5d\xc1\x55\x47\x3b\x3e\x06\x6c\x3a\x93\x62\xce\x17\xb5\x82\xe2\xfb\xe3\x92\x0a\xba\x60\x93\xcc\x7d\xe8\xa4\x59\xb9\x49\x33\xcb\xe3\x67\x05\x9d\x2e\x78\xc9\x31\x0c\x12\x64\x6b\xef\xbf\x03\x49\xed\xfb\x68\x04\xbc\xa5\xa4\x77\x10\x10\xd1\x52\xd6\xc2\xb8\x3a\x01\x58\x6f\xa4\xcc\x66\x97\xdc\x3b\xb7\x0d\x09\xdb\x43\x10\x01\x11\x78\x02\x47\x87\xa4\x70\xce\x5b\x2e\x8d\xab\x68\x6f\xb9\xa2\xc6\x30\x25\x5e\x91\xff\x3e\xf8\xc7\x57\x1f\x27\x87\xdf\x1c\x1c\xfc\xf8\x62\xf2\xa7\x9f\xbe\x3a\xf8\xc7\x14\xfe\xe5\x37\x87\xdf\x1c\x7e\x0c\x7f\xf8\xea\xf0\xf0\xe0\xe0\xc7\xbf\xbf\xf9\xf6\xfd\xd5\xf9\x4f\xfc\xf0\xe3\x8f\xa2\x2e\x6f\xdc\x9f\x3e\x1e\xfc\xc8\xce\x7f\xfa\x4c\x21\x87\x87\xdf\xfc\x1a\x1d\x1c\x46\xb8\x1f\x69\x9c\x8f\x24\xae\xc7\x03\x38\x1e\x1e\x5d\x92\x44\x3d\xbc\xf3\xb2\xd2\x28\x08\x9f\x31\x49\xaf\x20\x82\xbd\x82\x0a\xe2\x30\x67\x7c\x12\x52\x96\xdc\x18\x96\x43\xca\xa8\x43\x2f\x82\xc5\x81\x73\xd3\x6b\xc6\xed\x55\x2e\x14\x18\xa1\x21\xd0\x5c\x77\x71\xd5\x9d\x4a\x59\x69\x96\x4c\xdd\x72\xf4\x7b\x90\x0d\x90\x44\x9b\xcd\x00\x25\x38\xc9\xd9\x9c\x0b\x74\x82\x04\x9c\xb8\xc1\xfe\xdb\xa8\x86\x47\x35\x3c\x44\xca\x53\x52\xc3\x9a\x65\xb5\xe2\x66\x7d\x2a\x85\x61\x77\x88\x84\x48\x5f\x0b\x5f\x7b\x71\x44\xc2\xdf\x60\xeb\x9c\x2a\x99\x87\xaa\x36\x55\x0b\x28\x5d\x8f\x74\xa9\x3e\xe7\x1e\x57\xb2\xe0\xd9\xfa\x38\x2c\x09\x5c\x58\x76\x67\x8e\x1f\x2c\x06\x30\x54\xdf\xb4\xea\x83\x4d\x6c\xe4\xd7\x6a\x89\xad\x79\x3c\x2b\xc7\x1f\x3c\xe1\x2b\xc5\x57\xbc\x60\x0b\x76\xae\x33\x5a\x80\x7e\x4c\x61\xeb\x4f\xee\x91\x8d\x7f\x1f\x32\x4a\x16\x9a\xdc\x2e\x99\xb5\x49\x84\xda\x6f\x87\xd4\x5b\x46\xb1\x42\x17\x94\x0b\x52\xda\x63\x50\x85\x89\xda\xdb\x60\x2d\x16\xda\xe0\x57\x54\x31\x61\xc2\xe4\x3c\xc1\xd0\x4c\xca\xc2\x97\xd8\xa1\x31\xd7\xcd\x0a\xf8\x5a\x62\x21\xff\x29\xd8\xed\x3f\xed\xcc\xb1\x73\x9d\x17\x74\xd1\x70\x96\x69\x66\x02\xd8\x2b\xa6\x22\x9b\xb8\x53\xe9\x3e\x3e\xf1\x21\x80\x9a\xaa\x9a\x11\x5a\xdc\xd2\x35\x1c\x85\x34\xf3\xe5\xfa\x15\x79\x79\x08\x6a\x8c\x6a\xd2\xcc\x37\x27\x5f\x63\x9f\xc8\x97\x54\x93\xd3\x93\xab\x7f\x5e\xff\xd7\xf5\x3f\x4f\xce\xde\x5c\x5c\xc6\xb8\x13\xf6\xf4\x30\xd4\x21\xcf\x68\x45\x67\xbc\xe0\x78\x2f\x62\x0b\x77\xd9\x15\x19\xe1\x14\xe6\xf9\x71\xae\x64\xe5\xf6\x50\xd5\x02\x68\xfd\x5a\xfe\x1b\x6c\x26\xb9\x9b\x35\xec\x30\x04\xda\xc3\x8d\x4d\x46\xce\x7b\x9f\x4c\x16\x8a\x0a\xeb\xcd\x43\x66\x2a\xe2\xb5\xdb\x43\x73\x54\x2d\x0c\x2f\x9f\x6f\xf1\x35\xcd\x53\x15\x5e\x9f\xe4\x39\xcb\x53\x1c\xaf\xa7\x58\x78\x70\x1a\x3e\x2b\xa6\xe2\x86\xb4\xac\x89\xe4\xea\xed\xf5\xc5\xff\x9d\x66\xb5\x88\x5f\xb1\x98\x07\xac\x04\x9c\x2d\x4a\x56\x89\x4e\xd2\x3b\xcf\xde\x31\x9e\xa5\x9f\x1b\xbf\xd0\xb3\xd4\x78\x72\x29\x30\x53\xef\x6a\xd1\xd1\xd5\x68\x02\x83\x76\x4e\xa4\x94\x39\x9b\x92\x2b\xe7\x20\x31\x9d\x44\x66\x87\x36\x8e\x2a\x46\xac\x60\x61\x38\x2d\xd0\xae\x26\xfb\x57\xcd\x57\xb4\x60\xae\xc0\x0f\x28\x1c\xba\xfc\x81\x09\x6c\xf3\x9c\x16\x3a\xca\xe8\xe1\x7d\x22\xeb\x9c\xbe\x91\xb5\x48\x81\x4f\x6a\x64\x91\x9c\x09\x69\xa2\xf2\x99\xf6\xbb\x80\xf0\x51\xc9\x8c\xb8\x9c\x66\x14\x14\x3b\x60\xf3\x3a\x4e\x15\x38\x70\x78\xd2\x64\xe2\x5c\x70\xbf\x8f\x57\xcd\xb7\xbb\xb7\xdf\x5a\x47\x7d\xfe\x96\x4b\x14\x0b\x65\xb1\xdf\xaf\x18\xcd\x81\xc9\xa7\xa2\x66\xe9\x70\x7a\x25\xd5\x37\xe8\xdc\x23\x88\xf1\x31\x9d\xcf\x12\x3b\x02\x9e\x66\x31\xde\xe3\x95\xdf\x9c\x51\x53\x2b\xe6\xa2\x32\x57\x0c\xc8\x04\x9d\x15\x58\x64\x75\xa4\x22\xb5\x6b\xf7\x56\x14\xeb\x77\x52\x9a\xd7\x0d\xdb\x4a\x82\x4b\xf3\x83\x8f\xe0\xfb\x0f\xbb\x11\x81\x16\x40\xe4\xf2\x09\x6c\x34\x28\xab\x78\x72\x18\x7f\xc6\xed\x71\x7f\x44\x55\xa5\x6a\x71\xa2\xbf\x55\xb2\x46\x7a\x46\x5b\xc1\xdb\xb7\x17\x67\xa0\xd1\x6b\x11\x11\xbc\x30\x61\xd4\x1a\x98\xd0\x52\xb4\x7d\x20\xdd\x7c\xc1\x07\x6b\x12\x37\xee\x3f\x56\x51\xcd\x49\x2d\x34\x33\x53\xf2\x86\xae\x09\x2d\xb4\x0c\x49\x0e\xb4\xc9\xbd\x02\x44\x7e\x37\x15\x3b\x25\xc0\x2c\x8a\x0e\x2e\xb9\x20\x33\x69\x96\x64\x43\x6c\x04\x95\xe8\xf6\x1c\x81\x21\x2a\x0a\x48\xdf\x76\xe6\xe0\x62\x73\xaa\x58\x8d\x4f\x6f\x98\x26\x95\x62\x19\xcb\x99\xc8\xa2\xee\x57\x22\xc4\xcc\xef\x7f\x87\xbd\xa1\x97\x52\x58\x25\x99\xe0\x8e\x5e\x88\x9c\x67\xd4\xb8\x2c\xa4\x49\x92\x60\x00\xac\x9e\xcf\x6c\x51\x20\x0f\xb2\x2a\x12\x29\xb6\xd6\x4c\xc1\xab\xa8\x51\x35\x73\x07\xeb\xef\xf5\x8c\x15\xcc\x60\xc9\x16\x49\x60\x80\xa6\xc6\x31\x9b\xf1\x92\x2e\x18\xa1\x26\xa8\x01\x7c\x8e\x89\x09\x6d\xcd\x29\xac\x24\x37\x24\x97\xac\xa1\xe4\xc2\x26\x3b\x34\xf9\x70\x71\x46\x5e\x90\x03\xbb\x86\x87\xe0\x4f\xcc\x29\x2f\xf0\xdc\x1c\x50\x35\xb0\xe1\xff\xf0\x79\x98\x2e\xd6\x7a\x5d\x78\xdd\x47\xa4\x72\xe6\xeb\x88\x08\x49\x74\x9d\x2d\xc3\x5a\xe3\x73\xb0\x21\x5d\xec\x2b\x80\x00\x47\xe3\x15\x2c\x52\x62\xa3\x96\xef\x53\xb0\xd8\xb5\x75\x42\x77\x29\x58\xf4\xfb\x64\x7e\x9f\x82\x8d\x42\x24\x3e\x71\x05\x1b\xe9\xc0\x7c\xd0\x4c\x25\xf2\x5f\x3e\x3c\x71\xff\xa5\x1b\xe2\x5a\x5d\xd9\xee\x2c\xde\x41\x70\x0a\xb1\x64\x86\xe6\xd4\x50\xef\xd7\xc4\x72\x88\x6e\xfb\x44\xe3\xe5\x7b\x9a\x97\xef\x31\xbd\x1b\xcd\xbe\xe3\xa2\xbe\x73\x05\x2b\xa9\x1e\x90\xae\xcf\x41\x28\xc9\xe2\x96\x18\x8e\x2e\xad\xaa\x82\x03\xa3\xe4\x46\x0d\x45\x94\xe1\xec\x36\x0a\x88\x57\x0e\x21\x9c\x01\xc3\x49\x8b\x42\x5a\x07\xcf\xc6\xac\x54\xe4\x12\x8b\x64\xdf\x58\x44\x48\x76\xb0\x5e\x9b\xbc\x29\x5c\x72\xec\x5d\x1b\x55\xc3\x33\x50\x0d\x8f\xfa\xf0\x57\xb0\x15\x43\xf7\x35\xd8\xec\x3e\x68\x65\x11\xae\xc3\xb1\x8e\x78\x3d\x80\x69\x91\x82\xce\x58\xe1\x3c\x7f\xa7\x22\x12\xd4\xc3\x45\x2b\x97\x24\xcf\x64\x4a\x16\xa9\xf8\x3e\xde\xc9\x02\x8a\x61\x68\x82\x65\xb7\xd3\xfa\x05\xaf\x3a\x88\x48\xb3\xea\xef\xd7\x55\xb2\x55\x87\x27\x83\x5f\xee\xaa\xd7\xe8\xc0\x81\x6c\xae\xba\x8d\x41\x52\xad\x3a\x38\xf6\xbf\xcc\x55\xbf\xe5\x22\x97\xb7\x3a\xad\xc3\xf7\x83\x13\x1a\xac\x29\xb6\x8c\x5d\x33\x63\xb8\x58\xe8\xae\xd3\x47\x8b\x22\x01\x68\x68\x97\xd7\xe7\xb1\xb1\xd8\xa7\x9c\xd0\xf4\x73\xdb\x2b\x89\x4c\xbb\xd4\xda\xd7\x25\x74\xbc\x28\xac\x0f\xb9\x9d\x74\xde\xe5\x45\x45\xbc\xe9\x8d\x5e\xd4\xa7\xc6\xa2\xd4\xf4\x54\xd9\x8f\x30\x9c\x16\xd7\x15\xb6\x87\x09\xd9\xbc\x78\xdf\xbe\xb9\x3e\xe9\x0b\x8e\xd0\x4f\x1c\xb0\x96\xca\x25\x68\xad\x64\x42\xf3\x92\x6b\x8d\xcf\x22\xda\x71\xcb\x66\x4b\x29\x6f\xc8\x41\x40\x5f\x2f\xb8\x59\xd6\xb3\x69\x26\xcb\x0e\x10\x7b\xa2\xf9\x42\x1f\x7b\xc5\x34\xb1\xeb\x85\xc5\x64\xc2\x97\x88\x82\x0b\xff\x66\x0b\xb1\x93\x30\x9a\x48\x7c\x3b\x44\xd2\x2e\x49\xd6\xac\x36\x9c\xf8\x08\x91\xae\x71\x9b\x03\x18\xee\xd8\xc8\xcb\x38\xfe\x02\x60\xbc\x7c\x54\xbb\xbe\x7d\xe8\x2f\xa3\x08\x55\x3f\x71\xf0\x23\xd7\xcb\x35\x82\x71\x64\x1b\x3e\x5f\x68\x7f\x23\x42\xe2\xc6\x49\xf1\xc9\xc2\xc7\x0d\x2b\x42\xa2\x36\xe1\x4e\x40\xc2\xd6\x8b\x8c\xba\xb2\x8d\x07\xd1\xa6\x7e\x3b\x49\xdc\x08\xd1\x9b\xe9\xdf\x26\x91\x1b\x21\x73\x13\x81\x9c\x24\x0d\x4c\x1e\x30\x15\x4c\x3e\x3b\x1d\x1c\xf1\x03\x7d\x87\x25\x91\x17\x40\xee\x4f\xfd\x44\x2a\xf4\x07\x73\x5c\x48\x32\xe7\x85\xc4\x5d\x7c\x4f\x57\x96\xa4\xa5\xdf\x75\x47\x16\xe1\xe1\x09\x1b\xf1\x55\xe1\xd1\xdb\xee\xa8\x23\xad\x6c\xa8\xe0\x8a\x75\x20\xde\xe4\xff\xc6\x9d\xf5\x7e\x0b\x58\x21\x5d\x6d\x6b\x87\xc9\x12\x21\xd3\xf7\xf4\xca\x49\x2d\x0c\x2f\x02\xa2\xa9\xac\x0a\xeb\xb9\xf4\x66\x8f\x9c\x31\x48\xec\x74\x0d\x3c\x6a\x96\x27\xa6\xb9\xa1\xe7\x02\x3d\x22\xff\x53\x6b\x43\x68\x53\x52\x14\x08\xed\x60\x27\x11\xc2\x03\xd7\x1e\xe0\xe3\x7c\x2b\x57\xe0\xb3\x37\xd2\x7e\xc4\x8a\xe7\x18\xa9\x39\x9f\xcf\x59\x28\xaa\x9a\x31\x52\x51\x45\x4b\x66\x00\xee\x8a\xc5\x48\xcc\xd8\x82\xbb\x9a\x13\x39\x27\xd4\x2e\xe8\xfe\xbe\x6e\x59\xd2\x30\xfa\x03\x2a\x59\xb8\x21\x25\x5f\x2c\x0d\x5c\x72\x42\x49\x21\xc5\x02\xb8\x70\x70\x10\x81\x42\xd2\x9c\x80\xae\x97\x8a\xdc\x52\x55\x12\x4a\x32\x9a\x2d\x01\x7b\x81\x7a\x91\xcd\x6b\x05\xed\x08\x0d\xa3\xf9\x7a\xa2\x0d\x35\x36\xd6\x65\xae\x2e\xda\xed\x1c\x42\x6a\xb6\xc5\xc9\xe2\xce\x00\x64\x5c\x66\xcc\x60\xba\x83\x07\x38\xa4\xc7\x40\x06\x7f\xb8\xab\x6c\x22\xa4\xce\x0b\xba\x78\x6a\x24\x40\x63\xf7\x4c\x3f\xc6\xee\x99\x9f\x3b\xc6\xee\x99\x9f\x3d\xc6\xee\x99\x63\xf7\xcc\xb1\x7b\xe6\xd8\x3d\x73\xec\x9e\xb9\x31\xc6\xee\x99\x63\xf7\xcc\x9f\x19\x63\xf7\xcc\x4f\x0b\x1c\x99\xb1\x91\x63\xec\x9e\x39\x76\xcf\xbc\x7f\x8c\xdd\x33\x1f\xdb\xb5\x18\xbb\x67\x8e\xdd\x33\xc3\x18\xbb\x67\x0e\x18\x63\xf7\xcc\x61\x63\xec\x9e\xf9\xc9\xf1\xc4\xfa\x69\x8c\xdd\x33\xc7\x7e\x1a\x9f\x2b\xe7\xe9\xf5\xd3\x20\x63\xf7\x4c\xdc\x18\xbb\x67\x0e\x1f\x63\xf7\xcc\x61\x63\xec\x9e\x39\x5c\xe6\xd8\x3d\xb3\x1d\x63\xf7\xcc\xb1\x7b\xe6\x33\x3d\xba\x63\xf7\xcc\xb1\x7b\xe6\xee\x31\xbe\x11\x8c\xdd\x33\x87\x8d\xb1\x7b\x26\x5e\xe8\x18\xed\xe3\xe5\x3c\xbd\x68\x7f\xec\x9e\x39\x76\xcf\xfc\xe4\x88\x71\xdd\xb4\xc9\x39\xa2\x6d\xca\xc3\xf0\xa2\x7a\xb4\x6c\x87\x6b\x66\x56\xcf\xe7\x4c\x81\xdb\x0d\x33\x45\x25\x6e\x76\xd3\xf4\x4e\x43\x99\x02\x46\xa6\x73\xfc\x34\x33\x47\x40\xe1\xaa\x5d\xe1\x34\x4c\x11\x07\x78\xec\x4f\xd1\x53\xee\x40\xb3\x10\xc5\x34\x2e\xbe\xe6\x82\x9c\xbf\x7d\x3d\x4d\x40\x09\x1b\xc3\xa6\x06\x6b\xf2\x56\x64\xb1\xc5\x3a\xed\x21\x8b\x63\x36\x0a\xac\x46\xfe\xac\x65\x85\xd4\x0e\x5b\xeb\x36\x2f\x5b\x52\x21\x18\xa6\x40\xc5\x29\x44\x6e\x20\xed\x36\x63\x4c\x10\x59\x31\xe1\xf0\xff\x94\x68\x2e\x16\x05\xc6\x02\x50\x63\x68\xb6\x9c\xda\xef\x17\xe1\x80\xf9\x6e\x32\xcd\xac\x31\x57\xcd\x28\x46\x4b\x77\xd0\x14\x2b\x29\x77\xd3\x25\x34\x53\x52\x6b\x52\xd6\x85\xe1\x55\xc4\x84\x89\x66\x50\x66\xad\x5d\xcd\x7f\x38\x04\x04\x75\xdd\x34\x73\x60\x4f\xe0\xee\x6c\xd6\xc0\x2f\x2f\xca\x05\x6b\xaf\x1a\x04\xf0\x47\xd0\x48\xb0\xac\xcc\xda\x15\x44\x21\x2f\xf0\x9c\x2b\x6d\x48\x56\x70\x88\xe0\x60\x1d\x18\x58\x32\x98\x33\x06\x01\x4c\x45\x6e\x25\x0b\xbf\x47\xda\x6f\x92\xc8\xc1\x01\xad\x50\x0e\x3f\x94\xe5\x84\xba\x2f\x16\xa6\x9b\x73\xed\x03\x0a\x8d\x9a\x68\x60\x53\x77\x97\x2b\xec\x11\x5c\xaf\x1c\x49\x0b\x1c\xbe\xd9\x0b\xe9\x4c\x39\xe2\xfe\x03\x01\xba\xcf\x8a\x37\x26\xc0\x51\x97\x07\x05\x89\xfa\xfe\xed\x62\xdc\x40\x86\x0b\x06\x02\x21\xb2\x63\x52\xe0\x9a\x0a\xb6\xb2\xd6\x8b\x65\x8c\xaf\xac\x13\x8e\x10\xb9\xd3\x1e\x7c\x51\x73\x60\x98\x2a\xb9\x80\xa2\xad\x37\x4c\x6b\xba\x60\x57\xa8\xd7\xef\xfb\x62\x6b\x78\x00\x0f\x87\x11\x7d\x8d\x0b\x08\xb0\x5b\xe7\xb6\x2d\x41\xd8\x47\x95\x87\xb6\x1f\x4d\x4a\xf7\xd5\x0d\x2f\xca\xad\xe2\xc6\x30\x94\x63\xa3\x5d\xb7\x05\x00\x0e\x6d\x32\xf1\xe0\x26\xda\x29\xaf\x20\x6f\xc2\x44\xdd\x04\xed\xcf\x59\x27\x55\xe4\xa8\x1c\x97\x43\x39\xcd\x14\x67\x73\x32\xe7\x50\xc5\x00\x78\xfb\x23\xc7\xee\x4b\x31\xb3\xa5\x82\x50\xad\x99\x82\x75\xf5\x78\xeb\xb0\xbe\x53\xf2\x03\xba\xce\xd4\xa8\x5a\x64\xb4\xed\x95\x45\x84\xcc\x19\xe1\x73\xb2\x00\x64\x3f\x46\xeb\x40\x6f\xbe\xdf\xbd\xf8\xd3\xef\xc9\x6c\x6d\x03\x0d\xc0\xb2\x18\x69\x68\x11\x26\x8c\x10\x5a\x30\xb1\xb0\xa7\xdd\x99\xec\x3e\xa5\x50\x44\x99\x2d\x74\x55\x77\xb5\xaf\x2f\xbf\xbe\x99\xf5\x62\x32\x84\xc4\xe3\x9c\xad\x8e\x3b\x37\x60\x52\xc8\x45\xa7\x19\x3e\x42\x62\x28\xd5\xc4\x16\x2a\xa2\xc2\xfc\x1d\x8a\x0b\x3a\x7a\x46\xaa\xae\x40\x9c\x4e\x96\xf2\xd6\x75\x53\x69\x7f\x07\xb1\x34\x41\xbb\xb4\x75\x87\x95\xac\xea\xc2\x55\xb6\xbe\xe6\x28\x87\x0e\x34\x55\xad\xd9\x26\xf7\xcc\x3d\xba\x1c\xa7\x1c\xc2\x34\x37\x02\x21\xa7\x24\x22\x16\x42\x7a\xe2\x06\xff\xba\xd4\x30\x9f\xd7\x0a\x55\xf9\xf8\x9a\x16\xc5\x8c\x66\x37\xef\xe5\x77\x72\xa1\xdf\x8a\x73\xa5\xa4\xea\xad\x10\xe6\x1e\x53\xeb\x35\x2e\x6b\x71\xe3\x9a\x81\x87\x8f\x2f\xe4\x82\xc8\xda\x54\x35\x2a\xfa\x9b\x6f\x1e\xa7\x66\x4d\xe6\xb8\x73\xd0\xb8\xc8\xde\x29\xed\xcc\x94\xdd\x71\xdc\xd3\xc7\x2d\xb7\x0a\x4c\x10\x66\xd7\xd1\x69\xc5\xf6\xab\x71\xc1\x42\x47\x7d\x7d\xfd\xe2\x77\x7f\x74\x0a\x97\x48\x45\xfe\xf8\x02\x8a\x32\x51\xee\x2d\xb8\x02\xe0\x7f\x71\x4d\x74\x49\x8b\x82\xa9\x58\xc5\x68\xaf\x63\x47\x11\x36\x6a\xed\x8b\x6a\x35\x13\xab\xc0\x1e\x30\xf9\xf3\xfe\xfd\x7f\x41\xe6\x87\x1b\xcd\x8a\x39\xca\x2b\x2f\xb4\x6c\xfb\x1d\xed\x83\x33\xbd\xef\x7d\x11\x1b\x4d\x62\x54\xc0\xe3\xa6\x53\x56\xb2\xa8\x4b\x76\xc6\x56\x3c\xc3\x3c\x6b\xf5\xb6\xae\x27\x0b\x5f\xf9\x5c\x70\x0d\x84\xf4\xb3\x42\x66\x37\x24\xf7\xe2\x5a\x58\x3b\xc6\x0b\x59\xc7\xf2\x4a\xc6\x14\x21\xa0\x8b\x0f\xee\x5d\xdd\xb6\x74\x00\x95\xe0\xa5\xa4\xa4\x55\xd5\x90\x7e\x28\x7a\xdb\x5b\x6c\x94\x4c\xab\x79\xb9\xe8\xc6\xad\x98\xcb\x10\xf9\x38\x1c\xf3\x34\x3c\xf1\x5f\x8f\xf4\x39\xd0\x75\x09\xb1\xaf\xca\xed\xac\xb1\x0f\x5f\xbd\x63\xd6\x8a\x8b\xe5\x2e\xa8\x40\x86\x2b\x5a\x4f\xd4\x5f\xa2\xc3\x8c\xe4\xe6\xd9\x84\xbd\xf6\x40\x47\xb0\x8a\x19\x89\x7d\x74\x8c\x7e\xe9\x8b\xa9\x02\xe9\xed\x9c\x68\xde\x54\x4b\x6a\x50\xc9\x0a\x37\xba\x24\x7f\x94\x54\x4c\x69\xae\xad\x8f\xfe\x3d\x28\xa0\xd3\x82\x72\xec\xc3\x59\xf3\x78\x52\x49\xec\x56\x45\x2c\xb7\x53\xa0\xd0\x9c\x30\xd6\xd2\x5d\xc9\xdc\x8b\x03\xc3\x04\x69\x13\xd4\x8b\xca\x56\x9a\x25\x96\x92\x22\x99\xfb\xf7\x98\xa6\xee\xfb\x76\xa7\xe2\x2d\x9d\x95\xd2\x98\x3a\x27\xd9\x1b\x2b\xa4\xc4\xe7\x6b\xe0\x60\x2d\x9e\x9b\x7d\x6b\x26\x9d\x44\x49\x82\x61\xf3\xbe\x4a\x8c\x71\x6b\x63\xd5\xf6\xa5\x62\xc9\xbc\x52\x40\x4b\x6d\xd3\x2c\x3e\x13\x3b\xf5\x60\x51\x81\xee\x54\xd7\x4c\x95\xec\xbf\xda\x7f\x34\x23\xe7\x36\x51\xc9\x8a\x2e\x20\x77\x90\x64\x2f\x37\x85\x46\x20\xbc\x5c\x5a\x83\x69\x48\x9b\x81\x5c\x2c\x13\xa2\x1b\x95\x9f\x15\xcb\x5b\x0a\xf4\xa5\x04\x86\x85\x14\x47\xce\x27\x4c\x1c\x71\xe3\x6d\x44\x5d\x34\x55\xb2\x16\xb9\x7f\x0d\x6e\x20\x08\x6f\x36\x16\xf6\x12\xcf\x60\x06\x69\x1e\xc7\xd5\x0e\x44\x78\xae\x50\x92\x6b\x2c\x19\x9e\x97\x29\xc8\xcb\xe9\xcb\x17\xcf\xdf\x67\x83\x35\x49\xe4\xb3\x5d\x36\x3e\x9b\xb3\x72\x8f\xb6\x3a\xa1\x61\x72\x92\x15\x7a\xe3\x9f\xa4\x9a\xce\xc6\xf8\x43\x13\xba\x75\x82\xa8\x5b\xc5\x8d\xbf\x41\xb7\x3c\xa2\x50\xed\x00\x92\x36\x44\xaa\x2e\x05\xf1\x61\x9b\xcb\x8b\x08\x49\x62\x3a\x2e\xc7\xb7\x2c\x24\x44\xd7\xb3\x27\x67\x77\x9d\x81\x75\x4a\x75\xd7\x7b\x2a\x7e\xbd\xbd\xe4\x6d\x13\x8c\x96\xd8\xc5\x1e\xee\xed\x91\x03\xf7\x0b\xfb\x8e\xcd\xee\xf0\xd1\xae\xa7\xdf\xd6\xf3\xbb\x0a\xdd\x54\xa6\xb7\xb5\xe7\x77\x15\x15\x39\xcb\x5d\xc0\x1f\xe1\x5a\x93\x40\x3a\xbd\x6b\x8f\xe3\xcd\xe6\xbe\xee\xef\x31\x5a\x62\xd7\x3d\xfb\x2b\x5b\xd2\x15\x03\xce\x3f\x5e\x50\x15\xa1\x9e\x8c\x24\xd7\x6e\x67\xc8\xac\x36\x84\x89\x15\x57\x52\x94\x2c\x82\xd8\x7d\x45\x15\xa7\xb3\x82\x11\xc5\x80\x38\x38\x63\x9a\xfc\xfa\xe0\xfb\x93\x77\x00\xb3\xc6\xb7\x8f\xa0\x8a\x11\x16\x76\xbd\xd6\x50\x9e\x9b\xe8\x16\x76\x3e\x7b\xba\x71\x81\xf0\x2a\x7a\xe3\xe2\x85\x75\xb6\x37\x00\xbf\x06\x22\x6f\xf6\xcb\xae\x47\x59\x9b\x9a\x16\x40\xfb\x98\x15\xb5\xe6\xab\xc7\xb0\xbf\x9e\x86\xf3\x8c\x23\x6e\xf6\x06\x7d\x69\x7b\x69\xb6\xb8\x3d\x91\x14\xde\xe0\x5e\xa6\x6b\x29\xe9\x81\x97\xfb\x3a\x14\xab\xf4\x5a\x03\xa1\x1f\xe5\x3c\x6d\xf5\x0c\x26\x37\xe7\x8b\x5a\x39\x22\x1d\x9c\x0a\xea\x34\xb3\x2e\x01\x45\xf2\x58\xcf\x73\x42\xe6\x6c\x68\x4b\x8b\x7e\xe1\x8b\x17\xe0\xa8\xac\x3b\x84\x71\x3a\x5b\xb2\xbc\x1e\xf8\x02\xec\xe8\xdc\x65\x4e\xa4\x30\x92\xd0\xa6\x25\x16\xcc\x13\x60\x74\x7c\xf0\x73\xad\x90\x62\x02\x0f\xca\xee\x6c\x85\x79\xa9\xc0\xc7\x1a\xfe\x62\x98\xd4\xfe\x4c\x21\xfd\x6c\xe7\x78\x44\xa8\xd6\x75\xe9\x54\xdf\x40\xce\x50\x6e\xc8\x9c\x1b\xc0\x0d\xca\x5a\x65\x2c\x64\x75\xac\xd2\x1b\xc4\x93\x85\x3e\x09\xd7\xac\x80\xab\x8c\x3e\x0d\xfb\x97\x1d\x29\xee\x48\x68\xff\xa7\x41\x4b\xe1\xaf\x9c\x2f\x04\x02\x14\x72\x53\x0c\x2c\xe1\xcd\x7d\xce\x87\x2d\xae\x14\xd0\xdd\xdf\x9e\xa2\x66\x7e\x9d\x5f\x81\x30\x8b\x0c\x8b\x3c\xad\x34\x60\xc5\xa7\x33\x56\xe8\xcd\x09\xce\xda\xa3\x36\xcc\xa5\x00\x4a\x1c\x7f\x9c\x06\x17\x92\x04\xe5\x04\xf1\xf9\x31\xd5\x9a\x2f\xc4\xa4\x92\xf9\xc4\x4a\x3b\x1e\x82\x64\x42\x66\x24\x69\x1e\xf8\x83\xaf\x90\x09\x3e\xd4\xe9\x95\x2b\xa6\x96\x8c\x0e\x4a\x80\x6e\x60\x3b\xbd\x04\xa2\x58\xa5\x98\x06\xf0\x91\xe3\xbf\x73\xb7\x71\xd8\x1e\x06\x61\x54\x6b\x99\x01\x7f\x85\xc3\xa0\xa8\xda\x75\x55\xa0\x83\xdf\x3a\xec\xf1\xa2\x64\xc1\x57\x4c\x90\x77\xce\xc6\x9d\x16\x54\xeb\x5e\x02\x65\x30\x1a\x6f\xc6\x08\xad\x8d\x6c\xd0\x5b\x84\x9a\xb6\x77\x99\x03\x59\xcf\x86\xf9\xae\x76\xcd\xba\xf3\xeb\x88\xb3\x56\x4f\x49\xc0\xb4\x0c\x12\x79\x31\xff\x3c\xa9\xc3\xb4\xad\x0e\x9d\x13\x8e\xda\xed\x2a\x7d\x52\xb5\xed\xf3\x33\x48\xe6\x95\xcc\x49\x06\xe0\xcd\x60\x09\x3d\x04\xb3\x3b\xf5\x41\x12\x77\x7d\x66\xa8\xa6\xb0\x37\xb3\xf3\x93\x83\xe4\x86\xe9\x79\x1d\x68\x83\x15\x97\x3a\x6c\x0e\x6e\xa1\x18\xcd\x87\x6d\xbd\x66\x06\x6c\x74\x6f\xa3\x1c\x5c\x27\x78\x4c\x43\x11\xfa\xce\x7a\x34\xae\x16\xb4\x32\xaa\x58\x76\x44\x9a\xeb\x8a\x39\xf2\xa1\xd0\xa3\xe9\x64\x94\xb3\x39\x17\xed\xaf\x64\x52\x29\xa6\x2b\x29\xf2\xa1\xbe\x76\xf7\xd3\x8f\xda\x34\x92\xb5\xed\x9d\x1a\x98\x41\x22\x6b\x61\xa7\x0b\xb9\xdd\x96\xf1\xfb\xdf\x4c\xc9\xae\x71\x18\x24\xb1\xd3\x4f\x70\x7a\xf3\x47\xb0\x22\x4c\x2c\xa9\xc8\x9c\xab\x71\x7c\xc3\x2a\x7d\xac\xf9\xc2\x19\x8d\xaf\x5f\xbc\xfc\xd3\x8b\xaf\xbf\xfe\x3d\x98\x91\x70\x3e\xa6\xe5\xb0\x7d\xec\x27\x79\x69\x51\x2d\xe9\xc4\xb5\xa2\xa6\x80\xf1\xfc\x7b\x63\xd3\x06\x89\x5d\xbd\x9c\xbe\xfc\xfd\x11\xf1\x04\xfb\xd0\x55\x63\x29\x85\x54\x0e\x53\xed\x08\xe5\x86\xfa\x75\xd4\x78\xc5\x10\x0e\x5c\x73\xd4\x7c\x6f\x94\x41\x80\xe0\x47\x33\xa3\x15\x35\x86\x29\xf1\x8a\xfc\xf7\xc1\x3f\xbe\xfa\x38\x39\xfc\xe6\xe0\xe0\xc7\x17\x93\x3f\xfd\xf4\xd5\xc1\x3f\xa6\xf0\x2f\xbf\x39\xfc\xe6\xf0\x63\xf8\xc3\x57\x87\x87\x07\x07\x3f\xfe\xfd\xcd\xb7\xef\xaf\xce\x7f\xe2\x87\x1f\x7f\x14\x75\x79\xe3\xfe\xf4\xf1\xe0\x47\x76\xfe\xd3\x67\x0a\x39\x3c\xfc\xe6\xd7\xc3\x14\xdc\xf0\xd2\xec\x98\x72\xec\x88\x12\xec\x64\x65\xd7\x95\x62\x36\x1e\xe1\x52\x0c\x87\x76\xf7\x93\xa7\x1b\x82\x42\x2b\x46\xf7\xa7\xc1\xde\x45\x98\x97\x58\x58\xe7\x44\x3b\x87\xa5\x90\xb7\x50\x6a\xc4\xa5\xe2\x66\x60\x88\xff\x56\xc0\xc3\xc3\x25\x5b\x31\x75\x14\x66\xfb\x9d\x15\x78\x15\xe4\xe1\xf2\xe1\x46\xee\x94\xe6\x1b\xfe\x59\x2b\x34\xb8\x4f\xd3\x6e\xdd\xb4\xad\x57\x86\x99\x9a\x46\x07\x6d\xe9\x95\x4b\x29\xae\x9a\xf5\x0e\x1f\x30\x6c\xc6\x5e\x1b\x3d\x74\x60\x18\xf6\x1e\x7d\x4c\xdf\x43\xd9\xbe\xdf\x22\xb0\xb7\x53\xf2\x3d\x55\x5c\x0e\x44\xdc\x3b\xf4\x0b\xf4\x8f\x93\x02\xfc\x73\x87\x85\x6f\x2c\x0b\x84\x85\x03\x1d\x0c\xd3\x9d\x5c\x43\xbe\x11\x9e\x3e\x51\x1b\x73\xd2\xf8\x6c\xa7\xad\xcf\xd6\x75\x37\xb9\xb1\x77\x6d\x65\x3f\x61\x98\x27\xa0\xed\x49\x72\xf5\x7a\xae\xd9\x77\xe7\xeb\x9d\xa3\x89\xeb\x3b\xdc\xf1\x2d\x43\x24\xa0\xbb\x0b\x0b\x3f\x19\xd6\x02\x7c\x9b\x4b\x3a\xf4\x21\x11\x58\x75\xf9\x22\xd4\x56\xc3\x39\x70\x19\x99\xce\xdf\x62\xf4\x0c\xd6\x18\xe0\xe8\x0c\xaa\xcd\x55\x40\x5f\x8b\x7e\xbf\xc5\xa6\x2d\xe4\xe0\x8c\x62\x25\xf3\x7d\xdd\xae\x1c\xd9\x73\xf7\x04\x9c\xb7\x49\xa6\xb8\xe1\x19\x2d\x86\x65\xc9\xad\xde\x0b\x62\xb2\xa2\xd6\x86\xa9\x56\x12\xa4\xb5\xcd\xed\x30\xc0\x02\x7c\x29\x2d\xc8\x0d\x5b\xdf\x4a\x95\x87\xb8\x23\x7c\x75\x7b\x0e\x06\x92\xd2\xf8\xcf\xe6\xcc\x9b\x2b\xd7\x16\x4d\x95\x4c\x91\x19\x0b\x0f\x10\x11\x82\xd7\x53\x72\x22\xd6\x1e\x51\x21\xba\xec\x34\x3e\x64\x18\x6a\x0f\x20\x56\x73\x19\x80\xde\x85\xf2\x2e\x22\x7c\xc5\x70\x87\xd5\xce\x6c\x7a\x4f\x32\xbd\x92\x79\xf3\x35\xc3\x92\x70\x3e\x6f\x1e\xf2\xe8\x52\x11\xd7\x19\x08\xb4\xa4\x62\x8e\x9e\x62\x90\x48\x2f\xea\xc1\x6d\x96\x8d\x5d\xb9\x60\x5a\x7f\x6b\xaf\x14\x3e\x29\xd4\xbf\xa3\x14\x02\x38\x2f\x79\xd0\x77\x2f\xe0\x66\x87\x05\x65\x56\xf9\x39\x10\x90\x75\xbb\x64\xde\x4a\x1d\xa6\x53\x4f\xe0\x3f\x86\x52\x73\x9a\xaf\x5d\x87\x4d\x3b\x49\x6e\x3a\x35\x32\x03\x13\x0e\x8a\x79\x69\x27\x97\x67\xa1\xd8\xd3\xc5\x22\x1a\xd9\xa6\xb9\x69\x24\xe1\xbf\xd1\xaf\x06\xe4\x1c\x7c\x37\x2c\xf6\xaf\x9a\x0e\x8b\xe2\x8d\x24\x7b\xef\x55\xcd\xf6\x76\x65\x48\x3f\x1d\xd8\x32\x73\x2b\xd5\xcd\xf1\x8b\x17\x2f\xfe\x00\x71\x2d\x7c\xf2\xff\xfa\xfa\xaf\xff\xeb\xeb\xbf\x4e\xcb\x7c\x78\x80\x37\x14\x16\x8b\x00\xc4\x6e\x22\x8d\xdf\x75\xcf\x78\xd8\xee\xa1\x2f\xac\x6e\x63\xfc\x2b\x30\x10\x8e\xc1\x91\x6a\xf6\x1c\x91\xb9\x45\x80\x58\x71\xf0\xd5\x49\x3b\xcd\xf7\xeb\x6a\xa0\xd1\x44\xa3\x4f\x7b\xbf\x19\xff\x9c\xda\xca\x72\xfb\x80\xaa\xfb\x97\x0e\x7e\xec\x64\x75\xc0\xf4\xfb\x1a\xb9\x93\x6e\x40\xc5\x15\x98\x55\x78\x1e\x01\x73\xba\xae\xd0\x95\x68\x83\x75\x38\xd0\x67\x44\xc6\xc8\xfb\xef\x9c\x18\x52\xb9\x10\x19\xd2\xe8\xbd\x12\xf6\x81\x36\x31\x40\x95\x5c\x94\xe0\x43\xdc\x13\xe0\x50\x3a\x22\x6f\xc5\x6b\x57\xf4\x3b\xec\x9d\x19\x22\xe4\x96\x31\xc3\x48\x2f\x30\x29\x8f\xd8\xf1\xaf\xfc\x8a\x4e\xdc\x52\x0c\x57\x72\x43\x37\xb0\x93\x0b\x8d\xf2\x94\xf7\xdf\x6d\x48\xf2\x57\x65\x28\x6a\x96\xf6\x33\xd3\xde\xe3\xf2\xdb\x09\xcf\x6d\xce\x68\x0c\x33\xed\x4a\xd6\xd5\x91\xf7\x67\x5b\x94\x58\x68\xeb\xad\x6a\x31\x9c\xfd\x0b\x8e\x96\x73\xe7\xfa\x53\x6e\x9e\x86\xe1\x42\x0e\x7e\xb2\x76\x05\x3c\x39\xc9\x5c\x7a\x3a\x78\x87\x8e\xf6\xc5\xbd\x7a\xa8\x5a\x0c\x7e\x9c\x71\x19\x6a\xa9\x48\xe7\x99\x7d\xaf\x60\x0b\x9a\xad\xf7\xf0\x4f\x1f\x3d\xd8\x46\x88\x17\x34\xa1\x02\xe8\x6b\x79\xc6\x8d\xfb\x8e\xc1\xf7\x17\x0a\xc1\xa1\xc2\x1c\x7c\x78\xa7\x34\xc1\x8d\xae\x35\x22\xfe\x0a\xee\x71\x60\xfc\x5a\x52\x91\x43\xd9\x36\xca\x31\x91\x39\x3b\xf6\x92\x26\xf0\x79\xa8\x4c\x7b\xd3\x57\xbc\xe9\xe7\x1d\x9d\x66\xff\x1d\x22\xed\x3d\x50\x61\x34\xd0\x8c\x84\x71\x75\xf7\x8c\x0f\x7d\x26\xca\xb9\xae\xe0\x9e\xb9\xd7\x84\x20\xb4\x9d\xe7\xe0\x9b\x72\x4f\x78\xd6\x44\x5a\xcd\x0f\x0e\x0d\x2b\xc3\x21\x44\x4d\x0d\xb7\x59\x2c\xab\x21\x7a\x95\xc2\xb0\xbb\x41\x3c\xba\x7d\xe5\x7e\xdd\x17\x44\x96\xb2\xc8\x01\x5a\xe3\x92\xb0\x03\x9f\x0b\x9d\x2c\x42\x8d\x51\x7c\x56\xdb\x38\x83\x8a\x1c\xba\x30\xfb\x37\xd4\xe1\xb8\x32\x9f\x6b\xd3\x53\xd2\xf2\x3f\x75\x21\x88\xa0\x4b\xa6\x84\x5c\xb3\x81\x60\x27\xeb\xf4\x75\xd6\x02\x7c\x93\xb0\x91\x90\x1f\xb3\x77\x76\x90\x48\x46\xb3\xa5\x4f\x07\x7e\x81\x47\x2a\xac\x13\x3d\xd7\xdf\x5a\xa3\x39\xd4\x79\xee\x1d\x9b\xbd\x93\x26\xa7\xa4\xeb\xca\xd3\x99\x0f\x8c\x21\x49\x30\xdf\x4e\xfb\xd3\xaa\x2a\xb8\xab\xdc\x8c\xf0\x10\x89\x8b\x78\xa9\x33\xe2\xd7\xb2\x6c\x80\xcb\x76\x95\xb5\xeb\x83\x38\xdc\x83\x5e\x32\x50\xde\x85\x7b\xb9\xce\x96\x40\xba\x0c\x2f\xf6\xb7\x76\x8a\x4b\x5e\x0d\x96\x09\xd9\x6e\x6a\x9a\xe9\x01\x66\xc9\x8a\x0b\x84\x54\x83\x25\x56\x32\x7f\x45\xfe\x21\xc8\x4b\x97\x8c\x96\xb7\x80\x75\xf9\xf6\xe2\x2c\x68\x38\xd4\x77\xbf\xbe\x86\xe3\x42\xbe\x76\x52\x35\x33\x0b\x9e\x93\x99\xeb\x82\xae\xd9\x70\x1c\xf4\x81\x60\xb7\xae\x9e\xd6\x43\x27\x9a\x87\xff\x55\xa8\x03\x45\x90\x5a\x75\x17\xcf\x4f\xf9\x90\xfc\xd6\xcd\xb9\x62\x0a\x93\x97\x07\xb1\xdc\xd5\x9c\x91\xb7\xef\xf6\x03\x88\xe8\x76\xa2\x6e\x27\x93\xc9\xc4\xae\xf5\xc5\x30\x0d\x41\x02\xa2\xe0\xa8\x77\xa6\x1a\x17\xb0\x94\x39\x9f\x0f\x47\xab\xf7\x4e\x22\xa8\xdc\xf6\x93\xc1\xf3\xa0\x62\xb8\x50\xb7\x1b\xd3\xa1\x08\xef\x18\xa6\xe3\xce\xa3\xc0\xef\x7f\x87\x51\x6a\xa7\x70\x33\x71\x9c\x5d\x7d\xbb\xb8\x43\xa0\x4f\x3a\x0f\x57\x48\x33\xb6\xa4\x2b\x2e\x81\x8f\x1b\x74\x07\x54\x3e\x77\xf7\x6b\xf8\x5d\x6f\xf6\x37\x3c\x9b\xf9\xcb\xe3\x9b\x39\x41\xfa\x7d\xb0\x54\x76\x57\x49\xd7\xa2\x14\xf8\x21\xae\x64\x1e\x87\x6f\x23\x00\xa8\x2c\xd6\xa0\xdc\xd7\x56\xc7\xf5\x94\xb1\x8f\xda\x5c\x53\x8d\xc1\x82\xfd\x0e\x91\x19\xb5\x53\x6e\x96\xf3\x60\xe3\xf8\x23\x4a\x7a\x2e\xfc\x8d\x84\x1c\xa9\x90\x84\xcd\xe7\x36\x54\x95\x82\xb0\x6a\xc9\x4a\xa6\x10\x96\xae\xf7\xe1\x9e\x0d\xf1\x95\xf5\x98\x94\x55\x06\x0e\xa3\x55\xd2\x6a\xf8\xe1\xb2\x9f\x0b\x3e\x50\xce\xd5\x94\x7c\x4f\x0b\x9e\x07\xf7\xc5\xea\xad\xbd\xb7\xe2\x9d\x94\xe6\x0d\xd7\x10\xb4\x0e\xaf\xd7\x80\xd7\x28\x97\x10\xd9\xdb\x7e\xe4\xc0\xf7\xa4\x30\xb2\x15\x3b\x94\xe3\x0f\x8d\x22\x51\xb5\x38\x49\xe0\xfe\x58\xa3\x62\xed\x6a\x93\x61\x60\x84\x09\xa3\xd6\x95\xe4\x88\xc2\xa0\x4d\x1a\x96\x40\x2d\x3b\x25\x1f\x6c\x44\xec\xe3\x51\x44\xae\xd3\x53\x58\x35\xb0\x8c\x37\x74\xed\xc8\xb2\x1c\x08\x0f\xe3\x58\x6d\x84\x0b\x2e\x4f\xe2\xfb\x55\xcf\x24\x82\xc3\x60\x33\xfe\xb0\xc7\xed\x0a\xba\xa3\x75\xff\x7a\x78\xe1\x48\x8b\x2e\x6c\xcf\xea\xf6\xfc\x87\x8b\xa5\x37\x4c\x93\x4a\xb1\x8c\xe5\x90\xb4\x77\xb8\x73\x6a\xf0\x04\x14\x8f\x63\x30\xe1\x26\x5c\x4a\x50\x0e\x51\x77\xe1\xa2\xf3\x74\xee\x59\x80\xf0\x05\x44\xf0\xbc\x6b\xaf\x14\xd5\x50\x30\x20\x26\x4a\x4a\xc8\x0c\x29\x47\xe3\xac\x6a\x04\x71\xf3\x96\xab\xb5\xb2\x5a\x32\x3c\x7c\x43\x0d\xd0\x70\xb5\xd8\xa6\x9c\x6c\x10\x2a\x74\xad\x98\x5b\x01\x6e\x48\x2e\x11\x5e\x82\xd5\xab\xfe\xd3\x3f\x5c\x9c\x91\x17\xe4\x00\x0a\xe3\x1a\x32\x4b\x0c\x4b\x81\x4b\xbe\xf7\xb5\x0b\x9f\x87\x29\x4e\xd1\xee\x2b\x91\xca\xb3\x68\x5b\xfb\x08\xe6\xcc\xaf\x29\xc6\xc9\x0e\x09\x18\xdf\x78\x90\xe5\xa3\xaa\x7a\x00\x55\x85\xd3\x4b\x98\x52\x75\xd0\x2d\x1f\x34\x1b\x5c\xef\xb8\x65\x64\x3f\x7c\x01\x23\x8b\xe6\x04\x70\xcd\x74\x55\x7f\xd7\x40\x9b\x90\x92\x19\x9a\x53\x04\x97\x86\x33\xd6\x41\xe0\xd6\x3d\xc0\xb4\x1d\xf9\xd4\x3d\x88\x3e\x68\xf7\xdc\x83\xf6\x5c\x0f\x57\x5b\x3f\x73\x0f\xdc\xb9\x1e\x1e\x30\x3d\x7f\x93\xad\xd9\x77\x5c\xd4\x77\x2e\x0d\x3a\xf8\xe5\x7c\xeb\x6e\x5d\x9f\x83\x38\x47\xf6\x7c\x87\x22\xc1\x99\x31\x9f\xb6\xcb\xb7\xd3\x76\x53\xff\x36\xd5\xe4\xdb\x51\x7a\x71\xab\xa1\x4f\xe8\x9a\xe3\xf8\x63\x87\x9f\x55\xa2\xa8\xc8\x65\xb9\xf5\xf5\xf6\x50\x30\x8a\x20\x7b\xe9\xf4\x76\xdb\x71\x5b\x77\xde\xbe\xe1\xf7\xe1\xfe\xdb\xfa\xdc\xac\x50\xb2\xdb\x87\x62\x6b\x8b\xa1\x3d\x83\xf7\x90\x68\x16\xbd\xef\x00\xda\xce\x75\x73\x00\x87\x3f\xb3\x34\x13\xa2\x33\x56\x6c\x25\xcf\x23\x29\x75\x23\xa9\x4c\x94\x2c\x50\x1c\x4c\xbd\x35\x7a\x27\x0b\x5f\xd1\x1e\x16\xc9\x8a\xfd\xc5\xac\x91\x41\x41\x97\x36\x35\xf8\xba\xda\x58\x23\x33\x14\x85\x15\xc6\x53\x5c\xa3\x1a\xe1\x3d\x92\xcd\x35\xb2\x2e\x68\x7f\x8d\xac\xd8\x5f\xc4\x1a\x75\x5f\xdd\x20\x9f\x15\xe7\x0f\x9c\x34\xfc\xde\xf0\x22\xa7\x83\x59\xc7\xf8\xc4\x6d\x8f\x2c\xef\x62\x83\xfb\xce\x85\x7b\x1e\x6d\x96\x6b\xb8\x85\xe2\xa2\x29\xcc\xdb\x5a\x7c\x87\xc1\x2f\xa9\x1a\xfe\xce\xf1\xed\xc5\xd9\x94\x6c\x3a\x2b\x36\xac\xf5\x4b\x81\x7d\x8e\xa2\x79\xee\xfd\x22\xb1\x8e\x35\x76\x18\xde\x57\x24\xeb\x6b\x5c\xa7\xca\x08\xef\x76\xad\x33\x53\xc4\x1d\xe3\x6b\x27\x03\x40\x0c\x84\x86\x33\x3d\x3c\x13\x43\x4b\xa6\x2b\x9a\xb1\x3c\xcc\xca\x01\xca\x3a\x1c\x13\xc3\x2f\xfb\x55\x53\xd4\x57\x8b\xa6\x8f\x78\x23\xff\x60\x60\x9d\x3f\xb9\xcf\x3f\x3e\xf4\x54\x39\x73\x8a\x68\x70\x67\x24\x29\x68\x2d\xb2\xe5\x93\x3f\xa5\x3b\xb6\x3d\x3c\xcf\x11\x4a\x6e\x98\xc2\xb5\x77\xac\xa8\xa2\x25\x33\x4c\x05\x0e\x11\x44\xea\x29\x8a\x4c\x18\x4f\x25\x8c\xa4\x02\x9e\x20\x43\xf4\x38\x02\x61\x3c\x55\x67\x9f\xfe\xa8\x25\x44\x77\xd3\xc1\x12\xbd\x19\x89\xda\x6a\x12\xcf\xfc\x07\xab\x9f\x60\x29\xbe\x87\xd0\xed\xb9\xae\xc5\x2d\x17\xb9\xbc\xd5\xa9\x52\x1b\x3f\x38\x71\x2d\x81\x55\x00\x91\x0d\xcf\x17\x3c\x6c\x7a\x43\xba\x0f\xde\xd1\xa7\x63\x5f\x47\x87\xde\x5d\x08\xef\xf4\x3f\x3c\xe9\xf7\x4c\x72\x0c\x8b\x52\xd3\x53\x65\xa7\x6c\x38\x2d\xae\x2b\x96\x45\x07\x41\xdf\xbe\xb9\x3e\xe9\x8b\x44\x5d\x6d\xae\xc9\x2d\x94\x1d\xda\x0d\xb6\x32\x3b\xe4\x38\xb7\x6c\xb6\x94\xf2\x06\x25\xf7\xa0\x03\xce\x5e\xd6\xb3\x69\x26\xcb\x4e\x8d\xc5\x44\xf3\x85\x3e\xf6\xda\x61\x62\x57\x07\xc7\x8f\xc9\x05\x34\x05\xdb\x6e\x6e\xe7\x3f\x06\x25\x34\x6b\x56\x15\xce\xae\x47\xf7\xfb\xae\x46\xdb\xcb\x7e\x89\x63\xea\xf7\xe4\x08\x5f\x3c\x02\xdf\x3e\x8a\x43\x71\xe1\x61\x7c\xe2\x38\xa2\xd7\xc5\xf3\x6d\x84\xae\x28\xcd\xc1\x6c\xf7\x05\x25\x16\xf6\xd2\xbd\xed\x7c\xf9\xf4\x59\x78\x39\x4b\xb2\xd6\xf0\x82\xe6\x85\x59\xa5\xea\xcd\x22\xce\xb4\xef\x7a\x85\x4b\xd3\x41\x68\xeb\x25\x2e\x44\xf7\xe8\x6c\xcd\xcf\xbc\xc8\x11\x3e\x3c\x1e\x24\xee\xd9\x3b\xe9\xab\x1c\x71\x21\xe1\xd6\xf3\x40\x63\xa6\x51\x12\x1f\xf4\x85\x80\x3c\xdc\x2b\x01\x49\xf0\x5e\x4d\xf0\xb5\x14\x6a\xc5\x33\x76\x92\x65\xb2\x16\x11\xa5\x14\x67\xcc\x4e\x9e\x1a\x96\x5f\xf7\x24\x0e\xa5\x4c\xa5\x24\x07\x49\x8e\xb8\x90\x16\x9c\x3a\x7a\xcb\xbe\xd4\xe1\x1c\x20\xed\xfc\x20\x35\xba\xf1\xdd\x5e\x49\x68\xc3\x28\xa6\x7c\x21\x6a\xcd\xe3\xea\x13\xb7\xd7\x05\xd3\x24\xad\x6b\x46\x36\xf6\xcf\x19\x03\xaf\x02\x07\x09\x0d\x3c\xb5\x9f\x5b\x4a\x6a\xa8\xbe\x69\x69\x44\x19\x14\xc7\x37\xca\xb5\xf3\xf7\x7e\xf9\x26\xd4\xcd\x10\x41\x2d\x3a\x74\xbf\x96\x54\xb1\x2b\xa7\xa8\x2f\x43\x7a\x2c\x62\xcb\xac\x38\x42\x89\xe6\x62\x51\xb0\x26\x51\xdc\x24\xde\x06\x2d\xf2\x8c\x99\x5b\xe6\xb9\x17\x36\x0d\x92\x6e\xab\x41\x06\xc9\x04\xfe\x21\xe3\x8b\xf9\xac\x42\xde\x68\xba\x0d\x09\xde\xd9\x50\x7e\x65\x49\x56\x9c\xdd\x82\x42\xd6\x7c\x21\x68\x11\xbe\x9c\x79\x62\x21\x60\x3a\x19\x24\xb3\xff\xa5\x40\xb1\x6c\x0f\x72\x25\xf3\xa3\xa6\x23\x0d\x64\xe3\x07\x49\x0d\x1b\xb2\x95\xb5\xef\x56\xab\x0e\x53\x6a\x40\x86\xcb\x72\x72\x75\x71\x46\x5e\x4e\xc9\xdf\xa4\x36\xf6\x5f\x81\xb1\x7d\xd7\xe1\x1a\xb6\x0a\x9e\xc0\xdb\x9a\x3f\x67\x93\x77\x94\x8b\x0d\xdd\x2b\xd7\xe8\x63\xf8\xd5\x1a\x0a\x99\xd2\xf5\x2c\x97\x25\xe5\x83\xfa\x2f\x7d\xa2\xe8\x72\x5e\x17\xc5\x9a\xfc\xab\xa6\xc5\x70\xc6\x90\x2b\x99\x43\x5b\x24\xd0\x88\xe1\xb0\xef\xfd\x39\xfc\xd5\x5f\xa6\x7f\x6e\x66\xfc\x97\xe9\x9f\x87\x32\xe9\x36\x77\xfc\x2f\x53\xbd\xca\xa6\x7f\xf6\x0c\x47\xc4\x0b\x6c\x30\xe6\xc3\x1e\x0f\xee\xa9\xea\xb4\x87\x02\x50\xfc\xd4\xcb\x1f\x9c\x23\xa5\xc6\xea\x95\x07\xaf\xe7\xec\x74\xf0\xfe\x56\xd1\x8c\x5d\x31\xc5\xc1\x65\x93\x22\xc7\x33\xe8\x84\x2b\x40\x72\xcf\x49\x6d\x2f\xb4\x76\x42\x07\xda\x31\xb7\xa8\x82\xb1\xdc\xb9\xe7\x7e\xbe\x8c\x2c\xec\x74\xe1\xb8\x0d\xd3\xb0\xd6\x87\x06\x7a\xa3\x4c\x31\xea\x8a\x4e\x48\xce\x0a\xd6\xb2\xf7\x4e\x5d\x52\x73\x90\xd4\xc0\x0f\x25\xa4\x98\x08\xb6\xa0\x86\xaf\x58\x78\xcc\x72\xc5\x60\xc3\x93\x53\x8e\x76\xa9\x81\x39\xfb\x49\xf2\xb2\x64\xb9\x75\xd1\x8a\xf5\x60\x1c\x2d\x18\x16\xe7\x46\x73\x4d\x04\x2f\x8e\x7c\xf7\x54\x87\xd8\x87\x25\x25\x15\x1c\x81\x81\x69\xd4\x36\xe3\xd7\xf8\x72\xf0\xd5\x68\x91\x3e\xc8\xde\x71\x80\x08\x9d\x9b\x86\x38\xce\x5b\xb1\x41\xa2\x03\x1b\x77\xcb\xe8\x01\x15\x2b\x9a\x09\x43\x68\xf7\x46\x0c\x53\x05\xce\xb0\x06\xdb\xe7\x30\x63\xce\x9a\x63\x27\x6a\x67\x35\x97\x2a\xe3\xb3\x62\x4d\x96\xb4\x68\xf8\xc4\x29\xb9\xb1\x2b\xee\x7e\x72\xd8\xf1\xbf\x66\xa6\x7b\x0c\x0a\x29\x16\xb0\x98\xd4\xc7\xd8\x77\x15\x30\x2f\x0f\xb3\x82\xd6\xec\xd4\x95\xfb\x66\x1b\x31\xac\x65\x1d\x0b\x74\x35\x92\xfc\xf6\x45\xd8\xf2\x2f\x4c\x0c\x38\xe0\x05\xd9\xc8\x82\xb9\x13\x8a\xd7\x96\x3b\xa9\x0b\xf6\x75\x57\xf6\xf0\x05\xf8\xd2\xd4\x54\xef\x43\x0f\x04\x7b\xb6\xde\x37\x33\x1f\x1a\x83\x5a\xc3\x67\x28\x90\x2f\x58\x6d\xef\xe4\x40\x39\xff\x9a\x58\x4f\xd0\x0c\x6f\xb0\x41\x02\x6d\x8a\xbb\x97\x8a\x57\x05\x23\x7f\xbe\x61\xeb\x23\xc7\x46\xe9\xaa\xec\xfe\x32\x50\x66\xdb\xe8\xa8\x61\x49\x92\x95\x9d\xac\x54\xe4\xcf\xe1\xdf\xfe\x32\xec\x6e\xa2\x93\xff\xf8\xd4\xbf\xfb\xf8\xc8\x77\xf0\x73\x57\xa7\x88\x27\xb3\x74\xc3\xed\xaf\x2f\x7a\x34\xd2\x2d\xec\x94\x9c\x03\x69\x4b\xc9\xe8\x60\x9a\x33\x12\xf6\x1e\x42\xb4\xae\x78\xed\x99\x5e\x23\x9e\xd1\x88\xab\xe9\x67\xbd\xaa\xc7\x4b\x79\xed\xa9\x38\x80\xf9\x78\xce\x54\xfb\x37\x98\x5f\x10\x39\xb9\x94\xe7\x77\x2c\xab\xcd\x97\x22\xe0\x72\xe3\x86\x21\x1a\x36\xf6\x0e\xc5\xdf\x59\xc3\x4c\xed\x56\xfe\x86\x61\x5e\x86\x9b\xe2\xae\x56\x1b\x76\x90\x70\x98\x5c\x5d\xe7\x3c\x6d\x9d\x8e\x1b\xb6\x1e\x48\xc6\xe8\x86\xef\x55\x71\xe3\xbe\xd9\x13\x22\x35\xfa\xc0\x3a\x87\x08\xa1\x33\x46\xce\xef\xb8\x36\xfa\xff\x38\xad\x9a\xc9\x72\xe6\x3d\x13\xf4\x75\x08\xd7\x0a\xbe\x39\x1c\x5c\x91\xc3\x1f\x71\x1f\x1f\x71\xc8\xc2\x02\x45\x9e\xb4\xb7\x61\x9d\x3b\x3d\x5c\x30\xdd\x64\x6f\xd8\x7a\x5f\x13\xc5\x0a\x67\x73\x97\xbc\xea\xb5\x8b\xc0\x9c\x0b\x57\x16\x1d\xbe\xd3\xe9\x08\xb7\xa7\xb0\xea\xe7\x36\x50\xc6\xc8\xed\xbe\x58\x38\x21\x41\x2c\x07\x5a\x4d\xbe\xa2\x05\xae\x57\xa0\x91\xd6\x9b\xcf\x33\xaa\x1c\xee\xcc\x33\x36\x6b\xdf\xed\x0a\xb3\xae\x40\x2d\x69\xfd\x4b\x6f\xcd\xdb\xfb\xe6\x38\x22\x70\x78\x29\xc3\xb3\xba\xa0\x8a\x58\x8b\xb3\x40\xf5\xa1\x8b\x38\xb9\xad\x32\x42\x84\xca\x6e\xf4\xbd\xa7\x4d\x79\x9d\xb3\x8c\x52\x9a\x21\xe6\x82\xc4\x24\x14\x8b\xf6\x54\x28\x42\xe6\x41\xbf\x3b\x97\x9c\x07\x4b\xdd\x18\x28\x8c\x0d\x6d\x7b\xa5\x98\x5e\xaf\x10\xbe\x00\xde\x7d\xcc\xab\x7b\xeb\x34\x36\xb6\x67\x4a\xfe\xda\x90\x65\x61\x66\xe9\x48\x67\x9a\x8e\xd8\x7e\x25\xc0\x82\x84\x5f\x43\xee\x92\x33\x3b\x73\xa9\xd8\x8a\x29\x72\x90\x4b\xf8\x15\xb6\xe2\x19\xae\x27\xec\xff\xc3\x94\x04\xd5\xd2\x24\x21\xbc\x92\xc7\x52\xf1\x90\x6e\xff\x99\x17\xe4\x00\xa6\xd6\x4d\x42\x60\xb6\xc8\x63\x15\x1c\xd7\x38\xf6\xe2\x7e\x79\xa8\x30\x1a\x35\xb7\x03\x31\xd7\x73\x8d\x70\xc0\x25\xb2\xe9\x17\x35\x71\x8e\x9c\x7a\x8f\x04\x73\x23\x83\x35\xe5\xda\xdb\x94\xa3\xee\xeb\x2b\xb6\x59\xee\x8c\x35\x6e\x51\x73\xe5\xff\xc7\xea\x12\x4a\x14\x5b\x58\x4d\x8e\x10\xea\x74\xf7\x17\xd2\xfc\x46\x56\xb2\x90\x8b\xf5\x75\xa5\x18\xcd\x4f\xa5\xd0\x46\x81\x11\xc3\xb7\xc8\xb8\x4f\xa2\xff\x3f\x9b\x0d\xcc\x17\x2d\xe5\x2d\xa1\x9e\xdb\x4c\xce\x5d\x3b\x17\x59\x2f\x96\xae\x33\x27\xfc\x08\xa1\x99\x92\x03\xd9\x33\xc3\x87\xfb\x54\xb6\x9e\x92\xeb\xa6\x9b\x26\xa8\x15\x54\xd3\x4f\x98\x1d\x3c\x92\xdd\xd2\xb5\x57\xa9\x74\xc6\x73\xa6\x83\x7a\xc8\xda\x05\x19\xda\x74\xa2\x6b\x4a\x36\xfb\x43\xf9\xc4\x7f\x5c\x83\xa8\xf3\x15\x13\x57\x32\xd7\x6e\xeb\x30\x5d\x59\x08\x39\xb1\x6e\xd0\xbd\x47\xc0\xba\x8a\x27\x97\x67\xc3\x7a\xc2\x3e\x52\xee\xe7\x9e\x8f\x18\x78\x2f\x43\x30\xae\xe1\x20\xb7\x47\xb6\x49\xb0\xd8\x23\x33\x34\x9b\x54\x4a\x9f\xa6\x71\x3d\x14\xc3\x7a\x7f\xa1\xc4\x0c\x96\xe2\xbc\xa4\x77\xd7\x37\x6c\x18\x61\xe0\xa4\xf9\xb8\xbf\x0f\x8c\xb4\x27\x90\xa8\xfe\x20\x34\x35\x5c\xcf\xf9\xe0\xf7\x65\x7c\xfa\x09\xca\xdb\x30\xfd\x67\xdd\xe8\x57\xb8\x76\x65\xd9\x8b\x5f\x6b\x44\x21\x19\x09\xfd\x84\xfa\xc7\x6e\xea\xea\x68\x10\xc9\x47\xd2\x24\xa1\xc0\xc3\x75\x05\x7d\xa1\x3d\x2e\xdc\xf2\xcc\xb5\x8f\xc7\x4d\x35\x67\xee\xc1\xc2\xa9\x25\x51\x97\x33\xa6\x82\xf2\xc7\x78\xba\xf0\x0c\xc0\x55\xbf\x19\x62\x73\xb2\x10\x12\x9d\xd1\xc0\xda\x68\x64\x39\x4b\x5c\x95\x08\x6c\xd7\xf9\x9d\x0d\xc0\x34\xa6\x2e\xc0\x8d\xde\xe1\xdc\x14\x89\x92\x48\x5c\x51\x69\x28\x99\xec\x1f\x25\xa4\xc4\x5e\xb7\x69\xc8\xe2\x77\xff\x06\x29\x14\x65\xbb\xda\x81\xaf\xea\x72\x03\x59\xdb\xe5\xc6\x66\x7d\x6a\x8a\x45\xee\x2d\x73\x44\x83\xec\xee\xe8\x72\x19\xf8\xd7\x3c\x7d\x04\x35\x68\x6b\x1c\xc4\x92\xf8\x84\x33\x15\x6d\x0c\x00\x3f\x02\x19\x31\x44\x15\x44\x3b\x53\x97\x19\xb5\xc2\xdd\x3c\x71\xc7\x22\x52\x27\xb8\x81\x2f\x74\x73\x63\x82\xcc\x63\xbb\xff\x36\x2c\x2c\x52\x40\x9c\x5a\x73\x03\x95\xd9\x6f\x47\xef\x7a\xdc\x34\x39\xfe\x08\x89\xa1\xc8\xdd\x0a\x6b\xb2\xfd\xd1\xd7\x83\x34\x45\x54\xd8\x77\x82\x30\x22\x0b\xed\xdc\xc0\xa7\xba\xdb\xd1\x5b\x7a\xb9\x9d\xf4\x8e\x5b\xab\xdd\xe9\xef\x48\x99\x40\xd9\x36\x0f\xb7\xde\xa5\xc3\xa3\x44\xf6\x53\xe9\x17\xe2\x88\x5c\x4a\x73\x21\xf0\x1a\xcf\x8e\x4e\x46\xfe\x4c\x32\x7d\x29\x0d\xfc\xcd\xa3\x1f\x1a\xb7\x6c\xc9\x8e\x8c\xcf\x04\x42\x37\x8d\xb8\x7d\xb5\x96\xd9\xee\xab\xfb\xbe\x48\xa5\xee\x86\x7f\x41\xeb\x66\x9f\x2e\xe2\x66\x29\x95\x3f\x1b\x6d\xfa\x4a\x47\x38\x15\x61\x74\x91\x5e\xbe\x07\x00\x82\x59\xa9\x3b\x36\xbf\xdb\x1d\xc7\xd8\x6f\xef\x9e\xe4\xee\x12\x24\xd8\xf9\xb0\x04\xfe\xf3\x07\x77\xdd\xdd\x2d\x15\x1a\xda\x55\x05\xd0\x1f\xe4\x75\xd4\xc5\x21\x4e\xf9\x18\x45\x0d\x5b\xf0\x8c\x94\x4c\x2d\x18\x81\x26\x1b\xf1\x97\x3a\xf6\x08\x45\x79\xa7\xdd\x89\xa0\xb5\x0b\x04\x23\x10\x2e\x27\x0b\x6d\x9c\x34\xd0\x2d\xc8\x2f\x2b\x29\x24\x2d\xff\xdf\x06\x98\xf3\xff\x91\x8a\x72\xa5\xa7\x04\x57\x25\x49\x02\xc8\xbf\x2b\xd1\x43\xfe\x3a\x53\x8e\x98\x6d\xef\xa9\xd5\x11\xae\x10\xe6\xc8\x71\x90\x52\xe5\x7c\x2b\x50\x3c\x22\xb7\x4b\xa9\x59\x84\xd7\xd9\x24\x42\xf7\x6e\xd8\x7a\xef\xa8\xa7\x6e\xf0\x61\xe8\xde\x85\xd8\x6b\x91\xfe\x09\xb4\x6b\x13\xca\x40\xbe\x76\x0f\x24\xee\x3d\xad\x88\x34\x22\xf0\x88\xef\xec\xbf\x39\x19\xd4\xed\xf7\x79\xc5\xc8\x4c\xdb\xfe\x1b\x27\xa6\x7d\xa6\x40\x86\x00\x39\x5b\x28\x06\x05\x4e\x2e\xff\x0f\x6f\x02\xa5\x03\x68\xd7\x82\xad\x98\x28\x50\x29\x27\xae\x7d\x1f\xa0\x7c\x4a\x2e\xcc\xfe\xbe\xf6\xb7\xfe\x8e\x97\x75\xe9\x48\xfa\x0d\x2e\xe3\x96\xf3\x79\x68\x9b\x19\xca\x7f\x7a\x79\x37\xac\x36\x6e\xda\xef\x73\xe1\xb0\x8e\xb7\x32\x3e\xe9\xe6\xe0\x15\x1b\x99\x6f\x64\x33\x47\x42\x5e\x4b\x45\xd8\x1d\x2d\xab\x82\x1d\xb9\x87\x9b\xdf\x4e\xfe\x2d\x05\x0b\x0f\x2a\x18\x1f\x3c\x1c\x24\x5f\xec\x64\x24\x79\xe9\x94\x4a\x15\x58\x8b\x90\xaf\xa2\x50\x8c\xd4\xcb\x2e\x37\x0f\x60\x18\x15\xf2\xf2\xf8\xe5\xf1\x8b\x57\xe4\x23\xb1\x1f\xfc\xd2\xff\xf3\x6b\xff\xcf\xdf\x92\x8f\x08\x91\x1f\x09\x21\x57\x1b\xff\x74\x7f\x3f\x21\x7c\x1e\x56\x06\x93\xc2\xd5\x76\x11\xb9\xc8\x64\xe9\x4f\x15\xa0\x6f\x40\xad\xce\x58\xf3\x58\x87\xcc\x37\xbb\x0f\x06\x96\xa2\x4c\x96\x0c\x56\xe6\xe5\xff\x09\x52\x71\xfe\x08\x37\x44\x0a\x2f\xfb\xe5\x01\x2c\xed\x21\xb9\x85\x9e\x8a\x25\xbd\xc1\x3e\x8c\x9f\x64\xa6\xa6\x85\x5d\xc4\x83\xaf\x27\x2f\x0e\x89\x14\xbd\x1f\x40\x48\x5d\x71\x59\x50\xc3\xc2\xde\x1c\xbc\x3c\x9c\x26\xd8\xac\xaf\x77\x6c\x56\xe4\x3e\xc1\x6a\x5a\x35\x62\x3f\x35\xa8\x40\xda\xe4\xbe\x10\x12\x1d\x17\x44\xd3\xab\xb4\xa9\x21\x79\x09\xb7\xf5\x05\xee\xcb\x85\x34\x01\x44\x3b\xb8\x15\x47\x42\x14\xc8\x6f\xbf\x1e\x8c\xfe\x6a\xde\xd9\xa2\x71\x5f\x8d\xa4\x80\x08\xc1\x39\x7a\x72\x0e\xad\x4c\x9d\xca\xd3\x53\x72\x29\xf3\xd0\x19\x61\x49\x57\x28\xec\xb1\x4f\xcb\xf9\x06\xfb\x5c\x37\x39\x5c\x0e\x2c\x17\x19\x8a\xe6\xa2\x83\x95\xce\x24\x74\xfb\x51\x0e\xea\x3f\x63\xde\x39\xc7\xc0\x40\x28\x74\x43\xf0\x2f\xbb\xe4\x87\x56\x36\x8e\x5a\x99\xb8\xf2\x00\x37\xd9\xbf\xb8\x9e\x10\x7b\xb3\x3a\xbb\x61\xc6\xf9\xbc\x28\x14\x15\xf4\x21\xaa\x6a\x43\x66\xb4\xa0\xc2\x46\xb9\x09\x5e\xeb\x8c\x74\x85\xb2\x6e\x76\x70\xd5\x93\xdc\xf4\x2f\x03\xa9\x71\x63\xeb\xf1\x39\xd6\x3d\xfd\x61\x53\x60\x5b\x9a\x80\x58\x10\x0f\x46\xc8\x19\x2d\x42\xf5\x15\xf4\xdf\x6f\xda\x59\x88\xfd\x7d\x4c\x50\xe0\xe6\xe7\x91\x70\xce\x37\x69\x11\x2f\x53\x32\x41\x88\x3c\x93\x97\xd2\x04\x70\x0e\x39\xf0\x88\xc7\x43\x62\x58\x51\x60\x7d\xf4\xa6\xb7\x28\xa8\x6b\x23\x9b\xbf\xb0\x9f\x3f\x69\xa0\x40\x27\x62\x7d\x8b\x8a\xfd\x9a\xb9\x75\x7e\xc9\xfe\x8a\x41\x23\x8b\xdc\xe0\xc6\xdb\xbd\x8e\x9e\xa1\x9a\xec\xf5\x0e\xc6\xf0\xb6\x54\xd0\x2a\xc1\x6a\x41\xf0\xa7\xf8\x9c\x54\x05\xcd\x5c\x35\xa1\xb3\xe1\x08\x89\xf6\x38\x49\xef\xf7\x07\x2f\xdd\xfb\x1a\x9a\xec\x79\xe7\x62\x6f\xf4\xd9\x87\x8d\xdf\x5a\xcf\x34\xb5\xcf\x7e\x05\xff\x6f\xdb\x77\xbf\x98\x93\x2d\xad\x83\x73\x8a\xfc\x9a\xf6\xae\xf2\x51\xec\xe9\xda\x19\x00\x04\x77\xfe\x6b\xf0\x88\x7f\x8b\xc3\x5a\x87\x38\xe0\xb7\xc7\x5f\x1f\xbf\x3c\xb0\x6b\xfe\xf5\xa1\xbd\x67\x3d\xef\xfb\x25\x46\xb6\xf7\xd7\xc3\xec\xbc\xbe\xe4\x4c\x77\xfd\x6f\x84\xdc\x0b\xe1\x20\xa8\xe4\x56\xaa\xdc\x83\x5b\x03\x19\x40\x86\x7a\x19\x71\xba\xca\x7a\x30\x65\xb0\xed\x47\x64\x56\x77\xfa\x32\x23\x84\xde\x4a\x6b\x57\x20\x00\xb2\xba\xec\x37\xa5\x54\xec\x37\x9d\x5f\x40\x7d\xfa\x46\x20\x80\x68\x1a\xec\x06\xd2\xda\xdf\x4d\x3a\x14\x7b\x05\xd7\x66\x52\xd2\x6a\x72\xc3\xd6\x83\x72\x61\x58\xa0\x5b\x1c\xcc\x6d\x7b\xee\x6e\x11\x4a\xfa\xf9\x3d\x78\x5d\x33\x46\x3c\x60\x78\xff\x3b\x0f\xfd\xf1\x82\x3c\x08\x04\x02\xc6\x41\x7b\x58\x3a\xc8\x19\xc0\x61\x5b\x22\x97\x19\x2b\xa4\x6b\x12\xea\xea\x9e\x06\x89\x1c\xc0\x36\x94\x49\x91\xb1\xca\xe8\x63\x6d\xa4\xa2\x0b\x76\xec\x3f\x67\x38\xe5\xc9\x97\x46\xba\x7e\xef\xba\x69\x76\x0b\xcd\x1c\xfd\xe2\xc0\x1b\xe4\xbb\x72\x06\x8e\x20\xb7\x8f\x3e\xf1\x49\x33\xa0\x0a\x18\x2a\x72\xb6\xee\x13\xbe\x77\xe8\x0d\x9e\x38\xd8\x75\x30\x37\x0a\x1e\x06\x43\x6f\xf5\x79\x41\xb5\xe1\xd9\x5f\x0b\x99\xdd\x5c\x1b\xa9\xa2\xa3\x8d\x93\x1f\xae\xb7\x64\x22\x74\x73\xf7\x4c\x09\x72\xf2\xc3\x35\x39\xe3\xfa\x86\x28\xa6\x65\xad\x06\xd2\x12\xb9\xe1\xba\x02\xea\x5e\x45\x3d\x25\x37\xae\x21\xe1\xfe\x3e\x2e\x16\xd2\xf6\x9c\x66\x4b\x2e\x58\x78\xfc\x11\x4d\xfb\x5e\x14\x5c\x24\x9c\xd1\x48\xdd\xf1\x2b\x7a\xab\x99\xdb\x86\x99\xdd\x06\xfb\x3f\x33\xac\x61\x7b\x04\x12\x75\xf7\x19\x17\x67\x83\xff\xd3\x38\x4c\xd8\x5c\xbf\x47\x76\x85\xd9\xbc\x06\xaf\x79\xc1\x5c\x41\x17\xbe\x23\x0c\xd9\x68\x2a\x0d\x27\x78\x2d\x6b\x72\x4b\xd1\x6f\xaa\x46\x3a\x6b\x37\x25\xef\x79\xf5\x8a\x9c\x77\x3a\x66\xe2\x71\x6b\xf3\xfe\xc7\x82\xdf\x1e\x7a\x2b\x20\x45\xfa\xa2\x17\xb8\x61\xee\x79\xd6\x1a\x62\x6c\x89\x9c\x1b\xe7\x2e\xf4\xd3\xaf\xc8\x1e\xbb\x33\xbf\xdb\x3b\x22\x7b\x77\x73\x6d\xff\x21\xcc\x5c\xa3\x22\x4a\x3b\x2e\xca\xaa\xe0\x19\x37\x36\x00\x16\x73\xa6\xda\x14\x9e\xfb\x19\xec\xab\xf2\x66\x0f\xc2\xf4\x0a\x01\x39\xb3\xf7\x6f\xcf\xde\xbe\x82\x44\x50\x2e\xc9\x2d\x23\x95\x62\x2b\x26\x0c\x61\x4a\xc9\x81\x85\x44\x9d\xcf\x15\x9e\x24\xaf\x39\x4a\x40\xc5\x97\xc9\xb2\x52\xb2\xe4\x1a\x0f\x80\x71\x8f\x9d\xa0\xa4\x87\x6b\x40\x12\x8f\x2f\x81\xea\x6c\x50\x0b\x09\xf4\x0a\x10\xcb\x04\x81\x58\x7e\x5a\x72\xaf\x56\xc1\x63\x1c\xbd\x56\xb9\x98\x13\xe9\x9e\x93\x7b\x64\x5a\x78\x64\x45\x50\x58\x56\x23\xf8\x19\x8b\xc1\x9c\xab\xed\x68\x75\xc0\x6b\xa9\x82\xc0\xe3\x9c\xad\x8e\x75\x4e\x5f\x62\x81\x93\x76\xf9\xdc\x55\x75\x6a\xab\xdd\x21\x54\xae\xc6\x8e\xbd\x97\x7b\x53\x72\xcd\x4b\x5e\x50\x55\xac\x8f\xba\x3b\xd6\x48\xc7\xaa\x6b\xa9\x9a\x4f\x06\xf0\xca\x8b\x3d\x72\xe0\x78\xaa\xb0\x68\x15\x2a\x48\xc1\xe8\x8a\x05\x7a\x2f\xe8\x7c\xe1\x10\x71\x87\x88\x80\x9a\x44\x3f\x68\x91\xc8\x47\x2d\x02\x0e\x0c\xcd\xdf\x8a\x02\x09\x10\xdf\xa0\x5a\xf5\xa7\x63\xcf\xa8\x9a\xed\xe1\xaf\xd9\x5c\xaa\xcc\xf9\x9a\x90\x19\x5b\x32\xf2\xce\xcf\x32\xb6\xe1\x08\x17\x3e\x9e\x7b\x63\xaf\x1b\x5c\x3c\x37\xd9\x08\x44\xe7\x2e\x55\x00\x27\x0e\x48\x3d\xd1\x16\xf7\x49\xf8\xc6\x24\xaa\x39\xb3\x1b\xc1\xcd\x4d\x71\xc2\x3e\x08\xfe\xaf\x9a\x91\x8b\x33\xef\x35\x22\xd7\xb6\x62\x4a\x73\x6d\xac\x3d\xcf\xbb\x11\x17\xde\xd6\xd8\xe0\xed\xe0\xa4\xa4\xff\x96\x82\x9c\xff\xf5\xda\x7f\xf4\xa1\xf3\x68\xd0\x87\xf5\xa9\x6c\x3e\xca\x2d\xa0\xff\xae\x15\xb3\x01\x6d\x64\xb4\x7d\x12\xe4\xc4\xd5\x3d\xd8\x08\xdb\x4a\x22\x67\xd4\x50\x17\x68\x3b\x9b\x2b\xb1\x6f\xd0\xe0\xb7\x5b\x2d\x35\x83\xda\xd1\xc0\xdf\x8d\x6e\xdb\xf6\x68\x81\xa8\xbd\x03\xa8\xd6\x18\xee\x3f\xfd\xf0\xee\xe2\x0b\x87\xb0\x19\x78\xba\x8b\x37\x32\x4f\x12\xc7\xfe\xcd\x6e\xe4\xa9\x93\x49\x4a\xb4\x50\x42\x2e\xa5\x60\x47\x60\xac\x88\xb5\x56\xfe\x5f\x7f\x50\xdc\x0c\x23\x77\x6e\x47\xa4\x5b\x1e\x76\x36\xc1\x2a\x59\xa7\xfc\xb2\x43\x5c\x8f\xea\x39\xdf\xce\x2a\xc4\x42\xb3\x42\xce\x88\xd7\x5f\x8f\xb5\x42\x1f\xde\x5d\x24\x5a\xa0\x0f\xef\x2e\x7e\x49\x8b\x93\x2c\x55\xb4\x91\x29\x8a\x8e\xc0\xde\xf8\x72\x14\xda\x89\xa5\xb1\x51\xa2\x9d\x4f\xdb\x25\x73\x67\x4e\x06\x29\xda\x67\x72\xc8\xf9\xdd\xf4\x39\x66\x63\x1e\xe3\xc4\xdd\x70\x81\xac\xd3\xed\xab\xf4\x73\x4f\x6a\x1c\x57\x01\x05\xdd\x02\xf2\x57\xa4\xac\x0b\x03\x1c\xb2\x70\x21\xed\x0d\xc5\x4a\xac\x98\x0a\x17\x9a\xf8\x8e\x1a\x84\x9c\x31\x07\x55\x42\x57\x28\xfb\xb2\x97\x66\x76\xdd\x9f\x41\x8a\x6c\x26\xf7\x86\x0a\xba\xb0\x8b\x00\xfe\x1c\x29\xdd\x1f\xb1\xca\xcd\xfa\x5e\x30\xc3\x03\x07\xa6\x11\x41\x20\xa1\x2b\xca\x0b\x3a\xe3\x05\x47\x47\x77\x9a\x99\xc3\x69\x08\xc1\x20\xb8\x83\x5e\x22\xf9\xa3\x98\xde\x84\x81\x75\x97\xfa\x11\x82\x4a\xe4\xfa\x1c\xd8\x39\x1d\xdf\x5a\x77\xe4\x70\xda\xc6\xd4\x4b\x86\x0e\x51\x80\x0b\xca\x85\xeb\xbd\x30\xdd\x37\xc1\x4c\x13\xa5\xc7\x28\x22\x5c\xd8\x0a\x47\xdd\xda\xac\x14\xa1\x8b\x95\x93\x28\x74\x01\x51\xbe\x63\xd0\x18\xbd\xc0\x98\x10\xcd\x32\xc5\x0c\x32\x7e\x01\x05\x81\xfa\x6f\xe3\x22\x98\x51\x3b\x3c\x5f\xed\x40\xc0\xd4\x84\x43\x97\x60\x07\xbb\xad\x25\x9d\x60\xf4\x8b\x47\x97\x20\xc6\xe9\x8c\xeb\x28\x37\x20\xf4\x25\x83\xc8\xcf\x6a\x8b\xa1\x44\x63\xcd\xd4\xe2\xac\x69\x73\x4f\x13\x2c\xb7\xeb\x08\x86\xee\x05\x1a\xf1\x25\x19\xab\x96\xf3\x58\xe2\xe0\x53\x56\x2d\x5f\x5f\xf7\x01\x49\xf6\xef\x10\x1f\xf3\xfa\xba\x67\x45\x9c\x4d\x80\x43\x04\xeb\x8d\xb2\x55\xbe\x93\x45\xc1\xe7\xcc\x70\xc4\x12\x3f\x9a\x1d\x29\xa5\xe0\x06\xf3\xb6\x1b\xc9\x3c\xe6\x7f\x36\x45\xd4\xf3\x2e\x7c\x3e\x79\x83\xfd\x18\x37\x80\xaf\x2a\x93\x45\xc1\x32\x78\xe1\x93\x73\x38\x62\xf8\x35\x72\x63\xc7\x9b\x86\x87\xaa\xeb\xe9\xcd\x1f\x21\xb1\xed\x53\xd8\xc7\xee\xaa\x1c\xbf\x3b\x3f\x39\x7b\x73\x3e\x2d\xf3\x5f\x2d\xe5\xed\xc4\xc8\x49\xad\xd9\x84\x9b\x18\x8f\xfe\x91\x48\xc6\xa2\x1f\xd8\xcd\x32\xc5\x11\x69\x5b\xd5\x7d\xd0\x0c\x09\xb3\x27\x01\x70\xe0\x21\xa5\x4a\x4a\x73\x44\x14\x05\x88\xb5\x59\xa2\xa9\x66\x42\x37\x39\x77\xd6\x8c\x62\xec\x28\xfe\x6d\x7d\x50\xc3\xca\xce\x5c\x9e\x4c\xf4\xb7\xbf\xd5\x5d\x10\xbd\x67\xde\x41\xbc\xc7\xd5\x43\x4a\x85\x56\xed\xf7\xb8\x7a\xf8\x40\xde\xf8\x76\x5d\x3d\x57\x2f\xdd\x6b\xda\x97\x57\x3b\xb1\xbe\x26\x2e\x1c\x25\x3f\x73\x9a\xae\x1b\xb9\x11\xc8\x15\x00\x82\x98\xa5\x3d\x5b\x37\x6c\x4d\x80\x1c\x6a\x8e\x66\x19\xf9\xa0\x99\x3a\xea\x3e\xa2\x1f\x33\x93\xc1\xa6\x1c\xd7\x9a\xa9\x69\x94\x77\xfc\x24\xac\x0f\xde\x03\x86\x4f\x7f\xc7\xe6\x0f\x71\x08\xde\x31\x2c\xfa\x01\x28\x9c\x02\x3f\x86\xcf\x1f\xd0\xda\x2c\x5d\xbd\x70\x04\x80\xc7\x7d\x2f\xe0\x78\x36\x4f\x05\x52\xa2\xe7\xae\x7a\x12\xc7\x20\x82\x57\x26\x9e\x11\x52\xa0\xe3\x28\xb2\x75\x92\x3a\x4f\x82\x68\x89\x24\x1c\x21\x33\x18\x01\x2a\x57\x4c\xad\x38\xbb\x3d\xbe\x95\xea\x86\x8b\xc5\xe4\x96\x9b\xe5\xc4\xad\xae\x3e\x86\x06\xb0\xc7\xbf\x82\x7f\x44\xcc\xce\x61\x41\x4f\xf2\xdc\x57\x91\xd5\x9a\xcd\xeb\xc2\x55\x52\x45\x71\xe0\xd1\x8a\x7f\xcf\x94\xe6\x52\x1c\xc1\xcb\xc7\x11\xa9\x79\xfe\x0d\xee\x5c\x91\x78\x15\x63\x55\x6c\x72\x1f\x53\xe1\x2f\xac\xd5\x25\x8a\xe6\x12\x78\xbd\x15\x1c\xdb\x04\x0e\x21\xcd\x4b\x2e\x9e\x86\x16\xc0\x25\x11\xb8\xc8\x31\xfb\xd4\xdf\xa3\x53\x90\x12\xdb\x3f\xcb\xcd\x25\x60\x36\x9b\xaa\x13\x1a\x32\xca\x48\x2a\x93\x50\xb1\xa2\x7b\xd5\x27\x5d\xe5\x80\x49\x78\xdf\xb3\xcd\xe5\x5a\xff\xab\x98\xb8\x2f\x99\x54\x79\xbb\xcf\x63\x29\xc9\xa7\xc6\x53\x2b\x25\x69\x0b\x3f\x9e\x1b\x40\x60\x77\xd1\x06\x52\xac\x07\x17\xec\x82\x09\xe0\x17\xb6\x01\x17\x24\x81\x09\x7c\x96\x37\x9e\xf0\x66\x92\x31\xa4\x1f\x30\x7e\x11\x21\xfd\x83\x9c\x9e\xd8\x28\x3e\x79\xfc\x56\x49\x8e\xa7\xc8\x84\xea\x50\x1f\x68\x39\xab\x15\x5e\x8f\xf0\x3a\xad\xa2\x8a\x96\xcc\x30\xe5\xba\xb1\xd8\xdf\xc8\xa4\x10\xae\xc1\x2f\x52\xe6\xdb\x8a\x89\x6b\x43\xb3\x9b\x28\x14\xe5\x18\x73\xf5\xc6\x18\x73\x3d\x85\x98\x2b\x65\x75\x44\xa0\x18\xc8\xc3\xcd\xc3\xea\x55\x60\x7b\xf3\x65\x5e\x2d\x6f\x81\x53\xa5\xff\x11\xf6\x3e\x93\x62\xce\x17\x6f\x68\x15\xfb\x56\x1b\xe4\x44\x02\x80\xda\x09\x85\xe7\x59\xa0\xca\xac\x64\x55\x17\xd8\x4e\xa4\x5c\xfb\xbd\xfd\xb2\x61\x4e\x9c\x2a\xf5\xd1\x7f\x2a\xe4\x7f\x6b\x47\x4b\x99\x33\x32\xe3\x31\xa6\xb4\xd6\xcc\xc6\xae\x99\x6f\x9e\x0a\x81\x87\x0d\x17\xfc\x9c\xd1\x17\xa7\x09\x65\x1c\x05\x67\x20\x21\x7e\x81\xa4\x25\xb4\xe3\xc5\x1f\xfe\xf0\x87\x69\x0f\x39\xf4\xe2\xf7\xbf\xfb\xdd\x94\x9c\x71\x05\x2c\x5c\x1c\xad\xbb\xad\x2d\x08\x34\x24\xd4\x2c\x81\xf6\x11\x48\x3f\xa1\x73\x70\x5c\xa9\xbc\xa3\xca\xb2\x6e\xa4\xeb\x40\x40\x4a\xbe\x58\x62\x33\x41\x8e\x7d\xd2\xde\xab\x82\x67\xc6\xd1\xfc\x39\x53\x23\xe1\x50\xe0\x93\x56\x34\x7c\x6d\x53\xec\x0d\xa7\xeb\x88\x14\x1c\xc5\x6c\x4b\x20\xd2\xfe\x56\xc9\xba\x6a\xe9\xd7\x15\xd3\x75\x61\x90\xec\x55\xc4\x7d\xbf\xfb\xdc\xe6\xe4\xdb\xc5\x7d\xb6\x75\xac\x11\x6f\xf3\x3d\x95\x70\xd1\x0b\x6e\x8f\xb0\x6c\xa2\xc4\xb5\x5d\x9a\xb8\x2b\x5b\x51\xde\x90\xf3\x40\xf9\x19\xb8\x31\x48\xb1\xbe\xfe\xa6\x79\x75\xc9\x5b\x2b\x83\xbe\xb3\x8e\xcb\xac\x52\xf2\x7f\x1c\x6a\x1e\x58\x46\x5b\xeb\x8f\x94\x0b\x2c\xaa\x70\xfe\x5d\x43\x03\xc0\xb8\x45\x35\x8f\x0a\x7c\xb4\x36\x4a\xf1\x7d\xd5\xa2\x9a\xf5\x13\xd7\x86\xa6\xb3\xdf\x56\x5c\xc1\xb5\x5d\x84\x1b\xb6\xc6\x6b\xc1\x7b\x57\xb4\xf9\x2d\x74\x7c\x65\x96\xda\xe9\x81\x5a\x74\x66\x0a\xbf\x89\x0d\x4e\xa4\x71\xb3\x05\x0f\x05\x08\x0e\xa8\xef\xf4\x85\x0d\xf7\xc3\x57\x7a\x9a\x7f\x4f\xfd\xec\x7f\x01\x1d\xef\xc3\x0a\x36\xc7\xfd\x28\xfe\x88\x6a\x66\xea\xca\x6d\x17\x30\x7b\xd8\x35\x65\x5a\xbb\xf6\xef\x48\x99\x25\x55\x37\x2c\xf7\x66\x84\x16\x53\x72\x65\xb7\x0c\x5a\xe8\xe0\x75\xb5\x6b\xd2\xb5\x72\x20\xcc\x92\xae\x61\x39\x7d\xb0\x1e\xf1\xbc\xb2\x3f\x9d\xee\x3b\x43\x2d\x15\xd1\x86\x2a\x83\xa5\xf3\xb4\xc3\x4a\x7b\xee\xfd\x1f\xdf\xd0\x4a\xbb\x4e\x42\x5c\x2c\x22\x7a\xb0\xf8\xec\x0a\xac\xad\x77\x8a\xa8\x3f\xab\xff\xb1\xbd\x10\xed\x62\x60\xd5\xde\x13\xeb\x83\xf8\xde\x77\xb8\x8c\xec\x97\xe7\x0d\xc4\xa3\xf7\x9d\x8b\xa9\x7a\x26\xf7\x87\x55\x51\x6b\xd3\x3a\xa6\x6d\x70\x65\x62\x1b\x8f\x59\x77\xe4\xa8\x69\x67\xe6\x63\xaa\x28\x89\xbd\x78\xcc\x47\x56\x91\xed\xe1\xac\x6e\xdf\xf0\x49\xa2\xac\x9c\x1b\x9d\xd8\xb9\x71\x50\x6a\x8d\x7f\xc1\x71\xa3\x0d\xc4\x36\x42\xaa\x28\xa9\xdb\xe1\x18\xb6\x11\x77\x3b\x76\x06\x65\x51\x12\x6d\x40\xb7\x15\x9a\x45\x49\x6c\xc3\xba\x7e\x80\x16\x77\x42\xe3\x82\x3b\x37\xe2\x43\x3c\x37\x62\x03\x3d\x37\xf0\x70\x68\x37\xb6\x74\x79\xf0\xaf\xe2\xb4\x39\x38\x52\xf3\xf6\x88\x19\x39\x88\x2c\x78\xd7\x30\x8d\xa1\x99\x92\x37\xde\xef\x1b\x48\xfd\xbb\x39\xa8\x20\x74\xa6\x65\x51\x1b\x97\xa4\x01\xc1\xd1\x0a\xcb\x3b\xa3\x6d\xea\x27\xae\x31\x9e\x1b\xe0\x51\x36\xdf\x1d\xed\xa0\xba\x01\x61\x98\xf3\xef\xf0\x1e\xab\x17\x15\x67\x7c\xf1\xaf\x42\xf7\xbe\x08\xb5\xef\x3a\xe9\x12\xf5\x8f\xfa\x1a\xf4\x20\x2f\x41\x29\x5f\x81\x22\xcf\x80\x8c\x72\x96\xfa\x95\x6d\x9e\x80\xed\x76\xc9\x7c\x2d\x06\x56\x51\xb4\x0f\x17\x52\x11\x6b\x3e\x20\xc5\xe0\xdd\x26\x74\x98\x35\xe7\x02\x99\xf7\x88\x79\x7d\xcf\x34\x8f\x7d\xc6\xb9\xbe\x20\x07\xa7\x0d\xcd\x36\xbe\xa4\xf2\x42\x18\xa6\xe6\x34\x63\x87\x5d\xe4\x5d\x20\x84\x40\x7a\x38\x5c\x93\x25\x15\x79\xe1\xc0\x49\x54\x10\x76\x67\x98\x12\xb4\x80\x79\xe7\x8a\xaf\x50\x06\xfb\xe0\xa4\xa8\x96\x94\xcc\x19\x35\xb5\x62\x88\xbe\x0b\x8f\xc7\x67\x85\xfb\xe4\xc8\x97\x29\xf8\xd1\x14\xf5\xdc\x20\x28\xa4\x36\x07\x33\xa5\xb7\xc3\xdb\x83\xf6\x10\x84\xe6\x60\xf6\xac\xe0\x9f\x37\x9a\x77\xc3\xa9\xd5\x12\xe0\xae\x82\xb7\xbe\x96\x35\xd6\x2f\x74\x90\xdc\xb9\x54\xae\x33\x87\x54\xca\x3a\xea\x90\x2e\x46\x17\xa8\x29\xb6\xe0\xda\x40\x0f\x20\xef\x94\xf8\x8e\x1f\x8f\xc2\x6b\xf3\x64\x99\x94\xd2\x73\x13\xcd\x7d\xa6\x57\xae\x78\x1e\xa2\x57\x28\xbd\x88\x8a\xb5\xb9\x26\x15\xd5\x1e\x50\x04\x45\x26\x5a\xcb\x8c\x53\xfc\x93\x62\xe7\x5e\xb8\x1c\x35\xc4\xc4\x39\x33\x4c\x95\x5c\xa0\x21\xa8\x1d\x12\xd0\x2e\x65\xb8\x24\xb4\xaa\x8a\xf5\xa3\x1c\x3e\x21\x73\x76\x55\xcf\x0a\xae\x97\xd7\x09\x51\x68\x97\x3b\xc4\xe2\x77\x97\x6e\xd7\x11\x45\x55\x7b\x6d\xe1\xd9\x88\x66\x42\xf3\x88\x18\xcf\xfa\xc4\x36\x76\xe5\x52\x40\x5f\x3f\xaa\x75\x98\xe9\xe9\xf5\x70\x0a\x44\x37\x82\x66\x96\xc0\x02\x5e\x30\xc3\x1a\xa5\xdd\x59\xdf\xef\xa3\x9e\xe1\x44\x0e\xb2\x3e\x88\xaa\x2b\x8d\x64\xb4\x28\xd0\x0e\x34\xa4\x7d\x9a\x3e\xe3\xc1\x87\x75\x49\x10\x52\xa2\xc3\xc9\x59\xd0\x15\xdc\xaa\x91\x80\x4d\x84\x22\x33\xe7\x0f\x44\xa8\xa5\xf6\x48\x6d\x1c\x0e\xf4\x43\x8f\x74\x6d\x05\x04\x91\x22\x88\x3e\x22\xb4\x28\xe2\x4e\x6e\x73\x0f\x5c\xd3\x4c\xa7\xf6\x1e\xa9\x89\xf9\x08\x7c\x1c\x81\x8f\xf7\x8c\xa7\x03\xa7\xbf\xf6\xa9\x72\x67\x44\x68\x3e\x91\x78\x9c\xba\x03\xda\xd5\xca\xa9\xf9\xe0\x92\xc6\xbd\xdb\x6d\x31\x34\xf5\xd1\xfa\x5f\x3c\x20\x26\x0d\xee\xf4\xc4\xf8\xae\xf9\x29\xa0\x33\xdf\x6f\x88\xc4\x3e\xc9\x1b\xa9\x98\xf6\x86\x71\xe2\x9f\x41\xb2\x8e\x26\x8a\x02\x66\x35\x0a\xb5\x63\xba\xfd\x6f\x61\xb7\x37\x44\x41\x36\x00\xf2\xa2\xf6\x35\xc9\x65\x56\x97\x4c\x98\x98\x1a\x68\x7b\xfc\xda\xca\x23\x47\x65\xf9\x48\x86\x80\xe6\x39\x77\x36\xfe\x2a\xda\x24\x44\x68\x8e\x5c\xde\x8a\x5b\xaa\xf2\x93\x2b\x04\x65\x6f\x3f\xcc\x6e\x25\xc5\x81\x73\xc3\x94\x88\x95\x44\x67\xb2\x36\x81\x44\x0f\x9b\xd0\xd9\x40\xf7\x8e\x58\xdd\x11\xab\x3b\x62\x75\x47\xac\xee\x88\xd5\xdd\xc4\xea\x5a\x39\x2e\x77\x50\xb8\x2e\xa9\xd8\x20\xbc\xab\xc2\x7d\xc1\xcb\x1c\xcb\x8b\xf3\x74\xa0\x6c\x1d\x13\xe7\x7c\xb3\x08\xae\x9f\x5e\xb7\xca\x7e\x26\x04\x2d\xd1\x69\xdf\xf6\xe6\x45\xd7\x1e\x36\xad\x25\xa3\x00\xd6\x4f\x02\x66\xf7\xc8\x50\x39\x58\x3f\x74\x9a\xd0\x8d\x7b\xb8\x09\xa3\x9e\xee\x5d\x9b\x78\x87\x2b\x67\x45\x1e\x9f\x0c\x80\x2e\xc6\xaf\x5c\xa7\x74\x2a\x84\x74\xfe\xba\x8e\xc4\x05\xd1\x19\x2b\xf4\x91\x7f\xc1\x10\x39\xfc\x8b\xae\x28\xaa\xa7\x6b\x3b\xac\x7d\x6e\xc2\x81\x04\x60\x9e\xa8\x23\x4e\x12\x1c\x73\x02\x47\x1d\x76\xf2\x0a\x7f\xde\x49\xa2\x33\x4f\x7a\x49\x92\x38\x39\x9b\xa1\xb1\x93\x19\x29\xb2\x79\xd2\xd3\xd9\x92\x95\x34\xfa\xe4\xdb\xf1\x3a\x2c\xbe\xb5\xa3\xb7\x8a\x1b\xc3\xe2\xa7\x69\x9d\x4a\xa6\x4a\x4d\xe4\xbc\x21\xec\x89\x83\x6d\x12\xe7\xb6\xef\xad\x5e\xa2\x1f\xa6\x1a\x31\x29\xf0\xb2\x24\xe8\xc8\xab\x48\x20\x1a\xd9\x3c\x2a\x57\x0e\x43\x16\xbf\x5a\x60\x55\xad\x8e\x34\x92\x68\x50\x9b\x49\xf6\xb5\x5b\xc2\x62\xfd\xa5\x68\xa1\x2b\x77\x37\x9e\xc4\xb6\x8e\x30\x68\xf4\x18\x61\xd0\x23\x0c\x7a\x84\x41\x7f\xf6\x78\x82\x30\xe8\x44\x2e\x7a\x70\x26\x7c\xea\x23\x15\xac\x5a\x74\x20\xae\xe8\xd8\x3c\x0c\xc7\x67\xe5\xb3\x7f\x9e\x2d\x4c\xc8\xb8\x7b\x65\xf5\x68\x40\x55\x4b\x15\x59\x9b\xe7\xa7\xb9\x64\x64\x7f\x7f\x3a\xdd\xdf\x0f\x38\x6d\x7c\x0d\x61\x33\xc9\xda\xcc\x27\x7f\x24\x4c\x64\x32\xb7\xdf\xfe\x3e\xf2\xaa\xce\xb9\xd2\x06\x92\x16\x2d\x00\x39\xd5\x9e\x97\x7e\x5f\x52\x01\xbf\xdd\x5a\xc6\x5f\xff\x48\x2f\x23\xb4\x9b\x7d\x9d\x3c\xc8\x6e\xc2\xe3\x58\xed\xeb\xda\xe1\xfa\x0d\xcd\x02\xf2\x35\x4e\x31\x40\x8c\x1d\x64\x6b\x52\xf0\x12\x9f\xc2\x77\xc3\x9a\x1a\x1b\x83\x32\x6d\x34\x39\x70\x02\xa7\x59\x55\xc7\x9a\x33\x90\x53\xb2\x52\xaa\xf5\x51\xf3\x03\x56\x70\xb2\xd9\x7a\xe9\x87\x36\xa6\x8f\x12\x9a\xd5\x4a\x31\x61\x8a\xf5\x2f\x31\x33\x10\x0e\xcb\x13\x48\x0c\x34\x77\x00\xdf\x84\xa6\x1d\x1b\x54\xac\x41\x74\x74\x28\x05\x58\x9b\x66\xed\x23\x78\xd8\xdb\xe1\x49\x70\x8f\x1a\x88\x57\xb4\xc4\xb9\x54\x84\x89\x15\x59\x51\xa5\x63\x4e\x2a\x49\x19\xcb\xe7\x7c\xc5\xb5\x8c\x54\x70\xf7\xc1\x52\x92\xc4\xf2\xb2\x36\x55\x6d\xbc\xdf\x98\x2a\x91\xc4\xee\x2a\xa9\x59\xde\x6a\xe5\x38\xcd\x49\xda\xf0\xca\xf5\xd6\x7f\x89\x6d\x45\x1a\x46\x45\x8d\x61\x4a\xbc\x22\xff\x7d\xf0\x8f\xaf\x3e\x4e\x0e\xbf\x39\x38\xf8\xf1\xc5\xe4\x4f\x3f\x7d\x75\xf0\x8f\x29\xfc\xcb\x6f\x0e\xbf\x39\xfc\x18\xfe\xf0\xd5\xe1\xe1\xc1\xc1\x8f\x7f\x7f\xf3\xed\xfb\xab\xf3\x9f\xf8\xe1\xc7\x1f\x45\x5d\xde\xb8\x3f\x7d\x3c\xf8\x91\x9d\xff\xf4\x99\x42\x0e\x0f\xbf\xf9\x75\xe4\xc4\xa9\x58\xbf\x8d\x32\xec\x04\x34\x60\xaa\x70\xa3\x2b\x2d\xc1\x75\x21\xe4\x6e\xd2\x22\xe5\x26\x5c\x98\x89\x54\x13\x27\xf8\x15\x31\x2a\x32\x97\x10\x8e\x63\x5a\x3d\x9b\x26\xbc\xe9\xce\xaf\x4d\xad\x3d\xa2\x22\x03\xbc\xec\x19\x8f\x66\x04\x3f\xf7\x72\x62\xa9\xea\x0c\x2b\x2b\xa9\xa8\x5a\x93\xdc\x23\x14\xd6\x49\x7a\x8a\x75\x9a\x8a\x0d\x46\x6e\xfa\x0a\xab\x40\xe9\xfe\x2b\x58\xb3\x9c\xab\x2f\x4c\xf1\x1d\xd9\x29\x8c\xe5\xbc\x2e\x53\x40\x69\x7e\xb0\xdb\x01\xe5\x23\x72\x1e\xd9\x27\xd8\x4d\x2a\x40\x96\x66\x34\xbb\x71\xe0\x8f\x66\xef\xf1\x00\x73\xd6\x6d\x04\xb3\xb7\xe7\xab\x34\x4a\x46\xf1\x78\x0f\x97\x40\x85\xba\x2a\x99\x33\x7b\xa4\xc2\x4f\xb8\xef\x88\xc6\xfd\x08\x0f\x5f\xf7\xe5\xc5\x07\x5e\xfc\x21\x52\xae\x54\xe4\x0d\x04\x0a\x8f\x78\xe2\x49\x82\xde\x35\xfc\xdf\xec\x3b\x1b\x55\xa5\x38\xbc\xef\xa5\xa1\x05\xa1\xbe\x71\x21\x36\xc3\x5c\xc8\x8c\x16\x4d\xe5\x65\xd7\x65\x8e\x49\xae\x37\x3a\x34\x54\xc8\xd9\x53\x6c\xbf\xde\x05\x95\x48\xa9\x5c\x13\x5a\x68\x57\x41\xc4\x33\x3a\x2b\x18\xcc\xd3\x85\x90\x51\xf7\xd6\x4d\xb0\xa4\x77\xbc\xac\x4b\x52\x6b\xbb\x16\xe8\x67\x4a\x37\x9f\xa0\x11\x9a\xa5\xb8\xb5\x9a\x01\x0f\x7c\x82\x46\x73\x5c\xc0\x04\x7b\xa0\x3a\x34\xe6\x8b\x91\xeb\x70\x1e\x3b\x4f\x59\x11\x7d\x6e\x03\xce\x4b\xd7\x90\x03\xf3\xeb\x10\x95\xdf\x90\x73\xa8\x23\x69\xa2\x4e\x4d\x80\x3f\x0a\xd5\x99\xd9\x8d\x0d\x7d\x2a\x78\x91\x42\xa1\x82\x21\x59\xfa\xe3\x6d\xe5\xd6\xc2\x97\x79\x27\xa2\x1f\xd8\xad\xe6\x6a\xcd\xd4\x64\x51\xf3\x3c\x95\x82\x7b\x66\x71\x46\x44\x74\x91\x22\xa6\x48\x10\x49\x24\x8e\x1f\xe6\x59\xa4\xfb\xfb\xfa\xb4\xdf\x51\xf7\x35\x9f\xa1\xf4\xc1\xe9\x92\x0a\xc1\x8a\x4e\x88\x60\xaf\x88\xd5\xe0\xbe\x39\x0e\x42\x26\x10\xc9\xf9\x96\x38\xfb\xfd\x9e\x38\x48\x5c\xb1\x59\x32\xd1\x04\xff\x8f\xd6\xf5\x7d\x6c\x3e\xf3\x69\xa1\x5f\xa2\xf9\x4c\xea\x0a\xf0\xed\xb6\x33\xbd\x06\x32\x58\x2f\xa8\xdf\x76\xc6\x17\xca\x2d\xe5\x2d\xc9\xb1\x10\xd4\x5b\xe0\x3c\x5d\x31\x61\x1c\xfb\xa7\x0e\x08\x97\xe8\x7d\x9b\x2b\x59\x42\x45\xaf\x92\x25\xd7\x36\x14\x00\x3f\xc6\x5d\xda\x47\xf1\xc1\x8b\x1a\x09\x69\xbb\xaf\x0a\xe3\xf5\x29\x31\x54\x2d\xd0\x65\xae\x45\x2d\x88\xa8\xcb\x19\x8b\x8a\x49\x1e\x13\xc7\x3e\x76\x04\x7a\x88\x8e\x40\x8f\xd3\x9e\xc7\x1d\xe5\x1f\x7e\xb8\x4c\xd2\x88\x3d\xdd\x2d\xb9\x95\xaa\xc8\x6f\x79\xee\x98\x60\x34\x39\xb0\x53\x3c\xfc\xcf\xeb\x7f\x7e\x7b\xcb\xf3\xf4\x5b\x13\x05\x27\x83\xad\x21\xb0\x37\xbe\x63\x0a\xb7\x81\xda\x01\x4c\x15\x9b\xf1\x39\xe7\x00\x76\x02\x19\x0e\x46\x52\xce\xb8\x88\x29\x22\x95\xf3\xce\xe1\x86\x58\xd5\x6a\xde\x38\x2a\x2f\xcd\xcc\x11\x99\xd5\x0e\x9c\x31\x93\x66\x49\x34\x2f\xeb\xc2\x50\xc1\x64\xad\x8b\x75\xd4\x25\x7e\x7e\x07\x74\x5e\xb0\x3b\xa7\xc3\x62\xa3\x90\x46\x50\x6c\x16\x7e\xc1\x04\x53\x3c\x0b\xd5\x4c\x9b\xe1\x08\x42\x26\x30\xfa\x68\x2e\x05\xcb\x8f\x9b\x4e\x9f\x35\xf8\x36\xc0\x39\xc6\x32\x84\xd0\x19\xb5\x11\x48\x55\xd4\x0b\x8e\x40\x00\x8f\x0c\x63\x9f\xfd\xdf\x3e\x24\xc3\x58\xcb\x61\x53\x6b\x16\x9b\x42\x8d\xa1\x5a\xf8\xa5\x92\x74\xfd\x87\x07\x94\xef\x77\x73\x6a\xe5\xac\x62\x22\x47\x67\x58\x45\x57\xdb\xba\xcd\x7b\x94\x53\xe7\x81\xdd\x69\x7d\x9b\xf3\x3b\xa3\xb0\x20\xc0\x4c\x96\xa5\x75\x13\x02\xe2\x9c\xcf\x09\x15\x71\x26\xfd\xf9\x13\x4f\x90\x31\xde\xfb\x45\xc5\x7b\x0f\xd4\x8e\x35\x01\x11\xde\x3d\x34\x78\x71\x98\xcc\x5d\x34\x78\xdd\x32\x6e\xfc\xe1\xeb\xd2\xe0\x39\x3f\xce\x2b\xd3\x38\x6a\xb9\x92\xae\x77\x93\xc1\x61\xd5\xbd\x63\x7c\xe3\x9a\x74\x52\x88\x17\x31\xd5\xc3\xbb\xa9\xe4\x80\x14\x0e\xff\x9a\x76\x1f\x95\x1c\x56\x3b\x6c\xf3\x1d\x6d\xec\xd1\xd8\x50\x77\xe4\x95\xfb\xc5\xf0\xca\xcd\x0b\x99\xdd\x60\x42\xa4\x8d\x20\x1c\xa4\xf4\xde\x03\x11\x5f\x13\xc4\xf8\x08\xbc\x09\x99\xfb\xaf\x79\x08\xc1\xdd\xf7\x3f\x4f\xae\xe3\x5d\x61\x57\x1a\x8a\x39\xc3\x61\xb2\x56\x8d\x29\x69\xb5\x8e\x5a\xf1\x8c\x91\x19\xb3\x26\x43\xd5\x02\xc5\xca\xf1\x98\xe4\x53\xd4\x50\xcd\x0c\x1e\xad\xdf\xa7\xba\xed\x14\x9f\x79\xc9\x58\xab\x61\xa4\x62\x39\xa1\x9a\x94\xcc\x50\x2b\x8b\x4c\xfe\xe2\x8b\xdb\x62\x20\x2d\x7e\x56\x10\x7d\x87\xcd\x74\xa0\x3c\x3c\xf4\x26\x93\x42\xf3\x9c\xf9\xf9\xe6\xf6\x3a\x64\x68\xc2\xe5\x48\xdf\xdb\x7f\xdf\x87\x0f\x49\x5a\x65\x5b\x31\x1b\xfb\x19\xe5\xad\x00\xf0\x85\xff\xab\xee\x66\x82\xf1\xd8\x34\xda\xec\x60\xcc\x59\x8b\x58\xf0\x45\xc6\xae\xac\x4a\xd7\x86\x09\x73\xc6\xf5\x4d\x2c\xb6\xf8\xdb\xd3\xf3\xbe\xc0\xd8\xf4\xe6\xb7\xa7\xe7\xc4\xcb\x79\x20\x9c\xc5\xc3\x02\x2d\x3a\x2e\x02\xc6\x02\x20\x00\xa0\x8b\x8c\x55\xcd\x16\xe4\x5c\xdf\x7c\x61\xec\x73\x4c\xba\xb5\xca\x2f\x31\x49\xca\x5f\x16\xbe\xc4\xab\x2b\xef\x4e\xc0\x71\x5f\xcb\x9a\xdc\x52\x74\x8b\xa5\x16\xb1\xf2\x9e\x57\xaf\xc8\xb9\xd0\xb5\x62\x0d\xa6\x0f\x8b\x7c\xd8\xc8\x7d\xda\x88\x2b\xa4\x1b\xb1\xa6\x68\x57\x92\x32\xa4\x1b\xb1\xef\x6c\x77\xb4\xac\x0a\xa6\x5f\x3d\x4b\xec\x4b\x24\x18\x7c\x4b\x17\x60\x6d\x5f\x07\x82\xb3\x0d\xa6\xc1\x7e\xeb\x26\x04\x67\x1b\x4c\x13\xe1\x27\x3d\x26\x04\xa7\xa2\xca\x40\x2e\x33\x09\x0c\x1e\x58\x3b\xbd\x40\x12\xd5\x04\x78\x97\x4a\x89\x7e\xb3\xb8\x98\x13\x59\x72\x63\x02\x73\x8b\x4f\xe0\xe3\xf3\x62\x41\x5b\x59\x75\xe0\x67\x6c\xdd\xe6\x78\x05\xf0\x5a\x36\x41\xda\x71\xce\x56\xc7\x3a\xa7\x2f\xb1\x75\x90\x76\xf9\xb4\xef\xc2\x65\x7a\x3b\x84\x6e\x64\xb3\xf7\x72\x6f\x4a\xae\x79\xc9\x0b\xaa\x8a\x75\x97\x06\xa7\x95\x8e\xd5\xd5\x52\x35\x9f\x0c\x45\x36\x2f\xf6\xc8\x81\x54\xf6\x2b\xb0\x79\x46\x2a\x48\xc1\xe8\xca\x65\x8c\xbd\x01\x5e\xbb\x34\x1e\x92\xe9\x7c\x70\x47\xba\x07\xf0\x7c\xc8\x93\xc0\x9b\x39\x37\x28\x85\xf2\xf8\xe0\x82\x15\x11\x9d\xf7\xba\x3a\x6b\x3d\x70\x2e\xac\x5b\x3e\x25\x1f\x9c\xaf\x8b\xbd\xe9\x2e\x80\x72\xd7\xc7\xee\x56\x23\xf7\x0d\x3e\xb3\xfa\x44\x0e\xcf\x93\x78\x79\x0a\xcf\x38\xed\x1b\x0f\x5e\x7b\x6c\xbc\x0c\x75\xde\x78\x90\x32\x7b\x2f\x43\xdb\x8d\x13\x7e\x09\x1a\x04\xf7\x66\xb5\xe0\xe6\x1d\xab\x10\xd1\xe2\x46\x20\xee\xc4\xc4\xe6\x36\x17\xdc\x58\x11\x52\x73\x28\xef\xa5\x06\x3a\xdd\x2b\xc3\xb3\xba\xa0\x8a\x28\xe6\x90\x42\x98\xed\x3a\x3b\xbf\x7a\x77\x7e\x7a\xf2\xfe\xfc\xec\x15\x09\xb3\xe5\xdd\xec\x13\x46\xe8\x7b\xd9\xc2\x97\x08\x6d\xcb\xaa\x1c\xc1\x5a\xcc\x0a\x1c\x79\xa7\x84\x8a\xb6\xe2\x8d\x0b\x94\xf6\xa3\x82\x5c\x08\x6e\xda\x3e\x93\xe0\x90\x65\x85\x14\x4c\x23\x55\xb4\x9d\xa1\xc7\x68\x2d\xb8\x39\x72\xe9\x08\x37\x61\x7b\x6f\xc3\x8c\x11\x92\xed\x37\x82\x8c\x2b\x57\x9a\xdd\x2c\x29\xe2\x45\xe9\xd1\xf2\x0a\xed\x11\xfe\xd2\xd9\xe9\x50\x1d\x9d\x40\xa1\xbf\x07\x70\x67\x2b\x32\xe2\x3d\xad\x65\x42\x6b\xba\x39\x4b\xe5\xc8\xb7\x90\x52\xe1\x7e\xb9\x26\xce\x36\x22\xd8\x9f\xee\x87\x84\x40\xc1\x59\x8e\xf5\xb2\x3b\x2e\x70\xcb\x31\xe0\xb9\x1c\x23\x44\xf6\xb5\xda\x94\x90\xb7\x66\xc9\xd4\x2d\xd7\x68\x7e\x44\x3e\xdf\x4d\x60\x19\x63\x76\xbb\x7d\xb6\x37\xf4\x70\x54\x14\xa8\xeb\x59\x77\x31\xcd\xd2\xff\xc2\x0a\x5d\x6a\x8b\x0f\xcf\xa2\xdd\xa5\xb0\x24\x09\xee\xd7\xbb\x76\x7d\x3f\xbc\xfb\xee\x71\x3e\xc7\x59\xae\x04\x1f\x73\x2a\xcb\x92\x1b\xb2\xa4\x7a\x19\x9a\x5b\x61\x1f\xb2\x9a\xca\xe9\x18\x6b\x1f\xf7\x4c\xe1\x1a\xba\xce\x11\x2a\x78\xc3\x2b\x0a\x82\xa2\x9f\x25\x1a\x41\x9e\x9e\x40\xb4\x99\x4b\x74\x33\x20\xaa\xa0\xb3\xd9\xcf\x70\xa0\x44\x3c\x21\x30\x9f\x06\x99\xde\xfc\x11\x1c\x61\xef\xf2\x1e\x37\x6b\x7b\xfc\xee\xfc\xe4\xec\xcd\xf9\xb4\xcc\x9f\x91\x61\x67\x22\xaf\x24\xc7\xec\x22\xb2\xf3\x42\x9c\x3b\xd0\x4c\x37\x45\x7c\x77\x1e\x84\xc1\xa3\x35\x1a\x87\x0d\xf4\x60\x5e\x94\x4b\x14\x80\x3b\x9a\x33\x43\x79\x81\x15\xda\xde\x0f\x23\x2b\x59\xc8\xc5\x3a\xf2\x18\x13\xdc\x51\xfe\x95\xa3\x7e\x9d\xd0\x89\xbd\x55\x8f\x93\x0b\xc6\x32\xf7\xf6\x77\x3b\xb0\xed\xda\xed\x6a\x56\x17\xb9\x90\x4d\x56\x11\xa8\x66\xb7\x43\xe6\x67\xb5\xc0\x4f\x3c\x65\xd2\xde\x84\x90\x7d\xc7\x26\xcc\x66\xcc\x19\x1b\x96\x3b\xaf\xad\xe9\x80\x49\x2a\xa6\x4a\xae\xad\x69\x46\x03\xbc\xb6\x33\x30\xcf\xfb\xbe\xe2\x92\x2f\xd6\x7e\xe3\x1a\x3d\xf4\xcf\xd1\xdf\xbc\x9c\x58\x37\xa3\x52\x6c\xc2\xee\xb8\x86\x5c\x1b\x90\xb8\x4b\x15\x15\x00\x76\xfd\x94\x00\x78\x08\x80\x0a\x27\x17\x05\xfb\xde\x00\x3e\xb4\x39\x82\x80\x9a\xc1\x24\x5e\x98\x60\x8a\x16\xc5\x1a\x48\xfb\x5d\x8b\x4c\xf7\x4c\x48\x17\xc8\x05\x95\xca\x63\x22\x2b\xc5\x57\xbc\x60\x0b\x3b\xe5\x25\x17\x0b\x34\xdb\x3e\x55\x8c\xd0\xa2\x90\xb7\xcc\xb7\xdf\x60\x5b\xeb\x8b\xb9\x91\x6f\xec\x7f\xdf\xe1\x04\x82\x90\xf7\xf2\xed\x7b\x22\x98\x9b\x32\xea\x9e\x47\x26\x47\xed\x47\x21\xbb\x55\x4d\x26\x13\x78\x43\x3e\xf8\x1f\x29\x98\xce\x8b\x43\xf2\x03\xf3\xdf\x22\x89\x62\x56\xf7\xa3\xf0\xc5\xb7\x4b\x09\x2f\x51\xb5\xf6\x6b\xde\x06\xb6\xa0\x2a\x51\xb7\x4e\xe4\x41\xee\xb1\x95\x2d\xa4\xf1\x4e\x7e\xef\x17\x70\x74\xaf\x54\x93\xb6\x7a\xe3\x39\x65\xd0\x1e\xc1\x59\x4e\xea\x39\x05\x0c\x60\x64\xf2\xac\xa3\x3f\x43\x55\x81\x63\xb0\x47\xbb\xdf\x94\xe8\x75\x59\x70\x71\x73\x44\xb8\x09\x95\x38\x56\xa3\x44\x84\xec\x56\x5c\xd0\xc5\x8a\xd1\xa2\xe3\xe9\x7d\xf1\x77\xb5\xa0\x35\x1e\xc5\x37\x34\x89\x80\x5d\xef\xd7\x95\xab\x77\x0d\x86\x3d\xea\xd5\xab\xe7\x6c\xed\xed\xa5\x73\xb4\x9e\xc5\xbe\x70\x9d\x69\x1e\xeb\x60\x5d\x5c\x9f\x5e\x5f\xf4\x1e\xb7\x30\xb9\x4b\x27\x65\x84\x97\xde\xe7\xa0\xc3\x56\x3d\xcb\xbc\x10\xff\xd7\xf0\xf3\x30\x21\x45\x8d\xf9\xaf\x1c\xe9\xc6\x95\x54\x06\x41\x9a\x1f\x67\x22\xb3\x25\xad\x4e\x6a\xb3\x3c\xe3\x3a\x93\x2b\x96\x24\x0d\x7e\xbb\x64\xe0\x23\x7b\x30\x27\xe1\xf6\x92\x60\xa3\xca\x30\x2f\x72\xfa\xb7\x93\x2b\x42\x6b\x7b\x8e\x0d\xcf\xf0\xa5\x88\xb1\xe5\xa0\x61\xc5\xae\x99\x4e\x94\x69\x4f\xb9\x5e\x7e\x56\x4f\x66\xb5\x46\x68\x34\x6a\x8c\xd0\xe8\xa7\x0f\x8d\x06\xdb\x86\x9c\xca\x08\x87\x1e\x34\xb8\xe0\x86\x53\x23\x23\x5a\xea\xf4\xdf\x36\x6b\x6d\x64\xe9\x14\x2d\x20\x69\x40\x38\x72\x71\x2e\x01\x0e\x71\x31\xef\xcf\xb2\x57\x3f\x1e\x03\x89\x80\x63\x76\x21\x0c\x53\x73\x9a\xb1\x0d\xf6\x2c\x2c\xda\x40\xb0\x5b\xff\xf5\xbc\x91\xfc\xe7\x28\xf6\xb9\x0a\xbc\x97\xbf\xbc\xfa\x73\x07\x70\xfd\x97\x48\xa4\x85\xef\xba\x17\x9e\x9f\x49\x26\x85\x60\x99\x79\x8c\x07\x64\x3b\xf8\xbf\x52\x58\x7b\x0f\xc2\x71\xab\xff\x7f\xd5\xb4\x88\x39\x21\x97\x8f\x85\x9b\xe8\x9f\xca\x04\xcb\x12\xee\x62\x38\x8d\xa8\x32\x2e\x37\xc0\xf6\xd6\x9a\xd9\x98\xce\xcb\x35\x8a\x0a\x6d\x8f\x68\x8a\xd7\x8d\x7d\x5f\xa0\xb0\x4f\x0e\x4c\x56\x21\xb1\xea\x4f\x82\xa3\xd5\x2d\x8e\x3f\x91\xdf\x21\x62\x17\x37\x1c\x37\x6b\xcc\x3a\x3c\x2a\x56\x1e\x34\x57\x8a\x07\xf5\xde\x72\x22\xc3\x39\x37\xbe\xe3\xda\xb8\x8e\x0b\x6e\x76\xd6\x9a\x30\xc7\xf7\x88\x72\xc3\xed\xb8\xb8\x22\x52\x11\x5e\xfd\x93\xe6\xb9\x7a\xe5\x22\x0d\x9f\x7f\x94\x68\xd4\x1e\xd7\xfe\x41\x04\x18\x49\x02\xf5\xd6\x81\x59\x57\x3c\xa3\x05\x9a\x01\xe8\xfd\xe9\x15\xcc\x4a\x93\x3f\xfe\xde\xb5\x89\xfe\xed\xd7\xbf\x7f\x11\x75\xd5\x9e\x1f\x57\x24\x49\xfb\x36\xfd\x9f\x87\xe6\x7f\x4a\xcc\x4f\x10\x90\x3b\xce\x27\xf0\x67\x62\x82\x7c\xe7\xa8\xc1\xb5\x68\x7c\xce\x74\xc1\xfe\xc8\xd5\xd3\x1b\x23\x57\xcf\x63\x73\xf5\x90\xe6\xc8\x3b\x9b\xfa\x30\x96\x3a\x86\x72\xf2\x6a\xdb\x48\x3b\x73\x8b\xb5\xaa\xf7\x18\x69\xfc\x23\xe1\x33\x31\xd2\xa8\xf3\x81\xd3\x19\x7d\x5d\xe1\xec\xcf\xfe\xbe\xee\x54\x37\x20\xbe\x03\x98\x57\xcf\x2e\xaf\xff\xf9\xdd\xc9\x5f\xcf\xbf\x83\x35\xf1\x6c\x2f\xf6\xf2\xa3\xac\xe3\x8e\x87\x9a\xc4\xea\x07\xfb\x2a\x83\xdb\xac\x78\x0c\xf6\xe5\xeb\xeb\xfe\xc3\x1d\xb9\x7c\x7d\x8d\x58\xd9\xdd\xc0\xeb\x06\x46\x8d\x0a\x25\x7a\xc0\xeb\xd8\x0c\xa3\x98\xa3\xf7\xe6\xb9\x00\x3c\x26\xc0\x1f\xf6\xc5\x09\xb2\x93\x22\x43\xc2\x83\x2f\xbb\x4b\x91\xa0\xb7\xa7\xdb\xad\x49\x42\x00\xe5\x83\x9f\x3a\xf2\xa4\x42\x9d\x87\x80\xe1\xda\x7d\x71\x3b\xec\xdf\x22\x3c\x94\x36\x26\xb7\xfb\x6c\x00\xb8\x5f\xf0\xfc\xc4\x84\x6b\x2a\x0d\xeb\xfd\xfe\x35\x48\x0a\x60\x79\x6b\x1a\x62\xa8\xef\x95\xf5\x05\xad\x3f\xc7\xb4\x0e\x0f\x90\x9d\x5b\x8e\x14\xfb\x18\xb6\x85\xc4\xdd\xf2\xb6\x32\xde\xb9\x5b\xa7\x05\xe5\x88\x2e\xc5\x1b\x2a\x78\x97\x50\xf7\xaf\xd7\x00\xc8\x41\xa9\xa2\x4e\x7f\xbf\x1e\xcb\x32\x25\x3b\x7f\x0f\xf5\xa6\xe5\x6a\x29\xa9\x7f\x2c\xd1\x15\xcd\x52\x95\x6a\x7d\xce\x41\x68\x37\x63\x12\xce\x44\xfb\x57\xee\x6f\x32\xfb\x69\xcf\xc9\x05\x81\x09\x3f\x02\x01\x5c\xf3\xbb\x29\x94\xcf\x69\x10\xe6\xf5\x4f\x44\x26\x05\x9a\xc3\x26\x3b\xb1\xe4\xbe\x53\x4b\x68\xcc\x44\x2b\x19\x9a\xc3\x40\x3b\xf0\xd0\x0f\xf9\x8b\x62\x4d\x1f\xf0\x32\x90\x27\xe5\x19\xfd\xf0\x45\x88\xfa\x83\x2f\x82\x75\xba\x1e\x27\xe5\x5b\x2d\xa5\x91\x22\x29\x9d\xe9\xd5\x0e\x91\xb1\xf6\xc8\xc9\x3c\x75\xf4\xcb\x05\x53\x1d\xb3\x8a\x10\x0d\xbc\x49\x0d\xe3\x34\x15\x79\x53\x22\x26\x45\x80\xa0\xc6\x52\x4f\x3f\x1f\x03\x52\xe5\x17\x67\x5f\xd8\x76\x8c\xad\x84\x9e\x66\x2b\xa1\x2f\x03\x42\x7b\x0c\x73\x62\x0f\x79\x82\xf3\x76\x71\xe6\x33\x1f\x81\xc7\x1a\x9b\x9b\x76\x0a\x8d\xa4\xd2\x68\xc4\x6b\xb5\x2f\x1e\xdd\x48\x65\x6e\xa5\x4a\xd3\xde\xef\xaa\x27\x2c\xba\x0a\xd4\x4b\xdb\xea\x30\xd0\xd1\xf7\x08\xc1\x1d\x0b\xf1\x4c\xf5\xbd\x5b\x8f\x67\xac\xf3\xaf\xa1\xb0\x28\xea\x78\x10\xff\xc8\xb0\x89\x39\x0e\xc0\x66\x6c\x7e\x62\x87\xf9\xd8\x30\x04\x71\x89\xd2\xc4\x48\xe6\x0d\xf3\x31\xed\x18\x00\x7c\x18\xb2\x6d\x36\x9e\x82\x01\x48\x18\x4f\x6c\x25\x1d\x91\x6b\xb5\xbb\x25\x19\xa4\x6f\xd1\x09\xd6\x9d\x91\x4e\x88\x59\xf0\xf1\x6f\x2f\xd2\x79\x94\x44\x67\xd0\x5a\x09\xf6\xef\x7b\x2f\xca\x3f\x53\xe2\xcf\x7a\xe3\x04\xd8\x08\xa5\x6f\x6e\xbe\xb8\x21\x56\xd2\x1a\x12\x8c\x45\xe8\x3b\x38\x86\x95\x1a\xc0\x3a\xb4\x28\xec\xce\x4b\x84\x69\x23\x4d\x61\xa0\x0e\x0d\xba\x8e\x48\x26\xc5\x9c\x2f\x4a\x5a\xe9\x23\x64\x39\x5f\x2e\x6f\xc5\x2d\x55\x39\x39\xb9\x1a\x8e\x22\x7a\x34\x73\xeb\x17\xe2\x0b\x5b\x5b\x0f\x78\x78\x23\xf3\x14\x26\xd7\x8a\x21\x33\xee\x54\x5e\x8d\x56\x78\x52\xb4\xf0\x76\x6b\x1f\xad\x55\xf3\x13\x45\xbf\x08\x34\x16\x77\x45\x8b\x9a\x91\x19\x33\xb7\x8c\x09\xf2\x02\x79\xc6\xec\x78\xf1\x87\x3f\xfc\x61\x4a\xce\x5a\xca\x02\x0f\x64\x88\xc9\xf7\x51\xb3\x04\xda\x0b\x21\x0d\xa1\xf3\x39\x5c\x55\x67\xd4\xd1\xf0\x16\xaf\xd4\x3d\x5b\x48\xc9\x17\x4b\x58\x09\x2e\xe0\xaa\x15\x38\x6e\x08\x12\x9e\xe9\x1c\x78\x26\x34\x39\x85\xa0\xc7\xcd\x3b\xd2\xdb\x22\xa5\xcc\xd9\x11\x29\xf8\x0d\x23\x73\xfd\xad\x92\x75\x85\x2d\xe8\xb0\x8e\xbc\x2b\xd6\xd7\x75\x61\x80\xd2\x62\xc6\xdc\xc4\xd1\x59\x80\x70\xce\xd1\x2d\x8f\x1e\x1f\xdb\xed\x15\x4e\x82\x6b\x5f\x70\xeb\x6d\xce\x1b\xe6\x2b\x67\x63\xec\x81\x88\x58\x9a\x47\xc2\x24\xf7\x23\xcd\xe6\x4b\xb0\x14\x36\x6e\xf8\x36\x9c\x8d\xf1\x25\xb4\x90\x62\x01\x17\x08\x2d\x53\x76\xeb\x62\x59\xde\x94\x6d\xae\x2b\x74\xb2\x21\x1a\xe3\x9a\x02\xe5\x4a\xbc\x07\xf0\x86\x56\x78\x11\x9b\x90\xc6\xe8\x16\xad\x6e\xd0\x99\xac\x4d\x28\xb7\x72\x73\x84\xe6\x62\x51\x42\x8d\x0c\x07\x23\x42\x4c\x82\xad\x23\x89\xb6\x8f\xc4\x5e\xc1\x30\xfa\x0e\x67\x2f\x34\xc4\x9a\x82\x76\x30\x9a\x2d\xc9\x0d\x5b\x4f\x9c\x3f\x50\x51\x14\x7f\x77\x7f\xf8\x07\xc0\x33\x6a\xa8\x43\x19\x47\x4b\xf4\x88\x88\xe6\x99\x3d\x5e\xe2\x69\x73\x70\xe3\xea\x0f\xdb\xd1\x6a\xb5\xc0\x66\x1e\x2d\x32\xa4\xe2\xb4\xcf\x90\x90\xdb\xa5\x44\x7b\x93\xed\x10\xed\xc3\xb1\xdd\xfa\x08\xd7\xaf\x1d\x99\x14\x86\x09\x13\xc4\xc2\x69\x8a\xc1\x96\xbb\x71\xb1\xc9\x78\x1d\x2d\xd1\xda\x68\x96\xdb\xcf\xd6\x4f\x79\xe7\x5b\x3e\x64\xeb\x0a\xa3\x43\xc0\xfe\xa8\xc5\xe6\xd7\xc7\x1f\x25\x69\x9c\x45\x87\xd4\xe2\x94\x5c\x60\xbb\x54\xb6\x83\xc2\x99\x4c\x50\x1a\xdd\x8e\xdb\x25\xcf\x80\xd7\xd4\x4e\xd7\xcf\x35\x95\x96\x6b\x14\x49\xbc\x2e\xee\xb0\x4e\x68\x66\xea\x2a\xcd\x16\x01\x5f\x80\xdd\x7b\xa6\x35\xe1\x11\xf5\x01\xed\x28\xa9\xba\x61\xb9\x8f\x76\x68\x31\x25\x57\xf6\x90\xc6\x8b\xf5\xc1\xa9\x62\x05\x85\x96\xf2\x29\x0e\xbd\xf5\x39\xbb\x2d\x08\x52\xdc\xce\xfd\xe9\x74\xdf\xc5\xa8\x91\x0d\x0d\xda\xd1\xb6\x36\x88\x14\x15\x1b\x35\xb4\x23\x89\xf3\xb2\x99\x19\xa1\x55\xfc\x39\x01\x3e\x3b\xc8\xfa\x81\xaa\x40\x3f\x62\xf7\x25\xc2\x7e\xfa\xcc\x45\x9c\x27\xeb\x86\x07\x29\xc5\x6b\x85\x34\x2e\xad\x1b\xf8\xcc\xdc\xe6\x98\xd8\xb5\x4f\x20\x05\x49\xf6\xd9\x1f\xa9\xfc\x75\x37\x6e\x18\xf2\xd9\x63\x73\xf4\x49\x1d\x12\x28\x1e\x37\xdc\xa1\x0f\x6e\x47\xfc\x09\x23\xf1\xcf\x45\x9b\xa3\x44\x27\x52\x37\x47\x1f\xf8\xf8\xd6\x9b\x9c\x34\xb2\xbb\x19\xac\x24\x5a\xc4\x8e\x5a\x33\x57\x30\x94\xc0\xd0\xba\x61\x5d\xff\xa3\x60\x1d\x13\xc9\xdc\x48\x00\x27\x92\xea\x4a\xfc\x20\x21\x9c\x48\xe2\xc5\x1c\xac\x77\xc2\x88\xd7\x8d\x6e\xd3\x9f\x36\xf7\x9f\x48\xb8\x0f\x2c\x80\x53\x3a\xd5\x42\xf4\xb2\xd6\x89\x64\xc6\xe7\xbe\x37\xc7\x76\x2e\x3c\xd9\x7e\xc5\x66\xd4\xb7\x25\x76\x33\xec\x89\x84\xa6\xc8\xd3\x6f\x8e\x7e\xde\x3e\x91\xd0\x04\xd9\xff\xcd\xd1\x7f\x0d\xc0\x97\x81\x77\x47\xfc\xf3\xc0\xe6\x88\x7d\x2e\xd8\x1c\xf8\x32\xc1\xcd\xf1\x40\xde\x42\x13\x4d\x25\xf1\xb4\xdc\xf0\xf9\x38\x7b\x7d\x52\xdd\x46\x49\x4a\x5a\x85\x94\x54\x32\xa1\x53\xf2\xc6\xc5\x7f\x89\x24\xce\x6c\x50\x4a\xe8\x4c\xcb\xa2\x36\xa9\xbe\xdd\x13\x67\x27\x9d\x68\xca\x70\xd7\x0d\x88\x8f\x58\xc1\xca\x14\xc9\x13\x37\x5c\x2b\xbf\xb4\x1f\x0e\xe1\x78\xd3\x71\x2e\x99\x50\x88\x36\x53\xc4\xe7\x6e\x24\x73\xb7\xe3\xc8\x50\xdc\xd8\x49\x89\x92\x24\x9b\xd5\x27\x46\x49\x90\x72\x7b\x52\xc4\x2a\x6e\xec\xa6\x57\x89\x16\xeb\xe9\x59\xba\x24\x2b\xd1\x32\x53\x90\xb4\xb8\x91\xec\xfc\xca\x44\x01\x5d\xef\x0c\x5f\xbb\x9e\xf9\x09\xf2\xc6\xcc\x73\xa2\x74\xf2\xbc\xf1\x8f\x59\x8a\x58\x27\x09\x92\xf0\xa9\x82\xba\x9c\xcd\xb9\x88\xce\x94\xc7\x82\x0e\xfd\x5c\x3c\xee\xec\xe4\xea\xe2\x09\xbf\x5c\x77\x66\x19\x25\x31\xa7\x86\x8e\x6f\xd7\xf7\x8d\x1d\x60\xc9\x04\x69\x11\xda\x40\x6d\xce\xda\x5d\xfc\x1e\x0f\x24\xed\x8e\x04\x3e\xed\xd3\x4e\xc1\x6f\x2d\xd9\xeb\x34\x5e\x7c\xa7\x00\x31\xd5\x6d\x75\xc3\x48\x0f\x83\x4c\x19\x73\x78\xff\xd8\x95\x14\x03\x7b\x52\x02\xa1\x69\xc0\x0e\x4f\x36\xe1\xff\x04\x53\xf5\xb0\xe2\x68\xf6\xc5\xcd\xb1\x49\x10\x93\x6a\xe9\xdc\xb8\x66\x85\xf5\x3e\x49\x2a\x50\x8c\x1b\x32\x50\xbf\x25\x9b\x27\x90\xcd\x50\x21\xa4\x81\x1b\xac\x93\xe5\xc6\xe8\x8c\x15\xfa\x88\x44\xf0\xa4\x6c\x0e\x2a\xf2\x96\x62\x20\x95\x4c\xd5\x29\x3f\x4a\x9a\xc6\x4a\x74\xa5\x49\xd2\x6b\x4d\xe0\x6a\xc3\x89\x8c\xe8\x39\xd5\x1f\x69\xef\x38\xe9\x51\x4d\xa6\x92\xb8\x59\xe4\xe2\xa4\x27\x13\xde\x5c\x4c\x9d\x2d\x59\x99\xe2\x3d\x39\x0c\x2b\xf4\x75\xd2\xed\x72\x83\x6b\x72\xab\xb8\x31\xc9\x1e\x83\x88\x07\xc9\x30\x55\xa6\x7a\x05\x20\xb0\xae\x47\xe1\xc9\x26\xa5\x58\x23\xc9\xde\xea\x25\xba\x14\x7c\x87\xc0\xb4\x2f\xaa\x24\x58\x3b\x5c\xeb\xd8\xfb\x46\x1f\xe7\x9d\xf6\x44\x35\x59\xe2\x74\xd6\x8e\xb8\x9d\xd2\x60\x4a\x13\x9f\x53\x7b\x59\x93\x41\xce\xda\x71\x72\x75\x41\x56\x4e\xbb\x3c\xd9\xc3\x35\x3e\xd7\x8f\xcf\xf5\x49\xc6\xf8\x5c\xef\xc7\xf8\x5c\x3f\x3e\xd7\x8f\xcf\xf5\xf1\xe3\x99\x3c\xd7\x27\x4f\x16\x5c\xb9\x7e\xcf\x24\xe1\x23\xe6\x43\x00\x01\x44\x92\xfe\x09\xdd\x01\x77\xdc\xb1\x61\xf8\xe2\xe7\x54\x2a\x19\x6a\x9f\x5d\xc1\x42\xaa\xab\xee\x71\x00\x78\x16\xff\xcd\x91\xfe\xd9\x7e\x7f\x7f\x3a\xdd\x77\x68\xf5\xa4\x0b\x69\xed\xa5\x99\x4f\xfe\x98\x48\x26\x13\x99\xcc\x59\x3e\x4d\x08\x7c\x99\x73\xa5\x0d\xa4\xd0\x53\x3c\x67\xbb\xe1\x14\xbb\xbb\x47\x29\x71\x15\xa5\x3f\x9b\xe9\x41\x10\x6e\xff\x53\xaa\xf7\x64\x51\x47\x60\xbd\x78\xfd\x80\x49\x5c\x9f\x74\x4d\xe6\x86\x37\x2d\xbc\x93\x1e\x29\x7f\xed\xb1\xcc\xd4\xdb\x03\x72\xb8\x0d\xab\x48\x32\x6f\xa9\xe4\xd0\x4c\x21\x87\xfc\x23\xd3\xc9\xd6\xf5\xc0\x89\x9e\x66\x55\x9d\xce\xb5\x03\x89\x25\x2b\xa5\x42\xf7\xc0\xdc\x1c\xe1\xb3\xed\x44\x13\xba\x8b\x8d\x58\x37\xdb\xc3\x84\x99\xec\xac\x56\x8a\x09\x3c\x41\xd5\xe6\xf8\x8f\xcb\x8c\x87\x4b\xf4\x44\x13\xe3\x8d\xe6\xc0\x53\x4b\xef\x1a\x1b\x74\xd3\xe1\x47\x12\xa6\xc5\x00\xb8\xd6\xec\x56\x42\xc1\x73\xa9\x7c\xaa\x20\xd9\xcb\x15\xe9\x00\x95\x12\xcf\x94\x89\x55\x42\x89\x2b\xaa\x90\xf4\xd3\xbb\xc6\x03\x64\xb0\x73\xbe\xe2\x5a\x26\x33\x73\x3b\x71\x5f\x78\x96\xd1\x5d\xc3\x9a\x67\x59\x9b\xaa\x4e\x99\x6e\x76\x51\x6d\x3a\x1f\x82\xf8\x89\xb2\xbb\x4a\xea\xa4\xb7\xa9\xf1\x21\x52\xde\xa5\x07\x7a\xbe\x79\x89\x25\xdc\xdd\x1e\x15\x35\x86\x29\xf1\x8a\xfc\xf7\xc1\x3f\xbe\xfa\x38\x39\xfc\xe6\xe0\xe0\xc7\x17\x93\x3f\xfd\xf4\xd5\xc1\x3f\xa6\xf0\x2f\xbf\x39\xfc\xe6\xf0\x63\xf8\xc3\x57\x87\x87\x07\x07\x3f\xfe\xfd\xcd\xb7\xef\xaf\xce\x7f\xe2\x87\x1f\x7f\x14\x75\x79\xe3\xfe\xf4\xf1\xe0\x47\x76\xfe\xd3\xff\xcf\xde\xbb\x37\xc7\x8d\x23\xf9\xa2\xff\xf7\xa7\x40\x68\x26\x42\xf6\x1c\x55\xb9\x7b\xb6\x63\xce\x5c\x9f\x8d\xdd\x50\x5b\xea\x59\x9d\xb6\xdd\x5a\xcb\xf6\xc4\xb9\xbd\x73\xf7\xa0\x48\x48\x85\x15\x8b\x60\x13\xa0\xe4\x9a\xdd\xfd\xee\x37\x90\x09\x80\x60\x15\x49\x80\x0f\x3d\x3c\x53\xfc\xa7\xdd\xa5\x62\x16\x1e\x89\x44\x3e\x7f\x19\x49\xe4\xe5\xcb\x7f\xfe\xed\x6c\x53\xa0\xf9\xf6\xe7\x99\x54\x6a\x02\x37\xe1\xfc\xce\x1d\x9f\xee\xac\x62\x86\x90\x2f\x8b\x3a\x3d\x78\xc1\x73\xb5\x10\xe5\x02\x7f\xe2\x35\x51\x65\x35\x9f\x4f\x05\x8f\xc7\x43\xdd\xbc\x73\xbb\x95\x88\x37\xe6\x87\x08\xc9\x3d\xb3\xcb\x07\xd1\x14\x9f\x71\x16\x2a\x0e\xf0\x00\x9e\xd4\xf6\x1c\xc0\x93\x9e\x2b\x78\x92\xe9\x51\x6c\xe3\x66\x0e\xff\x66\x86\xc9\x23\x7e\x4e\x8d\x7c\x34\x99\xa4\x8f\x9c\x34\x4f\xea\x59\x13\x39\xc9\x22\x1f\xcd\x45\x16\x91\x93\x9a\xc8\x47\xd3\x53\x4a\xd7\x6c\x0f\xf9\x68\x32\xd1\x06\x92\x9f\xde\xb9\x59\x86\xb9\x8b\x7c\x34\x9d\x01\xa0\xc1\xaa\x37\xfb\xc9\x14\x81\xef\x77\x90\x8f\x26\x13\xbd\xb8\xfe\xda\x90\x8f\x50\x0a\xcc\x03\xcb\x75\x80\x3d\x3a\xc0\x1e\x4d\x7a\x9e\x77\xcd\xc5\x01\xf6\x68\xf0\xf3\x6c\xab\x20\x0e\xb0\x47\xa1\xe7\x00\x7b\x34\xfd\x39\xe4\x51\x1e\xf2\x28\x0f\x79\x94\x87\x3c\xca\x43\x1e\xe5\x21\x8f\x72\x0e\x8a\x5f\x49\x1e\xe5\x01\xf6\x68\x16\xa2\x07\xd8\xa3\x03\xec\xd1\x2c\x44\x0f\xb0\x47\x43\x9f\x03\xec\xd1\xa4\xe7\x00\x7b\x34\xe8\x79\x70\xd8\x23\x74\xf2\x4e\x8f\x41\x39\xcc\xa3\xbf\x49\xc8\x23\xa9\x8f\x5d\xc2\x4e\x93\x44\x54\xb9\xfa\x28\x6e\xd9\xa4\x3a\xf5\x07\x0f\x3a\xef\x8d\x76\x12\xe5\x67\x07\x81\x34\x87\xbb\x6f\xb2\x8b\x6e\x2e\xe7\x1c\xad\x52\xce\xf2\xe9\x29\x26\x0d\xa6\x3a\x35\x44\xe7\x8a\x5a\x6a\x53\x25\x4f\x59\xea\x46\x3b\x57\xd4\x5a\x69\xee\x5c\x92\x53\x52\xb2\x84\x17\x7c\x0e\x25\x4c\x5c\x13\x8a\x74\x51\x16\x99\xbe\xa4\xd3\xe5\x26\x57\x92\x65\xd7\xa8\x84\xd1\xbc\xee\x77\x3a\xdd\x82\xab\x83\xa2\x26\xf6\xf6\x20\xcb\x3c\x4f\x97\x19\x50\x07\xee\xb9\x64\x44\xae\x45\x95\xa5\xa4\x64\xb3\xf8\xf0\x3d\x6e\xf8\x38\xe7\x0a\xa4\x5e\x7b\x62\x60\xe5\xf9\xb6\xcd\x2c\x2e\x2d\xb8\x16\xb9\xac\x9c\x27\xc8\x35\x83\xfa\xc1\xbe\x14\xbc\x84\x2b\xe5\x8a\x25\x22\x4f\xe7\x4d\xb3\x39\xdf\xa5\x3e\x97\x94\x31\x75\x12\x2c\x25\x69\x55\xce\x03\x2f\x26\xae\xc9\x1d\xcd\x78\xca\xd5\x76\xae\x3a\x46\x73\xbd\x12\x8a\xf7\xab\x61\xda\xc9\x64\x4f\x65\x7d\x04\x08\x2d\x8a\x52\xd0\x64\x3d\x83\x22\x5f\xf3\xc2\x09\xfa\x21\xb0\x5d\xff\x5c\x21\xfd\x22\xab\x6e\x78\x3e\x4f\x4c\x1f\xe6\xac\xf8\x1d\xcb\xb6\xa4\x14\x8a\xce\xe0\x8a\xf0\xf4\x21\xbb\x61\xd3\x69\xd6\x52\x6a\xae\xc5\x04\xd7\x3a\xda\xf8\xaa\xdc\xce\x11\xac\x52\xc2\x2c\x61\xcd\x55\xd3\x8f\xa9\x77\x99\xe8\x33\x2b\xb2\x74\x06\x29\xaa\xd6\x34\x27\x7f\xfc\x96\x14\xac\x4c\x58\x3e\x4b\xd6\x3c\x44\xbe\xf8\x06\x0a\x8d\x33\x7e\x37\x4b\x01\xef\x03\x4e\xfe\xf7\xdf\x93\xb5\xa8\x4a\xb9\x3c\x9b\x2b\x71\x5e\x09\xf2\x1d\xd0\x04\x37\xbb\x56\x83\xe6\x48\x07\xa3\x8a\x64\x8c\x4a\x45\xbe\xfb\x96\x6c\x78\x5e\x29\x36\xb2\xfb\xbd\x37\xd0\x19\x3d\xe1\x9e\x0f\xfc\x0f\xdf\x4f\xa2\x35\x87\xf7\x7b\x0f\x79\x69\x8e\x14\x25\x80\x02\xd4\xb4\x66\x2b\x52\x36\x5a\xd1\x06\xae\xb2\x42\xf0\x79\x14\x70\x17\x85\x9a\xc5\x6c\x34\x23\xad\x4f\x5f\xae\xc4\x13\xea\x5a\xbf\x56\x62\xb5\x55\x23\x0c\xb6\x06\x4b\xfc\x2b\x52\xf1\x71\x55\xc7\xe4\xe7\x58\x32\xb8\x81\x02\xcd\x87\xb5\x90\x0a\x63\x8b\x72\x4d\xcb\x51\x4a\x04\x25\x85\x48\x8f\x25\xc9\xf8\x35\xd3\xa2\x74\x30\x89\x49\xb6\xfe\x78\x0b\x7f\x41\x4a\x76\xc3\xa5\x2a\x87\xdb\x7b\x0b\xa3\xd3\x0c\x7e\x71\x9a\x2b\xe0\xa6\x14\xd5\xc8\x1e\xd0\x0d\x86\x82\xe8\xac\x8d\x38\x8d\x9c\x09\x3e\x34\x49\x98\x04\x83\xc9\x5c\x48\x98\x61\x8a\x23\x1d\x45\x73\xa2\x65\x53\x32\x9a\xfe\x9c\x67\x23\xf3\x97\x1a\xab\xf4\xc1\x90\x22\x6b\x56\xb2\x29\x6a\xeb\xb5\x28\x13\x54\xae\xec\x11\xb4\xad\xc9\xc7\xa6\xdc\xac\xcc\x29\x66\x29\xfa\x18\xf4\xac\x17\x50\xe9\x5f\xb0\x72\xc3\xa5\xe4\x22\x1f\x7d\xe1\x9e\x79\x66\xf0\x35\xcd\xe4\xc8\x14\xbe\xa9\xfe\x54\x7b\x38\x67\xd9\x49\x24\xe5\x49\xd0\xb1\xfc\x4e\x24\xcf\x6f\x32\xad\x26\x92\x4d\x95\x29\x5e\x64\x6e\x57\x47\x92\x74\x83\x33\xc6\xc7\xf4\xa4\x6f\xe8\x12\x6d\x22\x76\x54\x82\x88\x7f\x5d\x88\x52\x4d\x29\x4b\x79\xe1\x66\xcb\x72\x55\x72\x26\x11\x1d\x97\x15\xb4\xa4\xe3\xeb\x3d\x80\x79\x13\xb1\xd9\x50\xf9\xd2\x64\xa8\x53\x00\x46\x96\x13\xec\x6f\x6d\x1a\x94\x34\x73\x0c\xe4\xd7\x81\x3f\x85\x48\x52\x2c\xa7\xf9\xc8\xd2\xb3\x66\x4a\x04\x10\x22\xe2\xde\x82\x95\x8f\x5c\xa0\x1b\x7e\xc7\xf2\x5d\x59\x34\x29\x54\xfe\x03\x4d\x6e\x59\x9e\x92\x4f\xd2\x4a\xa4\x74\x9b\xd3\x0d\x4f\x68\x36\x1a\x6f\xa2\x28\xc5\x1d\xd7\x82\x8c\xa5\x3b\x63\x1d\x5d\x0a\x82\x19\x7f\x1c\xf2\x73\xc8\x6a\x8b\x3a\x32\x78\x25\x9e\x82\x2f\x2a\x39\x16\xe5\xa5\xc1\x15\x9f\x24\x2b\x1f\xe6\x2e\x97\x58\xcd\x59\xf2\xbb\x84\x4d\xf3\x88\xe8\xa9\x3e\xc5\x12\xe3\x7a\xcc\xb0\xc8\x9f\xcd\x21\xa9\x25\xeb\xc8\x95\x00\x55\xdb\x15\xe0\x49\x48\xa6\xc9\xf4\xf5\xbd\xb5\x20\x67\x23\x09\xef\x1c\xe7\xd5\x16\x32\x23\xa6\x5c\xdd\xa3\xe6\x59\xae\x46\x68\xe2\x3b\x95\xce\x3f\x9c\x35\x4c\x1d\xf2\x81\xa6\x62\x8c\xe4\xfe\x21\x13\xc9\x2d\x39\x63\xe0\xd2\x6b\xb7\x7a\x46\x50\x45\x3b\xc9\x58\x3d\x9e\xd9\x83\x29\x1e\x98\xa2\x31\x82\xac\x4d\xea\x60\x5f\xe8\xa6\xc8\x98\x5c\xde\xfe\x11\xd2\x3a\x8c\xc8\x7b\x55\xae\xd2\x57\x1f\xce\x4f\xcf\xde\x9d\x2f\x37\xe9\xf0\xec\x85\x27\xb3\xb1\xf8\x86\xde\x0c\x97\x48\x0b\xb2\x11\x39\x57\xa2\x1c\xbe\xef\xd3\x4c\xac\x6b\xf9\x51\xaf\xd4\x74\x89\x71\xfc\x23\xcf\x98\xdc\x4a\xc5\x36\xb0\xf8\x23\x8f\xb5\xf1\x90\x58\x83\x41\x4b\x8f\xad\xa8\xc8\x3d\x1d\x2d\x8b\xf5\x55\xa1\xcf\xc2\x92\x7c\xe4\xc5\x6b\x72\x9e\xcb\xaa\x34\x94\xc7\x2b\x00\xd7\xcd\xc9\xc2\x1d\x6b\xf1\xa1\xc6\xda\x38\xdb\xfa\xa8\xea\x1d\xa5\x4a\x6b\x3d\xf8\x23\x63\x4d\x9b\x73\x73\xb8\x5e\x93\x23\xf6\x45\x7d\x7f\x74\x42\x8e\xbe\x5c\x4b\xfd\x9f\x5c\x5d\xcb\xd1\x90\xef\x17\x9b\x22\xe3\x09\x57\xd9\x56\x1f\x7f\x56\x96\x2c\x35\xc0\x95\xf8\x33\x23\xc9\xf2\x46\x91\xba\x2f\x5f\xa2\x52\xc0\xa4\x12\x25\xbd\x61\x56\x82\xfc\xa6\x5c\x8d\xdd\x0a\xcc\xf0\x5a\x8b\x7b\x92\x0a\x72\x0f\xa5\xae\x77\x2c\x57\x58\x59\x39\xd6\x94\x32\xf1\x6b\x8f\x73\xae\x4b\xb1\xd1\xd6\x40\x51\x8a\x0d\x97\x53\xee\x58\x46\x36\x34\x59\xf3\x9c\x8d\x4b\xf3\x9a\xa8\x75\x80\xc8\x9b\x43\x84\x7c\x5c\x33\x52\xea\xcb\x6f\xa4\x14\xc5\x07\xf4\x80\x36\xe6\x89\xba\x6a\x7e\xb3\x16\xf7\x0b\x25\x16\x95\x64\x0b\x3e\x12\xd5\x63\xe2\x7a\xde\xb2\x2d\xc0\xb5\xcc\xb0\xa2\x3f\x21\x29\x1b\x46\x9e\x90\xd8\xa3\x04\xe4\xb0\x01\x35\x6d\x60\x7e\xf8\xe1\x4c\x6b\xe2\x4b\xab\x3c\x8f\x3d\x15\x92\xbc\x62\x2a\x79\x95\xb0\x62\xfd\xca\x4c\x7c\xa2\x66\x41\x86\x6a\x17\xcf\x60\xcb\xed\xed\x3f\xc7\x9e\x9f\x92\x44\x64\x19\x4b\xf4\xff\x8e\x0f\x19\xbe\x61\xc5\xda\x0d\xeb\x39\x1c\xa7\xf1\x15\xce\x93\xea\x9a\x27\x6e\x6c\x21\xc4\xc8\x54\xd7\x2e\xd1\xa8\x29\x4e\xb0\x75\x88\xef\xb9\x2e\x57\xed\xd7\xec\xd7\x72\x6c\x66\xf4\x7e\x1f\x3f\x80\xfb\xdb\x91\x94\x4c\x81\x36\x37\xd2\xf1\x42\x8c\x3d\xfe\x4e\xeb\xb1\x72\x39\x97\xc7\x9a\x3c\x83\xad\x1f\xef\x2f\x47\x00\xa9\xd1\xe0\xc9\xbb\x60\xc9\x86\x18\xc4\x73\xc6\x63\xe5\xd8\xbc\xb7\x4a\xad\x59\xae\x78\x02\xd9\x45\x66\xa8\xe3\xd9\xa9\xbe\x6c\x2f\xae\xd1\x4f\x98\xb2\x94\x88\x3b\x56\x96\x3c\x1d\x9d\x08\xe5\x6e\x5b\x3f\x94\xc5\xb3\x49\xa5\x1b\x4f\xca\x4b\x13\xb2\xa7\xa7\xa7\x2c\x4f\xab\xcb\x69\xad\xc8\x99\x98\x93\xd7\xac\xc5\x79\x6e\xb5\x34\xed\x55\x34\xb6\x0a\x66\x02\x61\xaf\x7e\x66\x96\xfa\x97\xe7\xe1\xf5\xf6\x14\x00\x4d\x71\x2e\x05\x80\xa6\x1b\x9e\xff\x9d\xe9\xdb\x32\xa1\x19\xbb\xf8\x79\xa2\xdb\xf6\x0a\xa9\x4c\x4d\x52\xb1\x64\x0a\xcd\xb2\x52\xb1\x5c\x39\x04\x38\xa5\x68\xb2\x1e\xe5\x4e\x82\xcc\x36\x13\x2f\x17\x39\xf9\xc9\x9d\x75\x92\x8b\x74\x4c\x66\xda\x93\x79\x53\x6f\xa8\x62\xf7\x23\xd4\xfe\x45\xad\x1e\x8c\x79\x17\xfc\x33\x5f\xab\x27\x76\xc7\x11\x3b\x3e\xeb\xc2\xb8\x4d\x6d\xd3\x13\xea\xf9\xae\x26\x18\x53\xb5\xa3\xb4\xdd\xe5\x39\x92\xb4\x71\x94\x92\xf3\x2f\xcb\x79\x9d\x9d\x9e\xb4\x04\x7a\x8f\x1e\x62\xd2\x8f\x39\x07\x73\x04\xd5\xed\x82\xd3\x34\x2d\x99\x1c\x7b\x85\x1b\x45\xd7\x8a\xaf\xd3\xcb\x0b\xf2\x27\x1c\xe3\x93\xac\x4f\x51\x0a\x85\x1e\x8f\x33\xb1\xa1\x7c\x64\x0d\xe2\xde\x42\x79\x4d\x9e\xec\x54\x47\xae\xd7\xa5\x1b\x20\xc1\x11\x82\x5e\x6f\x3a\xa0\x5c\xf3\x9b\x6a\x7c\x2b\x00\xe3\xf7\x7e\x92\x75\x9f\xd1\x00\xdf\x33\x6a\xc7\x66\xee\xe8\x31\xbd\xba\x2f\xb9\x62\x2f\x97\xcd\xa4\xb6\xd1\x59\x3b\x59\xd6\x63\xd5\x8f\x8f\x07\x34\xac\xfa\xaf\xde\x88\xae\x6d\xe8\x3a\xde\x3f\xde\xd9\xec\x61\x44\xeb\x93\x62\x05\xcd\xe8\xcc\x0a\xd4\x8a\xd0\xd6\x90\x2c\x97\x1c\x20\x52\xbc\x12\xe3\xd1\xc1\xb0\x6b\x80\xfe\xaa\xa1\x46\xd1\x3c\x3f\x21\x6f\xc5\xd8\x44\x1b\x62\x6f\x43\x91\x1b\xe6\xa3\x3c\x9b\xc2\x20\x07\xcb\xb8\xf1\x1c\x2c\xe3\xe7\x60\x19\x4b\x99\x9d\xe7\x74\x95\x8d\xad\x56\x6f\x2a\xbd\x19\xbd\xd1\x62\x83\x01\xc5\x57\x29\x97\xfa\xbf\x23\xa7\x76\x75\xf5\x16\xb2\x34\xab\xdc\x7a\xf0\x20\xc7\xcf\x28\x38\x63\xb3\xf1\x4c\xb9\xed\x84\xcb\x6d\xb2\xb4\x47\x4d\xe1\xdd\x68\xac\xc6\x26\xa6\x7c\x9e\xea\xe5\x61\xd2\xc2\x66\x4c\x08\x5f\x9b\x91\x81\xa8\xa7\x0e\x13\x19\xaa\xa8\xc7\xa6\x53\x30\xf2\x71\xcd\x93\xdb\x4b\x2f\xad\x52\x94\xfa\xb3\xdc\xfb\x68\x06\xa3\x60\x16\x8a\x53\x8f\x12\x2e\xdf\xe5\x3c\xc1\xa6\x8f\x9e\x62\x7f\x85\x94\xc7\x6a\xbd\x42\x64\x84\x4a\x29\x12\x4e\x5d\xf2\x3e\x04\xa2\x9d\x3a\x3c\xf6\x30\x81\x12\xfd\x34\x8b\x0d\x96\xe6\x03\x58\x18\x72\xd2\x5a\x1b\x93\x9f\x4a\xcf\xa2\xd0\x4a\xa6\xd9\xc9\x27\x59\x2a\x3c\xc8\xe3\x1b\xb4\x75\x2e\x17\x9d\x98\xfa\xdb\x4c\x41\x75\xb8\xee\x93\x4c\x3c\xeb\x73\x59\x53\x74\xad\x36\xd9\x7e\xb4\x70\xe4\xd2\xc9\x43\x68\x5e\xf3\xe8\x1b\x39\xb6\x95\x4c\x5b\x84\x6d\xaa\xbb\xd4\x58\x04\xa6\x80\x0f\x40\x36\x0a\x51\x54\x19\x56\x73\x8f\x2a\x23\x35\xb0\xdd\x53\xb3\xcd\x70\x64\x8f\x9c\xa8\x3a\x4d\x39\xf7\x70\x70\xe7\x88\x50\x38\xa8\xe6\x1a\x18\x74\xbc\xf9\x67\x40\x95\xed\x01\x05\xcf\x23\x59\x6d\xed\x98\x47\x07\xbc\x9d\x2f\xb3\x81\x86\x8c\x38\xc6\x23\x69\x02\xfa\x71\xc3\x7d\xf1\xed\x1f\xbe\xff\x7e\x49\xce\x78\xc9\x12\x25\xca\xf1\x5d\xf9\x0c\x38\xbd\x2b\x6d\xa6\x25\x03\x1b\x13\x61\x71\xa7\x65\x9a\x62\x55\x88\x82\x00\x70\x0d\x35\x3c\x5e\xd9\xf2\xa0\x85\xe7\x03\x05\xf6\x40\x80\x77\xe0\x7b\x01\x78\x77\x6c\x44\xdd\xc0\xf5\xee\x00\xed\x92\x64\x34\x0e\x9a\x05\xd6\x9d\x05\x12\x77\x7a\xe1\xff\x54\xc8\xdb\x09\x09\x53\x7d\x5d\xa7\xa0\x6b\xd4\xf8\x64\x05\xaf\xd7\xd4\x6c\xbd\xa2\xf6\x3a\x44\xf9\x1d\x9e\xc6\x33\x43\xb3\x3b\x90\x97\xd1\x3e\x56\x5f\x91\xfb\xdd\x9c\x4c\x4e\xe7\xf8\xf5\xf4\x7b\x38\x35\x7b\x30\x8d\xf7\x84\x79\x9b\xbd\xd3\x79\x69\x8a\xef\xb5\x7d\x45\xa7\x96\x8d\x62\x97\xa5\xfd\x2e\x49\x53\xf6\x7e\xa7\x37\x92\xdf\xdb\x68\xac\x56\xe9\x00\xd0\x66\xec\x68\xb4\xdf\xc7\xa8\xd1\x87\x68\xca\x5e\xed\x77\x1f\x32\xdd\x83\x46\x7b\x42\x1b\x3d\x87\xf6\x7a\x06\x4d\x70\x06\xb7\x74\x0a\x02\xc4\xdf\x09\xfc\xe4\xfa\x03\x4d\xed\xef\xf3\xa4\x39\xaf\x7b\x1d\x7c\x1a\xfd\x77\xc6\xfb\x0b\xc5\x6e\xd7\x9d\x89\x3d\x73\x66\x00\xcd\x9c\x0a\x98\x39\xa5\x2b\xce\x24\xa0\xcd\x39\x40\x36\x27\xf6\xbd\xd9\xb3\xce\x67\x68\xce\x34\x43\x8f\x9b\x59\xb0\x02\xa7\xf6\xb3\x79\x88\x2e\x36\x7e\xef\x9a\xd9\xba\xce\x34\x7a\xcd\x58\xbb\x68\x12\xc5\x86\x4d\x65\xac\xa3\x8b\x69\xc8\x65\xcd\x8e\x30\xd3\xf5\x29\x7c\x3c\xfb\x77\xc6\x0e\x2e\x8d\xbe\x2d\xb3\x75\x5c\xd9\x37\xa9\xc6\xd6\xf3\xd6\x4f\xab\x61\x35\x89\x62\xa3\x1b\x8a\x35\xaf\x26\x51\xac\x4d\xb3\xa6\x91\x35\x8d\x43\xe7\xe8\x59\x32\x17\x3e\xdb\x3c\xfd\x49\xa6\xe2\xb2\xed\xc9\xf2\x59\x60\xd4\x50\x25\x6a\x82\x9e\x6d\xe8\x58\xfd\x12\x1f\xe5\x2e\x1a\xd7\x49\x62\x2a\xa8\xba\xd7\xe1\xa3\xee\xcd\x31\x59\x60\xf9\x6a\xe5\x6c\xbd\x34\x1a\x1d\x34\x3c\x55\x73\xf2\x92\xce\xd4\xf1\x62\xe2\xe5\x3b\xad\x3b\x40\x5b\x4f\x00\x1f\xd3\x7f\x6c\x38\x18\x5d\x02\x35\x92\x7f\x6d\x85\x4c\x81\xe2\x9f\x27\x77\x67\xa6\xe0\x8a\x9f\x59\x31\xad\x5e\xc5\x72\x3c\xa2\x45\x40\x32\x44\x41\x13\x66\x74\x96\x19\x2b\x95\x1e\xc3\x3b\x4f\x26\x86\x4e\x70\x18\x62\x84\x8e\xde\xe4\x65\xa4\xf3\xf3\xd5\x34\x44\x2f\xea\x11\xda\xc9\x32\x1f\xe9\xff\x7e\x3e\x59\xe6\x87\xe4\xeb\xd0\xf3\x35\x26\x5f\x3f\x0e\xd2\xc4\x53\x84\xc6\x0f\x99\xb3\x87\xcc\xd9\xfd\xcc\x59\xcb\x93\xe3\x03\x66\x2e\x6b\xd6\xf8\x08\xae\x45\x49\xc4\x4a\x2b\xa2\xd3\x00\x46\xea\x9b\xe3\xf4\xf2\x82\x24\x25\x83\x66\x11\x34\x93\x4b\x32\xde\xba\xdf\xb1\xeb\x6d\x86\x1c\xf8\x20\xa6\x46\x0c\xa8\x52\x6c\x53\xa8\x69\xc7\xfb\x90\x38\xdb\x78\x0e\x89\xb3\xcf\x21\x71\x76\xd6\xac\xaa\xcf\x8e\xd8\xb4\x80\xe2\xba\xda\xd0\x7c\xa1\x6f\x10\xba\xca\x76\x2a\x67\xac\xe8\x18\x49\xda\x66\xe8\x58\x54\x42\xe0\x13\x48\x86\x10\xf9\x68\xb8\xcd\x2a\xe7\xbf\x56\xac\x8e\x44\x38\x43\xe5\x89\x13\xe5\x60\x0c\xb3\xee\x2b\x9a\x5f\xb3\xdc\x2c\x89\x28\xd8\x0e\x44\x1b\x2e\xe0\x58\xcb\xda\x72\xc6\xd2\x34\xfe\xae\xb7\x61\xac\x6e\xe0\xc1\x09\xeb\x61\xa2\x31\x7a\x29\xd2\xe3\xb1\x13\xaf\x2d\xd8\x86\x8f\x18\x1d\xbd\x63\xa3\x8f\x59\x26\xee\x31\xe2\xee\x9b\x4d\xfa\xcc\xe8\x35\x9e\x70\x53\x83\x6e\xbc\xe1\x65\x29\x4a\x93\x78\xc8\xf3\xc9\x07\x10\x4a\xd5\xf8\xcd\x5a\xb1\x12\x1d\x9e\x58\x9b\xb2\x24\x57\xa3\xbd\x04\x9e\xd8\x51\x82\xd0\x1c\xe1\x3b\xf5\xbf\x2d\xac\xc5\x04\x3e\xb5\x7a\xc4\x8a\xad\xe9\x1d\x17\x55\x09\x23\x1d\x6f\x8b\x1d\x19\x82\x47\xda\x70\xd8\x8a\xca\x25\x62\x55\x13\x50\xdb\x1c\x5f\xc9\xbd\x6d\x1a\x7b\x57\xbd\xaf\x49\x42\xe6\x54\x2a\x6c\xae\xc0\x82\x7d\xe1\xa3\x3b\x9d\xec\x0e\xcf\x1d\x04\x93\x9d\xf7\xe8\x12\xf3\x4e\x16\xda\x28\xf9\x3c\x12\xed\xb6\x29\x27\x7d\x5a\x53\xdd\x2b\x77\x57\x40\xac\xcd\xb9\x62\x5d\x25\x63\x9c\xa2\xb9\xed\xa6\x84\xe0\xe6\x16\xec\xef\x71\x1d\x2c\x53\xca\xf8\x71\x3d\x2e\xc7\x44\xbb\x0f\x7e\x9d\xd0\x73\xf0\xeb\xb8\xe7\x19\xf8\x75\x5c\x29\x4e\xc6\x93\xed\xc5\xd9\x1c\xde\x01\x53\x1b\x85\x24\xc9\x0f\x54\x8e\x4e\xa6\x7a\x47\x73\x7a\x03\x41\x28\xf2\xe2\xea\xf2\x87\x77\x2f\xf5\xf1\x82\xc0\xdc\xc5\xd9\x58\x55\xa6\xa5\xba\xe7\xca\x5f\x83\xf7\x4f\x01\xcb\x4d\x76\x77\x62\x26\x6b\xe9\x51\xf6\xe2\x49\x80\xcc\x89\xb3\x42\x2e\x47\x87\x92\xf7\x1b\x7b\x61\x31\x8c\xed\x2b\x3a\x56\x5d\xde\xb9\x56\xef\x36\xe9\xed\x43\x2d\x8f\xd7\x4f\xa6\x7b\x0d\x62\x92\xf3\x82\x09\x78\x3b\x7c\x55\x52\xc5\x6e\xb6\x67\xac\xc8\xc4\x56\x33\xc5\x65\x3d\x10\xf3\xd5\x15\x0b\x9a\xe7\xe5\x8a\x26\xa4\xac\x32\x00\xda\x4f\xf7\xfa\x71\xe6\x8c\xa5\xf5\x0d\xc1\x73\xa9\x28\x34\x57\xc4\xdf\xee\xa1\x1c\xa9\x38\xc4\xa8\x08\x0b\x1c\x5f\xef\x37\x9a\x6d\xba\xdf\xf7\xc3\xf1\xc5\x2a\x08\xf0\xb3\x21\xbe\x8e\x4f\xbb\x8c\x4c\xb0\x6c\x1e\x09\x90\x1a\x1f\xaa\x4c\x5f\xcf\x59\x2a\x7d\xf8\x01\xa3\xb1\x9b\x9d\x8e\x39\x29\x94\x14\x28\x85\xf4\xcc\x4e\xc8\xaa\xd2\x0a\x3f\x93\x8d\xdc\x83\x61\x2d\xd4\xb1\x51\xfa\xfd\x1a\xf3\xab\x35\x59\x42\x8b\x22\xe3\x0c\x42\x0b\xa2\x34\x29\xc8\x43\x6c\xf4\x16\x42\x61\xd1\x36\x48\x4f\x8d\xd7\x4b\x17\xe4\x8e\x95\xab\xf0\xd2\x0e\x53\x39\x69\xc1\x21\xdf\x29\x52\x3f\x6d\x36\x23\xbf\xbc\xc0\x77\x6d\xfe\xbd\xef\x36\xb3\x7f\x8c\x14\x75\xc0\x3f\x66\xdf\x6d\xd3\x60\xac\x18\x44\x17\x7d\xdd\xbf\xe9\xf4\xf2\x22\x92\xe6\x0d\x0e\x0e\x5a\x1f\xd5\x6e\x7a\x6d\xad\x53\xc4\xb2\xa9\xfb\x12\xd3\x1b\xfd\xbb\xb1\x66\x85\xc8\xdd\x34\x59\x5e\x6d\x18\x34\x55\xaa\x07\x4c\x78\x0e\xbf\x72\x7a\x79\x31\xa8\xb5\x9a\xf3\xfd\x67\x99\xb8\x8f\x55\x00\x87\xa6\x5a\x0f\x4a\xad\x1e\x78\x23\xe7\x22\xff\x60\x16\xe1\xd3\x87\xb7\x63\x58\xea\x7d\x93\x82\x69\xe1\xc2\x94\x5e\xee\x82\x96\x8a\xd3\xd8\xda\x86\xaa\xcc\x8c\x1f\x81\x22\xe6\xa0\x29\xb8\x5c\xd3\x3b\x56\x37\xcf\x59\x12\xf2\xbb\xd8\x7b\x5d\xf3\x91\xd9\x1a\x94\x57\xd0\xc2\x0d\x9b\x5f\x91\xeb\x2a\xcb\x4e\xc8\x35\xcf\xa9\xbe\x92\x58\xec\x96\xfb\x09\x56\x57\x3c\x4f\x98\x5e\xc3\x85\xe5\x24\x02\x6b\x60\xdc\x35\x91\x14\x9d\x78\x83\x4c\x53\x2e\x31\x80\x00\x8d\x6d\x61\xb8\x5a\x90\x25\xe0\xe4\xbe\x8e\x6e\x9e\xfb\x26\xab\xa4\x62\xe5\x07\xa1\xaf\x66\xaf\xda\x08\x5a\x00\x50\xff\xcf\x3f\xf0\x3c\xe5\xf9\x4d\xac\xfe\xf7\x01\x2e\xfb\x84\xe6\x84\x71\x08\x7a\xe8\xe1\x6d\xb5\xb8\xd6\x67\xa7\x3e\x50\x2f\x64\x15\x5d\x7b\x45\x25\x39\x2a\x44\x2a\x8f\xb4\xc8\x3f\xc2\x70\xa2\x3c\x7a\xa9\xff\x6f\x77\x6d\x23\x29\x42\xa9\x0d\x8e\x01\xa8\xbf\xa2\x05\x3f\x7a\x79\x42\x80\x09\x20\x81\x4f\xa8\xf5\xd7\x77\x5a\xed\x4a\x80\xdf\x6d\xc4\x59\xfd\xe0\xbf\x0f\x27\x35\x77\x19\x70\xfa\xae\x8d\xee\xb1\x97\x71\x09\x07\x1c\x23\x23\xb6\xb7\xc9\xde\xc5\x4b\xc8\x69\xac\xa7\x9e\x6d\x0a\x05\x71\x7a\xb2\x61\xd4\x24\x1b\x13\x76\xc7\xca\xad\x5a\x9b\x86\x02\x5f\xad\x90\x75\xa7\x62\xc2\x96\x19\xc1\x6a\x17\xde\x91\x8c\xbe\xac\xb9\x6c\xd9\x1e\x4b\xfd\x34\xcb\x86\xbb\x22\x29\xbc\x64\xaf\xfc\xaf\x6e\x57\x40\x37\x1b\xb1\x23\x9f\xf5\x7b\xcd\xdd\xc0\x8f\xf0\xea\xd2\xe2\x30\x76\xc0\x82\x9c\xbe\x7d\x6b\x32\x55\x70\x1d\x7f\xe2\x79\x8a\xb6\xd4\xa9\x52\x25\x5f\x55\x8a\x7d\x60\x7a\x4a\xc9\x90\xb2\x66\xa3\x95\x59\xa0\x09\xb3\xf5\x4b\x02\x03\x1d\xbd\xd7\xb7\x7a\x6c\x5f\xd3\x3e\xef\x9b\x75\x71\xe6\x58\x27\x69\x6b\xb9\xb6\x93\xe9\x79\xd9\x98\xbe\xef\x44\xda\x26\x04\x76\x50\x8e\xea\xaf\x1a\x25\x78\xeb\x79\x5b\x0d\x25\x63\xc2\x6d\x8b\x16\x09\xd0\xb7\xf8\x9d\x0b\xdd\x35\x86\xda\xdf\x06\xb7\x85\xf7\x97\x8f\xdb\x02\xa3\xb1\x84\x92\xeb\x8c\xb6\x6f\x85\x63\x34\x90\xe1\xa8\x80\xbf\xb9\xfa\x6c\x27\x24\x09\x6f\xd3\x92\x02\xf6\x58\x9f\x05\xb6\xe8\xed\x8b\xb5\xe8\x6a\x15\x16\x32\xc1\x1c\xd1\x2e\x0e\x0a\xa7\x77\xa9\x9e\xc0\x40\xd7\xea\x7f\x34\xbd\xbe\xa8\xc7\x01\xe0\x7e\x17\xd7\x96\x13\x3a\x39\x1a\xaa\xb7\xae\x45\x09\xeb\xed\xb3\x4d\xef\x0c\x5a\xd9\xf7\x96\x6d\xef\x45\x99\xb6\xac\xcd\x28\x5e\xeb\xf9\xa5\x8c\xae\x58\x16\x3a\x22\xef\x68\xa1\x17\xa0\xae\x10\x45\x89\x89\x59\x5c\xc6\x2e\xc5\xfa\x9d\x4a\xa2\x9f\x5f\x94\x37\x34\xe7\x7f\x6d\xdb\x79\x28\x4a\xd7\xa7\x5a\x94\xfc\xaf\x8c\xbc\xc0\x9c\x03\xf4\x66\x65\x2c\x51\x2f\x0d\x1f\xb6\x48\xbe\x5e\x36\xa5\x69\xca\x51\xb3\xba\xec\xe5\xad\xbe\xc5\xe0\xf9\xed\xbc\x6b\xde\x79\xa4\x42\xfc\xdf\x97\x1a\x16\x94\xc7\x55\xd9\x59\x5f\xd1\xf3\xee\x86\x72\xbc\xc5\xda\xba\x14\x3d\xc5\x1a\xb0\x0d\xe5\x63\x26\x82\xcf\xc8\x15\xdc\x50\x55\x95\x5c\xb5\x5c\x39\x7d\x2f\xf1\xfc\xa7\x6a\xc5\x4c\x0e\xd9\xa0\x57\x73\x28\xc2\x3a\xbd\xbc\x98\x6b\xd1\xf7\x1b\xe3\x9b\x61\x69\x55\x87\x54\x39\xdd\xac\xf8\x4d\x25\x2a\x99\x6d\x3d\xc7\x3d\xa1\xa0\x6e\x2c\x09\xb9\x68\x37\xa3\x53\xc1\x64\x7e\xac\x08\xcd\x45\xbe\xdd\x98\xd7\xf3\x24\xab\x52\xd6\xf8\x15\xc8\xf6\xb8\x13\x3c\x25\xb4\x52\x62\x43\x15\x4f\x48\x22\xf0\x6f\x61\xea\x95\x64\x84\x76\xd0\x4b\x2a\xa9\xc4\x86\x6c\x68\x29\xd7\x34\xcb\xda\xf7\x7d\xd2\x4d\xd6\xe5\x89\x5a\xc0\xda\xb4\xfe\xe1\x0e\x47\x39\x82\xbb\xe1\xc7\x46\x73\xb7\x1e\xd0\xe8\x97\xef\xba\xf8\x34\xf8\xbe\x01\xbf\x6d\x69\x78\xd1\xbb\xf0\xfd\x6b\xd1\x7d\x52\x03\x33\xe9\x94\x73\x3d\xef\x95\xac\xc8\x68\xab\x69\xd8\x83\x45\xa7\x6f\x74\x50\xeb\x45\xce\x1c\x85\x25\xb9\x42\x7f\xd9\x86\xaa\x64\xdd\x11\xba\xf9\xbf\x1b\xa6\x68\x4a\x15\x5d\x6a\x75\xf8\xff\x1a\x57\x93\xf1\x8c\x8a\x2c\xd5\xa4\xbb\x2e\xba\xd6\xf1\xe3\x25\x29\x5a\x76\xa0\x31\xfe\xb7\xfa\x5e\x77\x5f\x06\xb5\x04\x0a\x3e\x7d\x27\xec\xc0\x0b\xb6\x7f\x13\x61\x11\xce\xbf\x68\xed\xb3\x27\xb8\xd6\x18\xe3\xee\x2b\x4d\x1b\x2f\x6b\xce\xc0\x9c\xdc\x0d\xeb\x29\x08\xc0\xb2\xd6\xfa\x7b\xe0\x17\x3c\x7d\x7f\xd6\xe5\xc3\x08\x59\x4d\xbd\x56\x52\xd3\xcf\xdf\x33\x5c\xeb\xa1\x35\x7f\xe9\xad\xea\x76\xee\x7d\xd4\xad\x4e\x10\x5c\x06\x2b\xad\xc1\x77\xc4\x4a\x6a\x89\x98\x0d\x95\xb6\x60\xb6\x93\x68\xad\xab\x75\x2d\x5c\x44\x3c\x26\x14\x85\xe9\xc3\xc9\x58\xb8\x81\x77\x7c\x21\x26\x20\x13\xc0\xb2\x68\x6c\x07\x02\xf2\x20\x42\x11\xec\x0b\xd4\x13\x5b\xaf\x99\xdb\x0a\xe3\x9a\xe9\xb5\x51\xfb\xc3\x59\x51\xa6\xb1\x9d\x7c\xf4\xf0\xdd\x36\x37\xba\x86\xdf\xb2\xed\xb1\x34\x65\xdb\x22\x97\x6b\x5e\x84\x92\x94\x5c\x5c\xc0\xec\x3e\xf9\x4c\x33\x9e\x3a\xf2\x78\x3e\x2e\xf2\x13\xf2\x5e\x28\xfd\x9f\xf3\x2f\x5c\x06\x3c\x14\x9a\x97\xce\x04\x93\xef\x85\x82\x6f\x4f\x5e\x1c\x1c\x5a\xf4\xd2\x18\x9b\x03\x5d\xa9\x70\x72\x3d\xcb\xc4\x4e\xf3\x22\x5c\x06\xe1\x96\x98\x4b\x72\x91\x13\x51\xda\x35\x70\x20\x59\xd2\x90\xb7\x95\xc0\xb9\xc8\x17\xe0\x34\xed\xf7\xc8\x5c\x18\xd1\xee\xd1\xc7\x65\xd5\xbf\xe1\xaf\x9c\xff\x53\xfd\x4b\xde\x18\x06\x0e\x01\x41\x28\xf0\x2f\x5c\xda\x2b\x29\x25\x69\x05\x0b\x41\xad\xe7\x84\x27\xbd\xa4\x37\xac\xbc\x81\xd0\x4a\xd2\xeb\x9c\x8f\xf3\x2e\x45\xf8\x94\x02\x1c\x01\x17\xc2\xdb\x0e\x8b\x94\xb4\x5e\x1f\xf8\x6d\x14\xb1\x1b\x34\x53\xff\x53\x4b\x4c\x58\xd7\xff\x06\x2c\x39\xb9\x24\xa7\x44\xf2\xfc\xa6\x13\x2e\xdc\x7f\xc3\x84\x9b\x7c\xe2\x9a\x2e\x97\x44\x0b\xc0\x3b\x9a\x69\x89\x0e\x19\xcd\x81\x72\x7f\x71\xbd\x77\xc1\x9d\x18\x74\x37\x2d\x8d\x5c\xcc\xe9\xe8\x96\x6d\x8f\x4e\x1a\x4c\xd3\x41\x51\x7f\xf9\x22\x3f\xaa\x61\x0d\x1b\x7c\xea\xae\x0e\x08\x62\x1d\xc1\xdf\x8e\x96\x7b\x77\x62\x07\xed\xa8\x9b\xb2\xe7\x82\x88\xb5\xbe\x49\x3f\x17\x74\x6a\xa6\x8d\x9d\xff\xd9\xac\x93\x35\x11\x60\xf7\xef\x4b\x5a\x14\xac\x24\xb4\x14\x15\x38\x13\x36\x77\xac\x5c\xda\xaf\x40\x62\x43\x9b\x87\xd1\xfa\xc5\x12\x51\x96\x2c\x51\xd6\xbc\xd0\xa7\x48\x09\xf2\x7f\x4e\xdf\xbd\x85\xe5\xfe\xdf\x57\x3f\xbf\x1f\xa4\xa7\xdd\xb3\xd5\x5a\x88\x5b\xc0\x0f\x80\x95\x79\x10\xfb\xee\xcf\xf8\x2b\x67\xf5\x67\x56\x45\x97\x24\x65\x8a\xf2\x0c\x32\x3b\x7e\x7e\xfb\xce\xe4\x7e\xd8\x6b\xbc\x75\x6b\xcc\x98\xdb\x78\x64\x92\x5d\x45\x53\x93\xe9\xf4\x81\xdd\x71\x76\x6f\xf6\xa4\xed\x67\x16\xe4\x86\xe5\x90\x2c\xd0\x91\x14\xb4\x20\x92\xa7\xec\x1c\x80\x6d\xda\x09\x8c\x74\x38\x76\x8c\xb1\x9f\x87\xfb\x44\x62\x40\x1c\x06\x2f\x47\x1b\x53\x28\x2f\x45\xd9\x09\xce\x1c\x83\x51\x13\xc6\x9f\x49\x5d\x52\x5a\x9f\xcf\x3e\x38\xe2\x6b\xca\xb3\xaa\x34\xf9\x98\xa3\xa9\xf8\x0c\x30\x9a\x08\x48\xde\xfe\x81\xec\x78\x38\xdd\xf7\xc1\x05\xec\x8a\xa9\x40\xce\x5a\x0f\x30\x1a\x7a\x98\x94\x35\x76\x64\x78\x84\xae\x3a\xad\xb8\x96\xc1\xed\x19\x17\x68\x27\xc1\x67\xbf\x56\xac\xdc\x42\x49\x8d\xd3\xf6\x3a\x59\xce\x4b\x17\xfa\x58\x83\xe2\xda\x79\x99\xcb\x0e\x71\x13\x9b\xf7\x56\xb7\x65\xe1\x6e\x0d\x72\x9a\x9b\x90\xf2\xce\x58\x81\x16\x83\x60\xb2\x73\xec\x92\xd3\x4e\x8a\x79\x95\x65\x5d\x24\x72\xd1\xed\x1a\xf6\x57\xbf\xd7\x8e\x89\x31\x35\xe2\x6c\x59\x7c\x46\x5b\xb4\xbd\x8a\x52\xc3\xda\x1d\x6c\xd7\xfa\x8b\x31\x83\xd6\x36\xd2\xd2\xed\xa5\xb9\x9b\xce\x36\xc0\xde\x0d\xd2\x65\x0e\xfc\xb6\xdf\xea\xf5\x97\x29\x22\x17\x31\x2e\x0f\x31\x8c\x17\x19\xb4\x86\xf1\x89\x4f\x52\x8c\x42\x79\x1c\x61\x1f\x07\x69\x92\x11\x49\x9f\x51\xe9\x02\x31\x16\x73\xcb\xb4\x62\xed\xe6\x88\x89\x01\x94\xe9\x20\xeb\x39\x82\xa8\x31\x04\x87\xd8\xd0\x66\x34\xf1\x4b\x17\xb6\xa7\xf1\x19\x6c\x55\x47\xcc\xaf\xc5\xf6\xed\xb5\xad\x23\x48\xee\x5b\xdf\xbd\x16\x76\x04\xc5\x2e\x1b\xbc\xdb\xce\x8e\x39\x07\x11\x96\x78\xac\xb5\x8d\xcf\x90\x8c\x8e\xe8\x6c\x8e\x28\x3e\x0a\x5a\xe1\xf8\x8c\xb4\xc5\x7b\x47\x69\xed\xf4\xc1\x16\x79\xc0\x85\xe7\x59\xeb\xb1\x76\x79\x2f\xc5\x16\x9b\x3d\xd2\x3a\xef\x77\x4a\xf5\x5a\xee\x43\x6e\xfd\xe0\x75\x36\xc4\x5e\xf7\x09\xf7\xf0\x4e\xc9\x78\x7e\x27\xb0\x9f\xda\x00\xd5\xfb\xc3\xde\x6b\x3b\x1a\xf8\x3d\xdc\x4b\x46\x05\xef\x55\xbe\xf1\xf2\x77\x96\x1c\xd1\xc6\x2c\xa9\x64\xc8\xef\xdd\x37\xa7\xbe\x9a\x92\xc9\x36\x60\x73\x1d\xaa\x8c\xfd\x99\xab\xf5\xcf\xb6\x33\xa4\x39\x49\xaa\x2a\x32\x98\xba\xf7\x87\x7e\x2c\xb7\x0f\xb5\x9e\x7f\xa1\x50\x28\x25\x62\xb3\x61\x79\x8a\xc9\x19\x1b\x7a\xcb\x88\xac\x4a\x66\x32\xe8\xb2\x0c\xad\x1c\xfd\x43\x3d\x64\xd9\x97\x82\xe6\xa8\xd6\x6a\x4e\xbc\xd3\xb7\x61\x37\x27\x46\xf1\x61\x9c\x8e\x13\x59\x80\xd1\x5f\x78\xe1\x2a\x0d\x76\x4a\x27\x02\x52\x73\xc5\x32\x01\xae\xa0\x25\x39\xfe\xdd\xb1\xc9\x8a\x35\x84\xe0\x2a\x32\x9f\x1a\x7d\xe3\x24\x02\x60\x25\x63\xf9\x4d\x8d\x9a\x2a\x33\x9e\x30\x77\xeb\x88\x9c\x2d\xc9\x07\xa3\x68\xc6\xe8\xad\xe1\x0b\x22\xea\x72\x88\x54\x30\x6a\x9c\x9c\x81\x7b\x61\xdf\xf2\x77\xe3\xce\x7e\x36\x7d\x3f\x2c\xa9\xbf\xbf\x1d\x71\x7d\x64\x87\x6c\x48\x53\xc4\xd4\xb7\x98\xdb\x0d\x27\x42\x03\x83\x04\x01\x9b\xd0\x52\x5f\x73\xe0\x5e\x5c\x90\x37\x1f\xce\x4f\x3f\x9e\x9f\x90\x4f\x97\x67\xf0\x5f\x51\x92\xdf\x61\xd7\xc7\x2c\xf3\x7e\x26\xa4\x00\xb5\xef\x63\x70\xa7\x02\x54\x9f\xef\x3e\x46\xa6\xac\x37\xb6\xf1\x28\x94\xab\x5e\xa7\x22\x07\x06\xe9\xe7\xa8\xff\x5b\x4e\x7e\x14\x25\x61\x5f\xe8\xa6\xc8\xd8\x6b\x72\x5c\x88\x54\x1e\x9b\x2a\x01\xfd\xef\x25\x7e\xf4\x2a\x13\x37\x21\x84\x2c\x5b\x5a\xc0\x48\x26\x6e\x88\xac\x56\xae\xb4\x04\xae\x72\xa0\xf5\x3b\x4b\xbb\x91\xde\x1e\x32\xa7\x6c\x5d\x89\x47\xd3\x0d\xac\x41\xd1\xff\x42\xc8\xea\xac\xc7\xf4\x4a\x26\x34\x63\x0d\x3a\xfa\x83\xdd\x9f\xfb\xdd\xab\xdf\xc5\x2d\x41\x63\x6e\x56\x43\xe4\xe5\x0e\xbd\x7f\xcb\x35\xdf\xdf\xf3\x2c\x4d\x68\x19\x2a\x3b\xdf\x3d\x1a\x70\x1f\x63\x9a\x32\xd4\x1d\x60\xb3\x96\x1c\xee\xf9\xd8\x15\x30\x78\x32\xe2\x8e\x95\x19\x2d\x30\xd9\x98\xd1\xc4\x00\xd3\xc3\x00\xcf\x58\xc1\xa0\x80\x09\x9b\x13\x84\x38\x8b\xe5\x49\x26\x24\x7c\x1d\x54\x81\x93\xc6\x94\x0d\x8c\xbe\x69\xaa\x13\x59\x6f\xe2\x0e\x71\x3f\x88\xc4\x53\x9c\x62\xc8\x65\x1d\x70\x82\x31\xf7\xb5\xe9\x6c\xf6\x30\xb8\x5c\x1d\x01\x78\x1e\xa2\x0c\x7f\x50\xcd\x8e\x4c\xb9\xd9\xd1\x09\x39\x72\x90\x41\xa9\x31\x4d\x8e\x7e\x77\x54\x7f\x21\xf2\xfc\x52\x53\xc9\x97\xe0\x6b\x0b\x18\xa3\x5f\xce\x09\xcc\x06\x66\x55\xd0\x3b\xe7\x26\x55\x43\x97\x69\x6d\xc0\x78\x76\x61\xfc\xcd\x9f\x09\xf1\x83\x3f\xc5\xbd\x11\xd7\xb5\x7e\x3b\xa3\x0d\xcd\xdc\xe4\x74\xb9\xd1\xea\x65\xf3\x88\x2b\xc0\x2b\xc0\xba\x43\xb3\x65\xa5\x57\x37\x12\x1a\xf3\x55\xe3\x10\xd8\xfc\xb1\x06\xfe\x1a\x2f\x49\x41\x4b\x6d\xb1\xda\x6f\x86\x88\x7a\x3d\x8b\x8f\x7e\x17\x40\x6e\x09\x32\xb4\x17\x66\x1b\x1d\x85\x51\x7c\xc3\x44\xa5\xae\x58\x22\xf2\xb6\x64\x76\x9f\xcc\xd4\x18\x56\x74\xb6\xbf\x09\x99\x9e\x5a\x15\xc7\xa6\xfc\xfb\x81\x9e\xda\x84\xec\x09\x89\xe2\xd3\xc0\xe5\xf9\xf9\xed\xbb\xb1\x6b\x45\xa0\x4e\xba\x3b\xbb\xea\xb3\x11\xef\xf9\x8d\x1b\xb9\x99\x49\xe7\x2b\xef\x2a\x15\xff\x82\x99\x68\x1f\x36\x48\xc7\x1c\xa4\xa2\xaa\xda\xd9\xdd\xc6\x8a\x1b\x61\x73\x85\xd5\x41\xc6\x14\xb8\x82\xb7\x7c\x4f\xad\x8f\x95\x00\xda\xe4\xce\x30\xb0\x89\x01\xbc\x05\x49\x99\x85\x48\x97\xc4\x90\xd9\xd0\x2d\x51\x25\xe5\x68\xc9\xd2\x44\x55\x50\x64\x4c\x95\x49\xe0\x34\x38\x47\xdf\xec\x4f\xa7\xc5\x42\xed\xb6\x4a\x13\x56\x2a\xf9\x96\x4a\xf5\xa9\x48\x69\x6b\x71\xca\x4e\x12\xa6\x54\x70\x08\x50\xc7\xbe\xcf\x59\xaa\x65\x9d\x59\x08\xa4\x46\xee\xb5\x20\xa9\x90\xde\x1e\xb9\x5e\xb6\xb1\x87\x42\xbf\xba\xd0\x3f\xd3\x36\xda\x0f\x42\xaf\xc2\x69\x4b\x04\xb9\x99\xef\x1a\x1a\xa5\x16\xf0\x25\xd0\x22\x39\xfb\xb2\x6f\xd2\x4f\x1b\xa9\xc8\xd3\xae\x24\x89\xe6\x8a\x1a\x15\xb7\x7e\xe1\x84\x50\xb2\xe6\x52\x89\xd2\xf8\xac\xa1\x53\x70\x49\x73\xc9\xdb\x2b\xf8\xa6\x27\x5d\xbc\x71\x3f\xae\x15\x67\x46\x5d\xb7\x4a\xc3\x9d\xd0\xcc\xb1\x64\x89\x28\x53\x37\xa4\x76\x99\x55\x0f\xd3\x68\x53\xed\x67\xa5\xe5\xe5\x89\xa5\x15\x19\x95\xea\xa3\xfb\x75\xbd\xf9\x51\xb2\xb3\xc9\xd0\x66\xba\xf5\x2c\x6c\xbd\xbb\xc8\xed\x1f\xbb\xdd\x43\x82\xd0\x1c\xb5\xca\xf1\x12\x33\xc4\x56\xf5\x5c\xf1\xbc\x8e\x98\xe7\xbd\x3b\x9b\xde\x94\x1f\x7a\xc4\x1b\x26\x25\xbd\x89\x1b\xea\x29\x02\xf3\x12\x07\xcc\x6b\x5e\x26\x3c\x4f\x79\x02\xf2\xdf\x65\x02\xb5\x49\xd5\xfa\xb9\x5f\x6f\xbb\x59\x50\xdf\x90\xb6\xb6\xd5\x1d\xbe\xd1\x5b\x57\xac\xa9\x8c\x9b\x9e\x3b\x6b\xd6\xe6\x8f\x3d\x20\x51\xe3\x28\x19\x95\xdd\x75\x10\x3b\xeb\xbc\x2a\x39\xbb\x26\x6f\xe8\x86\x65\x6f\xa8\x7c\x8c\x85\x06\xc9\xb1\x24\x6c\x79\xb3\x24\xc7\x1f\xbc\x50\xc0\x7b\xa1\xde\x75\x77\x3b\xe9\x2d\xf7\x0b\x9f\xfb\x69\x27\xbe\x3d\x27\xb9\xf3\xac\x4f\xba\x36\x42\x27\x7b\xd2\x99\x9e\x34\xb2\xce\x13\x3c\xed\xec\x6a\xd6\x69\xbb\x0c\x26\x9e\xda\xbe\x82\x9f\xf6\x93\xda\x3c\xa3\x55\x09\x76\x4a\x32\xee\xac\xf6\x16\xeb\xb4\x9f\xcf\x89\x27\x73\xca\x32\x0e\x3e\x93\xbd\xd3\x73\xaf\x5f\xb5\x28\xd1\x7b\x33\xfd\xd8\xd0\x80\xc1\x31\xe3\x67\xdf\x00\x8a\xb3\x1e\xe3\x9b\xab\xcf\xf3\xa8\x3d\x8f\x5d\x4d\x67\x36\xae\xf5\x6f\x79\x67\x42\x68\xd7\x9d\x3c\xa5\x3a\x2f\x05\x37\x97\xde\xd7\xc7\x89\xfe\x9d\xd9\xdf\x33\x06\x8d\x31\x48\xcd\x6e\x83\xff\xbc\x1e\x53\xaf\x1f\xb9\xe6\x87\x17\x4a\x90\xa2\x64\x77\x90\x99\x95\x43\x1e\xb2\x56\xde\xa5\x3e\x10\x2f\xbb\x35\xb3\x98\xc0\x5d\x38\x17\xaa\x7b\xff\xed\xdf\x3b\xb8\xc0\xfe\x39\xa0\x40\xf6\x6d\x2e\x3e\x71\xc1\xc5\xde\x32\x4c\x7c\x22\x9d\x7f\x7d\x25\x99\x83\x08\x05\xd4\xbf\x41\xb4\xda\x8c\xf3\xdd\x67\x07\xa8\x52\xbf\xf0\x01\x04\x2f\x86\x15\x12\x2d\x57\x13\x2a\xc1\x85\x06\x1f\xa3\xa0\x09\xb9\x7e\x7d\x5b\xfd\xc3\xae\xa4\x83\x6a\x98\x26\xcf\xcf\x31\xdd\xaa\xe2\xf3\xec\x41\xa0\x44\x36\x92\xd6\x13\xd6\xf8\x06\x98\xe8\xa1\xca\xe7\xf1\xe9\xe7\xba\xb1\xfc\x16\x12\x09\x53\x39\x2d\x8c\xab\xd0\xc3\x5d\xb3\x17\x5d\x4b\x56\xde\xb1\xf4\x35\x51\xa5\x69\xd7\x6c\xe0\x8e\xfd\x4f\x3c\x2f\xb2\xa5\x6b\x96\x9e\xfc\xe7\x7f\x7f\x53\xef\x02\x4d\x12\x56\x28\x96\x7a\x38\x66\xc0\x5c\xe4\x08\x23\x00\x45\x56\x95\x34\x33\xff\xeb\x39\x63\xc8\x2f\x7f\xf9\x06\x7f\x98\xa5\x2e\xf0\xaf\x3f\xfc\x66\xb1\x58\x7c\x53\x67\x03\xbc\x26\xb4\xe0\xec\x8b\x62\x98\x1f\xb2\xbc\xfd\x23\xb4\x08\xba\xfb\xee\x1b\xfc\x99\x37\x50\xba\x6f\xc3\x95\x67\xae\x26\xe6\x1b\x5b\x1d\x0d\x83\xcc\x73\xa1\xfc\x58\x76\x22\x72\x55\x8a\x2c\x63\xe5\xe2\x86\xe5\xcb\xdb\x6a\xc5\x56\x15\xcf\x52\x56\x02\x71\xfb\xd3\x77\xdf\x2e\xff\x61\xf9\xad\x1e\x78\xc9\xa8\x35\x6b\xa4\xa2\x9b\xe2\x35\xa4\x93\x7f\x63\x98\xd9\x62\xb2\x14\x19\xcd\xe5\xd2\xa5\x71\x2e\x13\x51\x32\xa1\xff\xb3\xf9\x46\x16\x2c\xd1\xbf\x8d\xe7\x96\xb4\x7e\xc7\xe0\x07\x9a\x21\x1a\x20\x13\xfb\xff\x0b\x22\xb2\x8d\xb7\xbe\x06\x5a\xe6\x32\x33\x18\x35\x19\x97\xea\xa7\xdd\xbf\xbc\xb5\x9d\x1b\xec\x36\xf8\x03\xc5\x8d\x5e\x8b\x52\x79\x9b\xb7\x20\x26\x89\x55\xf2\xfc\xa6\xca\x68\xd9\x78\xe7\x1b\x1b\x88\xaa\x43\x2c\xfa\xa2\xbd\xf3\x32\x37\x16\x8d\x04\x30\x9e\x2b\x56\xbe\x11\x59\xb5\xc9\xdd\x0f\xec\x29\x9e\xd7\xbc\x94\xca\x60\xdb\x60\x48\xd7\xfa\xe2\xda\x54\xe6\xf7\x5e\xab\xa7\xff\x90\x22\x07\xbf\x32\x59\xea\x05\x5e\x76\xbf\xf0\xcb\xb7\x7f\x31\xef\xe0\x8e\xd5\x8a\xec\xde\xf1\x68\x19\x21\x2d\x8a\x52\xdc\xd1\xcc\xef\x1f\xbd\xfb\xdb\xf6\x3b\x8d\x9f\x39\x6d\x7e\xd8\xf2\x5b\xed\x64\x9c\xc3\xd6\x27\xe3\x3e\xdc\x47\x28\xc2\xaf\xdd\x7d\x47\xb3\x62\x4d\xbf\xc3\x0d\x4c\xd6\x6c\x43\xed\xe1\x15\x05\xcb\x4f\x2f\x2f\x3e\xff\xc3\x55\xe3\xe3\x76\xbc\x22\xcd\x3a\xa6\x3f\xad\xf4\xf1\x9e\xa9\x35\xc1\x5c\x02\x73\xcd\xc7\xdf\x34\xc5\xcd\x8e\x96\xb7\xaf\xd5\x69\x95\x1c\x4f\xa8\xf7\x91\x5e\x01\xf7\xbf\xed\x5a\x96\x27\x1a\x1a\xf2\xae\xd9\xb3\xac\x4e\x0c\x6a\xcc\xc3\x30\x2a\x4b\xcd\xea\xd4\xc1\x50\x1b\x2c\x68\x83\x55\xd2\x13\xce\xcd\x8c\x96\x44\x33\x17\x2b\xa5\x85\x34\x4d\x44\x7e\xc7\x4a\x05\x5e\xd9\x9b\x9c\xff\xd5\xd1\x86\xf2\x38\xcc\x83\x57\x6c\x0f\xdd\x16\x0e\x46\x4e\x33\x0c\xae\x9e\x98\xe2\x98\x2d\x29\x99\xfe\x15\x52\xe5\x1e\x3d\x9b\x25\xde\xd2\x38\xed\x86\x2b\x2b\x12\x13\xb1\xd9\x54\x39\x57\xdb\x57\x20\xdd\xf8\xaa\xd2\xfb\xf2\x2a\x65\x77\x2c\x7b\x25\xf9\xcd\x82\x96\xc9\x9a\x2b\x96\xa8\xaa\x64\xaf\x68\xc1\x17\x30\xf4\x1c\xa3\x8a\x9b\xf4\x37\x4e\xe0\x37\x2d\xcd\x8e\xeb\x67\x5f\x85\x68\xee\x00\x60\xc2\x60\xd5\x86\x97\xec\xdd\x44\x11\x03\xb8\xbc\xf3\xab\x8f\x2e\x0e\x09\x9b\xb1\xbb\xfa\xb0\xee\x5e\x38\xa7\xde\x02\xbd\x60\xd0\x03\xc2\x80\xad\x96\x62\x63\x70\x81\xd3\x42\xf0\x1c\x6b\x0e\x92\x8c\xef\x1b\x36\xb2\x5a\x6d\xb8\x92\x16\x84\x18\xf3\x53\xde\xc0\x3d\x01\x60\x53\xe8\xc4\x59\x92\x8b\xbc\x36\xfe\x1f\x7c\x03\x00\x03\x6e\x01\xd8\x7c\x51\x5b\xe0\x5f\x71\xbb\x5f\xde\xb3\xb2\xec\x05\xd4\xb1\x5f\xde\xc9\xbf\x2a\x58\xe2\x4e\x8d\x3b\xe9\xa7\x88\x5d\x6b\xa0\x9b\x5d\x1a\xd0\xae\x4b\x6e\xe5\x84\xc5\x4e\xcc\xa9\xd3\xf8\x6b\x37\xf8\x16\x64\x47\x9e\x36\x3f\xde\x21\xbe\x08\x5f\x15\xf8\x74\x5b\x6e\xf6\xe7\x42\x2e\x21\x7b\x13\x18\x33\x1a\xd0\x8d\xdd\xf5\x60\x50\xd5\xc1\xa8\xce\xfd\x35\x1d\xe4\x19\xb3\x53\xec\x2a\xeb\x6d\x87\xa6\xeb\x5e\x81\x99\xca\x83\x7b\x46\x6c\x2a\x2b\x7b\x10\xaa\xda\x83\xf0\xc8\x46\x5d\xef\xb4\xa3\xd4\xd4\xb0\xb7\xed\xed\xee\xc6\xc6\x92\x8f\xfc\x23\xb0\x17\x42\xc6\x5b\x70\x27\x8c\xdc\x6d\x3a\x40\x70\x8e\x15\xd2\x71\xb7\xbe\x0c\x12\xb1\x29\x32\xa6\x9a\xd7\x29\xa4\x3e\xb5\xc5\x9a\x77\x99\xa2\x2b\xf2\x7c\x34\xed\x98\x25\x54\xd1\x4c\xdc\x5c\xb5\x64\x71\x2d\xd0\x47\x1b\x7b\x80\x94\x62\x79\xa5\xc5\xe6\x55\x03\xac\xb3\xb5\xcf\x6d\xf3\x4c\x75\xbf\x59\x03\x5e\x1b\xaf\x55\xb3\x2d\x45\x1b\x97\x42\xdb\x10\xe9\xf0\x02\x53\x93\x44\x93\x7a\xf5\x14\xb8\xfc\xb3\x82\x14\x75\xa9\x25\xed\x13\xae\x73\x94\xad\x43\xdb\xb5\x47\x6d\x7d\x3b\x60\x02\x42\x65\x49\x77\x7e\x45\xf3\x62\xbe\x30\x8b\x5a\x1a\x20\x02\x4a\x0a\xce\x30\x6f\xd2\x69\x39\xb0\x44\x8c\xa6\xdd\x35\xbf\x34\x27\xfa\xe6\x2a\x99\xcb\xbe\x33\x3e\x6c\x20\x5b\xeb\x46\xd0\x4a\x82\x62\x0a\x21\x40\x1d\xbc\xfa\x53\x17\xb2\x0c\xd6\xc7\x18\x74\x78\xe0\xf3\x0d\xa4\x20\x5a\xe8\xef\x94\x49\xcd\xc0\x57\xe0\x26\xdf\xd0\x9c\x5f\x33\xa9\x96\xae\x98\x5d\xfe\xf2\xfb\xbf\x74\x85\x0d\xbd\xb4\xd3\x13\x8b\x5d\xea\xf4\x0a\xc3\x60\x20\xd1\xf5\x72\x38\x8a\xfd\x0d\x2a\x21\x4d\xc4\x4c\xfb\x1e\xa6\xab\xe8\x2d\x23\xc2\x4c\xb7\xd2\x66\xcc\x2d\x7b\x4d\x8e\xd0\x32\x71\xc3\xfc\x4f\xad\xab\xff\x77\x57\x7e\xdc\x8b\x7b\x48\xff\x3a\xd2\x5f\x3a\xc2\xc1\x39\x45\xd2\xef\xf0\x50\x0f\x12\x93\xc6\x4a\x7e\x73\xc3\xba\xd0\x17\x30\x00\x01\xee\x5a\x80\x62\xe7\xd0\x2f\xb3\x26\x91\x9b\x16\xae\x75\xfb\xcb\xdd\x41\xff\xf2\xfb\xbf\x74\x8e\xb8\xb9\x5e\x84\xe7\x29\xfb\x42\x7e\xef\xc2\x1a\x85\x48\x5f\x1a\x54\x19\xb9\xcd\x15\xfd\xa2\x7f\x29\x59\x0b\xc9\xba\x56\x16\xd2\xeb\x94\xc0\x6e\x01\x52\x40\x5c\x2d\xcb\x16\xa8\x92\xa4\xe4\x1e\x6b\x08\xed\xc6\x61\x2d\x5c\x41\xcb\x9e\x0a\x75\x4f\x7d\xc7\x4e\xbf\x30\x32\xcd\x50\x37\xe0\x1a\xd2\x6a\x1f\xb6\x0f\xc0\x04\x5a\x0f\xb9\xbf\x83\xa2\xac\x90\x7d\xb4\x58\x5f\xd3\x1c\x42\x42\xa6\x17\x81\x56\xef\x96\xed\x11\xd4\xc0\x39\xee\x76\xcb\xb5\xe8\xd6\xbb\x82\xe3\xc9\xb4\xd3\xc8\xc9\x75\xbb\xfd\x3a\xdb\x4d\x3f\x46\xd3\xe8\xd1\x73\xe9\xe9\xb6\xbb\x3f\x21\xcc\x46\x7d\x84\x59\x41\x0b\xcf\x57\xa3\x26\x65\xb5\xfa\xf8\x7b\xec\xf8\x0a\x05\x46\xb2\xfb\xae\x3e\x16\xd8\xf0\xc7\x58\xd7\x46\xc6\x76\x1c\x26\xae\x55\x9f\x14\x45\x33\xcd\xb7\x0f\xce\xca\x7a\x41\x21\xb2\x9c\x6c\x17\xc6\x15\xb8\xa0\x79\xaa\xff\x2d\xb9\x54\xfa\xf3\x51\x2b\xd8\xe9\xc4\x6d\xae\xda\xa7\x8b\xb3\xc7\x61\xf0\x8a\x8f\x38\xab\xab\x2a\x4f\x33\xf6\x56\x88\xdb\xd6\xba\xb8\xc6\x54\x7e\xf0\xbf\xeb\x22\x8b\x68\x30\xf2\x7c\x51\x94\xe2\xa6\xd4\xb7\xb9\x67\x66\x93\xa2\x6a\x4d\x91\xa6\x00\x21\x5b\xd0\xe4\x96\xde\x30\x33\x08\xb8\xa2\x0c\x2a\x16\x9a\xf2\x60\xe2\x74\x29\x6e\x53\x32\xef\xfc\x99\xa0\xdb\xc2\x8c\xd9\x0e\x79\x67\x80\x5d\x41\x2a\x3b\x62\xd0\xd0\xcd\x2c\x42\xa3\x9f\x18\x0d\x6f\x68\xf0\x1f\x58\xdb\x1d\xb8\xa8\xf1\x78\xdb\xf2\xa0\x17\xd0\x65\xa5\xf5\x0f\x16\x92\xb4\xe5\x8f\xa1\x28\xe8\xee\xb8\xe2\xb2\xb2\x76\x5e\xb2\x7b\x61\x95\x34\xb3\x96\x8d\xaf\x75\xd0\x45\xad\xc7\xec\x01\x34\xf9\xb9\xa7\x12\x24\x55\x76\x67\xb2\x8b\x1e\x18\xed\x25\x64\x14\xb4\xcc\x7f\xb0\x69\xe0\x0f\x38\x10\x7b\x0c\x98\x09\x2d\xa3\x19\x64\x2c\xf4\x10\xb5\x3e\xd4\xc1\x26\x43\x2f\x4d\x63\x4e\x3c\xa4\xe1\x80\xcf\x38\xf3\xa1\x97\xa4\x69\x8c\xfd\x30\x46\x04\x3e\xe3\x4c\x89\x5e\x92\xce\xcc\x18\x6a\x50\xf4\x52\x6d\x33\x36\xe2\xcc\x8a\x5e\xb2\xad\x26\x47\x84\x71\x11\xe2\xe3\x56\xc3\xa3\xd7\xc4\xe8\xa5\xd8\x6f\x7e\x74\x1a\x1a\xbd\x34\x7b\x8d\x10\x7c\xa2\x24\x46\x28\xf1\xe4\x6b\x30\x4b\x06\x4c\xb7\x2f\x33\x61\x7f\xba\xcf\xc2\x50\x19\x38\xbb\x1e\xa3\xa5\x6b\x8a\xcf\xc2\x74\x19\x30\xcd\x28\x33\xa6\x6d\xb2\x33\x19\x33\xf8\x7c\x35\x26\xcd\x80\x95\x0d\x64\x40\x3d\x3b\x23\x27\x72\x6a\x7d\x25\x42\x2d\x33\xf3\x6a\x74\x76\xe2\x03\x7a\xb8\xd8\x15\xd9\xf9\xe8\x7d\xb3\xa2\x5f\xd9\x9c\x0c\xf8\x39\x43\x5e\x65\x30\x31\xb2\x03\x01\x15\x9f\xb8\xac\xc8\xf8\xfa\x20\x7c\x7a\x6a\x06\xea\xac\xf0\xbd\xb2\x81\x5e\x92\xa4\x59\x54\x10\x2a\x17\xc2\x27\x1a\x28\x2d\xae\x10\xa7\x5e\x8c\x70\x01\xd1\x80\x85\xd0\x16\x4e\x51\x8a\x55\x1c\x10\xc5\xcc\xb3\x89\xca\x2e\x1d\x5b\xa6\x10\xd8\xd1\x3a\x1e\x57\xf3\xc2\x2c\x4b\xd0\x5f\xc8\xd3\x32\x27\x04\xd7\x6a\x64\x17\xba\xfd\x39\x96\xb0\xe5\x73\x8f\x71\x64\x2a\xae\x67\x00\xe0\xf0\x4e\x6c\x73\xe5\x8f\x65\xc5\x4e\xc8\x8f\x34\x93\x2c\x04\x97\xf1\x29\xbf\xcd\xc5\xfd\x3c\xf3\xe8\xab\xb4\x6e\x99\xc5\x47\x53\x53\x1d\xac\x1a\x8b\x1c\x44\xed\x23\x89\xba\x08\x2e\xdc\xd7\xad\xe7\xcb\x78\x3c\x16\x55\xce\x7f\xad\x9a\x46\x56\x10\x98\xf3\xc5\xae\x59\xf6\xe6\xea\x33\x30\x10\x3a\x30\x64\x03\xd5\x54\xff\x51\x76\x25\xda\x87\x6b\xe4\x7a\x5c\x00\xcd\xa6\xf3\x54\xad\x77\x0c\xc7\xcc\xe0\xa9\xed\x3a\xb8\x8a\xaa\x2d\xa0\x6a\x9f\x0b\x75\x2c\xf5\xb8\x78\x42\xb3\x6c\xab\x6d\x25\xbe\xd1\xc7\xdc\xe9\x52\xe3\x61\xd4\x3a\x9b\xee\xb4\xcc\xe7\x83\xf9\x72\x5b\xcb\xf4\x7a\x2a\x86\x24\x98\x9d\xbd\xae\x25\x7d\x58\xae\x01\x12\x9e\x2a\x58\xab\x11\xb3\x68\x86\xdf\x1f\x3e\x53\xa3\x4f\xd9\x99\xee\x45\xf5\x52\x28\xea\xf2\xca\x1e\x2d\xa9\x43\xd9\xb0\xed\xdd\xbf\xb0\xa4\x72\xcc\x16\xc8\xa7\x79\xc4\xc2\xe5\x47\xae\x1f\x7e\xac\xe2\xdf\x39\x6b\x5a\xdd\xee\x4f\x2b\xf7\xd8\xad\xb9\x1f\x2d\x26\xfa\x6f\xc8\x30\xdc\x48\x2c\x04\x48\xdb\x01\x80\x6b\x0a\xbf\xb5\x62\x75\xf1\x15\xeb\x03\x54\x6f\x72\x3b\x81\x46\xfa\x09\x2b\x41\xf6\x63\x6a\x23\x40\x01\xdc\xaf\x45\x36\x46\x76\xc6\xd4\x5e\x7a\xbf\x7f\xa9\xbf\xee\x2e\x39\x53\x93\xe9\x17\xe1\xec\x26\xa3\xef\x4c\xa6\x67\xa8\x7d\x83\xcc\x68\x67\x3a\xd9\x14\x21\x75\xa5\x58\xb1\x2b\x94\xbc\xc9\xe4\xa0\x7c\xde\xf1\x14\xd3\xad\x58\x41\x3a\x52\x40\x26\x4b\xa4\xfe\xb0\x0e\x06\x2a\xda\x39\x72\xe1\x7c\x14\xad\x7f\xec\x14\xad\x21\x19\xe8\x7e\x73\x82\x8c\xe8\xca\xe9\xc3\x67\x6f\x27\x6c\xe9\x46\xcf\x8e\xf4\x4d\xd6\x0c\x4b\x90\x15\xc8\x89\xe4\x16\xe1\x72\xc2\x7b\x43\xe2\x0c\xe7\x70\x73\xb2\xbe\x62\xc4\xde\x52\xc4\xce\xc2\x53\xfc\x63\x9d\xe8\x18\xf1\x15\x70\x9e\x75\x7e\xaf\xbf\x9e\x31\xc6\x6e\x0f\xd6\x32\xce\xe2\x4e\x8e\x04\x91\xc6\x00\xce\x64\x42\x21\x6f\x6f\x14\x91\x7a\x0b\x66\x24\x15\xf4\xd2\x46\xd1\x8b\x28\x34\x9c\xb7\xdc\x8e\x15\xcd\x12\xe3\xb6\x9b\xa2\xa0\xa5\xe2\x49\x95\xd1\x6e\x4b\xc8\x15\x03\x80\x28\x0e\xdc\x2d\xad\xb3\x38\x14\xb8\xcd\x5d\xe0\x66\xcd\x57\x03\x4f\xfc\x38\x25\x6e\xb6\x19\xd7\x9f\x9c\x84\xad\x8b\xdc\x1a\x7f\xdb\x2b\x73\x6b\x0e\x17\x37\x7c\xaf\xd0\x4d\x18\x66\x71\x85\x6e\x8d\xb7\xa2\x4a\xdd\x6c\xd9\x15\x12\x1a\x51\x70\xd5\x98\x86\xab\x29\xc8\x39\x82\xc9\x57\x99\xe2\x8a\xe5\x34\x37\x35\x05\x3f\xbf\x7d\xa7\xc5\x1f\xbd\xf1\xb2\x99\x1b\x80\x80\x17\xe0\x21\x90\xaa\x84\xce\x27\x6d\x95\x5b\x75\x8f\x09\x9e\x13\xae\x64\x1d\x15\x32\x8d\x29\x5a\x22\xb6\x26\xa1\x47\xd1\xf2\x86\xa9\xfa\x85\x59\x6a\xbe\x0e\x45\x5e\x87\x22\xaf\x43\x91\x57\xcf\x16\xcc\x59\xe4\xd5\x90\x36\x50\xe6\x65\x53\xf6\xf4\xbf\x4d\xd5\x52\x53\x24\xb5\x23\x84\x8e\x00\x38\x8c\xec\x2e\x6d\xdb\x97\x99\xef\xe3\xf0\x1a\x43\x3a\x96\x7d\x92\x28\x38\xc2\xfe\x51\x92\x43\xbf\xe9\x43\xbf\xe9\x43\xbf\xe9\xae\x2f\x1d\xfa\x4d\x1f\xfa\x4d\x1f\xfa\x4d\x93\x30\x47\x1c\xfa\x4d\xff\xbd\xf7\x9b\x96\x8d\x52\xd6\x76\x07\xd1\x8e\xe6\xb3\xfb\x82\x15\xfc\x34\xdd\xf0\xdc\x2b\xce\x0b\x17\xc1\x62\xba\x1a\x20\x2b\xaf\x58\x5d\x0a\x0b\xcd\x78\xdd\xde\xbc\x90\x2f\x5d\x36\xad\x3b\xe4\x60\xfb\x0e\x72\xd3\x4b\x6d\x4e\x25\x97\xd8\x1b\x3a\x3d\xbd\xbc\x08\x15\x8d\x5c\xc1\x0b\x44\xb1\x2c\x93\x60\xd2\x6a\x7d\x5c\x09\xa3\x8f\xb7\x2a\x7c\x85\x47\xbd\x65\xba\xb5\xfb\xa3\x63\xe0\xed\x15\xf3\xa8\x46\x3a\xf3\x3e\x88\x91\xb8\xf3\x75\x23\xba\xd9\x97\x22\xe3\x09\x57\xf6\x86\xaa\xb5\xd2\xf6\x4b\x0d\x7f\x15\x44\x3b\x07\x8d\x4a\x32\x75\x52\xeb\xbd\x5c\x12\x7e\x93\x8b\xd6\x56\x32\x73\x07\x83\x09\xf9\xb2\xa8\xf3\xef\x16\x5a\x5f\x5d\x98\xaf\xb3\x86\x59\x11\xaa\x9d\x6f\x1a\x16\x9d\x38\x83\x3b\xc6\xc5\x87\x61\xb6\x45\x57\x05\x7b\x1d\x45\x4d\x23\x6d\x91\x6c\x10\xce\xba\xf9\xa6\xe9\x99\x66\x1d\x64\x36\x48\x9d\x35\x32\xb1\x76\x18\xb7\x65\x3b\xcc\x7a\xdc\x53\x49\x0c\xe1\x99\xa1\x6b\xf3\x58\x7e\x6e\x72\xb2\x57\xb9\xb5\x67\x5e\xb9\x44\xa6\xc6\xf4\x9e\x0f\x7f\x92\x3d\x79\x1b\x06\x1d\x18\x0a\x35\xd0\x7d\x65\x38\xc1\x7c\x00\x14\x38\x00\x0a\x1c\x00\x05\x0e\x80\x02\x07\x40\x81\x03\xa0\xc0\x88\xb9\x1c\x00\x05\x0e\x80\x02\x3b\xcf\x57\x0c\x28\x30\x3d\x06\xef\x07\x58\x01\xd7\x12\xdb\x73\x1d\xc2\xac\x87\x30\x6b\x93\xe6\x21\xcc\x7a\x08\xb3\x1e\xc2\xac\x66\x68\x87\x30\xeb\x21\xcc\x7a\x08\xb3\x92\x43\x98\xf5\x10\x66\x3d\x84\x59\x0f\x61\xd6\x43\x98\xf5\x10\x66\x3d\x84\x59\x0f\x61\xd6\xa7\x0a\xb3\x1e\x42\xa7\x87\xd0\xe9\x53\x84\x4e\x0f\xe1\xd0\x43\x38\xb4\x6d\x16\x87\x70\xe8\x21\x1c\x7a\x08\x87\xee\x3d\x87\x70\xe8\x21\x1c\x7a\x08\x87\x1e\xc2\xa1\x4f\x10\x0e\xbd\xa6\x99\x3c\xd4\x24\x8f\xa8\x49\x96\xd5\xca\xed\xfa\x63\x95\x24\x5f\x79\xbf\x09\x1f\xd7\x15\xc9\xfe\x9f\xf6\x0a\x92\x1b\x63\xc5\xcd\xde\xab\x47\x96\xd5\xaa\xfe\x97\xf9\x92\xab\x4d\x96\xcd\x1f\x7e\x80\x2e\x9c\x16\xd9\xde\xfc\xd2\x0a\x9c\x19\x86\x0b\x77\x9b\x54\x7a\xc0\x15\xb8\x17\x97\xf8\xf2\x37\x1d\xdc\xdf\xf2\x73\x06\xf8\xca\xa0\x1e\xd4\x8d\x78\x9d\x8a\x54\x34\x48\xee\x8e\xa0\x01\x08\x82\x63\x68\x80\xc1\x47\x0d\x61\x4d\xf3\x9c\x65\x5a\x56\xa0\x53\x04\x34\x41\x37\xff\xee\xe9\x9b\x17\x1b\xbf\xfe\xa6\xf1\xd9\xde\xcf\xcf\xd4\xa0\xd3\x67\x32\x72\xcb\x58\x21\x3d\xe7\x7c\x55\x80\xfb\x89\x2a\x46\x56\x5b\x44\x43\xd1\xca\x1b\xea\x4f\x3b\x6e\x12\x03\xa0\x7f\xe8\xdb\x79\xc8\x35\x38\xe4\x1a\x7c\xc5\xb9\x06\xbe\x40\x68\x36\xee\xcc\x1b\x2d\x3b\x11\x3d\x92\xe6\x33\x36\xe8\xdc\x43\x2f\xb2\x80\x44\xad\x1f\xb6\xa3\x14\x75\x3b\x7d\x8c\x8c\xed\x02\x00\xeb\x02\x37\xbc\xe6\x2d\xd8\x55\x9d\x2b\xf6\x06\x5e\xa8\x23\x21\x48\xa0\xc2\x56\x96\xde\x5d\x74\xdd\x1a\x62\xa1\x8d\x5b\x79\x56\x77\x17\xcb\xef\x22\x34\xdd\xf3\xfc\xae\x99\x02\xc1\xf2\x3b\x5e\x8a\x1c\x92\x08\xee\x68\xc9\xe9\x2a\x33\x97\x1a\x53\x5d\x30\x66\xa4\xe9\xef\x68\x3b\x4e\x3d\x2a\xee\x1c\xb9\x10\xe7\xf9\xdd\x67\xda\x8c\x5d\xe7\xad\x53\x21\xe6\x0b\x1d\x44\xb5\x74\x26\x94\xbc\x71\x53\xe9\x9a\xef\x1c\xc9\x0b\x3d\xd8\x5d\x31\xc9\x09\x83\x5a\x0d\xf8\x26\x7b\xdb\xba\x2c\xc9\x3b\x13\xec\xa5\x3d\x24\x09\x79\xf3\xef\x17\x67\xe7\xef\x3f\x5e\xfc\x78\x71\xfe\x61\x9e\x38\x7c\xf4\x14\x8e\x3f\xdb\x3d\xf4\xfc\xca\xbf\x7d\xf1\xf9\xf4\xc3\xbf\xbf\x3f\x7d\x77\xfe\x12\xe2\x89\xec\x4b\x41\xf3\x34\xd0\x2d\xa4\x92\xf6\x0a\x2a\x4a\x76\xc7\x45\x25\x89\xf5\x5c\xb5\xb3\x7f\x44\xbf\x8c\xda\xc5\x86\x79\x33\x5b\xe7\xee\x6e\x25\x09\x51\xa5\xfe\xa5\x76\x2c\x9b\xb8\xd3\x64\x3b\x0f\x9d\xf8\x96\x69\xe2\x1c\x5b\x3c\x2f\xaa\xfe\xee\x2b\xe6\x42\x76\xf1\xc6\x1c\x35\xbb\x14\x63\xb6\xfe\x62\x1a\x47\x20\xca\xfb\x5e\x9a\x4c\x26\xb4\x60\x29\xba\x16\x29\x49\x45\xa5\x07\xfd\xdb\xdf\x9e\x10\xce\x5e\x93\xdf\x7a\x44\x97\xe4\xdc\x7c\xb7\xde\xc1\x5e\xd2\x30\xce\x9c\xdd\xb1\x12\xd2\x10\xcc\xde\x9e\x90\x92\xdd\xd0\x32\xcd\x98\x04\x48\xb0\xfb\x35\x53\x6b\x56\x9a\xf0\x34\x2e\x5a\xff\x88\x5d\x72\x44\x2e\xd4\x92\x9c\xb1\x6b\x5a\x65\xd8\x5a\xec\xe8\x68\x7a\xcb\x13\x60\xeb\x1f\x4b\xb1\x89\x66\xed\xab\xa6\x05\xd3\xc6\x31\xc7\x26\x3f\xab\x3f\x13\xc4\x13\xbc\x92\xa5\x84\x9b\x34\x1c\xeb\x40\x0d\xe6\x92\x44\xf5\x01\x88\xc5\xe9\xb7\xb7\xe9\x3b\x5a\xfc\xc4\xb6\x3d\xed\xbb\xda\xd7\xc4\xa4\x15\x42\x12\x12\x22\xbf\xbd\xb1\xe4\xfa\x17\x21\x7a\x1a\x24\xaa\xa9\x01\x3e\x7d\xb9\x66\xf6\x89\x5d\x16\x12\x4e\x2d\xb3\xcf\x9e\xc5\x09\x59\x65\xc2\xe4\x93\x85\xd6\x81\x0c\xc1\xe9\x27\x11\x77\x4a\xeb\xb0\x1e\xdb\x1f\x1c\x31\x3e\x62\x82\x08\xa7\x69\x4a\xa0\x33\x83\x3e\x0f\xd7\x55\x86\x31\x03\xb9\xf4\x6c\xc9\x13\xb0\x67\x42\x18\xf5\xf8\x54\x3c\xfd\xe7\x3e\xf1\x60\x9f\x41\x6b\x2e\x0a\x74\xb2\x0c\x5e\x77\x74\xed\x6e\x1b\xf2\xcf\x1d\x11\x08\x22\x05\x12\xeb\xec\xa3\x79\xca\xe6\x7a\x99\x8b\x30\x7a\x92\xed\x09\x1b\xcd\x07\x16\x7d\xe8\xf9\x3f\xae\x05\x00\x06\x7a\x0c\x83\x15\x22\x7d\x4d\x64\x55\x14\xa2\x54\xd2\x19\x42\xe0\x4f\x0a\x6f\x62\xe3\xeb\x60\x4b\x9c\xd4\x9f\x41\xda\xa6\xf4\x3e\xf0\xfc\x8f\x61\xd2\xe8\xd5\x12\x29\x98\x29\x27\xf8\xbf\xfb\xa9\x45\x27\xc6\x1d\xbb\x5c\x0b\xa9\x2e\x2e\x23\xc8\xe2\xd7\x0b\x91\x5e\x5c\x9e\x34\xfe\x4f\xf6\xde\x54\xe4\xa1\xc4\xa0\x8b\x64\xcf\x28\x0c\xe3\xba\x1c\xda\xa7\xc1\x26\x9f\x9b\x41\x7a\xe3\xdc\xd1\xff\xfc\x31\x72\xa0\xf8\x70\x49\xee\x4b\xae\x14\x03\xc4\x50\xc5\xca\x8d\xd6\x2d\x4e\xf4\x79\xa8\x95\x83\xbb\xef\x8e\x66\x17\xb9\x51\x2d\x15\x5b\xa7\x0e\xbd\x15\xcc\xbc\xf1\x88\xb8\x8b\x21\x46\x63\xb5\x4f\x6d\xa3\x7a\x49\x0f\xb3\x4e\xd3\xfa\x78\x7e\x9c\x28\x07\x9c\xaf\x68\x37\xc2\xfe\x1a\x02\xd2\xc1\x21\x3b\x37\x17\xc9\x38\xf8\x80\xb4\xaa\xee\xfc\x40\x2f\xf0\xc3\x65\x52\x54\x27\xe6\x0b\xcb\x0d\xdb\x88\x72\x1b\x3e\xa5\xe6\xeb\xac\x58\xb3\x0d\x2b\x69\xb6\x30\xb1\x99\x13\x47\x1e\xc9\xba\xff\x43\xc2\xe1\x83\xe1\x0d\x70\x9f\x3a\x9a\x3c\x06\x23\x37\xdb\x5a\xa9\xc8\xd2\xa7\x91\x0c\x41\x8c\x6d\x7c\x86\x08\x06\xb7\xc3\x21\x78\x64\xfb\x34\x59\xe7\x4d\x23\x7f\xe2\xb5\x9b\x0b\x68\xda\x77\x22\xab\x36\x2c\x42\xb2\x13\xef\x92\x86\x37\x59\x7e\xa7\xf5\xf2\xde\x9e\x61\xf6\x19\x24\x0b\x52\x7e\xc7\x65\x7f\xd2\x7e\xeb\x44\x4d\x90\xd7\xb8\xba\x45\xa5\x8a\x4a\x99\x54\x35\x73\x56\xa2\x26\xc9\xbe\x14\x02\x5b\x2b\x98\x73\xb2\x23\xfe\xbe\xeb\xef\x16\x8a\x4f\x41\x95\x62\x65\xfe\x9a\xfc\x7f\x2f\xfe\xed\x7f\xfc\xd7\xe2\xe5\x3f\xbf\x78\xf1\xcb\xb7\x8b\xff\xe7\x2f\xff\xe3\xc5\xbf\x2d\xe1\x1f\xbf\x7b\xf9\xcf\x2f\xff\xcb\xfe\xcf\xff\x78\xf9\xf2\xc5\x8b\x5f\x7e\x7a\xf7\xa7\x8f\x97\xe7\x7f\xe1\x2f\xff\xeb\x97\xbc\xda\xdc\xe2\xff\xfd\xd7\x8b\x5f\xd8\xf9\x5f\x22\x89\xbc\x7c\xf9\xcf\xbf\x8d\x18\x1c\xcd\xb7\x3f\x07\xc5\x0f\x71\x8d\xca\x5e\x83\xb3\xfe\x26\xd0\x88\xb5\xf9\x46\xe4\x56\xef\x00\x93\xf0\x5c\x2d\x44\xb9\xc0\x97\xbd\x18\x6f\xdf\x13\x02\xca\xf7\x9f\xe6\xb9\xf8\x60\xcf\xb4\xe7\x7e\xb7\x57\xc7\xac\x4c\x2d\x59\x52\x32\x35\x8f\xf5\x87\xb4\xac\xaf\xa3\x10\x69\x6b\x86\x67\xf3\xc9\x03\xc0\xf6\xcd\x09\xfd\xcd\x1a\x8c\x56\x39\xc2\x15\xac\xb5\x04\x68\x60\x4d\xc0\xf5\x17\x25\x20\x56\xcc\x25\x0a\x1a\x5a\xb7\x2c\x50\x9b\x82\xcf\xc1\x08\xfd\x7b\x32\x42\xaf\x90\x37\xd0\x02\x8d\x38\x06\xf8\xcc\x6f\x81\xb2\xfc\xae\xdb\x0d\xb7\x1b\x3f\xd0\xdf\x6c\x86\x42\xac\xb2\xa8\x04\x29\x44\x51\x65\x54\x35\x5c\x73\x1d\x03\xdc\xf5\x1a\xfb\x71\x11\x73\x1e\x6b\x77\xb3\xeb\xe1\xdd\xab\x39\xd9\x95\xa1\x4d\xf7\x3b\x39\xcd\x32\xc2\x73\x3c\x8f\x40\xd6\xfa\x75\x4b\x86\x7a\x20\xa1\x9d\xb5\x37\x39\x26\x9b\xea\x7d\xdb\x19\x26\xa4\x99\x2a\x5a\x2a\x9e\xdf\x2c\xc9\x9f\xf5\xdf\x51\x0a\x1b\xb7\x69\x67\x10\x08\x50\x10\x8a\x8c\x11\xa7\x3d\xb8\x82\x21\x42\xa5\x14\x09\x87\x4c\x7e\xf0\x13\xbb\xe4\xfd\xde\x89\xc3\x7c\x20\x67\xb7\x28\x59\xc2\x52\xe8\xf3\x46\x3e\x63\x09\x92\x5d\x43\xec\xd5\x72\x9e\xdf\x39\x0f\x74\x85\x41\xcb\x2e\xaa\x7a\x2e\xed\x94\x2f\x36\x9b\x4a\x41\x38\xe4\xe1\xe3\x55\x9a\xdf\xae\xda\xfb\xd6\x38\x23\xc7\x16\x53\x76\x9e\x05\xe7\xee\xe9\xda\xe7\x88\x8b\x2d\xe6\x12\x72\x8e\xdc\xc0\x3d\xbe\x77\xfb\xd4\xfe\xa8\xe6\xad\xf3\x78\x3e\xe8\x98\xdb\xe4\x79\xdf\x24\x43\x6f\x91\xa8\x1b\x22\xfa\x76\x88\xbd\x19\x06\xb8\x26\x87\x49\xfa\x38\x3f\x63\x51\xb2\x6b\xfe\x25\x9a\x37\x4f\xf3\xda\xa4\xab\x9b\x76\x82\xa8\x2f\x59\xc1\x72\xf0\xa5\x30\x9a\xac\x83\xd7\x97\x91\xf2\x75\x6c\xa2\x8e\xa4\xce\x1b\x2d\x45\x8d\x6b\xe8\x01\xbc\x6a\xd3\xf9\x0e\xa7\xef\xef\xee\xf4\x19\x3e\x98\xf7\xe8\xe5\x22\x65\x57\x9d\x70\x21\x7b\xe3\x3a\x7e\xef\x7d\x7f\x07\xa2\x02\x73\xd1\xed\xf0\xb4\xfd\xdb\x91\x32\x43\x4c\xba\x49\x21\xe0\x8c\x5e\x73\x85\x05\x3d\x7a\x2c\xcb\xba\x3a\xd3\xa3\x07\x25\xd1\xe6\x1b\xc7\x9d\x46\x23\x7a\xff\x5d\x0c\xd6\x90\x5f\xa1\x4b\x39\xad\x32\x96\x12\x9b\x04\x85\x3f\x55\xb3\x64\x07\xc5\x18\x46\x6d\xa4\x0b\xbd\xa2\x52\xf2\x9b\x7c\x51\x88\x74\xa1\x7f\xa3\xb7\x48\xe0\xe1\x0b\xa3\x89\xef\x32\x8d\xd9\xde\x0f\xce\xbf\xea\x69\x34\x89\xd8\x14\x95\x62\x9e\xf3\xd5\x5a\xd0\x1d\x23\x5a\x6d\x31\xa7\xcf\xd3\x9b\x6b\xbd\x6c\xa8\x20\x68\xae\x2f\x42\x72\x2d\xcc\x90\x16\x6e\x48\x0b\xf7\x5b\x63\x97\x3c\x2c\x0f\xd1\x45\xdc\x7d\x8e\x9b\x4b\xf9\x16\x1d\xd4\xcd\x9e\x9f\x1b\xfa\x85\x6f\xaa\x0d\xa1\x1b\xac\x9f\xbc\xb6\x8b\xdb\x73\x8c\xeb\x65\xa7\x59\x26\xee\x59\xfa\x54\x4b\x18\xb5\x8c\x64\x20\xf7\x92\xe7\xea\x70\x0c\x3a\x1a\xe3\x1d\x8c\xd1\x8e\xc5\x91\x0e\x45\x1b\x5f\x88\x65\xcd\x0f\x36\x60\xb2\xc3\x9c\x3c\x9f\xc0\x9c\x56\x26\x40\x5e\x94\xfb\x05\x2e\x89\xd8\x70\xa5\x8c\xc7\xde\x2b\xfc\xec\x73\x95\x70\xd5\x70\x5b\x9b\xa3\x04\x35\xa5\x14\xea\xf8\x2d\x10\x40\xb6\xad\x83\x5f\x27\x78\xbd\xdf\x73\xd9\x37\x60\x04\xe1\xe0\x9b\x02\x61\x38\xe0\x48\xb8\xaa\x47\xcc\xcf\x39\x1c\xaf\xc3\xf1\xb2\x4f\x37\x94\x1a\xe9\x84\x53\x6b\x60\x48\x39\xf5\x48\xb3\x7f\x21\x52\x69\x74\x12\xcb\x34\x5d\x99\xb5\x04\x01\x80\x78\x7e\x03\x1d\xeb\x79\x42\xaf\x98\x92\x06\x0a\x06\xe8\xd0\xd2\x82\x52\xa1\x0b\x05\x8b\xa4\xd1\x7f\xd4\xa3\x75\x09\x48\x0c\xbf\xbe\x6e\xbe\x87\x78\x25\x1b\xd0\xd4\x2f\x94\xaf\x75\x19\x55\xaa\x8b\x22\xdb\x14\x19\x55\xec\x58\x1a\xf5\x6b\x24\x12\x4c\xf8\xf6\x8d\x83\x8a\x23\x53\xe0\xe2\x7a\xe5\x9c\x07\x24\x37\x18\x32\x8e\x44\xc2\x21\x05\xc1\x90\x46\xc2\xc7\xf5\x1a\x09\x58\x15\x30\x02\x42\x2e\x40\x15\x03\x17\x61\x18\x39\x12\x6f\xb3\xc6\x44\x6e\x42\x51\x9b\x20\xac\x1c\x19\x60\x1c\x47\x84\x74\x46\x40\xcc\x05\x2d\x5a\x03\x41\x17\x80\x99\x23\xc3\xcc\xd4\x30\xdc\xdc\xde\x74\x62\x21\xe7\x82\x13\x42\x3c\xdc\x21\xb0\x73\x41\x92\x06\x3f\x6d\x08\xf4\x1c\x19\xb2\x60\x61\x08\x3a\x32\x12\x86\x2e\xbc\x5a\x3b\x50\x71\x61\x28\xba\x20\xc9\x06\x54\xdd\x00\x38\xba\xa8\xb1\xb6\x22\xe3\xf5\x42\xd2\x05\xc9\xee\x43\xd6\xc5\xc2\xd2\x91\x68\x68\x3a\x12\x07\x4f\x47\xe2\xb8\x26\x08\x53\x47\xa6\x40\xd5\xf5\x8c\x10\x41\xec\x06\xc3\xd5\x05\x75\x68\x03\x64\x37\x10\xb2\xae\x8f\xec\x0e\xcb\xc5\xc2\xd6\xf5\x90\xec\x04\xb4\x8b\xbf\xb1\x67\x56\xc6\x03\x9c\xa2\x44\xc6\x4a\xbf\x60\x7e\xf7\x69\xba\x87\xeb\x6f\xc3\x84\x5c\x5a\x85\x4f\xe7\xa1\x23\x61\x1f\xad\xaf\x4d\x9f\xe4\x7a\x44\xc0\xb2\x4a\xd1\x64\x8d\x88\x78\x66\x44\x3d\x6a\x03\xcd\xb7\x44\xef\xaa\xc2\x1b\x11\x98\xca\x98\xa6\xaa\x84\xb0\xe4\x3f\x3a\x1e\x3e\x61\xa0\xc1\xfe\x13\x56\x02\x75\x6f\xa1\xe5\x72\x2d\x2c\x1c\x6f\xfd\xa3\xfd\xd7\x3f\x4d\xa8\x0e\x8b\x51\x11\x70\x90\xd1\x0a\xdd\x39\x7c\x9d\xf0\x3c\x85\xe0\xa7\x99\x3a\xac\x08\x52\xd2\xeb\xb8\x09\x0b\xb8\x73\x2d\x5a\xc9\x86\xd1\x5c\x5a\xd7\x29\xc4\x4a\x6b\x42\xd2\x84\x85\x3d\xe3\xd9\x38\x97\x22\xee\x3c\x60\xb5\xf7\xe2\xca\x78\x55\x4f\xc8\x25\x78\xf9\xeb\x4f\xe0\xcc\xbe\x17\xe7\x5f\x58\x52\xa9\xde\x7a\x97\xa8\xdb\x76\x08\x86\xef\x4f\xb5\x82\x85\xf3\x6d\x28\x58\xf5\xa9\x88\x45\xf1\xed\x5d\xcb\x5b\xb6\x75\xb8\xb1\x56\xb5\x83\x6b\xad\xff\x5a\x74\x7c\x68\xaf\x42\xbc\x5b\xff\x97\x75\x9a\x6e\x56\x3c\xc7\x41\xe2\xcf\xda\x4d\xef\x25\xaa\x47\x65\xb7\x47\xeb\xec\x59\x86\xc3\x9b\xba\xf8\x83\x61\x88\x7f\x9e\x09\x86\xd8\xc9\xfc\x76\x4d\xd0\x53\xef\xce\x7f\xad\x68\x56\x17\x81\x05\xb6\xd4\x7e\xdd\x10\xd8\x83\x68\xbd\xe7\x59\x9a\xd0\xd2\x64\x98\x82\xac\xe9\xa5\x28\x05\xf2\x17\x40\x95\x41\xb5\x9d\x95\x74\x35\xa7\x48\x4c\x05\x28\x68\xa9\x78\x52\x65\xb4\x5f\xc3\x37\xf8\x23\x11\x65\x5e\x81\xbd\xab\xd9\xfd\x8a\x25\x22\x4f\xe3\x4d\xcb\x8f\xbb\x6f\xee\x66\x38\x14\xac\xe4\xa2\x07\xba\xce\x0c\xc0\xe2\x3a\x7a\x07\xef\x45\x33\x4e\x24\xae\xad\x6c\x73\x02\x23\x70\x7a\xac\x93\xaf\x09\x21\x66\x91\x3c\x5f\xd6\x17\x4d\x2d\x05\xfa\xc5\xe5\x0f\x5b\xeb\x6d\x3c\x31\x30\xa1\xb9\x50\x08\x15\x6a\xc6\x6a\x8e\xa1\xd9\x56\x47\xb6\x97\xea\xb5\x28\xa1\xec\xf1\x45\x2a\xb0\x72\xef\x8e\x27\xea\xe5\x92\xfc\xbf\xac\x14\xc0\xb6\x39\xbb\xa1\x8a\xdf\x39\xcd\xe6\x9e\x67\x59\x2f\x45\x88\xaa\x31\x8a\x59\x41\xe4\x5b\xf2\x02\x48\x12\xbe\xd9\xb0\x94\x53\xc5\xb2\xed\x4b\xf4\xe7\x30\x22\xb7\x52\xb1\x4d\x98\x81\xc2\xce\x35\x0b\x97\xc9\x73\xf5\x87\xef\x3b\xbf\x37\xac\x0e\xf8\xb3\xad\x68\xac\xc5\x34\xe6\x18\xed\xb0\x8a\xd1\x00\x82\x32\xba\xd3\x5c\xf1\xf3\x97\x0c\xe4\x87\xb5\x3c\x62\x99\xec\x3f\x34\x9f\x52\x52\x32\xc0\xe0\x31\x27\x6e\xc2\xc9\xc4\x9c\xf5\x77\xa2\xca\xbb\xfc\xf5\x4d\x00\x55\xe3\xa8\xfa\xec\xbd\x56\xd7\xf2\xef\x64\xa7\x3d\xb0\xa2\xe7\x8d\xc1\x8b\x1c\x50\x02\xe1\x02\x50\xb0\xb4\x90\xc3\x6f\xf5\xc3\x3a\x12\x3f\x10\xf0\xa0\x15\xfa\x30\xb6\x9e\x12\xa2\xc9\x35\xfc\xee\x07\xa2\xb9\x1f\x8a\x7e\x4c\xda\x60\x33\x6d\x8f\x2a\x07\xe8\xc6\x0c\xa3\xf4\x5f\x3d\x8e\xa5\x61\x14\x2c\x35\x99\xc0\x20\x6f\x2c\x2e\xe8\xf1\xeb\xe3\xc9\x17\x09\x4e\xb2\x14\x05\xbd\x81\x93\x19\x3d\xd7\xdd\x17\x49\xca\x14\x2b\x37\x00\x4e\xb2\x16\xf7\xf8\x77\xb8\xd0\x7b\x27\x5a\x18\x0a\x2c\xad\x71\x62\xd6\x42\x22\x32\x64\xa3\x6c\x1f\xe4\x00\xa4\x4c\xdc\x07\x6c\x7b\x5a\x8a\x2a\x4f\x8d\x1e\xec\x04\xfe\xbb\x9d\x01\xbf\x17\x39\x48\xaa\x4a\x62\x89\x7d\x27\x56\x25\x3e\xee\x36\x5a\x31\x45\xf5\x01\xfd\x6e\xf9\xdd\xb7\x93\x97\x7f\x10\x4e\x04\x38\x54\x76\xfc\xf7\x36\x23\xc7\x9e\xce\xc9\x23\x2a\x19\x4d\x7f\xce\xb3\x78\xbd\xfc\x1d\x32\x28\xbc\xb8\x00\xec\x51\x7e\x0d\x31\x97\x13\xfc\xe8\xbe\xe4\x8a\x45\x05\xf0\x08\x79\x01\x68\x79\x44\x94\xa4\xca\x9d\x01\xf3\xb2\x89\x02\x00\x5f\x09\x4f\x33\x94\x93\x26\xab\xd5\xa4\xb3\x8d\x87\x18\x99\xb6\x3e\xda\x8e\x65\x03\xf5\x0f\xe6\xed\x96\x63\xde\x04\x3c\x20\x2f\xf0\x9b\x5a\xc3\x16\x42\xbd\x9c\x9e\xa8\x86\xd3\x3e\xff\x52\xc4\xeb\xfd\xe7\x06\xdb\x81\x14\xa1\x35\x08\xaa\xfd\xde\xfa\xf4\xac\xc1\x0f\x6c\x4d\xef\x98\x24\x92\x6f\x78\x46\xcb\x40\xf5\xa0\x12\xe4\x0a\x67\x45\x56\x95\x6a\x47\x96\x69\x47\x25\x09\x48\x91\x1a\xd5\xc2\x43\x25\xf1\x67\xe0\xfd\x54\xbc\x91\xd2\xb2\xa9\x76\xfc\x7a\x57\x40\xd6\xd9\xf9\xe8\x31\x6c\x2a\x55\xd1\x2c\xb0\x06\xec\x4b\x92\x55\x92\xdf\x4d\x39\xff\xa6\xe6\x6e\xb0\xea\xb2\xab\xb5\x14\x22\xbd\x2a\x58\xf2\x38\x3a\x4b\xd3\x16\xd5\xe2\x34\xb5\x8c\x05\xb9\xfb\xe8\xbe\xea\xe9\xb0\xb4\xa1\x5b\xc8\x07\x05\xdc\x6c\x9b\xb1\xbe\xf5\x33\xee\xdd\xac\x9e\x33\xe0\x10\xbd\x97\xe7\x19\x95\x8a\x27\x3f\x64\x22\xb9\xbd\x52\xa2\x1c\x80\xde\x73\xfa\xe7\xab\xbd\xb7\x77\x00\x9b\x4e\xff\x7c\x45\xce\xb8\xbc\xed\x65\x43\x0f\x30\x0e\xb3\x39\x7c\x37\x21\x25\xb7\xd5\x8a\x65\x4c\x1d\x1f\x4b\xbc\xe3\x37\x34\x59\xf3\xbc\xff\x4a\x30\x57\x7f\xee\x0a\x20\x0d\x7c\x9f\xde\x8f\xa1\xe9\x1c\xa6\x34\xf7\x95\xe1\xf4\xdf\xd0\x7b\xc9\x70\xda\x2b\x3d\x6d\x40\x4e\x0d\x23\xcc\xcc\x14\xcb\xc4\x41\x5c\x9c\xcd\x10\xab\xbc\x96\x1f\xf5\xc8\x86\x04\xac\x8e\x7f\xe4\x19\x43\x5b\x12\xa6\x65\xb3\x7a\xcd\xd9\x81\xfd\xdb\x8a\x2a\x18\x1e\xb9\xa7\xe8\x5b\x01\xd9\xbd\x24\x1f\x79\xf1\x9a\x9c\xe7\xb2\x2a\x59\xed\x9b\xbb\x6e\xfe\x54\x90\x26\x97\x75\xb5\xb4\x35\x7b\x81\x5f\xd0\x0c\x04\x84\x7c\xb4\x82\xc9\x39\xa2\xd2\x47\xc4\x71\x8e\xd8\x17\xf5\xfd\xd1\x09\x39\xfa\x72\x2d\xf5\x7f\x72\x75\x2d\x8f\x96\xe4\x62\xe3\xd2\x8d\x00\xb2\xb0\x64\x36\xb5\x14\x5f\x08\x0f\xf6\xda\xd7\x55\x1e\x84\x25\x83\x63\xc0\x34\x68\xad\x75\xa7\x82\xdc\x23\x72\x96\xbe\xfe\x58\x59\x9a\x1e\xa5\x3b\xdb\x10\xc8\x33\xc7\x27\x11\x9b\xa2\x14\x1b\xee\xae\x3e\x73\x5c\x67\xcb\x9f\x06\xa7\x59\xc8\xe8\x20\x7b\x9c\x8b\x68\xb6\xe6\x55\xd2\x54\x45\x2c\xdf\x02\x5f\x86\x63\x7b\x8e\x6f\x2f\xae\x6d\x32\x1b\x3a\x16\x8c\xd7\xc8\x34\x35\xc0\xac\xb9\xd5\x36\xc6\x72\x23\x46\xab\xf7\x78\x13\xfa\x27\x98\x01\xbe\x4a\xd9\xdd\x2b\x99\xd2\xef\x4e\x60\x98\xc8\x38\xe1\x1a\x3c\xd5\x98\x33\x95\xe4\xe8\xbb\xa3\x25\xb9\xb2\xfa\xd1\x89\xbf\x06\xee\x7b\x41\xaa\xd7\xa2\x74\x03\x82\xb0\xdc\xb7\x47\xe4\x85\x28\x61\x64\x09\xcd\x49\xc6\xe8\x9d\x09\x3d\xa1\x24\x0a\x0f\x14\x3c\x30\x2f\x23\x31\x0e\xe2\x0a\xb8\x3d\x3f\xd5\x3f\xfc\x3e\x70\xfd\x84\x6d\x17\xd2\x81\xc2\xbe\x25\x47\xda\x68\x39\x02\x13\x43\xe8\x3b\x4c\xdf\x3c\x5a\xad\x01\x38\x54\x43\x39\x38\x7f\xbb\x50\x9a\x2f\x77\x3d\x3b\xf8\x03\x7b\xcc\x16\xa4\xe9\x31\xe3\x11\x58\x3f\x47\x8f\x7e\xf3\x91\x41\x98\x42\xf6\x6a\x1b\xb6\x0f\x9f\x72\xfe\x6b\xc5\x48\x8d\xee\x5e\xb0\x12\xf1\xe4\x15\x49\xb9\xbc\x8d\xc5\xb0\x80\xb2\x1f\xad\xae\xbc\x38\xdd\xd0\xbf\x8a\x9c\x9c\xff\x70\x65\x86\xf4\xf2\x09\x17\x2e\x20\x10\xe9\x5f\xab\x92\x69\x05\x2b\x3e\x49\xcc\xbe\xb1\xab\xa9\xe9\xcf\xc9\x19\x55\x14\x14\x36\x94\x5e\xfd\x3e\xd1\xbc\xbe\x63\x35\xd7\xaf\x78\x9e\x1a\xa1\xe7\x69\x5b\x8f\xa5\x18\xe9\xbd\x7e\xdf\xad\x0d\xd7\x5f\xfa\xf4\xe1\x62\x06\xe5\x29\x81\x5b\xed\xe6\x9d\x48\x07\x6a\x50\xff\xa2\x97\xeb\x0d\xbe\x4d\x36\xfa\x75\xf2\x5e\xe4\xec\x04\x84\x05\xd1\xd2\x02\xff\x19\x64\xd7\x3f\x97\x5c\x75\xb5\x3c\xa9\x9f\xe8\x6b\xd5\xae\xdf\xa0\xd9\x7c\xf4\x7c\x49\x70\x01\x6a\xf6\x81\x53\x67\x2e\xd8\x55\x26\x56\xb6\xab\xc1\x9c\x23\xfd\xf4\xe1\x62\xf0\x40\x3f\x7d\xb8\x78\xbc\x41\x8e\x50\xae\x77\x75\xeb\x5a\xcf\xa8\xcb\x0f\x6b\x6d\x2c\x7c\xf9\x6b\x1a\xf1\x1a\xf1\xd2\xea\xba\x61\x9d\x78\x98\x2e\x4c\x78\x38\x81\xcd\xd7\x85\xe7\xda\x81\xee\xbe\x3e\xf5\xd3\x3c\x9a\xe7\x5f\x0a\x4c\x82\x36\x01\xb8\xab\x35\x05\x44\x15\x57\x05\xaf\x19\x25\x7c\xef\x72\x79\x2b\xf5\x2d\x64\x59\xca\x75\x47\x23\x67\x0c\x13\x39\xd2\xd7\x36\x09\x2b\x9a\x62\x3b\xc1\x77\x50\x5b\x90\xbe\xc6\x7b\x80\x60\xa9\x41\x4a\x1a\x40\xfc\xbd\x54\x5f\xa0\xeb\x35\x77\xaf\xd2\x3b\xca\x33\xba\xe2\x19\x57\x5b\xad\xc7\xbc\x5c\xba\xca\x8b\x18\xc5\x58\xc2\x92\xcd\x26\x94\x46\xa9\x66\x7b\x6e\x5f\xf2\x42\xd3\x79\x05\x2e\xe5\x97\xcb\x78\xad\x0c\x9a\x82\x41\x02\x3d\xaa\x76\xbe\x4a\xa7\xd7\x06\x4e\xd0\x8e\xc6\x16\xc7\xbe\x21\x75\x08\xb6\x53\xcb\x83\x61\xd7\xba\x7e\xa3\xf5\x5a\x87\x3f\x98\x6e\x7e\xbd\x03\x34\x95\x3e\xcf\xea\x66\xc7\x2a\xe9\xe0\xdd\x0e\xac\x17\xf8\x56\xec\xed\xfe\xf7\xca\x77\xc4\x15\xa5\x0f\x56\x05\xfc\x5e\x79\x16\x95\xa8\x51\x48\x00\x9c\x18\x9c\xfb\x95\x11\x71\x06\x60\x13\xb5\x0b\xcd\x83\x3f\x05\x31\x67\xe2\x21\xac\x2c\xa7\x0c\x2b\xc1\x5e\x43\x9a\x5b\x3f\x83\x45\x8f\x23\x61\xc5\xfa\x3a\x3e\xff\xe6\x0d\x2b\xd6\x3f\x5e\x35\xdd\xd6\xfa\x33\xf2\xe3\xd5\xfe\x99\x0d\xc4\x53\xa8\xc2\x15\x90\xe8\xe8\x3e\x96\x24\xe3\xd7\xac\xa5\xf3\xe9\xfe\xa4\x66\x3a\xd1\x1b\x91\x73\x25\xca\xbe\x1b\x25\xf6\xa4\x5a\x52\xc3\x6e\xfa\x1a\x2d\xed\x9d\x79\x1f\x13\xaa\x13\x91\x65\x2c\x51\x88\x3e\x1a\xe4\x55\xd8\x00\x3b\x80\x36\x13\xd1\x74\xbf\xac\x7b\x65\xa1\x39\xf8\x0a\x37\xff\xd5\x87\xf3\xd3\xb3\x77\xe7\xcb\x4d\xfa\x9b\xb5\xb8\x5f\x28\xb1\xa8\x24\x5b\xf0\x20\x5c\xdb\x53\x24\xab\xe3\x53\x44\x60\x9a\x36\x17\xfa\x67\x0b\x76\x40\x3e\x49\x4c\x53\x02\x97\xa0\x0d\xfe\x0a\xa1\x4e\x48\x49\xd5\x3a\x02\x8f\x4f\xad\xa9\x6d\xf6\x98\x65\xb8\xf6\xaa\x64\xec\xc4\x77\x74\xf4\x54\x52\x0e\x9c\xea\x38\xa7\x50\x3d\xdd\xc0\x65\x10\x9c\xad\x93\xf7\x0f\x71\x19\x90\xc7\x66\xd6\xf8\x7b\x27\xa4\xf4\x90\x9e\x35\xbf\x72\x14\x6c\x2e\x19\x84\x9e\x95\x88\x02\x2c\x83\xfa\x91\x6b\x51\x6a\x4e\x2d\x9b\x5c\xc5\x54\x02\xcb\xf0\xaa\x92\xac\x5c\x9a\xdb\xed\x5d\x8c\x8f\xfd\xf1\x96\x38\x1a\xba\x71\x30\x5a\xef\xee\x02\x7f\x60\xd7\xc4\xef\x2f\x69\x74\xc2\xe0\x5a\xd0\x4a\xad\x59\xae\x6c\xf3\x21\xb3\x8c\xad\x2b\x1e\xec\x6a\x80\xcf\x23\x73\x71\x14\x98\xe4\x10\x00\xc8\x03\x2c\x62\xef\x33\x3b\x2c\xa2\x3e\xbe\x13\xee\x2f\x57\xc9\x5d\xd2\x54\x40\x0a\x18\xa2\x10\x87\x67\xe3\xb1\x36\x4d\x37\x3c\x7f\x6c\xce\x0d\x29\xa3\x3c\x4f\xfb\x57\x66\x07\x84\x19\xbe\xdf\xd4\x46\x91\x86\x8d\x26\xd9\x08\x7e\xef\xe8\xa8\xb5\x2a\x11\x88\xc7\xc4\xf9\x9b\x51\xfe\x56\xc6\xde\x5d\xaa\xcd\x56\xfe\x9a\x2d\x70\x04\x8b\x22\xad\xd7\xea\xef\x35\x2c\xff\xb8\xae\xc3\xaf\x20\x98\x3e\x0b\xc7\x90\x83\x02\xe9\x9e\x87\x5f\xe3\x78\x9d\x71\x82\x46\x03\x9d\x25\xa5\x2d\x37\x47\x8c\x5b\x6c\x51\x69\xfc\x16\x31\x48\xbb\x05\x2d\xe9\x86\x29\x56\x62\x5a\xb0\x49\x42\xce\x4d\x7d\xde\xcf\x05\xcb\xaf\x14\x4d\x6e\xe7\x84\xf0\x3f\x68\x19\xcf\x57\xcb\x18\x17\xc7\xb6\xe9\x87\xa9\xe3\x21\x03\x62\xb9\x8d\xcd\xfe\x27\x18\xc3\xc6\x03\xf7\x0c\xa4\xa0\x43\x98\x8d\xf7\x72\x39\x3c\xd1\xa6\x6a\x51\x23\xce\xa2\xf3\x4a\x54\x59\xbf\x66\xe1\xc0\x9d\xa1\x24\x2c\xb8\x76\x33\x23\x64\x1a\x6d\x6f\x78\x6c\xb8\x96\x4b\x1b\x91\x32\xb2\xe2\x28\x9a\x2a\xc9\xb4\x7e\x94\x60\xad\x57\x90\x07\xe0\xa2\xd7\x97\xb6\x19\x87\xaf\x04\x60\xe9\xd3\x8a\xa9\x7b\xc6\x72\xf2\x2d\xa8\x60\xdf\xfe\xcf\xff\xf9\x3f\xc3\x02\xdf\xbf\x8f\xbe\xfd\xc3\xf7\xdf\x2f\xc9\x19\x2f\x01\x9d\x84\x43\xad\x9a\x4b\xef\x2e\x4c\x0a\x72\x58\x2e\x09\xb5\x8f\x3b\x64\x2e\x24\x83\x03\xb1\xe1\x37\x6b\x85\xdd\x69\x81\x0b\x32\x1e\x94\x8c\x04\x31\xa3\x51\x40\x20\xd6\xa6\x34\x05\x99\xa6\x64\xda\x24\xb5\xc1\x1a\x9f\x90\x8c\xdf\x86\x87\x7a\x2d\xff\x54\x8a\xaa\xa8\xc1\x07\x4a\x26\xb5\x3e\x6f\x7a\xe7\xe2\x8f\xd5\x7b\x26\x99\x7a\xa2\x5c\xa6\x28\x8f\x5f\x83\xe9\x2e\x1a\xca\xd3\x89\x43\xc8\x5d\x20\xab\x14\x94\x97\xdd\xf8\xe0\xde\x74\xd6\x26\x79\xa4\xd1\xd9\xcb\xf9\x08\x52\xef\x6c\xf7\x43\x52\xd5\x4f\x51\x8a\xff\x40\xe6\xe0\xb9\x09\x3b\x59\xeb\x42\x1a\x7d\xd6\xc0\x4a\x40\xdc\x21\x50\x89\x43\x76\x30\x88\xf4\xfd\x6e\x70\x91\xbc\xca\xe2\x8b\x6b\xbf\x04\x3e\xc6\xab\x91\x71\xa9\x87\xd8\x00\x6b\x6f\x19\xb9\xdf\xc2\x5e\xad\x23\x5a\xd4\xe8\x31\x56\xf9\x1e\x75\xd3\x0b\xd2\x48\x47\xec\x39\x6a\x4a\xcd\x83\x24\xeb\x31\x60\xe9\x89\x29\x6c\x35\xb4\xf6\x60\x8f\xe3\xe6\x6f\xeb\x31\x98\xaa\xcc\xd6\x42\xfe\xa8\x1e\x3b\x93\xd2\xd4\xcf\x6e\x68\x79\xab\x8d\x3c\x23\xdf\xc2\xd2\xe6\x52\x2f\x92\xab\x09\xc6\x32\xf1\x3b\xe6\x1a\xab\xfb\xf5\x6c\x7a\xcc\xc7\xcb\xe0\x79\x43\xef\x35\x11\x25\x22\xe1\xa3\x94\xd0\xef\x3d\x3a\x36\x4c\xb3\x0e\x8a\x16\x5e\x5b\x75\xd3\x0a\x92\x36\x6a\x66\xc2\xa1\x7c\xbb\x0b\xe1\x75\x1d\xa0\x62\xc6\xf7\x45\x89\xeb\x8c\xa2\xbf\x55\xc4\xf4\x6e\x1b\xa2\xdb\x46\x37\x51\xe9\xee\xbb\x69\x0e\x6b\x4c\xcf\x93\x81\x1d\x38\x08\xe6\x77\x0d\x1f\x5d\x40\x11\x68\xe9\xab\xdf\xf5\x68\x21\x79\xe2\x75\x9b\xe8\xbc\xff\x63\x60\xa6\xf0\x81\xd2\xc8\x86\x8c\xb4\x32\xc0\xd3\x7b\xa2\x85\x3c\x3e\x75\x35\x65\xeb\x95\xdf\x72\xa5\x47\x12\x0e\x5c\xfc\x8d\x8b\x3d\x9a\xe4\x1c\xd7\xbf\xa1\x35\xb0\x23\xd5\x10\x55\x00\x9f\x98\x90\x1d\x3e\x7b\xe7\xc3\x49\xdd\xa2\xd1\x95\x30\x63\x21\xa4\x8e\xfa\xd9\x80\xce\x6e\x8f\xda\x92\xbc\x33\xb2\x5b\xf3\x62\x4e\xe8\x4a\x8a\xac\x52\xf8\x03\x71\xe7\x8f\x38\x12\xbe\xf8\x87\x01\x5a\xf8\x29\x90\xe9\xf6\x6b\x91\x44\xbd\x2b\x01\x2e\x6b\x94\xc6\x31\xb7\x03\x3e\xd1\x62\xe1\x00\x9e\x3f\x6d\xfd\x1e\xa0\x75\x45\xdd\xd3\x28\x3c\xf9\x87\x68\x73\x91\x48\x1e\x6f\x20\x5f\x5d\x90\x17\x75\x0b\x44\x9b\x2c\x73\x91\x2b\x56\x5e\xd3\x84\xbd\xf4\x0c\xe7\x7e\xc7\x99\x79\xd3\x56\xdc\xad\x69\x9e\x66\xae\xf3\x0e\xfb\xa2\x58\x99\xd3\x0c\x7e\x2f\x2d\x39\xc0\x96\x9c\x66\xc5\xba\x5f\x15\xb9\x66\x54\x55\x65\xbf\x73\x72\xde\x9c\x6f\x18\xda\x1c\x16\x3b\x10\x1a\x96\xed\x85\xcb\x62\xcc\x87\xdc\x3b\xa5\xde\xa2\xf5\xd6\x90\xda\x07\xd7\x5e\xfa\xbe\x8a\xa5\xe6\x4f\xb8\x62\x40\x26\x6d\x45\x55\x9a\xc0\x91\x69\x66\x10\x24\x9a\x88\x52\x5b\xe7\x38\x30\x2a\x49\xc9\x6e\xb4\x29\x51\x82\x4d\x82\x25\xc9\x59\xa5\x3f\x98\x2d\xdf\x76\xd6\x8c\x67\x2f\x1f\xd9\x84\x0b\xc2\xd1\x05\x1b\x4e\xb8\x36\x56\x8d\xb8\xe3\xa9\xd5\x50\x20\xa0\x5c\x77\xce\x2f\xa8\x94\x11\x9e\x14\x63\xbb\x79\x9d\xae\xbc\xbd\x45\x1b\x0a\xf4\x1c\x07\x62\x11\x65\x81\xda\x60\xa0\x5f\xe0\x28\x00\x7f\x2c\x18\xf2\x8e\xbf\x67\x44\xca\x2e\xab\x55\xc6\xe5\xfa\x6a\x94\x8f\xfc\x7d\x0b\x01\xcc\x91\xf2\xe3\xfe\x51\xf3\xed\xf2\xab\x13\xc9\x72\xc9\x41\xc3\xd0\x37\x99\xd6\x6b\x62\xca\xcf\xb4\xca\x4e\xa5\xb4\x9b\xe3\x9f\x36\x01\xd5\x87\x19\x33\x98\x4c\xfa\x4f\xde\x3c\x3e\xc7\xb9\x50\x11\xab\x2e\x65\x9f\xf2\xc2\x7f\x8f\x24\x34\xcb\xa4\x51\x52\x1d\xac\x87\xbd\x8f\xe2\xec\x79\x5b\x36\x8e\xdc\xc8\x35\xa3\xba\x1e\x98\x3b\x80\xf9\x31\x67\xbc\x75\x61\x25\xd9\x08\x2c\xa3\xcd\x89\xc8\xed\xea\x03\x9c\x9f\xf9\x77\x84\xdd\xe7\x60\x0f\x68\xc9\xcc\x61\x89\x63\xcd\x43\xf0\xa2\xf3\xf9\x3a\x82\x17\xa3\xc2\x96\x75\xb3\x62\xea\x01\xba\x34\xda\x20\xf4\xb4\xfe\xf1\x46\xe9\x6c\xc9\x16\xf0\x96\x41\xf1\xcf\xa1\x55\x87\xa7\x4a\x95\x7c\x55\xa9\x81\x00\xce\x9f\x77\x5e\x06\xbd\x8a\x49\x23\x90\x16\xc6\x4c\x4e\x06\xb8\x3c\x8c\xc5\xea\x8e\xdd\xbe\x98\x73\xba\x41\x90\x2a\xa8\x0d\xf8\xd2\xb1\x24\xa9\x48\x2a\xd7\xe1\x02\xf4\x88\x3a\xc2\x1f\x06\x64\x27\xc3\x8e\xf8\x50\x14\x5c\xff\x07\x02\x5c\x9a\x8a\xfb\xfc\x9e\x96\xe9\xe9\x65\x6f\x09\x58\x53\x59\xab\xdf\xf1\x43\x4b\x96\x14\xb4\xc9\xa7\x2b\x51\xa9\xa0\xdc\xb5\xc8\x20\x16\x80\xe6\x10\x69\x3a\x44\x9a\x0e\x91\xa6\xae\xa7\x19\x69\xd2\x6f\x34\xdb\x6d\x34\x0e\x60\x64\x88\x5b\xaf\xe8\x93\xba\xec\x3d\x61\x82\xf2\x7f\xb7\xec\x6a\x88\x36\x0b\xfa\x2c\x9e\xb7\x9a\x5f\x3c\x1d\xd9\x36\xae\x03\x35\xe1\xe9\xdc\xfb\x0f\xe0\xb8\x87\x19\x45\x98\x25\xf8\x74\xd5\x6f\xd4\x5d\xe5\xfd\xc0\x63\xa4\xdb\xaf\x10\xe9\x6b\x40\x8c\x27\x34\xcf\x05\xde\x8c\xf2\xc4\x34\xae\x39\x31\xb6\x73\x9e\x46\xf7\x9c\xb7\x0f\x74\xe2\xb1\x97\xeb\x20\x57\x70\xe4\xd6\x91\x41\xdb\x47\x60\x0b\x61\x7d\x7a\x90\x2f\x9b\xcf\xb0\xbd\x24\xd0\x83\xc4\x2a\xb0\xb1\x6f\xec\x2a\x53\xf8\xb6\x6b\x6d\x9f\xac\xd9\x86\xc2\x3f\x7f\x1c\x34\x74\x7c\xb8\x24\x5a\x55\x54\x0c\xc1\x5e\x58\xb9\x91\x44\x5c\x9f\x34\xfa\x88\x1d\xdd\x7d\x77\x14\xeb\x77\x1e\x1c\xfb\x21\x96\xc7\x43\x80\x81\xcd\x67\x1f\x3e\xd0\x79\xde\x35\x7f\xd7\x5d\x5f\x23\x82\xf2\xde\xd8\x1b\x21\x68\x90\xb6\xb8\xda\x0f\x36\xfd\x43\xe8\x2b\x8e\xe6\x21\xf4\xf5\xcc\x42\x5f\xde\xe5\x02\xc7\x8f\x4b\x3b\x71\x0c\x87\xc5\xde\x2d\xfa\x5d\xdf\x2d\x6c\x22\x67\xd0\xeb\x0d\xf5\xeb\xa5\x03\xe7\x8d\xa4\xa9\xf9\xd8\xc6\xcc\x44\xd9\xcc\x80\x38\x5e\x2e\x8f\x8f\x31\x92\x06\x64\xe3\x49\x56\xea\x7a\xf1\x47\xc2\xf2\x44\xa4\xc8\x8a\x7a\xac\xa5\x54\xa0\x1c\xd5\x5e\x94\xe1\xb3\xdf\x58\xe8\x61\x3f\xe3\x02\xc6\x39\x84\x45\xa2\x25\x8e\x05\xfa\xf9\x71\x82\x62\x51\xab\x13\x0e\x94\xd0\x2c\x80\x83\x76\x8c\x15\xe5\xa0\x57\xd4\xed\x30\xb1\x59\x2c\x48\x1d\xdb\x9e\x93\xbc\xc0\x0f\x97\x49\x51\xc5\xb9\x7b\x6c\xcf\xd9\xe5\x86\x6d\x44\xb9\x3d\x71\xa4\x34\x89\x06\x6d\xf3\x8d\x7e\xb0\xd2\xfa\xd1\x1a\x4b\x52\x95\x25\xcb\xa1\x85\xe6\x73\xd3\x5d\xa2\x31\x9c\xc8\x28\xd5\xc5\xed\x6d\x4c\x51\x78\xfd\xec\x14\xc5\xb8\xb0\x1c\xf8\x2c\xdd\x1c\xa3\x3c\x5f\xf5\x63\xca\x7e\x4e\xea\x66\xf6\xd7\xa2\x24\x2c\xbf\x23\x77\xb4\x94\x71\xfb\x41\xc6\x69\x2b\x29\xbf\xe3\x32\xdc\xf1\xcd\x7b\xa1\xdd\x09\x08\x98\xdb\x95\x2a\x2a\x65\x64\x76\x4c\x31\xb5\x37\xf2\x35\x73\xb0\x9d\xee\xfc\xec\x28\x6e\xdf\x85\xab\x42\xec\xf3\x2c\xbb\x9d\x36\x9f\x60\xef\xd3\xe6\x13\xdf\x09\xb5\xfd\xbd\x41\x4c\x31\xba\x09\xf1\xee\x63\xb7\x72\xec\xf9\xaa\xaf\xe5\x1a\x2f\xd6\x2a\xc3\x33\x1f\x0b\x88\xcf\x9c\xf1\x01\x15\x71\xe7\xe6\x8d\x66\xe2\xba\x62\x9b\x42\x94\xb4\xdc\x92\xd4\x78\xb0\x02\x98\xd4\x7b\xd8\x0c\x1e\x38\xc3\x64\x10\x3a\x98\x55\xca\xcb\x19\x8a\xe2\xa2\xd1\x19\x58\xca\xab\xcd\x30\xd7\xe4\x9f\x01\x00\xd6\x80\xcb\xda\x3c\x05\x24\xe4\x50\xbf\x69\xd2\x8f\x28\x8c\x8b\xc9\x65\xbd\xee\xa8\xd7\xf8\x98\x88\x47\x3b\xcd\x5c\xb4\x26\x1e\x15\xa1\xc8\x45\xca\xf4\xc6\x58\x62\x38\x36\xcf\xf7\x99\x9b\x00\x5f\xe4\x39\x7b\x61\x08\xbd\xd4\x3a\xdd\x3b\xb8\xb6\x1f\x65\xaf\xc9\xa0\xda\x71\xfe\x57\x06\x6d\xb7\x07\xa2\xae\x0a\x45\x33\xaf\x81\x78\x26\x12\x9a\xb9\x5d\xb5\x57\x64\xd8\xe7\x07\x59\x0f\x5c\x12\x77\xce\x6c\x98\x48\xef\xaa\x1e\x1b\x2a\x46\xe0\x5d\xcc\x24\x46\xd3\x79\x42\x57\x41\x57\x21\xd2\x46\x65\xc9\xed\xe4\x47\xaf\x33\x7f\x25\xf5\x48\xa1\xf7\x96\xf7\x9d\x20\x55\x37\xd0\x7b\x8b\x53\xaf\xbc\x8e\xea\x4d\x5b\x54\xff\xe5\xca\xae\x6f\x38\xea\xeb\xcc\x78\xa8\xec\xb3\x7e\x62\x59\x81\xae\x6e\x46\x69\xb4\x4d\x71\x4d\x68\xa0\x89\x10\xf1\xf5\x1f\xe9\xe0\xcf\xf7\xce\x4b\xce\x33\xff\xc0\x44\x9c\x14\x83\xe3\xec\x36\xa6\xca\x4d\xda\xd4\x1e\x77\xb7\x33\x77\x25\x59\xb9\xb8\xa9\x78\x3a\x9c\xad\x9f\xed\x9d\x1f\x75\xd3\x0f\xbb\xdf\x07\xdd\xea\xa3\xef\xf2\xeb\x24\xfa\x32\xfc\xf1\x4d\xf3\x16\xfc\x91\xaf\x4a\x46\xde\xac\x69\x9e\xb3\xac\x09\xf6\xde\x1f\x61\xe8\x02\x82\x6f\x56\x88\xef\x61\xbd\xf7\x5f\xb1\x73\xe2\x97\xfd\xed\x96\x74\x3f\x1b\x34\xc8\x38\x94\xf2\xb8\x48\x65\x8d\x62\xfe\xf0\x28\xe5\x59\x35\x10\x9f\xbc\xf6\x7b\xfe\xf8\x86\x28\x5a\xde\x30\xa5\x89\x90\xbc\xda\xac\x58\xe4\x3d\xfe\x3c\x90\xb1\x9f\x4b\x0d\xfb\x7c\x65\xe6\xb8\x1d\x7f\xfe\xf3\xfb\x81\x30\x63\x6d\x7b\x7a\x2f\xca\x2c\xbd\xe7\x29\xe6\x8c\x4a\xf2\x42\x93\x7d\xf9\x7c\x31\xbf\xee\xef\x79\x7f\x9f\x48\xd2\x3f\x6d\xe3\x20\x87\x69\x13\x98\xb7\xa9\x6b\xe6\xac\x17\x00\x0e\x9f\x17\xf0\xf3\x2f\xc9\x39\xc7\x1e\x5e\xfa\xff\xd0\xf5\x59\x37\x45\x15\xd7\xde\x06\x05\x29\xea\xdb\x42\x9f\x2b\x1b\x18\x80\x2e\x5f\xab\x0a\x1d\x95\x2b\xa1\xd6\x44\xf2\x4d\x95\x29\x9a\x33\x51\xc9\x6c\x1b\xc9\x46\x8f\xbd\x35\xd7\x19\xfb\x82\xdc\x1e\x7f\x2f\xbb\x57\x9a\xf7\xf3\x0d\xcb\x59\xc9\x13\xbb\x53\x51\xbe\x36\x9b\x37\x0e\x59\xb6\x92\x8b\x9c\xa5\xaf\xdc\x65\x8d\x6d\x8f\x20\x8f\x9c\x25\x64\x45\x25\x4b\x49\x91\x55\x37\xbc\x37\xda\xf4\x77\x90\x19\x5e\xe7\xa9\xc6\xd8\x9a\xce\xe8\x89\x2b\xee\x3b\x40\x53\xef\x29\x23\x1f\xdb\xb3\xad\x53\x56\xb0\x5c\xcb\x91\xdc\x3b\x13\x61\xbb\x0b\x96\x63\xb6\x5d\x30\xc1\xbc\xb1\x92\xf5\xfc\x8b\x2a\xa9\x16\x83\x1b\x2d\xd0\x6c\xf6\x11\xbf\xd6\x16\xc6\x9c\x40\x23\x0f\x98\xc8\x47\x0e\x1a\x86\x7b\x9e\x18\x9a\x6f\x58\x8a\x7e\x4c\xe2\xbf\x9f\xa2\x8f\xb2\xdf\x1c\x20\x9b\x42\xbf\x9f\x0a\x3f\x70\x94\x5c\x12\xcf\x4c\x30\x2d\x7f\xdb\x53\xe2\x83\x94\x43\x29\xf3\x72\x3f\x23\x37\xbc\x02\xcd\x59\x1f\xc0\x7f\xfe\xe6\xf3\xe7\xaf\x33\x91\xdc\x0e\xc0\xd1\xfb\x11\xbf\xbf\xe3\x2d\x31\x1f\x0e\x01\xd2\xeb\xf1\x8e\x98\xd3\xe6\x5d\x79\x90\x50\x85\x3f\xd2\x4b\x54\x1f\x9e\x52\xe8\x13\x00\xb0\xf1\x64\xc5\xb4\x40\x28\xab\x3c\x80\x89\x35\x77\x8a\x33\x55\x54\x8e\xc0\x23\xdf\x6d\x4b\x22\x99\xc2\xec\x7c\x40\x21\xde\x30\x45\xa3\xba\x24\x2c\xfe\xc9\x68\x70\x79\x83\x92\xd6\xcd\xec\x4e\xd5\xad\x48\x13\x91\x4b\x9e\xb2\x18\x8f\x36\x85\x3d\x29\x59\x12\x91\x68\x1d\xdf\x19\x05\x47\xf7\xe9\xd3\x40\xf0\x29\xfd\xc2\xce\x5a\x19\xbe\x01\xb7\x2d\x34\x58\xaa\xad\xb6\xe0\xdc\xa0\xb1\xb0\x5d\x1d\x43\x6f\x8e\x29\xde\x24\xec\xd2\x35\x77\x1a\xd4\xf4\xe8\xf8\x4f\x6f\xce\x9b\xaf\x36\x0f\xdd\x9f\xde\x9c\x93\xb3\xe8\x66\x51\x83\xda\x54\x3a\xf7\x64\x2f\xc9\x07\x68\x53\x79\x93\xb0\xba\x15\x56\xca\xe5\xed\xa3\x81\x61\x16\xe9\x4c\x6d\x18\x0e\x1d\x2a\x9f\x35\xa8\xe6\x24\x6e\x0c\x0e\xe0\xd0\x9e\xf2\xd0\x9e\xf2\x79\xb5\xa7\x7c\x54\x89\x4c\x1e\xcc\xab\x8f\xe2\x79\x54\x97\x45\xdf\x99\x75\x79\x56\xc7\xf2\x78\xae\xaf\xd0\xb0\xb9\xfd\xa9\x0d\xda\xd2\xb6\x62\xd3\x14\x9e\x68\x89\x1f\xcc\x53\x11\xe5\x5f\x88\x30\x7c\xdb\xfd\x0f\xfb\xee\x0f\x7f\x01\x83\x64\x1f\x71\x81\x43\x3e\x90\x1b\xae\x3e\xb0\xa2\x77\xcc\x3b\x0a\x1d\xbe\xb0\xe3\xc9\xe6\x4a\x7f\x20\x24\x57\xa2\xdc\x12\xaa\x00\x49\xad\x54\x3c\xa9\x32\xda\x7f\x80\x4a\x86\x7e\xec\x25\x39\x3b\xbf\xfc\x70\xfe\xe6\xf4\xe3\xf9\xd9\x6b\x62\x7f\x85\xfb\xda\xfa\x92\x7c\x14\xb5\xe3\xbb\x97\x2a\xf5\x3a\xc2\x43\xfa\x73\x3d\xc6\x13\x23\x80\x69\x5e\xe7\x8a\x00\x5a\x60\xc0\x53\x74\x91\x73\x55\xa7\x9a\x62\x8b\xa5\x4c\xe4\x26\xed\x52\x53\x36\xfe\xf7\x1b\xae\x4e\x30\x2e\x1e\x6e\xe5\xa9\x5f\x6d\x8e\x02\x4e\x38\x26\xa0\xb9\x29\xf4\xfa\x30\x66\xd5\x20\xeb\x4d\x9c\xc3\x82\xb4\x39\x60\xc3\x3a\x46\x62\xb8\xce\xbd\x6c\xee\x3f\x9b\xb1\x6f\x57\x25\x6c\x0c\xed\x03\x0e\x12\x7d\x33\x1f\x2f\x8f\xad\x42\x98\xed\x54\x93\x04\x69\xd6\x83\xb2\x88\x93\xfa\xe5\x26\xf7\x2f\x09\xf9\x59\xad\x59\x79\xcf\x65\x44\x83\x02\xbe\x8b\x7b\xe9\xe2\x76\xfa\x07\xfc\x42\x83\xe6\xaf\x84\x09\xe7\x26\x3b\x69\xe5\x0f\xda\xe0\x6c\xdd\xf0\x3b\x96\xe3\xc2\xce\x27\xa6\xed\xd0\x06\xed\xf6\x87\x5a\x6a\x7c\xfa\xf0\x76\xbe\xc1\xa0\x8c\x18\x34\x94\x37\x62\xb3\xe1\x8a\xac\xa9\x5c\x5b\xb4\x1f\x2f\xe7\xcb\xc9\xa9\x59\x0c\x6a\x84\x00\x1a\xd0\x87\xec\xf8\x4f\xf6\x95\x1d\x03\xda\x7d\x6c\xbb\x91\x05\xe5\x0d\x58\x3e\xc3\x33\x5e\xbb\xda\x64\xb8\xb9\x3c\x41\xf7\x07\x96\xa7\x08\x24\xdf\x6f\x16\xf7\x17\x30\xc6\x8a\x33\xf7\x63\x03\x9b\x9b\xda\xd7\xde\x23\x58\x2e\xa6\xd9\x9b\x0f\x51\xb1\x8b\x42\xab\x4a\x99\xa2\x3c\x93\xde\x8e\x2b\x51\x88\x4c\xdc\xb4\x27\xad\x0e\xd8\xae\xdf\x60\x59\xd4\x82\x2e\x34\x1f\xcc\x67\x8f\x0d\xed\x59\x66\xab\xbe\xf4\x02\xd5\xb3\x74\x76\x08\x14\x58\xcd\xd7\xfb\xe9\xd1\x16\xe2\x01\x14\x58\xb7\x3a\xc1\xb5\xb0\x96\x2c\x78\x20\x6c\xcf\x17\xb8\x07\x6a\xbc\x98\x82\x95\x1b\x2e\xb5\x70\xf3\x34\xdb\x18\x73\x77\x4f\xf3\x7d\xa4\x45\x0f\x29\xb5\x5a\xc2\x85\x8a\x7f\xf7\x9b\x83\x03\xfb\x35\x84\x6b\x51\xb2\x05\xfb\xc2\x25\xd8\x00\x50\x46\x18\xa8\x28\xaa\xaf\x5a\xbf\x93\xab\x75\x48\x5a\xf7\x25\x7e\x2b\xdb\x0e\xc9\x9b\xac\x75\x41\xe7\x1f\x86\xf4\x11\x9a\x65\x5b\x6c\x5c\x00\xc0\x32\xe8\x90\xa1\x37\x41\x1c\x42\x51\x9a\x68\x4e\x51\xf2\x3b\x9e\xb1\x1b\x6d\x1f\xae\x79\x7e\xe3\x01\xe1\xd0\x2c\x13\xf7\xcc\x94\x3e\xb3\x60\xec\x6d\xb7\x7b\x90\x54\x7e\x7e\x33\x70\xf0\xfb\x9f\x3f\x92\x9c\xe1\x4f\xc9\x88\xd3\x3c\xde\x1e\xd5\x83\x09\x62\x27\x2c\x16\x0b\xf0\x76\xbd\xf8\x0f\xad\xc7\xa7\xd9\x4b\xf2\x67\x66\xc6\xa7\x0d\x1c\x7d\xb6\x13\x45\xee\xd7\x02\xfc\x17\x95\x8c\xe8\xf2\x59\x73\x00\x1c\x36\xac\x3b\x34\x14\x5e\x69\x2a\x5a\x85\xc5\xab\x1a\xd6\x2b\xad\x11\x56\xfa\x0d\x1a\x49\xea\xf8\xfa\xe3\xd9\x03\x33\x5d\x9d\x23\xef\x02\x1b\x19\x69\x3b\x55\x51\xd5\xe3\x0e\xac\x06\xc0\x4f\xe4\x76\x93\xf1\xfc\xf6\x84\x70\x65\x05\xaa\xe6\x70\x93\x2c\x9f\xdf\xc6\xe2\xea\x95\x8c\x66\xde\x7d\x34\x03\x97\xce\x76\xd7\xa8\xc1\x6e\xfb\x8f\xdb\x82\x81\xec\x70\x22\xd0\xa4\xaa\xf9\x2e\x8e\xa3\xb0\xdb\xfa\x39\xad\x04\x97\x43\xb0\x5d\x8f\x2f\xae\xde\x5c\x5d\xec\xb4\xef\xc6\xcf\x1a\xa1\xa9\x09\x89\xf3\x73\x65\xce\x0f\xb9\x6a\x61\x11\x9e\x40\x27\xe7\xbf\xf6\x99\x20\x0b\x92\x55\xfd\x7f\xc7\x94\xd2\x4b\x51\x2a\xda\x57\x40\x13\x2b\x7a\x92\x35\x2d\x4e\x2b\xb5\x3e\xe3\x32\x11\x77\x6c\xa0\x79\x6a\x91\x8b\x4d\xf8\x88\x70\xcb\x16\x48\x8b\xbc\xf9\x97\xd3\xcb\x9d\xfe\x9a\xb3\x68\x30\xfe\xc8\xaf\x98\x1c\x6c\xcb\xb6\x8f\xdb\x50\x7a\xd0\x51\x1f\x42\x87\x7f\x33\xa1\x43\x90\x20\x7f\xab\xe1\x42\x9e\x73\xc5\xa9\x12\x51\xd0\x03\x4d\x3f\x51\x25\x95\xd8\x98\x23\x75\x61\xc9\x40\xde\x0b\x84\xfe\x1a\x94\xa3\x18\xac\x6e\x0f\xc3\x41\x57\x49\x24\x77\xc8\xe2\x3b\x59\xf1\x27\x24\x67\xf7\x61\xa2\x30\x36\xee\x68\xfc\xa3\xa9\x81\x28\x40\xaa\xfe\xd3\xeb\x7f\x34\x47\x2b\xa7\x1b\xf6\x4f\xa0\x0b\x05\x49\xd6\xe8\x29\xce\x39\x66\x7a\xed\xcd\xe5\x14\x83\x81\xff\x3a\x4c\xce\x19\x67\x31\xce\xf7\x5f\x2b\x9a\xe1\x3a\xbe\x9f\xd3\xb3\xd9\xdc\x8f\x41\xc3\xb3\x3c\x62\xf7\xe1\xbd\xf5\xf6\x68\x63\x02\xf4\x0c\xf8\x46\x58\xeb\x2c\x69\x2e\xf5\xe6\x35\x23\x4f\xc7\x26\xb0\x7c\x4c\x5e\xa8\xa4\x88\xc4\x66\x7d\x80\x1a\x2a\x9c\xa6\xd9\x8b\xb7\xae\x76\x2a\x6e\x3c\xb3\x47\x59\x81\xc7\x87\x39\xe9\x1a\x13\x40\xd5\x83\xbc\xe5\x52\x61\x26\x3b\x52\x8c\x69\xf4\xc4\xb0\x5a\x46\xeb\x8f\x97\xd0\xdf\xa0\xf8\x77\x9a\xa6\xe5\x6b\xbc\x83\xaf\x8d\x1e\x57\x82\x17\x40\xc4\x37\xdf\xb7\xf9\x03\x2f\xd4\xb6\xe0\x09\x98\xfc\x1f\xdf\x5c\x02\x25\x49\xfe\xf8\x07\x84\xd4\xfa\x87\xdf\xff\xe1\xdb\x48\x16\x78\x8a\x72\xa6\x51\x5e\xb0\x41\x59\xe2\x31\x21\x91\x50\x14\x77\x36\x35\x68\x5c\x5e\x39\x28\x66\x57\x75\x7f\x76\xe4\x4b\x23\xbc\xf5\x26\xbb\xbb\x25\x38\xd9\x11\xea\xdd\x21\x07\xba\xf3\x79\xfe\x39\xd0\xc4\x95\x4b\xa2\xfc\x9a\x2a\xff\x50\xf4\x5d\x5a\xd1\x67\x44\x5b\x98\xed\xa2\x45\x5f\x43\xb4\x05\xe9\xce\x25\xfa\x02\xab\x18\xe2\xd8\x26\xa7\xa2\x34\xd1\xd6\xbd\x17\xa3\x86\x9a\xac\xb3\xf7\x57\xff\xfe\xf6\xf4\x87\xf3\xb7\xa6\x9d\x20\xff\x35\x00\xd7\xe3\xa3\x2b\x8f\xc8\x41\x8d\x67\xf7\xb0\x1f\x20\xb4\x44\x43\xa2\x96\xef\x7f\xbc\xda\x71\xac\xe8\x4f\x6c\xa8\xb2\x19\x8e\xec\x97\xa7\x1d\xa1\xca\xa9\x36\x4e\x7e\x1d\xb1\x22\x8f\xe3\x4c\x5d\x40\xc6\xff\x2c\xc5\x93\x23\xfd\xad\x36\x40\xc1\xbe\x34\x0d\x5e\xbd\x67\x38\xb6\x51\xfd\xc9\x67\xdc\x0f\xf2\xc4\x81\x37\xbd\x12\xb8\x3a\x31\xf1\xb1\x47\x0d\xb9\x3d\xc8\x2a\xc7\xa9\x3a\xe5\xd0\x4a\xdd\xe3\x2b\x78\xc7\x06\x7b\xb5\x08\xc0\x0c\xc7\x52\xdf\x1e\xfa\xde\x60\x52\xc6\x80\xd7\xed\x70\xe7\x73\xe1\xbe\x3a\x53\x0f\xaf\x88\x37\x19\xe5\xbd\x68\x5c\x3b\x87\xb1\xed\x75\xfc\xe7\x15\xba\xa2\x23\xbb\x8d\x35\x9b\x06\x11\x4a\x5a\x29\xbb\x5c\x21\x6a\x5c\x02\x00\xb9\xdd\x7f\xd4\x47\x2e\x74\xbd\x30\x0b\xbb\xe6\xf5\x47\xf8\x49\xa2\x87\xf4\x78\x42\x19\x7e\x6e\xa6\xb2\x09\x47\x6b\xd8\x61\x78\x63\x5f\xdb\x2d\x5d\xef\xd8\xaf\x18\x43\x67\x7f\x3f\x09\x95\x0e\xd4\xbe\x32\x6e\xb5\xe8\x1a\xf7\xa7\xdd\x70\xf2\xe0\x52\xff\xcf\x03\x0b\x90\x83\xcb\x75\x66\xab\xdf\xe7\x33\x2b\x8b\xb5\x50\x22\x1f\x59\x88\x75\xd9\xf2\x72\x33\xd9\x01\xbf\xf1\x06\x8b\x0f\xb3\x80\xaa\x5f\xef\x21\x66\x91\xbb\xb0\x17\x34\x8a\x36\x77\x9e\xc8\x6d\x00\x4c\x86\x03\xe7\xc6\xbf\xfb\x68\xba\x58\x7a\x71\x36\xc3\x89\xff\xfb\x81\x74\x98\x1b\x5f\x6a\xae\xe3\xae\x37\x72\x58\x37\x94\x33\xa3\xe7\xda\xba\x4a\x69\x58\x9f\xd4\xbc\xef\xf1\x77\x70\x52\x11\x35\x55\x71\x3a\x83\x28\xd5\xbd\x28\x87\x82\xcb\x5c\x36\x5e\xdb\xc9\x5f\x32\x7f\x8b\x49\x6f\x8e\x3a\xc1\x8f\x7d\x4a\x71\xdc\x4f\x76\x52\xaf\x20\x39\xc2\x5b\xd2\x96\x08\x62\x4c\xd2\x08\xda\xbb\x6d\xc7\xbb\xe7\xf8\x06\xa9\xf6\x1e\x6f\x3c\xbe\xad\xc7\x36\xd2\x72\x71\xc7\xfa\x41\x8e\xed\xa8\x5b\x3a\x00\x3a\x12\x5f\xd7\x33\x0a\x74\x64\x36\x83\xc9\x72\xf5\x88\x8e\x77\x17\x67\xc6\x99\xa4\xf7\xb3\x16\x60\xd4\x89\x81\xe0\xd4\xa3\x2a\x1d\xe2\x04\x16\xf6\xef\xef\x3f\xc3\x2d\x8d\xa8\xae\x45\x09\x08\x1f\x1c\x41\x3f\x6a\xa4\x7e\x03\xf9\x71\x62\x1a\x18\x6e\x68\x21\xfb\xaf\x29\x2d\xaa\xfc\x4e\x56\x8f\x25\x96\xcc\x80\x67\x90\x4a\x63\xfb\xc8\xbd\xeb\x6e\x1e\xb7\xdf\x1c\x2e\xac\xdb\x47\xf4\x6a\xd9\x6f\x05\x17\x65\x9c\xdb\x56\x71\xd1\xad\xe0\x82\x54\x83\x6d\x5a\x76\x1b\xb0\x04\x29\xf6\x35\x68\xe9\x6a\xbd\x12\x21\xf3\xfd\xd6\x2c\x4f\x12\x09\x35\x6c\x3a\x88\xb1\x6c\x83\x38\x9b\x75\x8f\x67\x3c\xa2\xfb\xcd\xc3\xb6\x7e\xbb\x74\xe3\xc0\xdd\x35\x20\x46\x4e\x04\x11\x9a\x89\x28\x64\x7d\x8f\x5d\xbc\x2e\x9c\x26\xd1\x68\x5b\x44\x84\x83\x06\xf5\xdc\x18\xd6\x12\x23\xb1\xbd\xf1\x47\x74\x50\xf1\x61\xa2\x5c\x47\xcd\x9a\x22\x89\x02\x5d\x31\x33\x14\x76\x61\xa3\x5e\x18\xdc\x84\x64\x78\x9f\x90\x48\x96\xb1\x4f\xf3\xd2\x69\x28\x30\x27\x84\xd1\x64\x4d\x6e\xd9\x76\x01\xb2\x2e\x9a\x26\x21\x05\x85\x1a\x4d\x58\xd7\x33\xaa\x9a\x8d\xef\x6a\x47\x5b\x6c\x4f\x27\xfd\xbc\x71\xdb\x63\xeb\x09\x6b\x8e\x76\xd5\xa0\x91\xb5\x89\xf5\x43\xa5\xd1\x31\xc9\xfd\x5a\x48\xe3\x4e\x32\xae\xa5\x5b\xb6\x05\xb1\x96\x88\x3c\xca\xba\xa9\x1f\x43\x00\x56\x0d\xf2\x9c\x76\xea\x16\xb5\xe4\x60\xa9\xfe\x81\xd8\x46\x59\x04\xce\x63\xe7\xbc\xeb\xb4\x28\x7d\x89\x04\x54\x81\x9d\x15\x80\xa0\x9b\x37\x22\xfc\x1d\x40\x1a\x85\x0c\x35\xc9\xf2\xb8\x0c\x72\x8f\x26\xac\x5d\x33\x5d\x0b\x60\xd9\xb9\x34\x7d\xef\x81\xea\x90\x15\x45\x5e\x72\x4c\xd0\xa8\xff\x94\x4c\x55\x45\x5c\x6a\x56\xfd\x40\xce\x9d\x9e\x39\x93\x92\x20\xf8\xfb\x86\x96\xb7\x2c\x75\x4d\x6d\x96\xd0\x5b\x6b\xc8\x0e\x59\xbc\x56\xdb\x88\x0a\x0d\x44\xba\xf5\x8b\x71\x07\xb4\x7e\xd4\xcf\xf1\x72\x89\x1d\xb3\xda\x8a\x74\xa3\xe9\xc4\xdf\x38\xf5\x33\x50\x90\xec\x6a\x5d\xb4\x80\x3a\x02\xd0\x8b\x81\x1d\xc0\xa9\x1e\xd5\xa3\xd3\x7f\x4c\xb0\x97\x46\x3b\x5f\xeb\x67\xb0\xb0\xc5\x67\x58\xdf\x27\x7c\x16\x7a\x86\x83\xbe\x3f\x70\x21\x86\xdf\x03\xf8\xdc\xb2\xa0\xd9\xb8\xfb\x34\x93\x06\x8d\x1c\xac\xef\xb9\x21\x3b\x40\xc6\xf5\x78\xc2\x27\xbe\x39\x63\xc7\xd8\x3b\xda\x34\x0e\x24\x49\xfc\xb6\x8e\xed\x0d\x1b\x07\x53\x6c\x6f\xf0\xb8\xd3\xba\x71\x30\xd5\xfe\x56\x8f\xd8\xc4\x71\x30\xd1\x98\xa6\x8f\x83\x89\x86\x1b\x51\x0f\x26\x19\x61\x8d\x0c\x1f\xe6\xe8\xc6\x91\xf5\x33\xae\x0b\x16\x3e\x43\x9b\x49\xd6\x4f\x7c\x5b\xc9\xfa\xd9\x3b\xf7\xee\x16\x2b\xea\x02\xb3\xc1\x6b\x68\x3b\x4a\x6e\x68\xe1\x94\x2a\x25\x96\xe4\x9d\xb9\x15\x47\x6c\x0b\xcd\xeb\x0e\x93\xa6\xb4\xac\x79\xc5\x8e\x3a\x39\x30\x49\x96\xb1\x0d\xcb\x95\x81\xc0\xb0\x64\xe1\xda\x1d\x4c\xd4\x21\x48\x98\x3b\x70\xd8\x8d\x6d\x06\x36\x5c\x78\xc6\x26\x12\xe2\x33\x2c\x9d\x70\xc0\xe8\x9f\x20\xf1\x10\x9f\xf8\xf4\xc3\x01\x44\x21\x51\x31\x3a\x09\x11\x9f\x11\x7b\x67\x35\xcf\x49\xdd\x0d\xb7\xae\xa2\xa9\xa1\x31\x0f\x98\xad\x28\x89\x16\x77\x60\x0c\xd8\xab\xce\xb4\x45\x1a\x38\xfb\x18\x17\xaf\x99\x48\xdd\xb0\x7e\x36\x8b\xde\xa3\x19\x39\x6e\x6d\xf9\xff\xad\xd9\xf4\xe0\x48\x86\xa2\x5e\xeb\xb0\x3a\xab\xd7\x25\x12\x57\xbe\x7e\xb4\x3c\x7f\xc6\x66\xc7\xde\xd4\x7e\xd4\xf7\x4f\x64\x0a\xd0\xde\x50\x1a\x70\xe2\xc6\x69\x5c\x2b\x2a\x35\x04\xf9\x20\xaa\x36\xb1\x04\x24\xd2\x73\x35\x67\x1e\xc9\x3c\xb9\x1e\xd4\x06\xb9\x7e\xba\xba\x6e\xd6\xad\x91\x87\xae\x2e\x3e\xc2\x26\x5f\xa7\xaf\xb1\x37\x32\xcd\x73\xa1\x80\x03\xe4\x09\xc9\xe8\x8a\x65\x83\x9c\x2b\xf8\x80\x53\x49\xab\xa4\x5e\x82\x51\xc9\x06\x77\x30\xae\x9f\x91\xac\x40\x46\xb2\x03\x01\x96\x80\x15\xbd\x1c\x6a\xbf\x8f\xe7\x0d\xfd\xd4\xb7\xf5\xf0\x77\x77\x83\x82\x48\xc7\x6e\xb1\x4c\xd6\x6c\x13\xeb\xe5\x6d\x3e\x00\x4e\x6e\x17\x43\x4b\xd6\xfb\x92\x2b\xc5\x10\x11\x95\x95\x9b\x61\x42\xc6\x3e\xe2\x7a\xa7\x7d\xf0\xdd\x77\x47\xc3\xcd\xb5\x09\xf6\x36\xb1\xe7\x31\x04\x07\xd3\xf5\x34\xa3\x10\x1e\x28\x05\x3a\x7f\x47\x58\xde\x04\x52\x66\x33\xe8\xa4\x90\xef\x38\x3a\x4f\x2f\x2f\xc8\x1d\xee\xe9\xa3\x2e\xd3\xc1\x2d\x31\xf0\x39\xb8\x25\x0e\x6e\x09\xf3\x4c\x76\x4b\x78\x57\xbd\x15\xbe\xa3\xbc\x12\x4d\xd7\x86\x8f\x18\x6c\xfc\x15\x23\xce\x8e\x4d\x2a\xf0\xf0\x37\xf5\x59\xb4\x9e\x8a\x41\x0d\xf6\xf1\xf1\x21\x2d\x8f\x8f\x97\xcb\xe3\x63\xeb\xef\x30\x07\xbd\x52\xd7\x8b\x3f\x0e\x26\xcb\xf2\x44\xa4\xcc\x74\xcf\xbd\xe6\xa5\x54\xa0\x74\xd7\x86\x3f\xae\xcd\x60\xba\xb0\x96\x1b\x3b\x77\x3f\x56\x01\x63\x1f\xc7\xa2\x23\x24\xb4\xcd\x92\xf9\x71\x16\xe5\xb2\x56\x29\x1d\xb8\x4d\x44\xb1\xc5\xee\xd3\xc0\x25\x33\xba\x65\x9d\xcd\x83\x9d\x90\x47\x38\xc2\x52\xd0\xe7\x98\x54\x92\xbc\x40\x22\xcb\xa4\xa8\x4e\x0c\xc1\x25\x36\x5a\x1e\x2e\xb5\x2c\x51\x4d\xac\xf1\x2b\x86\xe2\xcb\xe1\x43\x2d\x19\x49\xaa\xb2\x64\xb9\xca\xb6\x5f\x9b\xe6\x1b\xd5\x70\x63\xff\x99\xa2\xf8\x3a\x5e\x89\x29\x91\x68\x7b\x76\xca\x26\x1c\x18\x33\xb8\x07\xe3\x9b\x9a\xb7\x3d\xd7\x0e\x54\x5f\x9e\x38\x97\x15\x7c\xca\xf2\xbb\x51\x14\xef\x68\x19\x2c\x6a\x68\x7b\x26\xe9\xba\x29\xbf\xe3\x52\x04\x8b\xb1\x5a\x5f\xdd\xf7\xba\x71\x03\x6e\x2d\x2a\x55\x54\xc3\x9d\xc5\xc4\xdd\xab\x56\x0c\xdb\x6e\x2b\x4e\x4a\x0c\x3f\xc6\xa4\xce\x9a\x43\x93\xe2\xbb\x30\x2e\xce\xfe\xf3\x6c\xfb\x94\xb7\x3d\x51\xbd\xcb\xdb\x9e\x61\xfd\xcc\xfb\x28\x8c\x64\xc7\x09\x7d\xcf\xbb\x1e\xcb\x3a\xd3\xe5\x47\xad\x76\x8d\x94\x85\xf8\x00\x3a\xa6\xbe\x4e\x1f\xe1\xb0\x63\x86\xec\x6c\xbe\x64\xd3\xb4\xef\x90\x1a\xf6\x0c\x53\xc3\x0c\x0a\xc8\x21\x2f\xec\xef\x36\x2f\xec\xca\x74\xc3\x6c\x4d\x0a\xc3\x54\xaf\x01\x44\x23\x92\xc2\xc0\xce\x19\x40\x32\x22\x29\x0c\x02\xc4\x83\x0e\xd2\x21\x29\xec\x90\x14\x76\x48\x0a\x1b\x36\xf6\x83\xf7\xf5\xe0\x7d\x3d\x78\x5f\xa3\x9f\x43\x52\xd8\x21\x29\xec\x90\x14\xd6\xfe\x7c\xbd\x49\x61\xc6\x60\x1a\xa4\x14\x9b\x8c\xb0\x47\x4b\x08\x33\x2d\xbd\x4f\x93\x44\x54\xb9\xfa\x28\x6e\x59\x64\x0e\x40\x94\x31\xbf\x47\x3b\x72\x1e\x8f\x92\x20\x36\x4c\xd9\x1c\xa0\x36\x0e\x57\x18\x69\x95\x72\x6d\x8e\x8f\x64\xbe\x53\xf3\xba\xb5\x7c\xf5\x95\x97\xa7\x2c\x75\x74\x07\x30\xa0\x11\x41\x4a\xef\xd6\x92\x9c\x92\x92\x25\xbc\xe0\x5a\x30\x03\xfc\x0f\x7c\x3e\xd4\x2c\x73\x3d\x3e\xb9\x92\x2c\xbb\x36\xfd\x0f\x73\xaf\x91\x78\xad\x7b\x0d\xb7\x4a\xed\x24\x1b\x43\x47\x3d\x44\xd8\xb6\x77\x03\xa8\x9a\x1e\xee\x25\xfb\x0f\xab\x1a\x99\xb5\xf8\xe8\xff\x56\x1a\x8b\x90\x56\x3f\xc6\x59\xe0\x4d\xda\x0c\x98\x16\x3c\x16\xcb\xce\xd1\x1a\x2e\xe0\xd8\x97\x82\x97\x70\x44\xaf\x58\x22\xf2\x74\xac\x8b\xea\x7c\x97\x8e\xe5\x3a\x13\xbd\x1a\xb4\x85\x69\x85\xa4\xa0\xc0\x97\x66\x3c\xe5\x6a\xeb\x72\x87\x50\x7c\x10\x8a\xf2\x63\xd0\x4a\x23\xf3\xca\x7a\xfb\x08\x2d\x8a\x52\xd0\x64\xcd\xa4\xb7\x12\x43\xee\x21\xd0\xa0\x10\x7a\xc4\xd5\x22\x67\xd5\x0d\xcf\x51\xcb\x07\xea\x5a\x65\x8b\x00\x7b\xa8\x9f\x52\x28\x9b\xec\xb8\x33\x5d\x9f\xeb\xcc\xcf\x0e\x75\x56\xa1\xcb\x42\x95\x5b\x80\xd6\x12\xfe\x8f\xe1\x9a\x44\x00\xe4\x34\xe7\x6f\x5e\x93\x44\x64\xa9\xc5\x4b\xfd\xe3\xb7\xa4\x60\x65\x62\x24\xc4\xb0\x00\x2b\xe0\x65\x2a\x41\x32\xad\xea\x8a\xd2\xa2\xb2\xb6\xfc\xcc\x00\xa2\xbf\xff\x9e\xac\x45\x55\xca\xa5\x0f\xce\xf1\x1d\x7c\x86\x4e\x21\xbc\x5a\x87\x38\xd4\x14\xc9\x18\x95\x8a\x7c\xf7\x2d\xd9\xf0\xbc\xd2\x1a\xd5\xc0\xa3\x3a\xd4\x0a\xf1\xec\x8f\x3f\x7c\x1f\xf9\xd6\x30\xcb\x63\x3f\x8f\xcc\x9c\xe3\x02\xbb\x8e\x19\x03\x64\x90\xd1\x0e\x6d\x11\x80\x7b\xb1\x97\x60\x33\xdb\xc3\x5e\xe7\x03\x8d\x19\xc3\x0d\xb9\x12\x33\xcb\xc7\x5f\x2b\xb1\xda\xaa\x78\x60\xa3\x7f\xc5\xef\x37\x11\x8d\xec\x87\x7b\x08\xb2\xbd\x63\xdd\x6f\x76\x59\x03\xc8\xf6\xbc\x38\x73\x67\xdd\x1b\x2e\x55\x6f\xe3\xd6\x45\xd8\xa5\x1f\xab\xec\xdc\x94\xa2\x0a\xa2\x08\x34\x96\x1b\xfc\x09\xd6\x7e\x35\x12\x97\x26\x09\x93\x70\xa0\xcf\x5c\x07\xfb\x20\x53\xe4\x02\x7f\x3d\xf0\xc5\x27\x04\x8e\xb7\x4c\x14\x19\x40\x79\x48\x20\xd7\xa8\x45\x8a\xb1\x2f\x2c\x7b\x0d\x5c\x25\x7c\xa9\x79\xc6\x24\xcf\x6f\xa0\xd5\x21\xd9\x54\x99\xe2\x45\x44\x6d\x84\x5d\x51\x47\xd0\x5c\xaf\x7e\x50\x84\x7a\x5e\x72\x1a\x5e\x22\x7d\xa8\x11\x3c\x1c\x82\x6b\x2f\xec\x58\x08\xcb\x15\x80\xd0\x40\xb6\x39\x2b\x68\x49\xed\xb6\x04\x69\x26\x62\xb3\xa1\xf2\xa5\x89\xcf\x50\xc8\x80\x42\x29\xac\x2f\xd4\x92\x66\x6e\x19\xfd\x7c\x90\xb9\x18\x59\xb1\x9c\xe6\xc1\xe0\x6d\xd3\x39\x05\xaf\x10\x71\x9f\xdb\x36\x38\xd8\xb9\x79\x20\x07\x1b\xd5\xfd\x07\x9a\xdc\xb2\x3c\x25\x9f\xa4\xe5\xe3\x74\x9b\xd3\x8d\x81\x55\x77\x8d\xd5\x59\x6a\xe9\x07\x09\xbb\x8c\x19\xc4\x0d\x42\x44\x1f\x0b\x62\x86\xfa\xda\x5c\xab\x57\xc9\x81\x18\xc3\x9f\xa4\x56\x66\xfa\xe5\x59\x94\x97\x5c\xb2\x92\xdf\x25\xcc\x6a\x8a\x7a\x20\x73\x4d\xea\x2e\x88\xf5\xb7\x37\x2d\x83\xf3\xc7\xbd\xd3\x04\xd7\x9b\x0b\x32\x03\xca\x3a\xcd\xb4\x88\x0a\xeb\xc6\x16\x33\xaa\xc9\x50\x7a\x07\x67\x6b\x0e\x5e\xae\xe2\x01\xc2\x8e\x3f\xfc\x70\xd6\x14\x46\x1f\x68\x2a\x24\xf9\x21\x13\xc9\x2d\x39\x63\xa0\xb2\x87\xbb\xea\xef\x22\xcb\x47\x35\xba\xee\xa5\x18\x6a\xb6\x57\xae\xd2\xa7\x68\xb5\xb7\xa1\x37\x7d\x87\x74\x41\x36\x22\xe7\x4a\x94\x73\x40\x95\x1d\x1a\xbb\xfd\xcd\x34\x76\x2b\x57\x61\xaf\xc1\xd7\xda\xd6\x4d\x1f\x89\x81\x1d\x50\xd7\x8c\x94\x20\x66\xe0\x65\xdb\xcb\x23\xbe\xd3\x66\xe3\xf0\xff\x66\x2d\xee\x17\x4a\x2c\x2a\xc9\x16\x3c\x98\x13\x16\x3d\xaf\x5b\xb6\x85\xa4\xb9\x41\x33\xfb\x09\x5f\x6a\x98\x9a\x4a\x80\xc7\x1b\x3e\xd7\x4a\xce\x87\x1f\xce\xf4\x4d\x19\x8f\x68\xcd\x25\x79\xc5\x54\xf2\x2a\x61\xc5\xfa\x95\x19\xd6\xb3\x5b\x2e\x2b\xf7\x86\xad\xd7\x29\x49\x44\x96\x19\x9c\x39\x71\x4d\xde\xb0\x62\xed\x48\x0d\x0a\x0f\x3d\xf8\x1a\x3c\x45\x0b\xaf\x42\x88\x61\x6d\x85\xbc\xa3\xa5\xdf\x35\x27\xcb\x63\xa4\x72\x95\xce\xda\xd3\xff\x31\x58\xeb\x01\xba\x8a\x44\xe3\xd6\x76\x41\xd3\xb6\x74\x32\x7b\x56\xdc\xfa\x70\x1d\xd3\x8e\xaf\xec\x6b\x90\x6f\xe7\x85\x75\x07\x35\x40\xb3\x3f\xdf\x10\x89\xe4\xe2\x1a\xad\xa2\x94\xa5\x44\xdc\xb1\xb2\xe4\x29\x93\x56\x14\x0f\x92\x98\x39\xcf\x1e\x57\x46\x1e\x7a\xb9\x75\x3e\x5f\x47\x2f\xb7\xc1\xf6\xae\x27\x6c\xf5\xbb\xfb\xc2\x96\xa6\x1b\x1e\x51\x56\xfc\x8c\x6e\x72\x99\xd0\x8c\x5d\xfc\x1c\x6d\x3e\x5e\xe1\xf7\x9b\x16\xa4\xfd\xd0\x6b\x59\x31\x01\x0e\xff\x27\xc7\xa7\x24\x17\x69\x7f\x64\x62\x56\x5b\xef\x86\x2a\x76\xdf\x7b\xe5\x2f\x6a\x11\xda\xff\xad\x50\x63\x89\x43\xf3\x8b\x5d\x03\xce\x3b\x45\x88\xab\x3f\x97\x32\x61\x76\x75\x98\x53\xd0\x4e\xb1\xee\x93\x85\x09\x30\x86\xd1\x4f\x2f\x2f\xc8\x9f\x90\xee\x7c\x5d\x36\x4a\xa1\x50\x2f\x3e\x13\x1b\xca\x07\x36\x69\xf6\x5a\x1a\xf9\x03\xbd\x74\x44\x09\x52\x0d\x6e\x8b\xd7\x79\xfa\x9a\xdf\x54\xda\x8e\x36\xb6\xed\xa1\x31\x41\x60\xea\x0f\xa7\x82\xd5\x1a\x98\xe7\x83\xb4\xb5\x1a\x4e\xab\x0a\x4e\xdd\x72\x05\x5c\x5e\x2e\x9d\x84\x48\x96\x4b\x0e\xb1\x51\x2f\xed\x09\x54\x33\xb5\x8e\x88\x46\xb9\x22\x0c\x54\xe3\x4e\xc8\x5b\x71\xc3\x73\x2b\x1d\x84\x49\x27\xb8\xa6\x3c\x8b\x5b\xc6\x83\x5e\xd5\xf9\x7c\x1d\x7a\x95\x94\xd9\x79\x4e\x57\x59\x38\x13\xad\x79\x71\x65\x14\xb2\x3a\x18\xbc\xfb\x2a\xe5\x52\xff\x97\x5c\x5d\xbd\x85\xa8\x52\x95\xc7\xda\x19\x10\x77\x31\xe2\xd9\x81\xe3\xa0\xd0\x98\xef\x1c\xa3\x4c\x1c\xdc\x55\xe2\x22\x4f\xf5\x34\x98\x6c\x24\x56\x1a\x6a\xd8\xb7\x23\x36\xe4\x64\xf2\xba\x56\x8c\x7c\x5c\xf3\xe4\xf6\xd2\x0b\x2e\x89\x52\x7f\x96\x7b\x1f\xb9\x0b\x36\xe6\x38\xef\xbe\x3b\x97\xe0\x37\xd3\xbc\x1c\xea\xe4\xf8\xe8\xdd\x68\x57\x66\xa9\x34\x11\x42\xa5\x14\x09\x8f\x8f\x4e\x82\x8b\xae\xbe\x12\x53\xb8\x12\xe7\x9b\x1e\x68\x41\x93\xee\x6d\xcb\x08\x46\x81\xa3\xd2\xbb\x87\x63\x62\x90\x66\x95\x66\x9b\x12\xb2\xe2\xe0\x7e\x8b\x1f\x1b\x1d\x16\x6d\x68\x10\x03\x66\x2e\x20\x16\xd9\xde\xc4\x6e\xbc\xd5\x69\x4d\x03\xdd\x9d\xad\xf7\x3b\x2d\x86\x4f\x0e\x94\x22\xcf\xb2\x48\xe1\x72\xe1\x36\x5f\xca\x4e\x36\x00\x7e\x66\xc2\x68\x70\xa8\x0b\x51\x54\x19\x0d\x84\x87\xfd\xe6\x92\x53\xe3\x15\x38\x86\x19\xc2\x6a\x0f\xdd\x96\xa7\xa3\x10\x6b\xa7\x43\x4f\x58\xcd\xdd\xed\xe0\x13\xd3\xa1\x27\xd6\x1d\x05\x03\xfa\xf6\x0f\xdf\x7f\xdf\xd6\xd3\xa7\xd1\xb3\x27\xac\xbb\x44\xf6\xf4\xd9\x29\xa8\x8a\xbb\x23\x7b\x7b\xfa\xec\xf6\xec\x09\x2f\x69\x44\x4f\x9f\x81\x05\x50\x0f\xd3\xb4\x27\xca\x69\x3f\xa0\x8a\xdd\xd6\xa6\x47\x89\xb3\xbe\xda\xf5\xce\x8a\xf4\x08\xd1\xdf\xa8\x58\x8f\xa9\x43\x8f\x08\x24\x42\x9d\xfa\xac\xd5\xe7\x03\x6a\xce\x1b\x95\xe4\x41\xc2\x7d\x95\xe6\x9d\xf5\xe3\xf1\xa6\x0d\xd0\x8a\xaa\x1a\x0f\xd2\x8c\x6e\x20\x12\x9d\xd7\x1b\x55\x21\xde\xac\xfb\x8e\x93\x0f\x31\x55\x66\x0f\xdb\x94\xaa\xa7\xf2\xdb\x55\x73\x47\x98\x2e\xb1\xf5\xde\x83\x4a\x6e\xe2\xcb\x6d\xe2\x2a\xba\x23\x0b\x72\x86\x15\xe3\x44\xd7\x6c\xcf\x52\xa9\x3d\xb0\x8a\x23\xbe\x2a\x7b\x88\x0a\x10\xe5\xb4\xc0\xa7\xb5\x02\xbb\xa3\xa2\x3a\x92\x64\xb3\xee\x3a\x50\x47\x1d\x49\x13\xaa\xad\xa3\xaa\xa7\xed\x65\x1e\x49\x38\x70\xe5\x37\xae\xf4\x68\x92\x73\x5c\xfc\x86\xd6\xe0\x4a\x83\xa1\x55\xce\xf1\x15\x06\x51\x15\xcd\x03\x61\x20\xbb\xeb\x98\xf7\xeb\x92\x23\x49\xbe\x6b\x11\xff\xdd\xd5\xc8\x91\x44\x3d\xa8\x90\x51\x35\xc8\xd1\x62\x21\xb6\x66\x35\xbe\x52\xd5\x75\x24\x08\x0e\x74\x58\x81\xea\x50\x8f\xef\x60\x13\xba\xe1\x7f\x34\x16\xa2\xdd\x4f\xcc\xb0\x74\xa8\xe0\xe1\x6b\x0d\x64\xe3\x23\xd8\x88\x24\xda\x6c\x46\xd2\xa2\xf7\x0e\x6b\xee\x32\xbe\xf1\xf3\xd5\x4e\xe8\xd1\x7d\x6c\x35\x5f\x13\x55\xec\x0f\x3d\x3e\x78\xc4\xf1\x10\xe0\xfb\x5a\xba\xdb\x1f\xa2\x51\xe3\xa3\x51\xb2\x81\x61\x69\xfd\x58\xa8\x89\xc5\x04\xa4\xc4\xca\x74\xc2\x40\xa1\xed\xce\xf2\xe9\xe5\x05\x49\x4a\x06\x85\xc5\x34\x93\x4b\x32\x02\xd1\xc6\xfa\xfd\x41\xa7\x93\xce\xf2\xa4\x4a\xb1\x4d\xa1\x62\x19\xe8\x10\x8c\xea\x7c\xbe\x8e\x60\xd4\x48\x0f\xf6\x67\xf7\x9a\xf5\x7f\xac\xab\x0d\xcd\x17\xfa\x94\x43\x58\xca\xb8\xb7\xe3\x5c\xd8\x3b\x97\xd4\x92\xd8\x1a\x13\x58\x6d\xa8\xb3\x82\x52\x37\x6c\x3c\x1f\x65\x9c\x03\x8e\x99\x53\x01\x1e\xc0\xe1\x0f\x74\x47\xae\x19\x36\x2b\xd9\x91\x0e\x89\x28\xa2\x57\xcc\x5c\xe6\x66\xa2\x6e\xfd\xac\x20\xf0\x3a\xa2\xf8\x5e\x9d\x18\xd2\xa8\x42\x5d\x42\x81\x6a\x4d\xa5\x81\x6b\x65\x80\xaa\x68\x96\x89\xfb\x88\x42\xc3\x35\x6b\x28\x10\x9a\x2f\xf4\x5c\x4d\x8d\xfa\x8a\x91\x0d\x2f\x4b\x51\x9a\x40\x45\x84\x9b\xb0\x66\x17\x48\xc6\xd0\x16\x1f\x2b\xd1\x0c\x2a\x4d\x6c\xfe\x8a\x29\x6f\xb9\x63\x14\x40\x9a\x63\xc1\x91\xfe\xb7\x4d\xb4\xc4\x6e\x57\x46\x4e\xae\xd8\x9a\xde\x71\x51\x95\x40\x3d\x86\xe4\x91\x79\x55\x5f\xdd\x64\x2b\x2a\xd7\x84\xbe\x82\xda\x03\xb7\xba\xd1\xdd\xec\xbd\x7d\x7e\x5f\xbf\x0c\x46\x6a\x2a\xac\x27\x6e\xc1\xbe\x70\xa9\x86\xaf\xa5\xdd\x62\x0b\xb7\x3f\xc7\x89\xb9\x93\x85\xbe\xc0\x3f\x07\x6b\xcc\x9a\xe7\xc4\x7f\xab\xa9\xce\xde\x5d\xc1\x9f\xa6\x28\xb3\x06\x5b\x41\xa2\x0a\x67\x8a\x3f\xa6\x2b\xb4\x71\x29\x74\x38\xee\x40\xb7\x9f\x83\x6e\xfc\xb5\xe8\xc6\x2e\x60\x9f\xf1\x64\x7b\x71\x36\x4c\x4b\x74\x81\x7a\xfd\x32\xf9\x81\x4a\x96\x92\x77\x34\xa7\x37\xe8\x88\x78\x71\x75\xf9\xc3\xbb\x70\x47\x80\xa2\x14\xe0\x54\xb9\x38\x6b\x09\xf9\xba\xab\x15\x7f\xe4\xfd\x5c\x05\x95\x7b\x73\x1f\xac\x3f\xcc\x3c\xfb\xd9\x4a\x45\x89\xbb\xe3\x63\xda\x35\xed\x43\x6a\x60\xf8\xdd\x22\xfe\xc8\x5d\x81\x75\xb7\x49\x6f\xc7\x0f\x93\xe7\x52\xd1\x2c\xbb\xcc\x68\x7e\x5a\x14\xa5\xb8\x6b\xf3\x04\x35\x81\xa2\xcc\xd7\xac\x92\x86\x99\x6d\xf6\xc3\x02\x17\x1f\xb2\x6a\x72\x72\x51\x53\xdf\x5f\xca\x9e\x51\xb5\x6b\xec\x3d\x2f\x74\xa1\xa7\x07\x5f\xe9\x51\xbb\xfa\xde\x55\xb4\xd4\x82\xe8\xcd\xd5\xe7\xe8\xf7\xa4\xa2\xaa\xda\x11\xbf\x9d\x17\x41\xbb\xe8\x5f\x90\x8c\x4a\xf5\xa9\x48\xf7\xe2\xed\xdd\xf2\x3d\xa1\x8a\x66\xe2\xe6\x5f\x18\xcd\xda\x98\xaf\xb1\xb5\x6f\xfc\xef\x5a\x7f\x26\xee\xf2\x55\xb5\x72\x5f\x3c\x96\x44\xdb\x34\xdd\x50\x3d\x25\xcb\xd8\x1d\xcd\x95\x25\x78\x85\x6d\x11\x8e\xcd\x1a\x2c\xc9\x05\xc4\xe0\xb4\xe6\xa7\x65\x6e\xca\x14\x2b\x37\x3c\x6f\xfe\xca\x15\x7c\xf7\x8d\xc8\x53\xde\xe5\x5f\x07\x7f\x30\xd2\x68\xfe\x52\x17\xb3\xb5\xc7\xcc\x3a\xa3\x64\x4d\xf1\xe2\x8d\xad\xb9\x50\xf8\xb5\x95\x51\xba\xd7\xf8\xa1\xb8\xee\x08\x93\x35\x46\xba\xb7\xb6\xe4\x36\x17\xf7\x12\x01\xf0\xda\xa4\x4f\x40\x75\xe8\x53\x19\x16\x96\x17\xf0\xa7\xdb\x13\xea\x17\x66\xfc\x6d\x6e\x94\x6e\xf6\xc3\x27\xa4\x64\xec\xfe\x7c\x97\x28\x6c\xe3\x49\xf7\x12\x62\x04\xb8\x00\x3e\x06\x27\x1b\x5f\xea\x12\xda\x11\x5a\x57\x8c\x9a\x14\xd7\xe8\xb0\x29\x32\xeb\x06\x78\x7b\x1e\x85\xa0\x9a\x18\xb8\x5d\xa2\xfa\x00\x36\x3d\x1b\x17\x26\xa7\xb9\x34\xf6\x12\x25\x05\x67\x88\x7d\x47\x73\xb3\x40\x70\x31\x30\xda\xaf\x06\xe3\x0b\xfa\x62\xd2\xd6\x34\xbc\x77\x62\xd2\x65\x30\x5e\x61\x52\xab\x6c\x64\x84\x22\x3e\x5b\x2f\xcd\xff\x7d\xf5\xf3\xfb\x57\x7f\x12\x26\x5f\xc3\x60\x5b\x68\xb9\x01\x97\xf8\x09\x91\x55\xb2\x26\x54\xea\x29\x69\x46\xd7\x52\x82\x2d\x37\x34\xe7\xd7\x4c\xaa\xa5\x6b\xc6\x23\x7f\xf9\xfd\x5f\xfa\x6f\xef\x1f\x45\x49\x4c\x09\xd0\x89\x05\x0d\x33\x73\xaf\xb9\x8b\x4b\x5c\x20\x47\xb7\x97\xa4\x73\x12\x14\x22\x35\x0b\x71\x0f\x0b\xa0\xe8\x2d\xc4\x49\x6d\xb8\x33\xe3\xb7\xec\x35\x39\xd2\xda\xa3\x37\xe4\xff\xd4\xd7\xde\x7f\xf7\xd7\xcd\xbf\xb8\x87\xbb\xff\x48\x7f\xf5\x08\x07\xea\xd2\xd2\xfd\xac\x46\x47\x15\xd4\x87\x5e\x92\xaa\xe4\x37\x37\x0c\xf4\xdf\x35\x23\x50\x0f\xff\xd2\x00\xa9\xe5\xc2\x23\x64\x13\x5a\xe2\x6c\xff\xdd\xc9\xfd\xf2\xfb\xbf\x1c\x91\x17\x35\x35\x50\x27\x79\x9e\xb2\x2f\xe4\xf7\x18\x65\xe1\x52\xaf\xdb\xcb\xfe\x5d\x03\x37\x81\xdc\xe6\x8a\x7e\xd1\x63\x49\xd6\x42\xb2\x1c\x3d\x39\x4a\x90\x35\xbd\x63\x44\x8a\x0d\x23\xf7\x2c\xcb\x16\x26\xae\x44\xfa\x2b\x8c\x80\x8f\xed\x96\x03\x8e\x0f\x29\x68\xa9\x1a\xc7\x61\x69\x5c\x6f\x30\x4a\xcd\x7a\x37\xfd\x76\xb0\xc9\x62\xb9\xe6\x39\xcd\x4c\x72\x16\xa0\x8f\x6b\x9e\x06\x8c\x06\x64\x34\x25\x48\xb2\xa6\xf9\x0d\x33\x71\xa6\x7e\xdb\xac\x52\x55\xc9\x7a\xe3\xb8\x51\x12\xe3\x96\xe7\x03\xb0\x4b\x7e\xe2\xf9\x6e\xda\x54\xbb\x1b\xf4\x86\x2b\x5b\x49\x67\x72\xc7\xd5\xf6\x95\xde\xef\x92\xaf\x2a\x25\x4a\xf9\x2a\x65\x77\x2c\x7b\x25\xf9\xcd\x82\x96\xc9\x9a\x2b\x96\xe8\x09\xbd\xa2\x05\x5f\x24\x22\xd7\x7c\x07\x80\x53\x9b\xf4\x37\x7a\x1e\x72\xa1\x07\xda\xdb\x6c\x2a\x6a\xba\x21\xef\xef\x93\x7a\x7d\x67\x99\x5d\xd0\x6d\xb8\x3f\x45\x74\xc1\x3d\xc2\x3c\xc1\x9f\xf4\x6a\xf2\x34\x6d\x2f\xa3\xa1\x37\xef\xb1\x69\xf9\x95\xec\x52\xd0\x47\x0f\x01\xb3\xe0\x64\x3a\x89\x1f\x3a\xd5\x1b\x9a\xe2\x75\x41\xf3\xed\x83\x1f\x03\xbd\xd0\xd0\x89\x2f\xd9\x2e\x80\x84\xc8\x16\x34\x4f\xf5\xbf\xb1\xe8\x33\xd9\x4e\x5e\xd9\x8a\x0f\x10\x06\x9f\x2e\xce\x1e\xe7\x70\x54\x7c\xe2\xc9\x37\x5a\x6c\x94\x8a\x89\x6a\x3c\x64\x2b\xaa\xb2\x62\x56\x19\x68\x2a\xea\x5c\x5a\x9a\xff\xab\x5b\x17\x83\xb0\xa4\x03\x0c\xee\x57\x44\xfb\x82\x85\x9e\x9e\x1d\x35\x83\xb7\xf5\xf7\x7d\xe7\x26\xa4\x8a\x52\xa9\x0c\x46\xaa\x05\x15\x6a\x4c\x0c\x27\xdf\x39\x25\xbc\x9e\xba\xae\xfa\x08\x0e\xb3\xe9\x41\x7a\x70\x8b\x16\x68\xca\xc4\x19\x78\x21\xe3\xd4\x7d\x11\x4d\x80\x8c\x4b\x07\x0e\xaa\xcd\x40\xa9\x08\xbd\xa3\x3c\x83\x50\x91\x58\x49\x56\xde\xd1\x2e\xc3\x11\xf1\xc5\xe9\xae\x55\x6b\xda\x5e\xa2\xba\xf9\xe0\x36\xa4\x9d\xcf\xfe\x8e\x35\x27\xd3\xba\xb0\xfe\x04\xb1\xe4\x63\x67\x2e\x1d\x73\x98\x68\x41\xa2\x01\xdf\xfa\xa7\x0e\x7c\xaa\x90\x49\xa5\xf9\xf3\x5f\x18\x2d\xd5\x8a\x51\xf5\x91\x77\xdf\xd5\x7b\x0c\xdf\x78\xcb\x7a\xa3\x6a\x76\xbf\x67\xe4\x46\x28\xad\xc2\x55\x70\x32\x3a\x59\x1c\xf4\x72\x44\x20\x74\xcc\xf8\x70\xfc\x5e\xcf\xfa\x63\x49\xa1\x08\x54\xe4\x83\xa6\xdd\x7c\x6d\x7f\xde\x46\xfb\xef\x9d\x87\x56\xfa\x81\x0a\xe0\x5b\x11\x91\x33\xb3\xb3\x18\xb6\xea\xeb\x0a\x33\xdb\x12\x6c\x98\x94\x3d\xa8\x56\xcd\x9c\x64\xfc\x2e\x1e\xfc\x9d\xa8\xf0\xc6\xfe\x0d\xcb\xfc\xfa\xee\xba\x94\x29\xca\x33\xe3\x5d\x31\x4b\xe6\x56\xb3\x5f\x5a\xf7\x4c\xb8\x64\x54\x76\xab\x24\xbb\x00\xae\x52\xe4\x38\x0d\x91\xb3\xc5\xbd\x28\x53\xf2\x86\x6e\x58\xf6\x86\x4a\x66\x28\xf9\xf5\xe0\xb8\x8b\xc7\xdd\x21\xd1\xb9\x26\xd1\xe6\x9d\xec\x98\x04\x3a\xe6\x2c\xe3\x19\xbe\xa9\xcd\x4e\x1c\xf2\x09\x30\x95\xb8\x26\x1f\xcb\xaa\xa7\x1d\xd0\x8f\xfa\xc6\x3c\x21\x9f\xf2\xdb\x5c\xdc\x8f\x1f\xbd\xea\x09\x5a\x35\xb3\x48\xb7\x85\x3b\x32\x16\xbb\xaf\xe1\x7e\x73\x13\x18\x31\x16\x73\x7d\xb4\x3a\x85\x9b\x57\x99\xfb\xa2\x1d\x8b\xfe\xe7\x9e\x2b\x50\x1b\xc4\xa5\xb8\x29\x99\x94\xed\x13\x6f\x43\xb3\x8e\xf3\xf5\xff\x89\xe5\xa6\x54\x3c\x30\xd4\x8b\xb6\x77\xec\xa8\xed\x7d\x79\x53\xff\xa5\xb3\xcd\x90\xf9\xf1\x22\x6b\x51\x79\xfa\x92\x8e\xbd\x41\xb7\xba\x0c\xbb\x46\xdb\xee\x2a\xf4\xee\x57\xef\xbb\x6d\x4b\xab\x95\xa5\x3e\x0f\xb8\x9d\xfb\x9b\xab\xcf\x5d\x9b\xd0\x71\xc7\xf6\xdf\x88\x21\xf7\xe2\x34\xc7\x62\xe0\x24\x05\x9c\x89\xe3\xdd\x88\xdd\x49\x28\x63\x1c\x88\xd6\x49\xd8\x75\xff\x3c\x9c\xeb\x70\x9c\xd3\xb0\x3f\x73\xe2\x61\xdc\x85\xe3\x1c\x85\xb5\x33\xb0\x4b\xfc\x0d\x73\x11\xb6\xba\x01\xbb\x46\x1c\xe3\x1c\x6c\x77\x00\x76\x50\x0c\xbb\x05\x3b\x5d\x7f\xdd\xdc\xda\xe9\x10\x0c\x38\xfd\x3a\x28\x76\xb9\x02\xfb\xdd\x7d\x81\x73\xdc\xed\xe2\xfb\x1a\x9c\x7b\x81\xc9\x75\x3b\xf4\x9e\xa1\x2b\x2f\x62\x2e\x3d\xee\xbb\x67\xea\xb8\x0b\x4c\x2a\xca\x59\xf7\x20\x6e\xba\xaf\xc6\x41\x17\x58\xc1\x4e\xa7\xdc\xb3\x73\xc7\x85\xd5\x4d\x96\x86\x15\xe2\x0b\xef\xab\xbe\x4a\x6c\x94\x2c\xc8\xd1\x32\xdf\xb0\x19\x61\xbe\x3a\x36\x46\x0b\xd6\x8a\x68\x60\x54\xc7\x66\x58\xd1\x7a\xa4\x55\x84\x5b\x6f\x4f\x6b\xd5\x35\x06\x4e\xce\xce\x2f\x3f\x9c\xbf\x39\xfd\x78\x7e\xb6\xab\xbd\xee\xaf\x77\xaf\x56\xd9\xed\xb7\x59\x78\x3a\x65\xcb\x1f\xb5\x20\x6e\xf9\x38\x6f\x4b\x72\x5d\x90\xaa\x6a\x89\xdf\x4e\xd3\x68\x47\xdf\x65\xa3\xef\x89\xd0\xe9\x8b\x3b\x7e\xfa\xf4\x01\x67\x60\xda\xa3\xd6\x9e\xd6\x22\x4b\xa5\x49\x29\x27\x17\x67\xa6\x10\xe2\x84\xf0\x3c\xc9\xaa\xb4\xdb\x35\xf1\xe9\xd3\xc5\x99\x5c\x12\xf2\x03\x4b\x68\x25\xc1\x77\x95\x8a\xfc\x58\x91\x9f\xdf\xbf\xfd\x3f\x50\xda\x01\xdf\x30\x4a\x22\x37\xcd\x10\x38\xed\xe9\xf4\x80\xb3\x03\x9a\xa8\xd8\xc0\x28\x13\x5a\x68\x59\x26\xb1\xbd\x9f\x02\x2d\x65\xcd\xb2\x42\xcb\xcd\x5b\x46\x1c\xf8\x7c\xd7\x38\x2f\xce\x24\xbc\x83\x49\xf4\x26\x43\xf8\x86\x29\x2c\x8c\xed\x4e\xf2\xed\x59\xf1\x5e\x5f\xf7\x04\x2f\xb7\x7f\xce\x5a\xc6\x64\xfc\x16\xf7\x54\x1a\xff\x60\xcb\xc8\x7b\xf9\x24\xe4\xe5\xea\x72\x0b\x75\x38\x84\x50\x88\xc3\xff\xed\x39\x02\xf4\x20\x6b\x1f\x4f\xab\x74\x51\x02\xca\x2e\xa3\x3c\xd8\x5d\x29\x6d\x6d\x6d\xac\xf6\x3c\x3f\x6c\x77\xe9\x1b\x3f\xe9\xc0\x10\xfb\x16\x7f\x6f\x14\xd0\xb9\x30\x7d\x0d\xd1\x17\xfc\x00\x53\x39\xfd\x4f\xaa\x95\x55\x0d\x9c\x90\x31\x3e\x2b\xf2\x9f\xff\xfd\x4d\xed\xbe\xd2\x66\x5f\xa1\x58\x0a\xca\x12\x7e\x13\x24\x08\x39\x42\xbb\xa3\xc8\xaa\x92\x66\xe6\x7f\xbd\xe0\x03\xf9\xe5\x2f\xdf\xe0\x0f\xb3\xd4\x88\x2b\xfc\xf0\x9b\xff\x3f\x00\x00\xff\xff\x61\xa3\xc0\x75\x4b\x6e\x0c\x00") - -func olmManifestsCrdsYamlBytes() ([]byte, error) { - return bindataRead( - _olmManifestsCrdsYaml, - "olm-manifests/crds.yaml", - ) -} - -func olmManifestsCrdsYaml() (*asset, error) { - bytes, err := olmManifestsCrdsYamlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "olm-manifests/crds.yaml", size: 814667, mode: os.FileMode(420), modTime: time.Unix(1591299779, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _olmManifestsOlmYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5a\x4b\x6f\x23\xb9\x11\xbe\xeb\x57\x14\x84\x00\x4e\x82\x69\xbd\x2c\x7b\xed\x06\x16\x58\xc7\x3b\xbb\xb3\xc8\xd8\x16\x6c\x4f\x2e\x41\x10\xb0\xbb\x4b\x2d\xc6\x7c\xf4\x92\x6c\x69\xb4\x41\xfe\x7b\xc0\x7e\xb3\x45\xc9\x1a\xaf\x9d\xc9\x61\x78\x91\x45\x56\xb1\x8a\xc5\x62\x3d\x3e\x39\x08\x82\x01\xc9\xe8\xdf\x50\x69\x2a\x45\x08\xeb\xe9\xe0\x89\x8a\x24\x84\x5b\xc2\x51\x67\x24\xc6\x01\x47\x43\x12\x62\x48\x38\x00\x10\x84\x63\x08\x92\xf1\xc1\xcb\x18\x33\x54\xc4\x48\xa5\x0b\xf6\x92\xfe\x01\xd5\x9a\xc6\x78\x15\xc7\x32\x17\xa6\xbf\xa7\x57\x78\x50\xef\x13\xe8\x92\x99\x54\xcc\x25\x4d\x21\xdd\xaf\xa5\x8a\x48\x3c\x22\xb9\x59\x49\x45\x7f\x23\x86\x4a\x31\x7a\xba\xd0\x23\x2a\xc7\x8d\xfe\xd7\x2c\xd7\x06\xd5\xbd\x64\xbe\x13\xe8\xad\x36\xc8\xc3\x58\x0a\xa3\x24\x63\xa8\xc2\x46\x17\x46\x97\x18\x6f\x63\x86\x01\x27\x82\xa4\xa8\x06\x2a\x67\xa8\xc3\x41\x00\x24\xa3\x3f\x2b\x99\x67\x3a\x84\xbf\x0f\xff\x3c\xfc\xc7\x00\x40\xa1\x96\xb9\x8a\xb1\x33\xb5\x46\x15\x35\x5f\x03\x10\x52\xdc\x57\x44\x9f\xee\x3f\xee\xa5\xfb\x5d\x27\xfc\x0b\x15\x09\x15\xe9\x73\x66\x8e\x4a\xb2\xc0\x9a\x54\x49\x86\xf7\xb8\xb4\x94\xf5\xb1\x0e\x48\x1d\x00\xec\x9a\xf5\x45\xc6\xd4\x79\xf4\x2f\x8c\x4d\x61\x4f\xaf\xe7\xbc\x8a\x83\x90\x2c\xd3\xad\xa5\x7e\xc4\x8c\xc9\x2d\x47\x61\x9e\xb1\xd0\xee\xc6\x00\x8c\x44\xc8\xb4\xa5\xb7\x96\xca\x7a\x0c\x3a\xc3\xd8\xae\x69\xa3\x88\xc1\x74\x5b\xd2\x99\x6d\x86\x21\xdc\x4b\xc6\xa8\x48\x3f\x65\x09\x31\x58\xf8\x4a\xc6\x68\x4c\x74\x08\x53\xcb\x81\x0c\x63\x23\x55\xc9\xc1\x89\x89\x57\x1f\x3b\xa2\x7c\xc2\x00\x0c\xf2\x8c\x11\x83\x15\x53\xe7\x30\x76\x30\x87\xdf\xbf\x03\x40\xad\x72\xf1\xb7\x63\xfb\xdb\x23\x0c\x6f\x87\xbd\x69\x42\x05\xaa\x8e\xac\xc0\x6f\xce\x7a\xc4\x92\x73\x22\x92\xb0\x33\x15\xc0\x38\xa2\x62\x5c\x5a\xb9\x51\x59\xa5\xda\x25\x0a\x82\xe6\x4a\x9c\xf9\x3f\xfc\xf1\x6e\xf1\xfe\xfe\xea\xf1\xee\xfe\x9f\xb7\x57\x37\xef\x1f\x16\x57\xd7\xef\xff\xd4\xe3\xdc\x28\x6a\xf0\xc1\x10\x93\x6b\x7b\x36\x67\x75\x38\xec\x7c\xa5\x9c\xa4\x18\xc2\xaf\x39\xd9\xda\x37\xd6\x1c\x7f\xa9\x08\xc7\x8d\x54\x4f\x56\xcd\x1f\xf4\x8a\xcc\xce\xce\xc3\x59\x7c\x7a\x71\x99\xcc\xf0\xf4\x62\x12\x5f\xcc\x67\x71\xb4\x3c\x9b\xcf\x2e\x66\x13\x92\xcc\xe7\x97\xa7\xb3\xf9\xe5\xf4\x7c\x7e\x3a\x99\x25\xc9\x72\x82\xe7\x97\x97\xd1\x84\x9c\x7e\x37\x9d\x9c\x25\xb3\xd3\x39\x9e\x7f\x87\xd8\x97\xbb\xc8\x19\x5b\x48\x46\xe3\x6d\x08\xbf\x2c\x6f\xa5\x59\x28\xd4\xd8\x58\xdb\x8e\x4c\x2a\xe3\xd8\xc5\x9e\xa0\xb9\x86\x85\x54\x26\x84\x8b\xc9\xc5\xe4\x59\x8a\xa9\x43\x51\xbf\x01\x8e\x46\xd1\x58\xf7\xd6\x32\x25\x8d\x8c\x25\x0b\xe1\xf1\x7a\xd1\x59\x63\x74\x8d\x02\xb5\x5e\x28\x19\xa1\xab\xd4\xca\x98\xec\x67\x34\x61\x7f\x27\x62\x56\x21\x8c\x57\x48\x98\x59\xfd\xd6\x5f\xf4\x69\xaf\x90\x24\xf4\xad\x85\x18\x54\x9c\x8a\x22\xce\xdd\xa0\xd6\xf6\x2a\xaa\x6b\xf8\x89\x30\x16\x91\xf8\xe9\x51\x7e\x94\xa9\xbe\x13\xef\x95\x72\xdc\x19\xc5\xba\x15\xef\xb8\x55\x69\xd0\x5d\xd7\x74\xf4\x59\x13\x96\xe3\x4f\x4a\xf2\xfe\x19\x96\x14\x59\x52\x85\x65\xcf\xca\xa2\x38\x62\xfd\xec\x47\xfe\x87\xe1\xd1\x60\x57\xf8\xde\x87\xda\x26\x34\x87\x49\xe1\xaf\x39\xea\xbe\x0f\x02\xc4\x59\x1e\xc2\x74\xc2\x7b\xd3\x1c\xb9\x54\xdb\x10\xa6\xe7\x93\x1b\xda\x59\x1b\x38\x1f\x42\x26\xf8\xe0\x84\x41\x3b\x22\x34\x64\xf4\x94\x47\xa8\x04\x1a\x2c\x72\x9e\xd4\x21\x30\x2a\xf2\xcf\xbf\x27\xd0\xc7\xc4\x10\x26\xd3\x2f\x0b\xf6\x3b\x4c\x6f\x1d\xf0\x3d\x5a\xbe\x20\xe8\x7b\x76\x79\xeb\xc0\xef\x15\x59\xb3\xed\x0b\xfe\x15\xd3\xc1\x04\x70\xd2\x26\x80\x13\x67\xc1\xcd\x1c\x01\x04\xb1\x14\x4b\x9a\x72\x92\xd9\x92\x02\xd5\x2f\x36\xb8\x7e\x7f\x20\xa6\x37\xf4\xed\xb1\x15\xa6\x54\x1b\xb5\x0d\xad\xc1\xb5\x71\xf7\xcf\x0d\x65\x41\x11\xb2\x9d\xf9\xaf\x94\x36\xbe\xa5\x2b\x77\xed\x5b\xba\x3a\x2e\x5d\x39\x09\xeb\x75\xc3\xfd\xc5\x1b\x44\xfb\xdd\xbe\xe3\xe8\x3e\x69\x37\x07\x90\x34\x55\x98\x12\x83\xb6\x07\x0a\x30\xa1\xa6\x17\xf4\xf7\xef\xd7\xb2\x1a\x19\x90\x84\x53\x11\xc2\xd0\xa8\x1c\x87\x5f\xc2\x68\x45\x36\x7c\xfe\xc6\xb2\xe9\xae\x47\xb1\x54\x28\xed\x07\xdf\xed\x35\x75\x1e\xe9\x58\xd1\xcc\x4a\xd2\x6e\x3f\x19\x2b\x24\x06\x87\xef\x60\x98\x17\x99\xc8\xfe\x95\xd9\x74\x63\xff\x48\x90\xa1\xc1\xa2\x33\x7d\x81\xd4\xb8\xbc\x86\x2a\x39\xac\xcb\x5b\xd0\x76\xdf\x2a\x92\x57\xb4\x76\x86\x0a\x6d\x08\x63\x19\x23\x25\xc5\x01\x8d\x5b\xa5\xde\xf6\xc2\xd7\x14\x37\x5f\xf3\xc2\xbf\x80\xcf\xaa\xfa\x2a\x8e\xf2\x7a\x57\xf6\x0e\x1a\x91\x69\xa1\x84\x7b\x89\x29\x1a\x4b\xc2\xa8\x2e\x3e\x37\x85\xc7\xed\xf8\x59\x46\xe2\x27\x92\xa2\x1e\x1d\xa7\x7d\x45\xce\x89\xa0\x4b\x1b\x90\x4a\x5f\x76\xe7\xc6\x34\x96\xe2\x38\x5d\x7a\xd5\xa3\x4f\x87\xb6\x9a\xbc\xab\x56\x0b\xe5\x3d\xbe\x95\x32\x19\x11\x16\xb4\x68\x98\x5b\x50\x3a\x20\xd9\xeb\x49\xed\x56\x69\x7d\x91\x8c\x37\xf5\xa9\x21\x2a\x45\xd3\xa0\x78\x95\xb7\x07\x5e\xb4\x64\x8f\x42\x84\x65\x2b\xd2\x43\x9b\x2a\xb0\xa6\x62\xf5\xa8\x57\xdf\x6f\x51\x81\x3d\x57\x62\x4b\xc6\x47\xeb\x5a\x8b\xc9\x68\x7a\x36\x9a\x36\x07\x48\xa8\xce\x18\xd9\x96\xa5\xe9\xa2\xdc\x15\x1e\xea\x6d\x13\x6c\x1c\x33\x84\x7b\xcc\xca\x12\x44\x03\x11\x8d\x01\x6b\x55\xc0\xac\x88\x01\xaa\x81\xac\x09\x65\x24\x62\x08\x4b\x25\x39\x10\x48\x6d\x65\x00\xd7\xe5\x33\x78\x28\x9c\x0e\x36\x2b\x1a\xaf\x60\x43\x19\x2b\x1c\x91\xad\x11\x8c\x04\xe2\x3f\xff\x68\x00\xc0\xa9\xf8\x6b\x1e\x61\x63\xcc\xe9\x68\x3a\x1d\xd9\xb4\xfd\x84\xdb\x8d\x54\x89\xf5\xc7\x93\xbe\xcb\x9e\xbc\x83\x13\xc9\xb8\xfd\xa8\x0d\x76\x62\x1d\x98\x13\xda\xad\xb0\xeb\xda\xfa\x1e\x13\xf8\x40\xca\x0a\x0b\x39\xa1\xac\xb8\x33\xa1\x57\x74\x69\x5a\x67\xf8\x41\x61\xb2\x22\xc6\xde\xde\xa0\x28\x87\xd6\x34\xc1\x2a\xd5\xf6\xf7\x61\x54\x3c\x39\x22\x76\x2c\x0c\x90\x2b\x16\x16\xd5\x8b\x0e\xc7\xe3\x94\x9a\x55\x1e\x15\x9e\xe1\x2b\x37\xf7\x02\x7e\x63\xa3\x10\xc7\x9c\x58\xe3\x8d\xb3\xa7\x74\x5c\x9d\x37\x68\x3c\xa4\x0a\x3a\x37\x32\xc1\x4a\xa3\xb2\x9b\xba\xdb\x88\x5b\xa7\xc1\xd5\x79\x66\xeb\x22\x4c\x42\xb0\x61\xb1\x43\xfa\x40\x45\xca\xf0\x58\xea\x9b\x9c\x19\x7a\x2c\xf1\x15\x63\xed\x23\xda\x43\x5b\x9d\xa0\xb4\x74\xd3\x18\x42\xd2\x76\xa3\xd0\x6b\xbf\xaa\xa0\xbc\xb0\x15\x9d\x2e\x02\x72\xbd\x12\xbc\xb0\x35\x03\xa8\x92\x44\xfd\xb5\x1b\x77\x7b\x75\xf6\x1e\x84\xf7\x99\x9a\x30\x80\x0a\xbb\x25\x71\x8c\x5a\x2b\xb4\x29\xaa\x5b\x84\x97\xd1\xb7\x5f\xd3\x17\xc5\x48\x6f\x32\x45\xf3\x9c\x9e\x3d\x80\xce\xab\x53\xd1\x31\x94\x1d\xdc\x41\x3d\x5c\x81\xf6\xbb\x4d\x0c\xce\x44\x91\x21\x8e\xd0\xc9\x9b\xb5\x8e\xd0\xd3\x49\xb5\xff\x23\x5d\x0f\xa7\xda\xe7\x95\xee\x07\xad\x17\xab\xdd\x3e\x84\x8e\x9b\xfb\xd3\x45\x39\xba\x4f\x05\xa0\x0f\xb6\xd4\xc3\x0f\xba\xb4\x87\xaa\xc1\x97\x59\x77\xa7\x9d\x06\x04\xfc\x60\x4c\x3d\x0a\x38\xc5\xaf\x65\x1f\x99\x69\x76\xeb\x21\x34\xf5\xe8\x23\x35\x47\x89\xd8\x35\x06\xbc\x18\xbe\xa9\x87\xbf\x13\xab\xc7\xc1\x8e\xcc\x25\xf5\xe1\x41\xe5\x38\x7c\xbf\x2d\xff\x0e\x30\x54\xb3\x17\xf0\xd0\x4e\xae\xe8\x53\x05\xeb\xef\xe7\xbe\xe9\x40\x63\x9c\x2b\x0c\x6c\xa0\xf6\xac\x0f\xcf\xe6\xf3\xd3\xa1\x97\xb1\x2a\xea\x7c\xd0\x6a\x4d\xe4\xe2\x4e\xe5\xf8\x5a\x88\x4c\x47\x7a\x17\x97\xb9\x62\x1b\xb2\xed\x03\x24\x5e\x5c\x06\x7c\xc8\x8b\x35\xcf\x0e\xd5\x01\x1c\xa5\x1c\x7b\x80\x8e\x72\xe8\x78\x85\xd6\x21\x3e\x3c\x3e\x2e\x1e\xbc\x14\x07\x01\x91\x56\xff\x3d\xda\x1d\x42\x60\xfe\x0f\xd4\x7b\x39\x76\x53\x1f\xcf\x9b\x93\xeb\x45\x3f\x5a\x53\x8e\x3d\x98\x4d\x39\x6a\xe4\xe6\xcc\x45\x6e\x2a\xa3\xd8\x47\x44\xcd\xf6\x5a\x0a\x83\x9f\xbd\x96\x53\xb9\xb8\xd2\x9f\x34\x2a\x2b\x62\x32\xd9\xa1\x58\x4b\x96\x73\xbc\xb1\x41\xc8\xeb\x78\x65\x94\x30\x3c\x5b\xee\x7a\x2b\x00\xb7\x7c\xe5\x8f\x1e\x63\xc3\xb3\x81\x6f\xef\xbd\xa1\xc7\xbf\x29\xf2\xcc\x6c\x7f\xa4\x2a\x84\x7f\xff\xa7\x28\xb8\x4d\x71\xc4\x10\x8a\x6e\xa7\xec\x21\x9d\x7e\xa4\xf8\x7d\xbc\x0a\xa7\x09\x2e\xa9\xa0\xa6\xad\xd7\xe4\x46\x60\x52\xb7\x56\x69\xf9\x23\xfa\xc1\xb4\x5b\xe9\xb3\xee\xfc\x6f\x44\x39\x53\x76\x59\x55\x15\x7e\x53\xa5\xdc\x1a\x39\xeb\x86\xd2\x7e\x3a\xf6\xf5\x49\x3d\x7e\xa7\x59\xba\xea\x13\x15\xad\x51\xe3\x60\x90\xa2\xb0\x6a\x63\x52\x76\x49\xf8\x99\x6a\x43\x45\xea\xb6\x49\xb6\xd1\x4a\xc0\xac\x90\x2a\xb8\x2e\x6a\xb0\x9b\xb6\x06\x6b\xd3\xfd\xed\xde\x1c\xe0\x0b\x38\x2f\x6a\x4b\xbb\x5a\x1d\xf8\x57\x95\x55\x1e\x51\x19\xb4\x3f\x37\xec\xe9\x9a\x4b\x1b\x3c\x16\x85\x45\xaa\xb2\x78\x70\x4c\x64\xcf\x33\x6d\x14\x12\x1e\xd8\x74\x96\x0b\x6a\xb6\x6d\x4f\xd6\xfe\x8e\xe0\xdc\xd3\x75\x4d\xd9\x74\xab\xd6\x78\x59\x1e\x31\xaa\x57\xf6\x31\xd5\xd3\x1f\xf2\xc8\x16\xe7\xff\x0d\x00\x00\xff\xff\xcd\x4f\x3b\xa4\xe0\x23\x00\x00") - -func olmManifestsOlmYamlBytes() ([]byte, error) { - return bindataRead( - _olmManifestsOlmYaml, - "olm-manifests/olm.yaml", - ) -} - -func olmManifestsOlmYaml() (*asset, error) { - bytes, err := olmManifestsOlmYamlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "olm-manifests/olm.yaml", size: 9184, mode: os.FileMode(420), modTime: time.Unix(1591299779, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -// Asset loads and returns the asset for the given name. -// It returns an error if the asset could not be found or -// could not be loaded. -func Asset(name string) ([]byte, error) { - cannonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[cannonicalName]; ok { - a, err := f() - if err != nil { - return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) - } - return a.bytes, nil - } - return nil, fmt.Errorf("Asset %s not found", name) -} - -// MustAsset is like Asset but panics when Asset would return an error. -// It simplifies safe initialization of global variables. -func MustAsset(name string) []byte { - a, err := Asset(name) - if err != nil { - panic("asset: Asset(" + name + "): " + err.Error()) - } - - return a -} - -// AssetInfo loads and returns the asset info for the given name. -// It returns an error if the asset could not be found or -// could not be loaded. -func AssetInfo(name string) (os.FileInfo, error) { - cannonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[cannonicalName]; ok { - a, err := f() - if err != nil { - return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) - } - return a.info, nil - } - return nil, fmt.Errorf("AssetInfo %s not found", name) -} - -// AssetNames returns the names of the assets. -func AssetNames() []string { - names := make([]string, 0, len(_bindata)) - for name := range _bindata { - names = append(names, name) - } - return names -} - -// _bindata is a table, holding each asset generator, mapped to its name. -var _bindata = map[string]func() (*asset, error){ - "olm-manifests/crds.yaml": olmManifestsCrdsYaml, - "olm-manifests/olm.yaml": olmManifestsOlmYaml, -} - -// AssetDir returns the file names below a certain -// directory embedded in the file by go-bindata. -// For example if you run go-bindata on data/... and data contains the -// following hierarchy: -// data/ -// foo.txt -// img/ -// a.png -// b.png -// then AssetDir("data") would return []string{"foo.txt", "img"} -// AssetDir("data/img") would return []string{"a.png", "b.png"} -// AssetDir("foo.txt") and AssetDir("notexist") would return an error -// AssetDir("") will return []string{"data"}. -func AssetDir(name string) ([]string, error) { - node := _bintree - if len(name) != 0 { - cannonicalName := strings.Replace(name, "\\", "/", -1) - pathList := strings.Split(cannonicalName, "/") - for _, p := range pathList { - node = node.Children[p] - if node == nil { - return nil, fmt.Errorf("Asset %s not found", name) - } - } - } - if node.Func != nil { - return nil, fmt.Errorf("Asset %s not found", name) - } - rv := make([]string, 0, len(node.Children)) - for childName := range node.Children { - rv = append(rv, childName) - } - return rv, nil -} - -type bintree struct { - Func func() (*asset, error) - Children map[string]*bintree -} - -var _bintree = &bintree{nil, map[string]*bintree{ - "olm-manifests": &bintree{nil, map[string]*bintree{ - "crds.yaml": &bintree{olmManifestsCrdsYaml, map[string]*bintree{}}, - "olm.yaml": &bintree{olmManifestsOlmYaml, map[string]*bintree{}}, - }}, -}} - -// RestoreAsset restores an asset under the given directory -func RestoreAsset(dir, name string) error { - data, err := Asset(name) - if err != nil { - return err - } - info, err := AssetInfo(name) - if err != nil { - return err - } - err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) - if err != nil { - return err - } - err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) - if err != nil { - return err - } - err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) - if err != nil { - return err - } - return nil -} - -// RestoreAssets restores an asset under the given directory recursively -func RestoreAssets(dir, name string) error { - children, err := AssetDir(name) - // File - if err != nil { - return RestoreAsset(dir, name) - } - // Dir - for _, child := range children { - err = RestoreAssets(dir, filepath.Join(name, child)) - if err != nil { - return err - } - } - return nil -} - -func _filePath(dir, name string) string { - cannonicalName := strings.Replace(name, "\\", "/", -1) - return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) -} diff --git a/internal/bindata/olm/manifests.go b/internal/bindata/olm/manifests.go new file mode 100644 index 00000000000..6db90fd6b08 --- /dev/null +++ b/internal/bindata/olm/manifests.go @@ -0,0 +1,316 @@ +// Code generated by go-bindata. (@generated) DO NOT EDIT. + +//Package olm generated by go-bindata.// sources: +// olm-manifests/0.15.1-crds.yaml +// olm-manifests/0.15.1-olm.yaml +// olm-manifests/0.16.1-crds.yaml +// olm-manifests/0.16.1-olm.yaml +package olm + +import ( + "bytes" + "compress/gzip" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "strings" + "time" +) + +func bindataRead(data []byte, name string) ([]byte, error) { + gz, err := gzip.NewReader(bytes.NewBuffer(data)) + if err != nil { + return nil, fmt.Errorf("read %q: %v", name, err) + } + + var buf bytes.Buffer + _, err = io.Copy(&buf, gz) + clErr := gz.Close() + + if err != nil { + return nil, fmt.Errorf("read %q: %v", name, err) + } + if clErr != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +type asset struct { + bytes []byte + info os.FileInfo +} + +type bindataFileInfo struct { + name string + size int64 + mode os.FileMode + modTime time.Time +} + +// Name return file name +func (fi bindataFileInfo) Name() string { + return fi.name +} + +// Size return file size +func (fi bindataFileInfo) Size() int64 { + return fi.size +} + +// Mode return file mode +func (fi bindataFileInfo) Mode() os.FileMode { + return fi.mode +} + +// ModTime return file modify time +func (fi bindataFileInfo) ModTime() time.Time { + return fi.modTime +} + +// IsDir return file whether a directory +func (fi bindataFileInfo) IsDir() bool { + return fi.mode&os.ModeDir != 0 +} + +// Sys return file is sys mode +func (fi bindataFileInfo) Sys() interface{} { + return nil +} + +var _olmManifests0151CrdsYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\xfd\x7d\x73\x23\xb9\x91\x27\x8e\xff\xef\x57\x91\xd1\xf6\x86\xa4\xb5\x48\x75\xdb\x6b\xff\x76\xfb\x7c\x37\xa1\xed\xee\x19\xeb\xe7\x7e\x50\xb4\x34\xe3\x73\x8c\x67\xe7\xc0\x2a\x90\xc4\xaa\x08\x94\x01\x14\xd5\xf4\xcd\xbd\xf7\x6f\x20\x81\x7a\x22\x8b\x22\x0b\x80\xdc\xea\x31\xd2\x11\x9e\x96\x44\x66\xa1\xf0\x90\x99\xc8\xfc\x64\xe6\x64\x32\xf9\x05\x29\xd9\x77\x54\x2a\x26\xf8\x4b\x20\x25\xa3\x9f\x34\xe5\xe6\x27\x35\xbd\xfb\x77\x35\x65\xe2\x62\xfd\xe2\x17\x77\x8c\xe7\x2f\xe1\x55\xa5\xb4\x58\x7d\xa4\x4a\x54\x32\xa3\xaf\xe9\x9c\x71\xa6\x99\xe0\xbf\x58\x51\x4d\x72\xa2\xc9\xcb\x5f\x00\x10\xce\x85\x26\xe6\xd7\xca\xfc\x08\x90\x09\xae\xa5\x28\x0a\x2a\x27\x0b\xca\xa7\x77\xd5\x8c\xce\x2a\x56\xe4\x54\x22\xf3\xfa\xd1\xeb\xe7\xd3\xdf\x4e\x9f\xff\x02\x20\x93\x14\xbf\x7e\xcb\x56\x54\x69\xb2\x2a\x5f\x02\xaf\x8a\xe2\x17\x00\x9c\xac\xe8\x4b\xc8\x88\x26\x85\x58\xd8\x41\xa8\xa9\x28\xa9\x24\x5a\x48\x35\xcd\x84\xa4\xc2\xfc\x67\xf5\x0b\x55\xd2\xcc\x3c\x7d\x21\x45\x55\xbe\x84\xc1\xcf\x58\x7e\xf5\x20\x89\xa6\x0b\x21\x59\xfd\xf3\x04\x44\xb1\xc2\x7f\xb9\x57\xb7\x0f\xbd\xc1\x87\xe2\xef\x0b\xa6\xf4\x9f\x76\xff\xf6\x96\x29\x8d\x7f\x2f\x8b\x4a\x92\x62\x7b\xb8\xf8\x27\xb5\x14\x52\xbf\x6f\x1f\x3e\x31\x1f\x52\x32\xb3\x7f\x64\x7c\x51\x15\x44\x6e\x7d\xf3\x17\x00\x2a\x13\x25\x7d\x09\xf8\xc5\x92\x64\x34\xff\x05\x80\x9b\x3e\x64\x34\x01\x92\xe7\xb8\x20\xa4\xb8\x96\x8c\x6b\x2a\x5f\x89\xa2\x5a\xf1\xe6\x31\x39\x55\x99\x64\xa5\xc6\x09\xbf\x5d\x52\x28\x25\xd5\x7a\x83\x13\x01\x62\x0e\x7a\x49\xeb\xa7\xe2\x37\x00\xfe\x5b\x09\x7e\x4d\xf4\xf2\x25\x4c\xcd\x9c\x4e\x73\xa6\xca\x82\x6c\xcc\x18\xdc\x27\xec\xa2\xbc\xb6\xbf\x77\xbf\xd3\x1b\x33\x50\xa5\x25\xe3\x8b\x7d\x8f\x36\x9f\x39\xee\x99\x76\x02\x6e\x37\x65\xff\x91\x9d\x5f\x1c\xf3\xbc\xb2\x9a\x15\x4c\x2d\xa9\x3c\xee\xa1\xcd\xc7\x7b\xcf\xbc\xde\xfa\xed\xc0\x83\x3b\x8c\xea\x63\x31\xdd\xd9\xd2\x3d\xa6\x97\x8b\xfe\x7b\xe4\x44\xdb\x5f\xd8\x3f\xaf\x5f\x90\xa2\x5c\x92\x17\x76\x77\x64\x4b\xba\x22\x2f\xdd\xe7\x45\x49\xf9\xe5\xf5\xd5\x77\xbf\xbd\xe9\xfd\x1a\xfa\x6f\xdf\xdb\x9f\xc0\x14\x10\x90\xb4\x14\x8a\x69\x21\x37\x66\x36\x5e\xdd\x7c\xa7\xce\xe1\xd5\xc7\xd7\xea\x1c\x08\xcf\x9b\xe3\x02\x25\xc9\xee\xc8\x82\xaa\x69\xc3\xd8\x8e\x50\xcc\xfe\x9b\x66\xba\xf9\xa5\xa4\x7f\xab\x98\xa4\x79\xfb\xfc\x09\xd4\xef\xde\xf9\x95\x99\xd7\xe6\xc7\x52\x9a\xa7\xe8\xe6\xc0\x59\xea\xc8\xa2\xce\x6f\xb7\xde\xe7\xc4\xbc\xb2\xfd\x14\xe4\x46\x08\x51\x85\x0b\xea\xce\x02\xcd\xdd\x2c\xd9\x85\x66\xca\xbc\xad\xa4\x8a\x72\x2b\x96\x7a\x8c\xc1\x7c\x88\x70\xf7\x46\x53\xb8\xa1\xd2\xb0\x31\x47\xb4\x2a\x72\x23\xbb\xd6\x54\x6a\x90\x34\x13\x0b\xce\xfe\xde\xf0\x56\xa0\x05\x3e\xb4\x20\x9a\x2a\xbd\xc5\x13\xcf\x1e\x27\x05\xac\x49\x51\x51\x3b\xa9\x2b\xb2\x01\x49\xcd\x53\xa0\xe2\x1d\x7e\xf8\x11\x35\x85\x77\x42\x52\x60\x7c\x2e\x5e\xc2\x52\xeb\x52\xbd\xbc\xb8\x58\x30\x5d\xcb\xe0\x4c\xac\x56\x15\x67\x7a\x73\x81\xe2\x94\xcd\x2a\x23\xce\x2e\x72\xba\xa6\xc5\x85\x62\x8b\x09\x91\xd9\x92\x69\x9a\xe9\x4a\xd2\x0b\x52\xb2\x09\x0e\x9d\xa3\x1c\x9e\xae\xf2\x5f\x4a\x27\xb5\xd5\x49\x6f\xac\x3b\x1b\xd8\x12\x0a\xbd\x07\x56\xc0\x08\x3e\xbb\x93\xec\x57\xed\x5b\xb4\x13\x6d\x7e\x65\x66\xe7\xe3\x9b\x9b\x5b\xa8\x1f\x8d\x8b\xb1\x3d\xfb\x38\xef\xed\x17\x55\xbb\x04\x66\xc2\x18\x9f\x53\x69\x17\x71\x2e\xc5\x0a\x79\x52\x9e\x97\x82\x71\x6d\x0f\x71\xc1\x28\xdf\x9e\x7e\x55\xcd\x56\x4c\x2b\xdc\x97\x54\x69\xb3\x56\x53\x78\x85\x8a\x09\x66\x14\xaa\xd2\x9c\xb0\x7c\x0a\x57\x1c\x5e\x91\x15\x2d\x5e\x11\x45\x1f\x7d\x01\xcc\x4c\xab\x89\x99\xd8\xe3\x96\xa0\xab\x53\xb7\x3f\xbc\x75\xfe\x00\x6a\x7d\x77\xf0\x83\x43\x87\x15\xec\xe9\xdc\x96\xb2\x96\x86\xcf\xa9\x21\x92\xe7\x92\xaa\x9d\x5f\xef\x1c\x56\xfb\x31\xbb\x5b\x96\x42\x99\x75\x23\x1a\x3e\xbc\x7d\x07\x19\xe1\x50\x29\x6a\x8e\x52\x26\x38\x37\x1b\x41\x0b\x20\x46\x2b\x4d\xe8\x27\xa6\x74\x7f\x46\xda\x37\x58\x30\xa5\xe5\x66\x0a\x5f\x0b\xb9\x22\xfa\x25\xfc\xa1\xfe\xd5\x04\x1f\x20\x24\xb0\xf2\x7f\xbd\xfc\x43\x29\xa4\xfe\x5f\xf0\x81\x17\x1b\xf3\x98\x1c\xee\x97\x94\xc3\xcd\xf0\x7b\x5a\xfa\x9f\x9d\x3f\x7f\x23\xcb\x6c\x0a\x57\x0b\x2e\x64\xfd\x5d\xb3\xe3\xae\x56\x64\x41\x61\xce\x68\x81\x27\x40\x51\x3d\x3d\xd9\xe1\xb4\x67\x4d\xc1\x9a\x43\x73\xb6\x78\x47\xca\x03\x13\xf7\xaa\xfe\x9c\x79\x8a\x79\x70\x57\x49\xb7\x7f\xd4\x02\xb7\xb4\x79\x3d\x2d\x06\xde\x68\x46\xb2\x3b\x20\xee\xa9\x2b\x52\x4e\x14\x1e\xaf\xce\x24\xee\x9d\x9f\xde\x6c\xbc\xaa\x19\x0c\x3c\x43\xc8\xce\x07\xaf\x9c\xec\x9b\x8e\x99\x94\xee\x9b\x8f\xfa\x5e\x6b\x8e\x1c\x98\xce\x77\xdb\xfa\xe8\x08\xee\x2c\xdb\x3f\x9c\x81\x93\x05\x7b\x4f\x17\xe0\x09\x9b\x11\x45\x7f\xff\x6f\x83\x83\x30\xfa\x32\x67\x44\x0f\xed\xca\xfd\x27\x10\x70\x7d\x6b\xa6\x43\x7f\x7d\xf0\xf5\x00\xa5\x8c\x7b\xec\xe8\x6f\x33\x73\x0e\x0e\x4c\xba\x3d\x2b\xe6\xe4\xf3\xc6\xa8\x98\xd4\x3b\x0f\x2f\x06\x84\x71\x2a\x2d\x2f\xb3\x95\x19\x57\x9a\x70\xcd\x6a\x0b\xa8\x4f\xa4\xd9\xb5\xf5\x2e\xbe\x67\x7a\x79\xec\x0e\xc6\xf3\x3c\xc0\xf5\x6a\x0e\x4e\xf9\x9c\xe3\xd9\x72\x72\xad\x3d\xe2\xcc\x8a\x80\x51\x1b\xba\x31\x1f\x47\x6d\x67\x45\x33\x49\xf5\x21\x91\x7a\x63\x3f\xd5\x2a\x4d\x23\x84\x8c\x64\x70\x5f\xb7\x02\xd6\x08\xd7\x07\x25\x03\xc9\x32\xf3\x9a\xa8\x45\x05\xd7\x46\xf9\x6e\x99\xc6\x53\xb8\xd2\x66\x02\x66\x54\xa1\x64\xbe\xa3\xb4\xb4\xca\xb8\x60\x3b\x36\x0f\x8e\x7f\x45\x8a\xe2\xdc\x5c\x61\x32\x0a\x94\x64\x4b\xb8\x67\x45\x01\x9c\xe2\x18\xcc\x70\xb4\x64\x34\x87\xb9\x90\x40\xd7\xd4\xec\x01\xfb\x24\xa0\xdc\xc8\xa2\x3d\x73\x45\xa4\x6c\xae\x16\x2d\x31\x4d\x57\x83\x47\xe2\xa1\x09\x6e\x76\xc3\xa1\x39\x6e\xf7\x90\x13\xbf\xf5\x7d\x45\xb5\x57\xc0\x23\x1f\x6a\xed\x8d\x1b\x2d\xcd\x1d\x73\x73\xe0\xc1\xdf\xf6\x3e\xdc\xd8\xb7\x4b\x71\x5f\xdb\x2d\xcd\x9c\x39\xab\x0a\x0f\xcf\xb6\x5d\x05\x78\xa7\xc5\x1d\x90\x33\x95\x89\x35\x35\x4a\xec\x95\xe0\x8a\x29\xbb\xce\x84\x5b\x33\x75\x4d\x0a\xbb\x61\xea\x47\x95\xa2\x28\x8c\xfd\x96\x57\x72\xc8\x5e\x36\x64\xec\x59\xc2\x81\xae\x66\x34\xcf\x8d\x4d\x5c\x0f\x77\x50\x80\x3d\x28\x30\x1f\x96\x6e\xf5\x79\xbf\x16\x45\xf1\x90\x84\xda\xc3\xfc\xf0\x03\xa0\xb6\xd6\xd7\x64\xcf\x03\x60\x47\xa8\xd5\xb3\xc6\x54\x7d\xba\x20\xa7\x9a\xca\x15\xe3\xd4\x6e\x15\xb6\xa2\x0d\xd7\xbd\x4c\x01\x66\x54\xdf\x53\xca\x21\x5b\xd2\xec\xae\x39\x7c\xf6\x46\xb1\xbd\xca\xee\x72\x33\x35\x77\xd9\x07\x58\xd6\xdf\x6a\xaf\x70\xa2\x28\xf0\xb2\xa2\x28\x05\x36\x07\x02\x9c\xde\xd7\xdc\x86\xaf\xc2\x43\xa4\xda\xcb\xe3\x9a\xb0\x82\xcc\x0a\x3a\x35\x92\xb3\xf9\xe9\xbc\x3b\x76\x56\xcb\xfd\xb2\x2a\x0a\xf4\x53\xec\x23\xb3\x93\x16\x1f\xaf\x5f\x81\x96\x64\x3e\x67\x99\xf9\x52\xce\x24\xcd\xb4\x9d\xd8\xbd\x13\x32\x24\xc9\x2d\xed\x39\x89\x4a\x13\x5d\xa9\x23\x8d\xe4\xfd\x9b\xa6\x31\xdf\x3e\xd2\x39\x95\x94\x67\x03\x92\xc4\xdb\x42\xe0\xad\x5b\x65\xfb\xd7\xe8\xf1\x19\x79\x7a\x0a\xa2\xb4\x95\x27\xb7\x6c\xc8\x40\x82\xc3\xf6\x01\x18\x59\x8d\x36\xb6\x61\x33\x31\x3b\x7b\xe0\x53\x7c\xd0\xfe\x3a\x82\x7d\xf3\x66\x5e\xdf\xae\x2f\x96\x83\x2e\x83\x23\x79\x54\x6c\x60\x25\x60\x47\x2a\x5f\xbd\xb6\x17\x18\xd4\x02\x28\x2e\x97\xa2\xc8\x15\x54\x9c\xfd\xad\xa2\x70\xf5\xda\xdd\xe3\xcf\x81\xf1\xac\xa8\xf2\x7d\xb3\x09\xf0\xed\xb7\x57\xaf\xd5\x14\xe0\x3f\x69\x46\xcc\xe5\xe7\x9e\x42\x2e\xf8\x89\x86\x0f\xef\xdf\xfe\x05\xaf\x43\xf8\x89\x73\xab\x68\xad\xed\x44\x0a\x86\x1e\x87\x3d\x2c\xed\xcb\x21\x4f\x23\xb8\xdd\x28\x33\x52\x9a\xbb\xa8\x42\x49\xc4\x35\x1e\xb5\x25\x2d\x4a\x73\xb3\xbe\xa3\xa0\x2a\x69\xdf\x64\xdf\x38\xaf\x5e\x2b\xfc\x0e\xae\x11\xe4\x02\xcc\xf5\x79\x41\x35\x1e\x81\x02\x6f\xd0\x63\x27\xdc\xdd\xf2\x98\xe0\x37\x9a\xe8\x98\x27\xc7\x6c\xf5\x0f\x33\xb4\x0a\x73\xe4\x3d\xf2\xa8\xec\xbd\xcc\x1e\x78\x23\x70\xc7\xec\x95\x7d\xb3\x47\x3c\x63\x3b\x6f\x38\xfa\x59\x56\x8e\xa2\x4d\xfe\xf1\x41\xbd\xba\xe3\x3b\x35\xcf\xb6\x5a\x0d\x2f\x9f\x7d\x7f\x22\xca\xfa\xc6\xa8\x5f\x12\x63\x2f\xd2\x21\xab\xc1\xa8\x22\x2b\xd5\x29\x77\xbb\x8f\xb6\xaa\xa2\x2a\x27\x5a\x4c\xf2\xa1\xa5\x7b\x70\xfe\x0e\xcd\xdd\x8a\x2a\x75\xf8\xa6\x72\x09\xcb\x6a\x45\x38\x48\x4a\x72\xa3\xce\xea\xaf\x01\xe3\x39\xcb\x08\x3a\xb4\x72\xaa\x09\x2b\x14\x90\x99\xa8\x34\xdc\x2f\x77\x4d\x52\x18\x9a\x1f\x73\x00\xed\x61\xce\x04\xb7\xfe\xf9\x51\x57\x09\x49\x89\x1a\x12\x6e\xbd\xf1\x7f\xc4\x0f\xd5\xb6\xaa\xfd\xca\xc0\x60\xee\x8d\x18\x91\x84\x2b\x1c\xc6\xa0\x66\x36\xb7\x30\xad\x20\xab\xa4\xc4\xab\x85\xd9\x6a\x23\xc7\x6b\xb7\xc2\x0d\x95\x6b\x36\x5a\x3d\x3e\x7c\x4c\xd1\x91\x4e\xf3\xcb\xc7\x3c\x68\xa5\x90\x7e\xec\x4b\x29\xb4\xc8\xc4\x83\x86\xea\xde\x2f\x2b\x3b\x5b\xc3\x9e\x8c\x71\xdf\x1f\xa3\x50\xad\x3c\x79\x09\x5a\x56\x76\x2e\x94\x16\xd2\x1c\x97\xce\x6f\xaa\x59\xe3\x3c\xae\xb9\x3a\x63\x0a\xfe\xef\xff\xfb\x45\x6b\x57\x99\x0b\x65\xa9\x69\xde\x89\x6c\xd9\xe0\xd9\xb3\x67\xf8\x43\x1d\x11\xc3\x1f\x9b\xb3\xa0\x5e\xc2\xf7\x3f\xfc\xc2\x3e\x98\xe6\xdf\xd5\xf1\x2c\xf3\xcb\x5f\x7c\x91\xe1\xc9\xa2\x52\x9a\x4a\xb7\x1e\x75\x7c\xee\x1f\x15\xa6\xb4\x0f\x77\x47\xcf\xcd\x1b\xfe\xbd\x13\xae\x1c\xfa\xcc\x6e\xd8\x72\xf0\x35\xec\x86\xd8\x0d\x5f\xaa\x75\xfb\x2f\xf7\xa1\x36\x8c\x39\xc4\xe9\x71\xc2\x99\x3d\x17\xe9\xcd\x77\x6e\xb3\x3e\x5e\x0c\x73\xeb\x1a\xb5\xff\x91\xeb\xce\x4a\xd4\x8f\xfb\xae\xf7\xbb\x63\x1e\x57\xbf\x1e\x31\x4f\xb2\x56\x28\xea\x15\xc1\x31\xf4\x52\x90\xac\xf1\x03\x6c\x0f\x60\xeb\xcf\x76\x04\x1f\xfb\xbf\x7c\x38\x98\x69\xcf\xf9\xb4\x5c\x12\xd5\x9f\xb6\xeb\xce\x6f\x76\x58\xc4\x0a\x61\x0e\xed\x59\x6b\x91\xdb\x53\x0f\xf5\xb1\xc7\xb5\x30\xe6\xef\xff\x19\xfc\xce\x4d\x49\xb3\xff\x93\xc2\x99\x29\x9c\x99\xc2\x99\x5f\x54\x38\xf3\xb0\x34\x30\x27\x1b\x72\x9a\x15\xc4\xba\x2d\x15\x68\x5a\x14\x18\x67\x5c\x8a\xfb\x26\xb8\x50\x6c\x3b\xe4\x3a\xa1\x89\xd6\x71\xbe\x22\xdc\x18\xff\xa4\x2c\x15\x3a\xab\x09\x2c\xd8\x9a\xf2\xc6\x0b\x77\x9c\x17\x69\x5f\xa8\x75\x57\x01\xd5\x7f\x19\x1a\xe2\x03\x11\xd8\x6d\x5b\x66\xef\x8c\x5d\xb6\x9f\x74\x2e\x85\x8a\x2b\x2d\x2b\x5c\xde\x1c\xee\xe8\xc6\x6d\xf9\x15\x29\x9d\x25\x86\xb1\x95\xa1\x9b\x72\xf7\x00\x10\x8d\xfb\x7a\x46\x31\x04\x31\xdb\x80\x31\xcf\x50\x54\x68\x21\x9c\xdf\xd1\x70\x43\x91\x21\xa9\x96\x8c\xae\x07\x23\x3b\x72\xc6\xb4\x24\x72\xd3\xec\x93\x7d\x57\x8e\x3d\xd7\x86\xae\xa9\xf0\xd0\x05\xe2\x01\x2b\x9a\x94\xcc\xd9\x28\x79\x63\x3a\x1e\x9c\xd7\xeb\x2b\xb7\x0b\x5b\x73\x53\xb9\x5d\x48\x15\x90\xa2\xa8\x6d\x83\xc6\x6e\xc5\xe7\x0c\x8c\xcc\x6e\xb9\x1c\x84\x6c\xf6\x8d\x99\xd0\xee\xf6\x9c\xa1\x7b\x47\x12\x6e\xfe\x30\x78\x08\x46\xce\xda\xc3\x97\x2d\x71\xcf\x87\x9c\x2d\x70\x20\x2e\x03\x0f\xc5\x66\x1e\x9c\xc1\xe6\xd7\x66\x60\x6b\x96\x53\xd5\xdc\xb9\xb5\xc0\x93\x8c\x57\xef\x3d\x6c\xed\x0a\xd6\x5f\xcd\x61\xcd\x08\x90\xc5\x42\xd2\xc5\xbe\x30\xc6\xc1\xf9\xb1\xb4\xdf\xef\x64\x69\x62\xed\xf7\xbd\x7f\x35\x42\x72\xef\x1f\x07\x5d\xbe\xf5\x1f\xfb\x66\xe3\x36\x1d\x8e\x6c\x98\x3b\x99\x79\xf7\x7a\x6a\x85\x7c\xe0\xa3\x87\x57\xd5\xd2\x83\x6b\x6b\xa9\xbf\xc2\x5b\x43\x70\x7f\x9d\x99\xf3\xd1\x0a\xec\x41\xb1\xb0\xfb\x26\xbd\xd8\x66\x49\xa5\xb9\xd0\x9b\x43\xc3\x81\x40\x66\x2d\xc1\x46\x3c\xd9\x60\xf2\x80\xd7\x7c\xf7\x9d\x1f\x5c\x7f\x4b\x87\x76\x81\xa5\x09\x94\x64\x50\x6c\xb6\x74\xcc\xb2\x59\x7a\x10\x15\xb1\x4d\x07\x7d\x1f\x1d\xbe\x0f\xa1\x26\x02\xf8\x9a\x57\x8f\xca\x10\x75\xd2\x61\x8e\x7d\x4f\x18\xb9\x7f\x57\xfb\xee\x10\xea\x48\xee\x81\xf2\x4c\x18\x91\xf0\xff\xbf\xf9\xf0\xde\x32\xdd\x1f\x3e\x6a\xe9\x4a\x03\x5b\x95\x05\x5d\x61\x68\xfc\x1d\x91\x6a\x49\x0a\x2a\x51\x97\x7d\xcb\x57\xbd\x9f\x33\xb2\xef\x94\x76\xa9\x8d\xc7\x43\x4e\x0b\xb2\xb1\x03\xca\x69\x26\x72\x23\xd9\x85\x84\xd2\x98\xd2\xab\xb2\xd2\x14\x08\xfe\xf5\x08\xae\xf8\x76\x8c\x2f\x0e\xbf\xd3\x88\xa9\x6f\x7d\x65\xb3\xcd\x20\x18\xa3\x4b\x9f\x26\xf9\x71\x12\xa6\x3b\x8c\x43\x72\xc6\xd2\x11\xd2\xa6\xcb\xf4\xc0\xbb\x35\x90\x93\xeb\xbd\x4e\xbe\x2e\x37\x73\xf1\x59\x34\x60\xdf\x21\xaa\x27\x89\x71\xfd\xdb\xdf\xec\xfd\x5c\x4e\xcb\x42\x6c\xcc\x3e\x3a\x74\xe6\x8e\x7a\x8b\x23\xe5\xc2\x71\xbc\x8e\x93\x05\x47\xf1\xb2\x6e\xac\x50\x2e\xbb\x97\x35\x0f\x26\xfb\x23\x92\x23\x98\xec\xb8\x3d\xf7\x73\x8a\xae\x34\xaf\xaf\x6a\x8f\x46\x13\x68\xb6\xf2\xec\x4f\xd5\x8c\x4a\x4e\x35\x55\xcd\xf8\x0e\x9c\x0e\x74\x87\xa0\xdc\x31\xf6\xe4\xb6\x9a\xfc\xc7\x6a\xc7\x07\x6c\xa1\xfa\x23\x0f\x58\x44\xf5\x47\x1e\xb6\x8b\x2c\x1d\xaf\x66\x0f\x6d\x38\x4b\x23\x64\xe7\xa1\xcd\x37\x9a\xe1\xfa\xa1\x00\xf7\x68\x9e\xe6\x76\xfd\x59\x2d\xc2\x9b\xde\x00\x7a\xf6\xa0\x03\xdd\x19\x73\xae\xe7\x5f\x1b\xa6\x59\x21\xb2\x3b\xe7\x11\xfd\xf8\x1a\x94\xe8\x63\x8b\x33\xc1\x55\xb5\xa2\xc0\x1e\xde\xbb\xc9\x04\x8c\xc7\x37\x99\x80\x07\x28\x99\x80\x9d\x61\x7c\x0e\x13\xd0\xc6\x31\x3e\xaf\xfc\xdb\x1a\xc2\x5e\x09\x88\x9f\x4b\x32\x30\xc9\xc0\x24\x03\x0f\x73\x4d\x32\x10\x8e\x7d\xb7\x23\xec\xc9\x83\xd0\xcb\x87\xc4\x40\x72\x0f\x77\x28\xb9\x87\xb7\x29\xb9\x87\x1f\xa0\xa4\x17\x93\x5e\x4c\x7a\x31\xb9\x87\xfd\xdf\x22\xb9\x87\x93\x7b\x38\xb9\x87\x93\x7b\xd8\x93\x67\x72\x0f\x0f\xbd\x64\x32\x01\x63\xf0\x4d\x26\xe0\x01\x4a\x26\x60\x67\x18\xc9\x3d\x9c\xdc\xc3\x49\x06\x26\x19\x98\x64\xe0\xa1\xcf\x3e\x25\xf7\xb0\xbd\x40\xd4\xf7\x87\xe3\xb1\xd4\xcf\xf6\xe5\xef\x0d\x03\xaa\x5f\x7d\x7c\xad\x6a\xd0\xf4\xc0\x40\xc3\x60\xd4\xf0\xd7\xa1\x8d\x7a\xd5\x3c\x19\x6b\x5b\xb8\xe2\x3b\xcc\x26\xda\x7e\xb8\xe7\x34\xc7\x34\xbb\x73\x60\x58\x36\xc7\x1c\x0b\x96\x31\x5d\x6c\x9a\xa1\x4c\x9f\xed\xb0\x7d\xea\x00\xed\x57\x1f\x5f\x1f\xed\x7a\x37\x13\xb1\x77\xd3\x98\x05\xdb\xf3\xc7\x28\x5e\xf6\xe4\x47\x4f\x7e\xf4\x0e\x25\x03\x22\x19\x10\xc9\x80\xf8\x3c\x06\xc4\x53\xf5\x40\x27\xdf\x71\xf2\x1d\x27\xdf\x71\x8f\x92\xef\x78\x98\x92\xdf\xa4\x47\xc9\xec\x49\x66\xcf\xa1\x4f\xfe\xd3\x9b\x3d\xc9\x77\xbc\xff\x45\x93\x0c\x8c\xc1\x37\xc9\xc0\x03\x94\x64\x60\x67\x18\x5f\x9e\xef\x18\xfe\x81\xd0\xe2\xe4\xd8\x4c\x8e\xcd\xe4\xd8\x6c\x28\x69\xb7\xa4\xdd\x0e\x7d\xf2\x9f\x5e\xbb\x25\xc7\x66\x72\x6c\x26\xc7\x66\x72\x6c\x26\xc7\x66\x32\x7b\xa2\xf1\x4d\x66\xcf\x01\x4a\x66\x4f\x67\x18\xc9\xb1\x99\x1c\x9b\x49\x06\x26\x19\x98\x64\xe0\xa1\xcf\x3e\x25\xc7\xe6\xa3\x34\x38\x7d\xe0\x7b\x0f\xb5\x2e\xf5\x6a\xa7\xb8\x57\xcc\x3d\x24\xdc\x1e\xec\x79\xfa\x70\xd7\xd3\xc3\xc2\xee\x50\xe7\xd3\x23\xd6\xf5\x40\xf7\xd3\x87\x67\xd8\x96\xea\x3e\x00\x6a\x36\x0b\x97\x5f\xd9\x8f\x36\x4d\x1d\xdb\xf2\xf0\x88\x1c\x6e\xb5\x11\x7f\xa0\x81\x47\x9f\x1a\x27\xe5\xfd\x92\xd6\x9d\x94\xec\x53\xda\x66\x8c\x4c\xe1\x7d\x80\xcd\xd9\xfe\xe6\xa5\x1e\xad\xb6\x6a\xfe\x3b\x7f\x7a\x78\xc1\x76\x6b\xba\x0f\x4e\x58\x3d\x49\xaf\xad\x17\xfe\x75\x93\x1a\xbd\x3d\x6b\x25\x91\x46\x1e\x3a\x6f\xfd\x9e\xf5\x43\x15\xdf\xe1\xb1\xb5\x12\x0f\x35\x30\x7b\x40\xaf\x3f\xac\xcf\x27\x9d\x7c\xee\xe1\x71\x1d\x56\xe3\xae\x67\xca\x35\x95\x2b\xa6\xd4\x30\x78\xbe\x3f\xdc\x87\x45\xe2\x41\x51\xb8\x67\x0d\xea\xf7\xe8\x0c\xa4\x31\xbc\x1e\x8c\x89\x18\x92\x33\x92\x81\xac\x0a\x6a\xfb\xc8\xb9\xe2\xea\x40\xb2\x4c\x54\x5c\x63\x57\x58\xeb\x5f\x19\xda\xbd\x07\xc5\xec\x41\xbb\xeb\x18\xab\x6b\x62\xc7\xf7\xe0\x27\xdc\xb8\x2f\xed\xb0\x77\x8a\xf6\xf7\xe9\x58\x0b\x0d\x1f\x7b\x48\x37\x1d\xaf\xec\x8e\x54\x75\xbd\x55\xbe\x16\x05\xcb\x36\x1f\xab\x82\xba\x5e\x86\x8c\x5b\xbd\xdd\x84\x49\x1a\x13\xfb\x08\x1d\x4a\xa0\x44\x7e\xf8\x66\xe7\x30\xab\x34\xe4\x82\x2a\x6c\x1a\xe8\xca\x2a\x74\x1f\x70\x0c\x47\xd7\x66\xcd\x36\x26\x31\x6c\x81\x94\x65\xc1\x28\x86\xe6\x84\x84\xfb\x25\xcb\x96\x0f\x34\xc7\xdc\xa5\x01\x46\xc7\x5a\x3e\x47\x98\xf9\x70\xb4\xa9\x0f\xb5\x47\x6e\x76\x78\x6a\x8f\xb7\xf9\xc1\xd6\x38\xfa\x46\x8a\xaa\x3c\xea\xc3\xbb\xfe\x53\xfb\xdd\xa1\x8e\xf3\xf5\x1f\x8f\x62\x0b\x2e\xcc\x66\xd7\xbd\xee\x49\xe7\x1c\xc3\x53\x4c\xa4\x59\x55\x85\x66\x65\x81\x8c\x8f\xe4\xb9\xb0\x83\x23\x92\xb6\x7a\xed\x1c\x08\xdf\xd4\xb1\x3d\xd7\x20\x85\xe6\x40\x16\xe6\xb9\x87\x97\xcb\x92\xe0\xcd\x6b\x52\x5e\xad\xa8\xc4\x36\xcb\xcd\x80\xf1\x62\xc9\x37\x66\xa4\x0f\x96\x72\xda\x26\xec\x7d\x3d\xa3\x40\x8a\x42\xdc\xef\xeb\x96\xb9\x4d\x63\x0c\x5c\x18\x63\xe4\xc2\x58\x23\x1e\x80\x0b\x5e\x3b\xd4\xbf\xfd\xf8\xd6\x67\x4b\xbd\xef\x73\x70\x3d\x76\x6c\xb7\xf2\x92\x48\xcd\x1e\xec\x8f\xdc\xa5\x4a\x16\xae\xb1\x39\x31\x17\x21\x59\xb7\x34\x5a\x92\x35\x6d\x5a\x99\x8b\x29\xc0\xbf\x1e\x23\xad\x00\x7b\x8e\x34\x4b\x63\xe5\x95\xe0\xc5\x06\x88\xdd\xad\xf3\xaa\x28\xce\x61\xce\x38\x31\x2a\x89\x1e\xbb\xe4\x2e\x17\xcc\xdc\x66\xe1\x06\xbb\xa0\x73\xc1\x27\x8d\xb1\x86\x73\x60\x9e\xcb\xc5\xb1\x7b\xb3\x11\x6f\xb9\xeb\x08\xdb\xb4\xa5\xb7\xc3\x35\x82\x2c\xc3\x8e\x95\x73\xf1\x50\x25\x9a\x2e\x39\x23\xf3\xa3\x28\x30\x20\xe2\x42\x25\xb9\xed\x49\x44\xba\x7f\xfe\x4f\xc6\x8f\xbb\x1e\x5a\xfa\x88\xca\x3e\x23\x1c\x28\xd3\x4b\x73\xbf\x2d\xcb\x62\x63\xc4\xb5\x39\x3b\xed\x81\x3a\x55\x55\xf6\xb0\xa7\xa3\x25\xa2\xe0\x59\x29\x72\xf5\xcc\x88\xfc\x67\xae\xc5\xfd\xb3\x33\xf3\xd3\xf6\xdc\x1e\xc9\xd1\xac\x8e\x1b\x03\x72\xbf\x20\x25\x7b\x76\x76\x0e\xb8\x09\xb0\xa9\x92\xd0\xcb\x2f\xef\xb4\xd6\x33\xd1\xe9\xcc\x77\x88\xb6\x5a\x88\x76\xbe\xef\xba\x04\x89\xd2\x36\xd5\x31\xba\xf6\xe0\x55\xbe\xa6\x82\x29\x3c\xe0\xb6\x71\xb0\x6b\x53\xb7\xab\x78\x01\x2e\x8f\x31\x03\x0c\xd1\x55\xa9\x37\x28\x37\x56\x94\x70\xc7\x93\xae\xa9\xdc\xe8\x25\xe3\x0b\x1c\xec\x97\x2a\x64\x8f\x0a\x98\xb6\x34\xb8\x64\x4e\xb0\xd6\x13\xdf\xb0\x3c\x5a\x59\x33\x35\xb0\x3c\x35\xf7\xcb\xa2\xe8\x5c\xbe\x8e\x3d\xb6\xf8\xa5\x5a\xe5\x7f\x71\xab\x82\xb6\x99\xc7\x8a\x7c\x67\xbe\xd7\x5f\x0d\xfb\x2b\xab\xba\x8c\x38\x3c\x76\xc0\x02\x2e\xdf\xbe\xb5\x6d\xe7\xdc\x3c\xfe\x89\xf1\xdc\xde\xa5\x2e\xb5\xed\xd9\x46\x3f\x52\xf3\x4a\x68\xfe\x1c\xbb\x32\x75\x91\xb3\xbc\xe9\x4b\x6c\x96\x7e\x0a\x38\x50\xef\xb5\xc6\x4e\x70\x5f\xd2\x3a\xef\x5e\xeb\x8e\xbb\x8e\x3d\xc8\xba\x73\xf3\xff\xbc\x17\x76\xec\x86\xd7\xb3\xbf\xd1\x98\x27\x07\x90\x04\xc6\xae\xc6\x86\x77\xe6\x1b\xed\xcb\xc0\xe5\xdb\x77\x4d\x0f\x49\x6c\xc1\xfc\x8f\xba\x9e\x1f\x00\x36\x4c\x0e\x45\xbc\x8f\xbd\x3d\x1d\x03\x3f\x38\x7e\x6b\xed\x75\x75\xb5\xd4\x5b\xbf\xad\x75\x73\xd7\x2f\x77\xc9\xc9\xec\x8d\x5c\xcc\x0f\xdf\x54\x71\xd1\x94\xad\x79\x40\x97\x64\xcd\x84\xac\x2f\x36\xed\x23\x0e\x1d\xd2\x11\xf7\xdd\x63\x6f\xbb\x13\x50\xb4\xa0\x99\x3e\x68\xa1\x4e\x40\xd3\x55\x59\x3c\xbc\xc1\x60\xe4\xad\x78\xc5\xf8\x47\x4a\xf2\xcd\x0d\xcd\x04\xcf\x8f\x92\x24\xbd\xd5\x79\xc7\x38\x5b\x55\x2b\xe0\xd5\x6a\x46\x71\x42\x95\xe5\x84\x27\x05\xbd\x10\x47\x09\x27\x02\x9c\xde\x17\x9b\xba\x89\x39\x94\x22\xaf\x0f\xd5\x0c\x7b\xb6\xe7\x1b\x6c\xba\x28\x2a\x6d\xee\x9b\x47\xf1\x14\x73\xdb\xad\xbd\x2e\x5c\x09\x99\x24\xca\xd8\x44\xe7\x38\x38\xa6\x8d\x1e\x99\x51\x0c\x69\xb2\x9c\xca\xc1\x5a\x19\x03\x43\x5d\x13\x56\x98\x5b\xc5\x14\x5e\xd3\x39\xa9\x0a\xec\x3a\x0a\xcf\xe1\xd4\x0c\xba\xbe\xd8\xfa\x32\x35\x56\xb7\x12\x82\x9b\xff\xda\x52\x19\xf8\xf2\x67\x47\x87\x6a\x0e\x17\xde\xac\xe9\xb8\x02\x9c\x35\x95\xa4\x52\xc7\xf8\x6e\xb6\x36\xc8\x15\xcf\xcd\x29\xed\x1a\xbb\x1d\xd9\xc9\x94\xe3\x7b\x8c\x76\xb4\xef\x37\x13\xa2\xa0\x47\x84\x05\x4b\x29\x16\x92\x2a\xf5\x9a\x92\xbc\x60\x9c\xfa\xee\xf0\xdb\x25\x85\x15\xf9\x84\xbb\x5c\xb3\x15\x35\x96\x41\x77\x8f\x93\xce\xfb\x1c\xa7\xe2\x05\xac\xc8\x1d\x6d\x06\x08\x33\x3a\xc7\x7e\xb4\x38\x1d\xed\xbe\xb1\xbb\xf3\x28\x96\x73\xc2\x0a\x9a\x4f\x71\xac\x9d\xd9\x6d\xdb\xb7\xdb\x6d\x69\x7e\x66\xbc\x3a\x8e\xa7\x16\x66\x84\xe8\x3b\xb0\xec\xbb\x0a\x1c\x0d\x2d\xd2\x36\xaa\x3f\x8a\xa3\x39\xbf\x40\xe0\x7a\x6b\x61\xde\x7c\xca\xac\xb7\x5b\x52\xa2\x04\xaf\x4f\xd0\x51\x2c\x55\x25\xe7\xe6\xfe\x5f\x3b\x17\x3a\x2f\xef\x7a\x72\xc3\x7b\xa1\x5d\x37\xd6\x7a\xc2\x8f\x1c\x6c\x51\x80\xeb\x22\x4c\x95\x66\x2b\x14\x4b\x79\x25\xeb\x7e\xc7\xb8\x17\x46\x2f\x7e\xbb\xe1\x7b\xc2\xe3\xf7\xcf\x9f\x1f\x65\x20\x3e\xee\x11\x97\x14\x1d\x26\xe3\xcf\xc8\xfb\x46\xfa\xd7\x2a\xb6\x14\xb9\x32\xfb\x91\x39\x83\x1f\xdb\x38\x1f\x35\x64\xdc\x79\x39\x53\x9a\xf1\x45\xc5\xd4\x12\x66\x54\xdf\x53\xca\x81\x7e\xb2\x25\x83\xe0\xef\x54\x0a\xdc\x80\x66\x79\x1e\x88\xe2\x0d\x51\x77\xd2\x5f\x3c\x85\x19\x5f\x33\xc5\x04\xff\x23\x53\x5a\xc8\xcd\x5b\xb6\x62\x0f\xd6\x56\xae\x69\xb7\xfd\x7d\xb3\x02\xa2\xc8\xb1\x79\x3d\xcb\xc8\x0d\xb5\x2f\x2a\xa9\x51\x80\xc7\xce\x3d\x7a\x0b\xc0\xc8\x8d\x19\xc9\xee\x06\x16\x71\x6b\x81\x8e\xe2\x7b\xec\x22\x36\x0b\x74\xec\x68\x5f\x3c\xff\xfc\xab\x58\x1b\x70\xa3\x57\xee\x2d\x99\xd1\xa2\xf9\x3a\xaa\x13\x7b\x70\xde\x7c\xb2\xf3\xdb\x5d\xc9\xe3\xc4\xd6\x52\x28\x8a\x4c\x6c\x2c\x00\x59\xd7\x91\x44\xa6\x1a\xf3\xc4\x48\x30\xc1\x8f\xf4\x82\x90\xf9\xbc\xcf\xa5\x15\x7a\x53\xb8\xd2\xb0\xaa\x94\x86\x15\xd1\xd9\xf2\x60\xdc\xb3\x26\x63\x2a\xd5\xe6\xec\x89\x82\xc2\x4c\xc4\x08\x09\x78\x64\xc4\x69\x6c\x84\x08\xec\x5b\xbc\xf9\x64\x2e\xf9\x07\x42\xcb\x7d\xea\x2d\xeb\x36\x93\xbe\xcf\x03\xdf\xf5\x48\xb6\xed\xde\xaa\xef\x13\x2b\xdb\x39\xff\x16\xa3\x46\xed\x6f\xcc\x6a\x1f\xcd\xf3\xf2\xfd\xeb\x63\xe5\xe5\x78\x8f\xc4\x48\x9f\xc4\x76\x9c\xcd\x4e\xcf\xe0\x6b\x1f\xcd\x11\xea\x58\x8a\xe3\xd1\x0f\xb8\x21\x50\x4d\x9d\x03\x81\x3b\xba\x39\x1f\xc1\x14\x6d\x9e\xed\x8e\xf8\x92\x16\xce\xba\xa5\xd8\x2a\xfe\x90\x17\xa1\x4f\x76\x2c\xc7\x2e\xc5\xe8\xdd\x6f\xe9\xf8\xb8\x6b\x4d\x13\xf3\x2a\x23\x3e\x5d\x4f\xc9\xd1\x5f\x19\x7b\x2c\x2d\xdd\xd1\xcd\x98\x8f\x6f\x6d\x2d\xb3\x3a\xce\x7b\x60\xf7\x98\xf9\x85\x59\xc3\x51\x2c\xad\x27\xa1\xd9\x5a\x63\x82\xe5\x3d\x26\xe3\x5c\xae\x35\xd5\x13\x1d\x30\x0d\xcd\xf6\xed\x60\x86\xf0\x28\x9c\x1c\xeb\xd2\xac\x09\xb7\xbe\x91\x6f\x4b\x56\xa2\xe1\x50\x47\x2f\xdd\xae\x86\xef\x48\xc1\xc6\x9c\x86\xee\x1b\x5a\xfd\x75\xc5\xcf\x8d\x01\x6f\xfe\x83\x2a\x51\x8d\x3c\x5f\x86\x5e\x0b\xaa\xde\x0b\x8d\xdf\xff\x87\x2c\x92\x7d\xfd\x80\x25\xb2\x0c\x5c\x98\x09\x25\x2f\x3a\x56\xc6\x8e\xa3\x1d\xcb\xb4\x2e\xcf\xd9\x2c\x3e\x53\x70\xc5\x41\x48\x37\xbb\x1e\x47\xc0\x0d\xd2\x0e\x0f\x2d\x80\x99\x8d\xe8\x62\x40\x6a\xdc\x44\xc3\xd0\xf8\xdc\x82\x0b\xd9\x5b\xc1\x68\x43\xb5\xc3\x44\xeb\x76\x24\x4b\xcb\x07\x3d\x33\x65\x81\xb7\x4f\x77\x2d\x24\x35\x42\x8b\x1d\x4a\x34\xda\xa6\x15\x95\x0b\x0c\x8d\x67\x47\x06\x57\x9b\xd7\x1b\xad\x9d\x2d\x8d\xd4\xd1\xdd\x87\x8d\xd8\x87\x68\x08\xa1\x91\x1b\x60\x48\xd9\xef\x5b\x95\xbe\x22\xa5\x39\x0a\xff\xd7\x68\x6e\x5c\xd5\xff\x77\xbc\xca\x21\x4c\xaa\x29\x5c\x82\x62\x7c\x51\xd0\x2e\x8f\xda\x7b\xd0\x79\xdc\xd1\x6c\xcd\x88\x98\x02\xa3\x62\xd7\xa4\xa0\x1c\x9d\x8a\x84\x03\xb5\x00\x77\x33\xda\x6d\x73\xf0\xf8\x2d\x6c\xad\x79\xa3\xa7\x1a\x64\xc3\xb3\x3b\xba\x79\x76\xbe\x7d\x58\x8e\xe6\xf8\xec\x8a\x3f\x3b\x47\x4b\x66\xe7\x60\x34\x06\x12\x82\x27\x9e\xe1\xdf\x9e\x1d\xbf\x1b\x87\x2c\x52\x1f\x4b\x73\x94\x71\x43\x72\xeb\x7f\x22\xc5\xb5\x87\x45\x31\x6a\x3f\xd7\xe0\x4b\xaf\xeb\x79\xcf\x2f\xe5\x20\xc8\x5a\x40\xa5\xa8\xbd\x9f\xa3\x1c\x39\x6a\xdc\xb4\xbe\x19\xe2\x1d\x0f\x5d\x6a\x9c\xde\xe3\x5d\xee\x09\x5c\x9f\xa4\x28\x0a\xc6\x17\xdf\x96\x39\xd1\x47\x64\x98\x58\xea\xcd\xd6\xc9\x47\xcb\x02\x2a\xe4\x61\x76\xe5\x9c\x2d\xa0\x24\x92\xac\x46\x18\xca\xd7\xae\x00\x35\xee\x65\x36\xef\x46\x91\xdc\xfc\xdf\x6e\x4a\x0a\xff\x13\x3e\x76\x47\x7c\x3c\xff\xc9\x64\x02\xb7\x1f\x5e\x7f\x78\x09\xf6\x9b\xf6\x5e\xac\x05\xcc\x05\xba\x4f\x44\x25\xcd\xd0\xd7\x94\x1f\xed\x1e\x05\xeb\x77\x30\x4b\xf9\x61\x7e\x0e\xf7\x4b\xa2\xe9\x9a\x4a\xb8\x37\xdb\x27\x63\x39\x6d\x22\x16\xd3\x93\xc7\x3b\x51\x3e\x96\xf9\x8a\x7c\xba\xa9\xe4\xe2\xe8\x05\x87\x9d\x45\xef\x3a\xd9\x5b\x57\x96\xd9\xe2\xe3\xb4\x61\xa7\x80\x89\xca\x96\x34\xaf\x0a\x9a\x03\x99\x89\x35\xed\x06\x00\x47\xf1\xec\x0f\x07\x8d\xda\x8a\xd6\x0f\x31\xf6\xd9\x4c\x89\xa2\x3a\x1a\x00\xd4\x63\x7a\x4a\x3f\xbd\x84\xdf\x21\x5e\x8b\x40\x49\x65\x46\xb9\x26\x0b\xda\x71\xa4\x8e\xe2\x8a\x22\x01\x79\xbe\x78\xfe\x2f\x67\xce\x73\x67\x46\xea\xfc\xd8\xcf\xcd\x49\x78\x47\x3e\x7d\xcb\x9b\x70\xd3\x38\xa3\x41\xc1\xf3\x29\x5c\xba\x17\xae\x5f\x02\x9f\x51\x64\x55\x81\x1e\xf2\xb9\x14\xab\x71\x83\x6e\x5f\x7b\xb6\x01\x29\x2a\x44\xd5\x41\x55\xf6\x3c\xe4\xa3\x58\xfe\xe6\x77\xff\x32\x85\x37\x9f\xc8\xaa\x2c\xe8\x4b\xb8\x5f\x52\x87\xe5\x60\x0a\x6f\x28\x5a\xc0\x6f\x9f\xff\xcb\x38\x43\x12\x51\x02\xf4\xbe\xe3\x8f\x6b\xf7\x19\x31\x9b\xac\x2a\x81\xad\x6c\xce\x0c\x3d\x1a\xc7\x62\xc9\x0d\x90\xd6\xd2\xb3\x16\x7d\x4a\x13\xa9\xd5\x39\x20\x18\x6f\xf4\x45\x15\x63\x14\x42\x93\x62\xcb\x37\x8c\x3e\x57\x7a\x6f\x37\x4b\x3e\x6e\x62\xcd\x3e\xa2\x18\xae\x81\x17\xbf\x7d\xfe\x2f\xbb\x0e\xff\x0f\x87\x4a\x02\x6d\x93\x19\x11\x8e\x04\xb1\xaa\x33\x4a\x39\xdc\xb1\xa2\xa0\xf9\xf9\xd6\x74\x8f\xe2\xba\xb3\x34\xf3\x4a\xea\x25\x95\xe7\x40\xb9\xaa\x43\x38\x63\xe7\x73\x6b\x2e\x71\xd4\xb2\xe2\x1c\x2d\x7f\x8c\x4a\x63\x4c\x68\xdc\xb5\xaf\x8d\x27\xb9\x45\x37\x66\xae\x86\x95\x50\x7a\x7b\x8a\x47\x8b\x82\xa3\xd5\x04\xa0\x73\x6b\xf3\x61\x3e\x46\x80\x4f\x46\x3b\xd5\xb7\xbf\x39\xfa\x42\xfb\x69\x72\xd7\x14\x2b\x99\x30\xae\x27\x42\x4e\x2c\x93\x97\xa0\xe5\x91\x71\x4d\xb0\x0a\xab\x23\x03\x9f\x94\xda\xaa\xda\x71\xed\xee\x8e\x71\x77\xc3\x7d\x9a\x6a\x4b\xfb\x8c\x3b\xaf\x7b\x35\xd5\xb6\xf6\x19\xc5\xf6\xb0\x4e\xe9\x3c\x74\x14\xe7\xae\x4e\xc9\xc5\x3d\x1f\xd6\x8a\xa3\x58\xbe\x73\xe6\x8e\xd3\x87\xdd\x90\x62\x4f\xf3\xf8\x28\x81\x1d\x2d\x65\x6f\x7a\xbd\x98\x5e\x80\x28\x34\x33\x60\x38\xff\xff\x76\x85\xf7\x38\x4b\xa0\x55\x75\x07\xd4\xd7\xb8\x7d\xf0\x01\xd3\x02\x6a\xed\x64\x6e\x90\x88\x7e\x39\x8f\x3c\x03\x8d\x3a\xb0\xd6\x3a\x46\xb6\x46\xf1\x34\xcc\xec\xab\x0e\x58\x06\xad\x96\x19\x2f\x05\x86\xb4\xb6\x9d\x0b\x2f\x8b\xcd\xe8\xa5\xa2\x40\xbd\xa4\xf6\x2a\x9b\x82\x92\xa3\xd3\x81\x2c\x0d\x6c\x9f\xa4\x6c\x86\xe8\xa1\xfc\xe9\x6d\xea\x3b\x0d\xcc\xed\x14\xa7\xb8\x8d\xb4\xbe\xb2\x1b\xf9\xd9\x47\x6a\x51\x72\xbb\xfd\x92\xf6\x91\x90\xf0\xac\x77\xd1\x7d\xd6\x88\x2d\xb3\x07\xbc\xee\xc0\xa3\xa6\xb5\x0e\xf5\x8e\x77\x9e\xb8\x2f\x76\x4a\x9a\x60\x12\x91\x39\x12\x78\x60\xee\x59\x71\x5c\x30\x75\x46\x6b\x70\xe1\x13\xf0\x93\xac\xa8\x26\x0f\x65\xe7\x6f\x53\xdf\xec\xb8\xd1\x84\xe7\x44\xe6\x6e\x7c\x27\x27\xaa\x61\x38\x85\x77\x62\x44\x24\x98\xf1\xb9\x78\x09\x4b\xad\x4b\xf5\xf2\xe2\x62\xc1\xf4\xf4\xee\xdf\xd5\x94\x89\x8b\x4c\xac\x56\x15\x67\x7a\x73\x81\x20\x32\x36\xab\xb4\x90\xea\x22\xa7\x6b\x5a\x5c\x28\xb6\x98\x10\x99\x2d\x99\xa6\x99\xae\x24\xbd\x20\x25\x9b\xb4\xde\x0e\x35\x5d\xe5\xbf\xac\x07\xf4\x88\xae\x8a\xde\x09\xc5\x58\x96\x5c\xd3\x49\xc5\xef\xb8\xb8\xe7\x13\xf4\x98\xaa\x11\x67\xf5\x18\x64\x72\x4d\x5b\xeb\xb1\x05\x46\x1e\x04\x1b\x1f\x7f\x58\xe7\xf5\x16\xb7\x8b\xf9\x88\x8b\x64\x5e\x79\x42\x78\x3e\xb1\x60\xb9\x47\x5c\xab\xb1\x31\xe8\x49\x0b\xdb\x3d\xd6\x32\xf1\xf1\x5c\x91\x4c\xb3\x35\xf5\x80\x88\xd6\xd4\xdb\x08\x1f\xea\x8c\xb0\xbc\x92\x76\x2f\xb4\x58\xd1\xd1\x77\xf7\x52\xe4\xb0\x22\x1b\xb4\xdd\x71\x94\x20\xac\x99\xc5\x45\x4e\x5d\xec\xf5\x60\x61\xdf\x2d\xb6\x02\x6e\x8c\x51\x76\xcb\x56\xb4\x46\x9d\x62\x34\x7b\xa3\x34\x5d\x59\x6c\x90\x7d\xd6\x48\x0f\x86\x96\x1b\x0b\x6b\x95\x77\xc0\x74\x8d\x17\x25\x3c\xc7\xcb\x3c\x10\xa5\x44\x66\xac\xc5\x71\x77\xd8\x76\x07\xd4\x5e\xb7\x3a\x76\x47\xa0\x14\x8a\xe1\xa4\x38\x8b\x60\x8c\x99\xe9\x6b\x4a\x74\x40\x61\xbf\xff\xb7\xe3\xb7\xd8\x1c\x7b\x35\x8e\x42\x2e\xf4\x11\xd4\xf3\x6e\x4a\xb7\xdb\x1a\x27\xaa\x76\x70\x8e\x35\x33\x33\xc1\x95\x96\x84\x1d\x9f\xc2\x04\xbe\xc0\x13\x5f\x9c\x07\xe0\x1e\xbf\xf4\x98\x38\xd8\xcd\x1e\xa9\xcd\x06\x3c\x36\xf5\x62\x8c\x64\x09\x9d\xc9\x76\x55\x3b\xea\x44\x20\x23\xa6\xbd\xc2\xa8\xa3\xe7\x12\x02\xe6\xd3\x7e\x97\xce\xa9\x94\x34\x7f\x8d\xf7\x80\x9b\xe6\x8d\xae\x16\x5c\x34\xbf\x7e\xf3\x89\x66\xd5\x71\xa5\xd1\x76\x69\x27\xee\x55\x3b\xe1\xe5\xf1\x76\xda\xf0\xb0\x8d\x78\xa9\x99\x39\xeb\x4f\xe0\x92\x8e\x0d\xde\x5b\x42\xd3\x51\x11\xcd\xd4\xdc\x96\x58\xa9\x37\x06\xd0\x36\x4e\xeb\xc5\xb9\x39\xaa\x0d\x58\x12\x0d\x11\x9b\x45\x7f\xa0\x68\xde\x3e\x32\x6a\x20\x5b\x0a\xa1\x8c\xe4\xc3\x7d\x8c\xe3\x5f\x33\x81\xd8\x33\x2f\x9e\x58\xd7\x41\xc2\xca\xe8\x80\xba\xbe\x43\xfb\xea\x63\xb7\xb4\xa5\xdb\x5a\x3b\xe1\xf0\x98\xb2\x6e\xcc\x66\xdf\x79\xf1\x74\x88\x2d\x33\x5c\x0c\x76\x9a\x1f\x16\x68\xc7\x2b\x0d\xaa\x1a\x17\x6b\xa8\x49\xcc\xe1\x9e\xb2\xc5\x52\xab\x73\x60\x53\x3a\xc5\xd3\x4c\x49\xb6\xc4\xe1\xfb\xef\xa8\x15\xa5\xba\xd7\x88\xd7\x53\x46\xd7\xd4\x8b\xa7\x9f\x36\xe9\xfc\xae\x96\xc7\x58\x28\x4c\x8f\xe7\x8e\x14\xf0\x97\x8d\x80\x61\xe9\x16\xde\x00\x54\x67\xd3\xb3\x73\x68\x2a\xee\xf9\x1d\xa4\x6a\x65\x8e\x10\xd3\xd4\xd8\x52\xe8\xb7\x90\xa2\x5a\xd8\x1d\xe0\xd0\x15\x9e\x5b\x7f\xde\xad\x16\x81\xa8\xce\x1c\xfd\x83\xcf\xec\xa6\x38\xfe\x5e\xdd\x25\x6d\x6b\xf1\x98\x61\xb3\x79\x6b\xa8\x21\xf8\xc3\x5b\x4a\x51\xc8\x84\x94\x54\x95\xc2\x7a\x30\xb7\xa1\x24\xff\xc3\x9b\xaf\x19\xdc\xa9\x3a\x6b\x0f\xd5\x92\x2d\x96\x21\x67\x8a\x38\x63\xb2\x7f\xe6\x7d\x04\x89\x2f\xa6\xc9\x92\x17\xb2\xc9\x52\x1f\x89\xcc\x5d\x69\x85\x30\xf9\xd5\x33\x1d\x34\x95\xab\x7a\x47\x18\x31\xe1\xc9\xd1\x9a\x0e\x0e\xfd\x51\x77\xd2\x76\x12\xcd\x93\xe5\x73\x38\x45\x41\xc8\xf4\x89\x42\x25\x33\x11\xe5\xd9\x14\x2e\x81\x57\xde\xc3\x6c\x26\x6e\xdf\x14\x78\xf2\xe5\xa2\x99\x01\x37\x68\x33\x99\x4a\xb4\xe3\xf6\x3b\x15\xfe\x66\x99\xa5\xf1\x38\xeb\x2e\x4d\xdc\x7c\xd1\xb1\x21\xd4\x96\x41\xc0\x0e\x08\x31\x2c\x6b\x0e\xf5\xe8\x7d\x39\xec\xa4\x02\xa0\x00\x3d\x32\x3b\xfa\x21\x32\x7b\xee\xbc\x73\x0b\x6d\x84\x5e\x00\xcf\xbe\x5c\xb6\x33\xef\xb7\xef\x20\xc6\xde\x83\x28\x6b\x08\x01\x19\x30\xc3\xb4\x9d\xdc\x61\x73\x60\x82\x58\x42\x7f\x5f\xf4\x8c\xa4\x40\xc6\xb3\x0d\xf2\x1e\x95\x90\xb4\x9f\xc2\xf4\x58\x4b\x01\x1a\xad\xa5\x81\xa3\x15\xc8\x71\x38\x37\x29\x98\xe9\x6e\xea\x4e\x30\xcb\xdd\xd4\x9f\x60\x96\x77\x74\x73\xbe\x9d\x10\x14\xcc\x74\x28\xa1\x28\x98\xa9\x19\xe4\xd8\x34\xa3\x3d\xc3\x8b\x21\xa4\x2c\x85\xa9\xca\x96\xc6\x25\x2a\xed\xe3\x11\x69\x01\xe3\xc8\x5f\x4b\xa3\x53\x9d\x86\x69\xdb\x21\x13\x81\x25\x84\x65\x4f\x0d\xd3\x50\x4e\x55\x1c\xc6\x23\xf3\xb2\xf6\x70\xf1\x0b\x21\x0f\x93\x5f\x0e\xd7\x30\x6d\x55\x3c\x1b\x59\x9b\xea\x61\x72\x49\x61\xbd\x34\xaf\x48\x6b\xb2\x93\x2a\x16\x85\x2f\xa6\x9b\xb5\x09\x64\x71\x26\xa1\x97\x84\x16\x85\xa5\xcd\x6b\x3a\x0f\xc8\x4b\xdb\x47\xdf\x68\xab\x93\xde\x46\xe1\x17\x75\xd3\xfb\xe4\xc4\x0d\xd3\xd6\x25\x3d\xd2\x2a\x87\xe4\xd8\x0d\x53\x3f\xf3\x2e\x0a\xcb\x7e\xf6\x5e\x1c\x96\x75\x06\x60\xb4\x41\xee\x24\xdb\x45\xe1\x1a\x92\x5b\x38\x4c\x5b\x19\x87\x51\x78\x46\xcb\x5a\x1c\xa6\xed\x94\xad\x28\x4c\xfb\xf9\x90\x4f\x79\x6a\xbf\xd1\x66\x5a\xdf\xea\xa7\xbe\x57\x6d\xd9\x65\x97\x67\x18\x85\xa3\x73\x77\x9f\x8f\x28\xa8\x76\x88\xea\x42\x20\x58\xd1\xa5\x94\x74\x6c\x70\x7e\x1f\x11\x4c\x5a\xf6\x88\xca\xef\x27\x04\xec\xd6\x49\xb7\x51\x38\x6e\x25\xee\x46\x32\x97\x9a\xe4\x5f\x9b\xce\x1b\x85\xab\x47\x4a\xf0\x30\xc5\x72\x46\x58\x8a\xe2\x92\xe8\x0e\x2c\x58\xf1\xa2\xdb\xea\x6b\x8b\xf9\xfa\xa7\xf4\x58\x59\xbc\x5b\xf2\x58\x3d\x48\xc9\x63\x95\x3c\x56\x7e\x94\x3c\x56\x07\x28\x79\xac\x92\xc7\xea\x08\x4a\x1e\xab\x0e\x25\x8f\x55\xf2\x58\xf9\x51\xf2\x58\x3d\x75\x2f\x40\xf2\x58\x25\x8f\x55\xf2\x58\x25\x8f\x55\xf2\x58\x79\xd2\xcf\xd9\x63\x65\xf1\x62\x91\x80\x72\x7f\x46\x66\xbe\x59\x56\x5b\x03\x63\x7a\x69\x7d\x69\x75\xaa\x78\x0f\xe8\x16\xc0\x99\x8b\x9c\xde\xb8\x0b\xd3\x2d\x02\xf2\x6c\xd5\xbd\x00\x96\x92\xf0\x05\x85\x17\x93\x17\xcf\x8f\x2a\x02\x3e\x4c\xbe\xd9\x60\x7d\x1a\x57\x30\x7c\x9b\xf6\x61\xf2\x1f\x29\x33\xc7\x69\xbb\x26\xe7\x25\xd8\x1f\xb9\x27\xe9\x65\x64\x3b\xc7\x3e\xad\xa8\x06\xa2\x7b\xd0\x61\xb6\xa2\x4d\x02\x9c\x17\xcf\x6e\x53\x87\xb6\x3e\x98\xe0\x16\xbb\xef\xc5\xd2\x6c\xeb\xe9\x3f\x6e\x46\x33\x4a\x94\x67\x82\x0a\xf6\xba\xa9\x67\x55\xac\xa8\x2d\xe7\x1f\xa2\x50\x4a\x91\x03\xad\x77\x25\x9c\xd2\xe9\x62\x0a\x79\x45\x6d\x05\x4c\x2f\x8e\xb6\x2e\xc5\xd9\x79\x37\x2d\x75\x65\x2e\x3a\xd2\xfc\xc7\x73\x81\x74\x9d\x9f\x4a\xd7\x94\xeb\x8a\x14\xc5\x06\xe8\x9a\x65\xda\x7b\xd1\xcd\x8b\x63\x51\x1a\xa6\x6d\x62\xa1\x7f\x9a\x83\xb7\x73\x32\xc4\x21\x39\xd9\x91\xc6\x3e\xbb\x34\xd4\x7b\xb8\x33\x06\x5f\x7d\xb8\xe5\x53\xb2\xf3\x32\x75\xc1\x1b\x6f\x91\x2e\xe6\x5b\x61\x1b\x6d\xc6\x38\x0d\x72\x4a\x22\x0b\x14\x8b\x1f\x3e\xfa\x25\xc7\x40\x14\xcb\x28\xd0\x1a\xda\x0e\xcd\x54\x45\x61\x8e\x28\x5e\xc8\x02\x4d\x84\xfe\x74\x07\x66\x8a\x40\x2f\x5b\x64\xb7\x6b\x42\x00\x5b\x9b\xe0\xb7\xea\x54\xb9\x45\xee\xb7\xa2\x14\x85\x58\x6c\xba\xfb\x3a\xe0\x29\x66\xa5\x31\xc3\xa7\xae\xa9\x0b\xaa\x9a\xa9\x91\x05\x90\x86\x06\x0e\xef\xb7\x0e\x5f\xca\x5d\xd8\xa1\x2f\x35\x12\x9c\x72\x17\x8e\xa0\x14\x09\x4e\x91\x60\x3f\x4a\x91\xe0\x03\x94\x22\xc1\x29\x12\x7c\x04\xa5\x48\x70\x87\x52\x24\x38\x45\x82\xfd\x28\x45\x82\x9f\x7a\x74\x2d\x45\x82\x53\x24\x38\x45\x82\x53\x24\x38\x45\x82\x3d\xe9\xe7\x1c\x09\x86\x94\xbb\x90\x72\x17\x8e\xa2\xe4\xb1\x4a\x1e\x2b\x3f\x4a\x1e\xab\x03\x94\x3c\x56\xc9\x63\x75\x04\x25\x8f\x55\x87\x92\xc7\x2a\x79\xac\xfc\x28\x79\xac\x9e\xba\x17\x20\x79\xac\x92\xc7\x2a\x79\xac\x92\xc7\x2a\x79\xac\x3c\xe9\xe7\xe7\xb1\x2a\x45\x1e\xb9\x21\x47\x29\xf2\x88\xfd\x38\x2c\xfa\x38\x13\x93\x42\x64\x75\x3f\xee\xd1\x5c\xcd\x90\x6c\x56\x02\x28\xb2\xb2\x45\xd2\xcf\xe1\xef\x82\x53\x5b\xd4\x1e\xc8\x78\x9e\x08\xb5\x16\x7a\x49\xa5\x61\x7f\xaa\xce\x46\x97\xa7\x4e\xfd\x42\xc6\x0f\x3b\xf5\x0b\x49\xfd\x42\x52\xbf\x90\xd4\x2f\xe4\x8b\xeb\x17\xb2\x24\x6a\x7c\x3b\xde\x9a\xd0\x60\x6d\x1a\x4c\xc4\xc9\xde\xeb\x28\xfe\x5b\x2a\x57\xff\x63\xa7\x7b\x88\xe7\xf6\xef\x75\x1c\xf9\xd9\x75\x0f\x31\xa2\xcd\x89\x0c\xb3\x7f\x02\x7a\x7d\xd8\xbd\x61\xd7\x34\x77\xb9\x9e\x34\xbf\xee\xaf\x8a\x27\x73\x1b\x77\xc3\xc9\x27\x79\x4e\x73\x28\xa9\x9c\x58\x89\x2c\xbc\x59\xf2\x7c\x60\x25\xeb\x1d\xe3\xb7\x59\x3e\x7b\x67\x8e\x08\xb3\xfd\xb9\xdb\x73\xf4\x5f\x21\x52\xee\x4f\x37\xd9\xca\x37\x29\xd3\x52\x63\x50\x6d\x37\xeb\x08\xe0\xd9\x18\x00\x4f\xb0\x59\x47\x78\x4c\x6e\x02\xda\x25\x1b\xfd\x29\x20\x2a\x17\x27\x8c\x86\x41\xaa\x3a\x9d\x28\x2e\x86\x01\xc3\x5f\x7f\xab\xa8\x0c\xbd\x49\x8b\x35\x95\x6d\x28\xa4\x36\x8e\x54\xa8\xb3\x90\xb9\xb6\xfd\x19\x51\xf6\xa6\x11\x03\xc6\x10\x21\xec\x1b\x2f\x3e\x1a\x37\xab\x0a\xb6\xd7\x78\x9b\x7d\x0c\x87\x89\x02\x52\xa3\x5f\xec\x0e\x8a\xc0\x74\x10\x02\x13\xc3\x59\x14\x31\x2b\xb1\xa6\x36\x2b\x31\x1c\x26\x11\xd1\x95\x15\xcd\x91\x35\x24\x24\xa2\xf8\xc7\x1e\x05\x64\x03\xdb\x40\x9b\x48\xf1\x09\xa2\x1b\xb0\x4d\x44\x07\xfd\xb9\x8d\x45\xc7\x09\xa2\xc4\x06\xed\xc0\x00\x70\x27\x0a\xd3\x3b\xba\x89\x08\xde\x81\xb8\x00\x1e\x88\x08\xe2\x81\x48\x40\x1e\x88\x09\xe6\x81\xc8\x80\x1e\x88\x07\xea\x81\x6d\x71\x13\x67\xea\x2c\x39\x6f\x55\x3c\xf9\x05\x6e\x2b\xe3\x19\x89\x75\x36\xa0\x2b\x18\x63\xe2\x85\x20\x1a\x66\x08\x62\x43\x28\x20\x32\x76\x08\xb6\xb7\x51\x54\x91\x08\x36\xcc\x16\x13\x90\x04\x8f\x09\x4a\x82\x3e\x30\x29\x1a\xcf\x1a\x06\x82\xe0\xa4\x68\x5c\xe3\x82\x9c\xe0\x71\x80\x4e\xd0\x80\x9d\x8c\x1e\x8b\xc6\x32\x3e\x6e\xea\x11\x0e\x6a\x3c\xbc\x13\x6c\x1f\x53\xcb\x3a\xa6\xc0\x27\x3c\x22\x9e\x04\xac\x8b\x30\xe2\x5c\x42\x0f\x4d\x15\xef\xb4\xc7\x86\xa8\x80\x9d\xcd\x2b\xde\xa2\xaa\xa2\x0e\x36\xf2\xc2\x47\x46\xbd\xc0\xa3\xa0\xb4\xe0\x91\xe0\x44\xd0\x45\x6b\xc5\xdb\xf7\x8f\x81\xfa\x82\x2f\x69\xf9\x23\x2f\x7d\x0b\xfd\x89\xb9\xea\x35\xfc\x27\x1a\x4f\x0b\x23\xea\x42\x80\xa2\xb1\x46\x28\x51\x3c\x18\x10\x44\x87\x02\x41\x5c\x38\x10\xc4\xd5\xc6\xe8\xca\x7b\x8b\xe5\x87\x1e\xc3\x49\x68\x39\xc7\xf2\x0f\xae\x48\x69\x54\xe7\xff\xbd\xa3\x9b\x73\x3c\xed\xff\x2f\xc6\x25\x96\x30\xa9\xa6\x70\x19\x0f\x8f\xd8\x19\x5f\x78\xc5\xd4\x9a\x3a\xd3\x69\xe6\x21\xce\x94\xd2\xbf\x55\x6c\x4d\x0a\xca\xb5\x7f\xf8\xb0\x4b\x84\xd7\x71\x7b\xb3\x4e\xdb\x6e\xe2\x18\xe2\xfe\x7e\x29\x14\xe6\x7d\xd9\x48\x68\x9c\x69\x78\x76\x47\x37\xcf\xce\x63\x2b\x51\xc3\xf8\x8a\x3f\xb3\x29\x07\x71\x36\x41\x0f\x8f\x1b\xd1\x91\x28\x78\xb1\x81\x67\xc8\xfd\x59\x58\xb9\xc4\x96\x7a\xc8\x16\x22\x63\xb0\x8c\xea\x1f\x8f\xe4\xe6\x23\x79\xce\x8c\xc0\x23\xc5\x75\x54\x6f\x58\x24\x19\xcf\xc9\x8a\xaa\x92\x64\xa1\x83\xea\x89\xf6\x96\x69\xe0\x8b\xd6\x50\x3a\xe5\x70\x30\xd1\x18\x37\x2e\xba\x9b\xb8\x4e\x30\x2d\xe0\xb4\x06\xeb\x90\x85\x39\x7d\xfa\xec\x7f\x04\xf2\xec\xd5\xe2\xb4\x31\xb0\x15\x25\xc1\xe7\xfa\x19\xc6\x38\x4b\x91\x9f\xa8\x76\x5e\xfd\x80\x4f\x35\x3d\xa9\x84\xed\x48\x07\xa4\x13\x91\x8f\x78\x42\x6e\xdd\xdc\x87\x9e\x8f\xa5\xa8\x8a\xdc\xdc\x1b\x1a\x98\x74\x28\xcb\xd3\x1a\xb6\x71\x66\xf6\x1c\x17\x3a\x26\x6b\xae\xd9\xa4\xe5\xef\x0d\x35\x6b\xc9\x95\x0e\x57\xbd\x02\xf7\x81\x3c\xfb\x72\x21\x8a\x81\xd6\x42\x82\x5b\x09\x16\x6a\xed\xdc\x2f\xa9\xec\xae\x7b\x78\x6e\x47\x4e\xe7\x8c\xd3\x1c\x88\x02\x59\x71\x6e\x66\x53\x84\x66\xc9\x39\xb4\xb2\x35\xcb\xd0\x80\x08\x77\x0e\x37\xc2\xdb\xc2\x81\x30\x38\x12\x01\x37\x63\xa9\x85\x5a\x12\x34\x52\x09\x0f\xe5\x88\x13\x20\xb8\x53\x61\x84\x6f\xe2\xcc\x80\x0d\xdf\xd0\xdc\xee\xff\xe0\xc5\x77\x2b\x3e\x85\x37\xa8\x66\xe2\x4d\x28\x53\x28\x45\x48\x51\x88\xfb\x50\xeb\xec\xa9\xf5\xe9\xb8\xff\x22\xfa\x74\x6c\x01\x05\x53\x9b\x8e\x96\x52\x9b\x8e\x5d\x4a\x6d\x3a\xbe\xe8\x36\x1d\xde\x6b\x64\x55\xea\x9e\x7e\x1d\x5e\x1c\x6d\x8f\x8f\x87\xfa\x75\xf8\x4d\xa8\xdd\x88\x5b\xfd\x3a\xe0\xcf\x4b\x8a\x72\xcd\xd3\x95\x60\x8e\xcc\xaa\x2a\x34\x2b\x8b\x36\xbb\xc4\x4e\x43\xe1\x1d\xe4\x70\x1d\x27\xd4\x16\x5e\xd9\xcc\x04\xf1\x4c\x44\xde\x92\xe6\x38\x6e\x4c\x42\x56\x68\x0e\xf8\x99\x95\x98\x02\x45\x8a\xc2\xb5\xb3\xa8\x73\xda\x6d\x7e\x1c\xfb\x92\xd3\x36\x5e\xa3\x51\xab\x42\x81\x09\x68\x64\x9d\x1a\xeb\xbd\x30\x62\xc1\x58\xb3\xb5\xae\xf6\xe4\xb8\xeb\x82\xb0\x98\x8c\x75\x40\xaa\x06\xa6\xc6\xb1\x35\xe5\xed\x3d\xe3\x54\x9d\x9d\x85\xd4\x19\xaa\xbd\x04\x31\xef\x9a\x8f\x70\xc7\x1c\xba\x5b\x9e\xdb\x3b\x92\x27\xc7\xde\xcd\x6a\xe0\x6e\xe4\xc9\x56\xf0\xe1\x3b\x51\x80\x45\xb6\x75\x17\xfa\x43\xc7\x76\xff\x5f\x9e\x2c\x07\x6e\x41\xf5\x3d\xc6\xd7\xee\xb6\xb7\x1f\xdc\x4a\x75\x6a\xa4\xc5\xed\x7b\xe7\xc6\xd9\x58\x64\xc0\x6a\x7c\xf6\x2c\xa4\xd0\x5b\x56\x38\xc0\x32\x52\x9a\xc7\xa3\xa4\x78\x3c\x42\x7a\x47\xc4\xd4\x8e\x7f\x8e\x26\x39\x91\x53\x39\x76\xd3\x38\x62\x21\xe8\x7b\x29\x1c\xb1\x13\x30\x22\x25\x5f\x3c\x29\xff\xf8\xa3\x24\x5c\xa4\x8a\xa6\xa9\xa2\xa9\x1f\xa5\x8a\xa6\x07\xe8\x31\x2a\x9a\xc6\x4a\x7c\xe8\x26\x3d\x44\x63\x5a\x27\x3c\xc4\xcd\xb1\x72\x71\xde\x7f\xaa\xc2\xa6\x51\x91\x9f\x6d\x52\x42\x9d\x4c\x10\x89\x6d\x9b\x90\x10\x07\x6c\x04\xa9\x4a\x2a\x26\x0e\x44\x07\xfc\x7f\x09\x85\x4d\x23\x82\x7d\x3b\x00\xff\x58\x89\x2d\x76\xee\xa2\x6e\xcb\x47\xaa\x19\x19\x1d\x8c\xff\xa8\x35\x38\x53\x89\xd3\x2f\xa5\xc4\x69\xaa\x49\x19\x4d\x10\xff\x9c\x6a\x52\xf6\x29\x1a\xf8\xfc\x91\x80\xe7\x8f\x03\x3a\xdf\x02\x9c\x47\xe4\xec\x0a\x61\xc6\x85\x8a\x6f\xc3\xc4\x81\x84\x62\x86\x1e\x11\x22\xbe\x05\x0f\x6f\xc1\xdd\x11\x00\x39\xdd\xea\xe2\x08\xec\x0e\x75\x3a\xb9\xb2\x5b\x11\xc5\x79\xe3\xf6\xe8\x01\xba\x03\x99\x6e\xfb\xda\x22\x80\xb9\xa3\xf9\xda\x22\xb8\x26\x1e\x03\xc0\x1d\x41\x3e\xc6\x00\x6e\xef\x01\x6d\xb7\xb0\xeb\x10\x38\xd3\x16\x60\x7b\x37\xde\x19\xc0\xbc\xbd\xc4\xc7\x85\x5b\x3f\x02\xd4\x3a\x32\xcc\x3a\x86\xca\x0f\x56\xf4\x11\xb6\x6f\x14\x58\xf5\x20\xa4\xda\x05\xaa\x03\x5e\xaf\x17\xe2\xee\x04\xab\x43\x42\x59\xdb\x61\xee\xed\x80\x75\x28\x70\x30\x36\x10\x7a\x08\x04\xdd\x62\xa3\x42\x8e\x58\x0b\x80\xde\x81\x30\x87\x04\xf6\x86\x42\xf4\x61\xf0\xe5\xd8\x61\x7a\xd8\x0d\xd5\xc7\x41\xd9\xee\x0b\xd6\x87\xec\xd7\x3e\x5c\xb9\x07\x38\x0e\x60\xeb\xa0\xca\x8f\x03\x36\x8e\x05\x34\x0e\x2a\xa8\xcf\x35\x7b\x8c\xa2\xfa\x5d\x59\x31\xfa\xc5\xf6\x54\xd6\x27\x6b\xc1\x72\x28\x2b\xad\x7d\xc4\x78\x83\x0b\x7a\xa8\xba\xfe\x68\xae\x44\xa5\xea\xfa\x0f\xd0\x17\x5c\x5d\x3f\x68\x07\x43\xbf\xbe\xf8\x2e\x48\xd7\x8b\x63\xaf\x2c\xff\x6e\x89\x7d\xff\x17\xaf\xcb\xf2\x0f\x94\xd8\x0f\x7d\xf5\xe9\x4e\x89\x7d\x2f\x8e\x5b\xa5\x9c\xb7\x4a\xec\x7b\xbe\x79\xbf\x2c\xff\x4e\x89\x7d\xbf\x35\xea\x96\xe5\xdf\x2d\xb1\xef\x3d\xd2\xae\x4c\x1c\x2c\xb1\xef\x8d\x07\xa3\x4a\x9f\xef\xcd\x2b\xf0\xe2\xda\x3b\x3b\x43\x75\xf6\xbd\xb8\x36\xb5\xf9\xf7\xd6\xd9\xf7\x9e\xdc\x1a\x3d\xbd\x5b\x67\xdf\xef\xfd\xfb\xb5\xf9\xfb\x75\xf6\xbd\x07\xd9\xab\xcd\xdf\xaf\xb3\xef\xcd\xb3\x8f\xf2\xde\xae\xb3\x1f\x34\xd4\xba\x36\xff\x76\x9d\x7d\xbf\x19\x4d\xb5\xf9\x87\x29\xd5\xe6\x7f\x02\xa8\xd8\x54\x9b\xbf\xa5\x54\x9b\x3f\xd5\xe6\xdf\xa1\x54\x9b\x3f\xd5\xe6\x1f\x41\xa9\x36\x7f\x97\x52\x6d\xfe\xd1\x94\x6a\xf3\xa7\xda\xfc\xa9\x36\xbf\x37\xa5\xda\xfc\xe3\x28\xd5\xe6\x4f\xb5\xf9\x23\x50\xaa\xcd\xdf\xa5\x54\x9b\x3f\xd5\xe6\x4f\xb5\xf9\x23\x50\xaa\xcd\x9f\x6a\xf3\xa7\xda\xfc\xa9\x36\x7f\x30\xa5\xda\xfc\xa9\x36\x7f\x10\xa5\xda\xfc\xa9\x36\x7f\xaa\xcd\x9f\x6a\xf3\xa7\xda\xfc\x9e\x94\x6a\xf3\x07\x50\xaa\xcd\x9f\x6a\xf3\x87\x0d\x26\xd5\xe6\x1f\x49\xa9\x36\x7f\xaa\xcd\x9f\x6a\xf3\xa7\xda\xfc\xa9\x36\xff\x30\xa5\xda\xfc\xa9\x36\xff\x18\x1a\xac\xcd\x1f\x9c\xa8\xd2\xbb\x3c\x45\xcc\x54\xa9\x8b\xfa\xef\x16\xe8\xf7\xe2\xd9\x2b\xea\x3f\x5c\xa0\xdf\x8b\x6f\x5d\xd4\x7f\xab\x40\xff\xd3\x9d\x56\xac\xec\xbf\x5b\xa5\xdf\x8b\x63\xb7\xb2\xff\x50\x95\x7e\x2f\xa6\xdd\xca\xfe\x03\x55\xfa\xbd\x78\xb6\x95\xfd\x1f\xac\xd2\xef\xc5\x1b\x2b\xfb\x3f\x54\xa5\xdf\x6f\xbf\xa2\x4d\xb5\xbf\x4a\xbf\x17\xd3\xc2\x56\x62\xda\x57\xa5\xdf\xef\xf5\x49\xb6\x4c\x55\xfa\x0f\x52\xaa\xd2\x9f\xaa\xf4\xa7\x2a\xfd\xa9\x4a\xff\x41\xfa\xec\xf9\x48\xa9\x4a\xff\x43\x94\xaa\xf4\x1f\x49\xa9\x4a\x7f\xaa\xd2\x3f\x9a\x52\x95\xfe\x54\xa5\x3f\x55\xe9\xdf\xc3\x23\x55\xe9\x1f\x45\xa9\x4a\x7f\xaa\xd2\x1f\xcc\x36\x55\xe9\x4f\x55\xfa\x43\x28\x55\xe9\x4f\x55\xfa\x53\x95\xfe\x54\xa5\x3f\x55\xe9\xf7\xa3\x54\xa5\x7f\x2c\xa5\x2a\xfd\xa9\x4a\xbf\xa5\x54\xa5\x3f\x55\xe9\x1f\x3d\xb8\x54\xa5\xdf\x97\x52\x95\xfe\x54\xa5\x3f\x55\xe9\x77\x94\xaa\xf4\xa7\x2a\xfd\xa9\x4a\xff\x67\xae\xd2\x4f\x2a\x2d\x56\xa2\xe2\xfa\x86\xca\x35\xcb\xe8\x65\x96\x99\x9f\x6e\xc5\x1d\x1d\x05\x20\xed\x47\xe5\x1e\x60\x3a\xea\xf5\x18\xcf\x59\x86\x31\xa4\xfb\x25\xc5\x02\xf8\x04\x94\xe5\x09\xc4\x32\x05\x3d\x9a\x6b\x8b\x08\xc2\xb7\x27\x9a\x65\xa4\x28\x36\x80\x43\x1e\xb7\x02\x76\xce\x67\x42\x14\x74\xc4\xf5\xc1\x99\xb3\x54\x8e\xd2\x66\xbd\x29\x7e\xeb\x62\xd1\x2d\x2b\x98\xd1\x42\xf0\xc5\x58\xd5\xe6\xa0\xa9\xa5\xc8\xa7\xf0\xaa\x65\x96\x11\x8e\x82\xbf\x92\x92\x72\x3d\x12\xf6\x38\xab\xcb\xf9\x62\x40\x75\x25\xd6\x34\xc7\xd0\x36\x22\x15\xad\x4b\x66\x64\x2c\xb4\xa0\xc4\xbc\x2f\xa7\xed\x0b\x1b\xe1\x4e\xe0\x1a\xc7\x6d\x07\x3b\x1b\x27\x39\x2c\x62\xd4\x63\xb9\xc7\x5a\x31\x1e\x76\xcb\x56\x90\xdb\xdd\xa8\xd1\x7c\xcc\x30\xdc\xd0\xce\xc3\x48\x79\x81\xc2\x76\x23\x2a\xb8\x27\xf6\xda\x2b\x2b\x8e\x82\x1d\xa7\xd3\x6c\x83\x71\xdb\xc7\xf7\xba\xe2\x17\x37\x9d\xa0\x1e\x1e\xf5\x15\xff\x58\x26\x91\x0b\x0f\x73\xb3\xb7\x74\x27\x97\x72\x51\xd9\xdb\xa5\x3b\x68\x94\x6b\xb9\x41\x50\xb4\x8f\xa4\x37\x77\xd6\x5c\x64\x77\x66\xfb\xaf\xc8\x82\x9e\x9c\x28\x78\xf5\xee\xb5\xd1\x21\x95\xf2\x52\x71\xcc\x15\xa4\x77\x5a\xa8\x94\x62\xcd\x72\x73\x5e\xbf\x23\x92\x91\x99\x57\x09\x01\x2c\xba\x4d\xb9\xb9\x3d\xfd\xea\xf4\xbb\xcb\x8f\x3f\xbe\xbf\x7c\xf7\xe6\x0c\xa3\x45\xf4\x53\x49\x78\xee\x35\xd2\x4a\xb5\xa9\x26\x6e\xef\x9b\xd7\xa7\x7c\xcd\xa4\xe0\x66\x92\x7d\x66\xf4\x6a\x0e\x04\xd6\xee\x5d\x6b\xb1\x37\xa3\x08\xdb\x2a\xd6\x7e\xb8\x64\x8d\x9e\x05\x37\x07\xb5\x11\xca\x78\x59\x69\xff\xcb\x07\xa6\x23\xcc\x28\x54\x3c\x5b\x12\xbe\x70\x12\xb5\x3b\xbf\x1e\x4c\xd5\x86\x6b\xf2\xc9\xbc\x35\xba\xc9\x55\x46\x4a\x9a\x5b\x33\x8f\x40\x2e\x2a\xbf\xe5\xff\xd5\xaf\xce\x81\xd1\x97\xf0\xab\xce\xe0\xa6\xf0\xc6\x71\x6f\x37\x87\xef\x2c\x70\xba\xa6\x12\x07\xec\x36\xd3\x39\x48\xba\x20\x32\x2f\xa8\xf2\x61\x2a\xe6\x8d\x79\x61\xfd\x56\x6e\x33\xd0\x3a\xde\xe1\xc1\x93\x0b\xdd\xd1\x4b\x8d\xae\x81\x77\x02\x61\xef\x73\xe1\x73\x7b\x5c\x6a\x5d\xaa\x97\x17\x17\x77\xd5\x8c\x4a\x4e\x35\x55\x53\x26\x2e\x72\x91\xa9\x0b\x4d\xd4\x9d\xba\x60\xdc\xc8\xe1\x49\x4e\x34\x99\x74\x94\xc5\x85\xbd\x62\x4c\x32\xb1\x5a\x11\x9e\x4f\x88\x13\x4a\x93\xe6\x20\x5d\xfc\xd2\x99\xb6\x13\xd2\x7c\x8a\xf1\x09\x99\xa8\x25\x2d\x8a\x93\xd1\x63\x0d\xb9\xee\x7b\x5f\xf3\x03\xae\xf7\xee\x9d\x43\xa5\xfd\x9b\x46\xb8\xdb\x77\x9f\xc2\x7b\xe1\xe3\xc5\xb3\x39\x32\xee\x28\xa2\x62\xc6\x75\x98\x76\xe4\xbf\x8f\xa8\xaf\x35\xc6\x9b\xf7\xb7\x1f\xff\x72\xfd\xe1\xea\xfd\x6d\xad\x38\x6a\x35\xe0\xc3\x75\x9f\xe2\x08\x3b\xe9\xfb\x14\x47\xab\x06\x3c\x98\xee\x55\x1c\x7d\x35\xe0\xc3\x79\x57\x71\xf4\xd5\x80\xcf\xcc\xee\x2a\x8e\x01\x35\xe0\x69\x45\x74\xe7\x77\x50\x0d\x78\x49\xe7\x8e\xe2\x18\x56\x03\x1e\x5c\x77\x15\x47\x5f\x0d\x78\x9d\xaf\x5d\xc5\xd1\x51\x03\x9e\x2a\x7f\x57\x71\x74\xd5\x80\x07\xd3\x61\xc5\x91\xd4\xc0\x31\x0f\xf5\x52\x03\x94\xaf\x03\x55\x40\x7d\x2f\xef\x08\x97\x66\x5f\xf8\x88\x41\x2d\x10\x0b\xe6\x44\x41\xb3\x50\x71\x36\xd5\x97\xb1\x9e\xbd\xf9\x7d\xc3\xd7\xdf\x11\xd9\x03\xf3\xf9\xf9\x4a\x87\x16\x08\x1c\x53\x60\x7e\x3c\x49\xeb\x41\xf1\x4f\x3c\xf4\x0e\xfd\x85\x20\x91\x3d\xee\xd5\x96\x42\x91\xc2\xe6\xb1\xbe\x81\x94\xde\xc6\x78\x4f\x56\xb5\x9f\xbb\xbb\xb6\xde\xde\xd4\x7a\x4f\x4c\xe1\x5d\xed\xb2\x82\x57\x3f\x5e\xbd\x7e\xf3\xfe\xf6\xea\xeb\xab\x37\x1f\x7d\xfd\xb4\xc1\x31\x28\xf4\xe8\x47\x99\xb2\x93\x38\x96\x9a\xa5\x87\xed\x35\x7f\xa7\xf6\x12\x4f\xe5\x9a\x89\xaa\x8d\x94\xc4\x5c\x5f\xb5\x23\x5b\xbd\x59\xda\x24\x8a\x4d\xe3\xa1\x8e\x3a\xcc\xe9\xa0\xa7\xc2\x9b\x6f\x54\x43\xd5\xd2\x03\xe6\xaa\x37\xcf\xa8\xde\x0e\x4b\xfb\x7d\x1e\xfe\x0b\x1f\xdb\xe4\xb5\xf4\xa0\xe1\x1b\xb2\xf2\x7b\xcc\x5f\x6f\x96\x0f\x78\x4f\xbc\x79\xd6\xc6\xf3\x6b\x3a\x27\x55\x61\xfd\xa7\xcf\x9e\x4d\xc7\xdb\xa0\x96\xe2\x88\xdd\xaf\xa5\xf0\xee\x5c\xd7\x13\xbd\x37\x98\x12\x8a\xbd\x5c\x43\x02\xb3\x43\x46\xcc\x89\x4b\x0e\xf3\xdf\x77\x1d\xb7\x95\x73\x0d\xd8\x28\x72\x00\xe0\xd5\xf0\x0b\x42\xe1\x46\x80\x45\xc5\x48\x6a\xca\x04\x9f\xb3\xc5\x3b\x52\xfe\x89\x6e\x3e\xd2\x79\x08\x18\xa5\xbf\x1f\x30\x46\xed\x32\x53\x82\x40\x5a\x62\x6e\xcd\x50\x3b\xcc\x10\x2c\x5a\x24\x24\x5a\x8c\x04\xb9\xd0\xe4\xb8\x58\xf9\x6c\x11\x72\xd9\x76\xba\xb4\xc6\x48\x3b\xc3\x5b\xa2\xd9\x41\x71\x12\x23\x23\xa4\xc8\x84\xd8\xf5\x35\xf5\x8d\x55\x67\xe0\x87\xcf\x55\x6b\xec\x68\xeb\x56\x09\x66\x79\xd0\x2d\x93\x09\x9e\xd1\x52\xab\x0b\xb1\x36\xb6\x21\xbd\xbf\xb8\x17\xf2\x8e\xf1\xc5\xc4\xd8\x1d\x13\x7b\xc6\xd4\x05\x62\x8c\x2e\x7e\x89\xff\x09\x1e\xd4\xed\x87\xd7\x1f\x5e\xc2\x65\x9e\x83\x40\xe5\x5c\x29\x3a\xaf\xc2\x33\xa5\x6d\xcb\xde\x29\x90\x92\x7d\x47\xa5\x62\x22\x42\x7e\xcd\x1d\xe3\xf9\x39\x54\x2c\xff\xca\x57\xbd\xd7\x14\x6d\xff\x8a\xd2\x62\x67\xa3\xee\xe1\x1b\xc4\xa1\x85\x1f\xf7\xae\xbd\xd5\x88\xfa\x60\xae\x42\x62\x51\xaa\x3b\xba\xa9\x51\x1a\xc1\x2c\xdd\x85\x2d\xca\xa2\x8e\x05\xd9\x6c\x13\x6e\xdc\x98\x3a\xfb\xa4\x51\xda\x41\xef\x67\x01\xfd\xce\x73\x51\x8a\xfc\x25\xa8\xaa\x2c\x85\x0c\x2c\xfe\xb0\xa2\x9a\xe4\x44\x93\xa9\x91\x26\xe7\xfd\x1f\x11\xc7\x18\x76\x6c\x1b\x7e\x88\x0c\x54\x9d\x07\xa0\xf1\x68\x53\x62\xc3\x1e\xa1\x4a\x9a\x4d\xb9\xc8\xe9\x7b\x7c\x03\xfc\x51\xf5\x00\x65\xf8\x87\xb0\x67\x68\xa2\x2b\x35\x5d\x0a\xa5\xaf\xae\xcf\xeb\x1f\x4b\x91\x5f\x5d\x47\x61\x8c\x9c\x94\xf7\xad\x05\x9e\x9a\x19\x86\x9b\xf5\x9a\x04\x55\x42\x8e\x65\x8c\xb5\x1a\x28\xaa\x90\x76\x3c\xc3\xc5\xa9\x43\x9f\x66\x4b\xba\x22\x51\x3a\x26\x7c\x5d\x4f\x3e\x30\x05\xf7\x92\x69\xed\x59\x38\xb0\x4b\x8c\xbb\xda\x79\x62\x7e\x6e\xe4\x35\x5e\xb6\x63\x18\xa4\xcf\xd6\x2f\x82\x53\x74\xa2\xa9\xf3\x66\xdf\x46\xdd\x2a\xb8\x16\x91\x4c\x52\xab\x06\x1a\x43\x3e\xca\xba\x76\xa1\xef\x70\x79\x7d\x15\xcc\x74\x6d\xcf\xc6\x93\x58\xd6\xba\xae\xd6\xd7\x4f\x54\xaf\xd7\xe3\xab\x05\x41\xe3\x5f\x0e\xdb\x82\x98\x01\xd7\xd4\x14\x83\x82\xad\x58\xe0\x79\x25\x3c\x47\xed\x40\x95\x56\x70\x6a\x19\x4e\xb3\xb2\x0a\x53\x80\x8e\xcf\x8a\xae\x84\xdc\x9c\xd7\x3f\xd2\x72\x49\x57\x54\x92\x62\xa2\xb4\x90\x64\x11\xa8\xbe\xeb\x61\xe3\x70\xdb\x9f\xec\x43\xa3\x4d\xca\xee\xa8\x43\xd2\x5e\x6c\xd5\x8c\x06\x58\x5d\x5b\x7b\x34\xff\xf9\x58\x09\xf5\xf6\x7c\x02\x46\x42\x73\xea\xde\x47\x77\x48\xbc\x0a\x0e\x18\xd5\x84\xce\x92\x66\xee\x61\x1e\xa1\x64\xc3\x5a\x14\xd5\x8a\xaa\xf3\xe6\x22\x1b\x7e\xf1\x17\x12\x28\x5f\xc3\x9a\x48\xf5\x64\xae\xe9\x39\x5b\x33\x15\x5e\x79\x68\xe0\x96\x1e\xa3\xc5\x34\x66\x57\x57\xba\xac\xb4\x2b\xfc\x1e\xcb\xa8\xa4\x9f\x4a\xa1\x30\x32\x14\xa1\xb6\xa4\xa5\xbc\x1b\x67\x79\x11\xd6\x59\x07\x4b\x45\x68\x2a\xf9\x4b\xf8\xaf\xd3\xbf\xfe\xfa\xa7\xc9\xd9\x57\xa7\xa7\xdf\x3f\x9f\xfc\xc7\x0f\xbf\x3e\xfd\xeb\x14\xff\xf1\xaf\x67\x5f\x9d\xfd\x54\xff\xf0\xeb\xb3\xb3\xd3\xd3\xef\xff\xf4\xee\x9b\xdb\xeb\x37\x3f\xb0\xb3\x9f\xbe\xe7\xd5\xea\xce\xfe\xf4\xd3\xe9\xf7\xf4\xcd\x0f\x47\x32\x39\x3b\xfb\xea\x57\x81\x03\x27\x7c\xf3\x21\xc8\x94\x00\x5b\x20\x35\x4a\xb7\x80\x3e\xb7\x28\x85\x8b\x3e\x4d\x5a\xf7\xe4\x84\x71\x3d\x11\x72\x62\x19\xbf\x04\x2d\xab\xb0\x4b\x4a\xbd\x1d\xe3\xca\xd9\x8f\x91\x2a\xec\x75\x4c\xb2\xc6\xcc\x7e\x12\x82\x4c\xd1\x4c\x52\xfd\xb4\x23\x4a\x76\x8c\xf5\xad\x02\xd3\xc2\x83\xe3\x03\xe8\x86\xfa\xb9\xd8\x3c\x29\x40\xf5\x10\x35\xa9\xb8\xb8\x8b\xe2\xdd\x72\xe7\x52\xac\xa6\xd0\x81\x68\xad\xa3\x34\xde\x77\xe3\xbc\xa3\xc1\x55\xa3\x52\x40\xcd\x87\x52\x40\x2d\x8c\x52\x40\x6d\x1c\x75\x03\x6a\x37\x78\xf6\x53\x34\x6d\x88\x28\x5f\xfb\x41\xa0\x06\x31\xf2\xb5\x0f\x4b\x0b\x28\x45\x59\x15\x44\x7b\xe5\x72\x0c\x21\xed\x77\x01\xf3\x1e\x9c\x9d\xf2\x6b\x71\xa7\x6d\x36\x96\xaf\x7b\x63\x35\x8c\x25\x86\xcb\xa2\x00\xc6\x7d\x95\x17\x0e\xb2\xce\x0c\x92\xd4\xba\x93\x80\x60\xfd\x4f\xec\x5c\xe4\xc1\xf3\x7e\x49\xb7\xa6\x10\x98\x02\xa5\x89\xd4\x8c\x7b\xb5\x6d\xfa\xb3\xe1\x88\xe6\x68\x9d\x20\xc3\x78\xdb\xb9\x28\xe0\x22\xdb\x14\x1b\xeb\xb4\xb6\x6b\xab\xcb\x14\x44\xf9\xbc\xbf\xbb\x29\xe0\xac\x6a\x72\x87\x28\xe4\x8c\xe6\x94\x67\x74\x0a\xdf\xf9\x56\x69\xad\x77\xd2\x6c\x63\xd6\xe6\x0d\x5f\x37\x39\x53\x95\x4d\xd3\xf1\xd9\x54\x66\x46\x87\xc7\xf9\xcf\x9b\x24\x62\xc4\x94\x03\x59\xb6\xb9\x22\x5e\x92\x13\xed\xd6\xc6\x93\xdf\x94\x66\x6e\x70\x17\x5e\x59\x3d\x61\x37\x97\xd0\xdb\x42\x83\x62\x0c\xb8\x70\xee\x5c\x13\x9a\x09\x09\xa9\x82\x6d\xaf\x05\x68\xd6\x7b\xf2\x78\x22\x40\xd1\x50\x73\x7d\xd0\x54\x0f\x8e\x22\xf7\xcd\xf4\xa7\x67\x66\x3f\x82\x89\x3d\x60\x5e\x5b\xf3\x38\x88\x6b\xa8\x69\x1d\xc5\xac\x8e\x61\x52\x0f\x99\xd3\x01\x69\xb0\x2d\xf5\xb0\x69\x51\x4c\xe0\x70\xf3\x37\x1c\x48\x56\x4a\x3a\x67\x9f\xa2\xc8\xcc\x4b\xde\x2c\x20\xb0\x9c\x72\xcd\xe6\x2c\x60\xce\x8d\x11\x2d\x69\x49\x39\x82\x08\xb0\xe3\xa2\xb1\x0b\x3c\x33\x19\x61\x7b\x05\x9f\x5c\x1a\x9c\x75\xd1\xc4\x54\x60\x37\xb1\x9c\x53\x49\x7b\x25\xed\x95\xb4\xd7\x21\x7a\xf2\xda\xcb\xc9\x83\xfa\xca\xfe\x79\xd5\x0f\xd6\x6e\x09\x2d\x4f\xf3\xba\x53\x39\x0c\xcf\xb8\xb7\xbb\xf6\xf8\xb3\xd7\x16\x28\xbc\xc0\xe7\xfa\x1c\x31\x2c\x91\xdb\x14\x3e\x6f\xb4\xa6\x16\xb6\x68\xa6\x07\xc7\x25\x5b\x98\x13\x5a\xd0\x35\x2d\xdc\x75\x08\x56\x84\x93\x85\xad\xe0\xee\x75\x83\x71\x11\x74\x10\x12\x3b\x40\x4a\x96\xf7\x9c\x27\xbe\x2f\xcf\x38\x18\xb1\x55\x08\x92\x23\x3b\x29\x8a\x82\x4a\x05\x05\xbb\xa3\xf0\x9a\x96\x85\xd8\xf8\xb6\x0a\x24\x3c\x87\x1b\x4d\xb4\x11\x53\x37\x54\xfb\xe0\x94\x03\x44\x01\xce\xc8\x75\x55\x14\xd7\xa2\x60\x99\x47\xdc\xaa\xbf\xb9\xaf\x70\x57\x97\x55\x51\x40\x89\x0c\xa7\xf0\x81\xfb\xec\x6d\x31\x87\xcb\xe2\x9e\x6c\xd4\x39\xbc\xa7\x6b\x2a\xcf\xe1\x6a\xfe\x5e\xe8\x6b\xeb\x44\xf0\x31\x78\xba\x39\xac\x96\x35\xb0\x39\xbc\xc4\xee\x78\x1a\x34\xf1\x11\xa2\xac\xd3\xf2\xfd\xdc\xec\xb9\xee\x20\xad\x02\xba\x67\xca\x2b\x0b\xf4\xc1\xb2\x65\x7e\x87\xfe\x97\xc8\xc9\xa8\x5e\xfb\xf3\x3f\x74\xa3\x15\x6c\x4e\xb3\x4d\x56\x84\xca\xcf\xcb\x0c\xb3\x1a\xda\x06\x6f\xad\xc4\xf0\x71\x30\xda\x7e\xf3\xae\x18\x2d\xba\xee\x18\x07\xdb\x6c\x5d\x79\xf6\xd2\x6e\xc5\x4d\xf3\xce\xd6\x01\xac\x3e\xab\x2f\xd0\xd3\x9e\x0d\xb3\x64\x4b\xa1\xf4\x8d\x26\x52\x47\x68\xc6\x7e\x72\x5d\x33\x03\x6c\xc2\x5b\x14\xde\x86\x00\x5b\xad\x68\xce\x88\xa6\xc5\x06\xc8\x5c\x63\x49\xe3\xd0\xd2\x13\x66\x4c\x92\xda\x93\xea\x7a\x3f\x2d\x09\xcf\x0b\x2a\x61\x4e\x58\xe1\x8d\x0e\xdb\x71\xff\x6b\x2a\x57\x8c\x07\x94\x3c\xb7\xb0\x5a\x8c\x22\xd0\x1c\x4b\x38\xcb\x1c\xcb\xb9\x09\xf0\x87\x31\x3b\x86\xad\xd8\x47\xeb\x3b\xe8\x70\x42\x8b\x59\x68\x27\x60\x56\x88\xec\x4e\x41\xc5\x35\xf3\xb5\xea\x71\x69\x84\xb8\x83\x4c\xac\xca\x02\x85\x67\x58\x49\x48\x78\xb8\x2c\xe4\x90\x44\x6e\xfe\x39\x69\x84\xc4\xc4\x8c\x49\x5d\xfc\xb2\xfd\x13\xfe\xc2\xef\x8e\x10\x7c\x87\x0d\xbf\xc1\xd2\x4f\x34\x8b\xd4\x9e\xe1\x03\xa7\xb8\x6b\x05\x1f\x59\x04\xbb\x4f\x82\x37\x89\x00\x73\x61\x8c\x56\xb3\xeb\x63\x74\x7c\x68\x8c\x80\x29\xbc\xf9\x44\xb3\x28\x3d\x50\xcc\x28\x09\x2a\x3b\xac\x5a\x4c\xee\x02\x8a\x49\x3c\xa1\x76\xe3\xde\x45\x3e\xbb\xd4\xdb\x1c\xaf\x2c\xc7\xf0\x56\x70\x56\xd0\x58\x66\x05\xe3\x9e\xea\xbf\x4b\xae\x84\x28\x30\xae\xcc\x45\xa4\x27\xc9\x62\x74\x8d\x72\xae\x14\xc8\x99\xc4\x5e\x1b\xa1\x20\x0c\x57\x0a\xa5\x99\x85\xf0\x39\x95\x42\x68\x38\x3d\xb9\x38\x39\xdb\x41\x03\x04\xf7\x7e\x9d\xb3\x82\x5a\x03\xce\x16\x26\x72\xa3\x0e\xe4\x6a\x6c\x7a\xb6\x2a\x8b\x0d\xae\xde\x49\x7e\x0e\x2c\x14\x88\xe2\xaa\xb3\xca\x8a\xd7\x3b\x21\xb4\x63\x38\x96\x82\x3c\x07\x25\x40\x4b\x52\xb7\x98\x8a\xc1\xd3\x0c\x50\xcb\xca\x19\xd9\xa7\x27\x3f\x9d\x84\xee\x53\xaa\xb3\x33\xb8\x17\xfc\x44\xe3\x76\x9d\xc2\x6d\xe8\xa9\xaa\x14\xad\x8b\xf1\x9e\x63\x15\x7d\x4e\xc3\x01\x39\x02\xe8\xa7\xb2\x60\x19\xd3\xc5\x06\x8d\x4b\x10\x55\xe8\xba\x63\xb5\x79\xa2\xeb\xba\xc1\x6f\x3e\x05\xef\x24\x9b\xd1\x6c\x94\xd8\x73\x34\x05\xad\xc1\x19\xc8\x94\x28\x28\xd8\x9a\x5e\x2c\x29\x29\xf4\x72\x03\xe1\x67\x88\x0b\x3e\xf9\x3b\x95\x02\x2b\x1b\x73\xc7\x37\x46\x4b\xb6\xf0\x3e\x76\x51\x1a\x55\x46\xf0\xbd\x1a\x7b\xf1\x1b\xea\x79\x2f\x82\x6d\x1d\xf8\xc7\xdb\xdb\xeb\x6f\xa8\x8e\x66\x78\x98\xd1\xd5\xa9\x77\x18\xd5\xa2\x72\x2e\xe4\xea\x33\x5b\x20\xe1\x20\xf1\x09\x94\x42\x7e\x6e\x13\x68\x29\x54\xc0\xba\xc3\xce\xda\x0b\xa5\x7d\x2b\x87\x76\x49\x0b\xa3\x9b\x39\xcd\xcc\x8a\x47\x4b\x43\x6f\x5b\xdb\xc0\xd5\xf5\x14\xfe\x22\x2a\x33\x8b\x33\x32\x0b\xb2\xe4\x0d\xd5\xbd\x53\x14\xd5\xf0\xcc\x4c\xc2\xb3\x90\x40\xab\x25\xb3\xef\xff\x48\x49\x4e\xa5\x42\x4d\x48\x49\x94\x4e\x92\xc1\xd0\xdd\xce\xb8\x62\x5a\xce\x95\xd2\x62\x05\x4b\xcb\x38\x7c\xa1\x3b\x45\x92\x9d\xec\x08\x45\xee\x1b\xb9\x66\xe3\x0b\x0a\x24\x2d\x63\x68\x3b\xf7\xb6\x3f\x23\x6d\xb4\xa3\x09\xec\x4e\x09\xe4\x5a\xf3\x9d\x51\x05\x04\x32\xdc\x2a\xc1\x2c\xed\xe4\x9b\xbd\xe2\x0a\x1b\x06\x73\x64\xdc\x6e\x12\x23\x54\x82\xf3\x0b\xa2\xf5\x7d\x8d\x93\xd0\x04\x21\x45\xa1\xfb\x4c\x10\x9a\x1b\xc8\x25\x56\x7e\x14\x44\xca\xa4\x81\x01\x00\x49\x04\x96\xcd\x2e\xb5\xc1\xce\x08\xd3\x0f\x31\x73\x38\x20\xb4\xfc\x74\x97\x1e\x7f\xfa\x62\x6c\x3c\x88\x37\x7f\x65\x70\xf9\x99\xdd\xe2\x33\x5a\x00\xc9\x32\xbf\xb6\x47\x5d\x12\x56\x75\xa2\x38\x53\x54\xae\xfd\x12\x26\x5a\x8a\x35\x65\xc2\x37\x7c\x53\xd3\x40\x8d\x78\x09\xbc\x5a\xcd\x82\x95\x54\x53\xb1\x4d\xea\xd8\xcb\xd0\x69\xf3\xf0\x3e\xc6\x50\x6b\x08\x4b\x6d\x20\x11\xbe\x08\x3d\x17\x2f\xcc\x3b\xff\xfe\x77\xbf\xfb\xed\xef\xa6\x76\x5a\xcd\x33\x02\x79\xce\x28\x10\x0e\x57\x97\xef\x2f\x7f\xbc\xf9\xee\x15\x56\xcf\x0e\xdb\x85\x11\x92\xf9\x63\xa6\xf2\x47\x4c\xe4\x7f\xc4\x34\x7e\x2c\x58\x16\x28\xe1\xfb\xb8\x2c\x64\x18\xee\xd1\xae\x94\x2d\x98\xed\x6e\x8a\x36\x6c\x18\xc1\x93\x6d\xee\xc4\xbd\x3a\xe3\x11\x2e\x0e\x9f\x5d\x7a\xea\xac\xbc\x11\xd9\x5d\x34\x2f\xcf\xc9\xed\xab\x6b\xcb\x30\x8a\xa3\x87\xf0\x3a\xc0\xc4\xf8\x5a\x14\x6b\xb3\x98\x04\x6e\x5f\x5d\x07\x2a\x8b\xa9\xe1\x81\x11\x56\xeb\xf7\xde\x04\x65\x72\x36\xa5\x99\x1c\xb4\x93\xad\xca\x22\x24\xa2\x0c\xd8\x2b\x40\x52\x52\x30\xa5\x59\x86\x63\x6d\x62\xb0\x41\x5e\x1d\x71\xe7\x8f\xe7\x4c\xfe\xb1\x96\x22\xfb\xc7\x4e\x3e\x44\xca\x7a\x6e\x1c\x6d\x1d\x57\x59\xb0\xd3\xe4\xbc\x57\xf4\x27\xbc\x42\xa5\x73\xb4\x85\xa5\x9c\x3f\x51\xcb\x11\xcd\x30\xbf\x56\xa0\x5d\xe2\x9d\x2e\x45\xce\x72\x0c\x8d\xa0\xa0\xdd\xb9\x6b\x39\x06\xb2\x75\x2f\xdc\xb7\x1c\x43\xfd\x12\xc6\xee\xdc\xb1\x1c\x23\xd9\xb6\xc9\x72\x3c\x8e\x1e\xc1\x72\x2c\x25\xbd\xd1\xa2\x8c\x82\xb3\xb3\xac\xa2\xa2\xec\x66\x74\x2e\x24\x8d\x03\xb3\x6b\x01\x70\x90\x57\x28\x8c\x09\x0f\xa8\xac\x5a\x87\xb9\x44\x17\xae\xe6\x9d\xb2\x0f\x68\xb2\x64\xcb\x3a\xaa\xca\xa9\x52\x17\x08\x8d\xab\x4a\xeb\xa4\xf4\x64\x3a\x27\xac\xa8\x24\x3d\x37\x2b\x4d\x57\xb8\x56\xe7\xa1\x45\x1e\xcd\x62\x50\x6e\x59\x51\x9d\x59\x18\x85\x43\x2d\xfa\xaf\x8f\xb1\xf9\xec\xc6\xb1\x1d\x6d\xc3\xdb\x7a\x65\x92\xa8\x25\xc5\x66\x9e\xf4\x13\xd3\xca\x0e\x54\x52\xa2\xbc\x6b\x44\x23\xd4\xc5\x6d\x24\x34\x81\x15\x94\x44\x29\x9a\xfb\x6b\x83\x0e\xe4\xd3\x0e\xf0\x5a\xe4\x27\x27\xaa\xfb\x18\x4f\xce\x0b\x49\x32\x0a\x25\x95\x4c\xe4\x80\x55\xd7\x73\x71\xcf\x61\x46\x17\x8c\xfb\xde\x00\xdc\x89\x34\x83\xae\x0f\xbc\x31\x61\x69\x00\x90\xaa\xee\x98\x3c\x85\x8f\xbd\x8e\xae\xfe\x5a\x4b\x54\x3a\x13\xad\xb6\x76\xb3\x7b\x1e\xc0\xb1\x45\x92\x62\xb5\x06\x3c\xe6\x15\x29\x8a\x4d\x2b\x56\x3c\x39\xbb\xc2\x24\xfa\xb1\x16\xfe\x0b\xc3\xd4\x9a\xc3\x1a\xca\xb1\x7b\x40\xbb\x53\xe1\x2f\x9b\x24\x25\xd9\x32\x2c\x99\x22\x41\x77\x0f\x50\x82\xee\x26\xe8\xee\x5e\x4a\xd0\xdd\x04\xdd\x4d\xd0\xdd\x04\xdd\x4d\xd0\xdd\x04\xdd\x1d\x49\x09\xba\x7b\x88\x12\x74\x77\x2f\x3d\xc9\xd0\x44\x82\xee\x26\xe8\xee\xd1\x94\xa0\xbb\x09\xba\x3b\x8e\x6f\x82\xee\x7a\x51\x82\xee\x3e\x48\x09\xba\x1b\x42\x09\xba\xeb\x4b\x09\xba\x3b\x9a\x12\x74\x37\x41\x77\x03\x28\x01\x30\x3c\x28\x41\x77\x23\x5c\x1c\x3e\xbb\xf4\x4c\xd0\xdd\x04\xdd\x3d\x92\x92\x7f\xac\xa5\x04\xdd\x0d\xa0\x04\xdd\x3d\x48\x09\xba\x9b\xa0\xbb\x01\xbc\x9e\x9e\xe5\x58\x43\x44\xaf\xa5\x98\x05\x97\x96\xbe\x46\x70\x14\xcb\xac\x47\xcd\x9c\x93\x10\xe0\x65\x3d\xb4\x29\xbc\xea\x63\xe6\xb0\xbf\x95\x2b\x1f\xe9\xc1\xd7\x61\x42\xed\x18\xb1\x34\xe6\x74\xa0\xda\xad\x07\xe3\x91\x90\xae\xba\xa0\xb3\xba\x28\x85\xfd\xbf\x16\xd0\xd5\x41\x72\x59\xef\xa4\x6f\xad\xdc\xcf\x52\x75\xd5\x1f\xbe\xb5\x17\xba\x05\xc2\xab\x8c\x33\xb4\x17\xfd\x6d\xd8\x56\x1f\x7c\xe5\xc9\xbb\x0f\xd9\xea\x03\xaf\x7c\x2d\x7f\x6f\xb8\xd6\x13\x00\xee\x05\x43\xb4\xf6\xc0\xb3\x02\xb5\xd7\x16\x34\xab\x06\x57\x05\x70\x1c\x84\x65\x05\x8e\x72\x07\x92\x55\x83\xaa\x22\xbc\x39\x62\x4f\xbb\x80\xaa\xc0\x28\x7f\x07\x8a\xd5\x05\x53\x05\x70\xed\xc0\xb0\x76\x81\x54\x21\x2b\xa5\x87\x40\x54\x0e\x03\x14\x72\xb9\xec\x01\xa8\x06\x20\x50\x01\xbc\x11\x3c\x15\x19\xfe\x34\x08\x7d\x0a\xb3\x5f\x07\x60\x4f\x35\x70\x29\x64\x62\x5b\xc8\x53\x17\xb4\x14\xb2\x05\x1a\xb8\xd3\x36\x60\x29\xc8\x05\x92\xc7\x06\x2b\xc5\x08\x0d\x07\x87\x85\x03\x2d\x55\x97\x26\x74\xbb\x94\x54\x2d\x45\xe1\xa9\x0a\x7a\x6a\xe0\x1d\xe3\x6c\x55\xad\x8c\xcc\x51\x46\x6e\xb3\x75\x60\x0e\x93\x6a\xd0\xaa\xd6\x08\xc4\x98\xb2\xb7\xc6\x43\x89\x22\x69\x8e\xdc\xcd\x16\xc3\x82\xee\x4b\xb2\xf6\x37\xf5\x55\x95\x65\x94\xe6\x34\xef\xf9\x35\xe1\xb7\xd3\x7a\x2e\x3c\xf9\xda\x06\xa9\x4c\xc1\x8b\x10\x0b\x23\xe4\x46\x34\x17\x72\x45\x34\xf2\xf8\xed\x6f\x3c\x38\x04\x61\xdf\x1e\x05\xf7\x16\x1d\xf3\x16\x6c\xc6\x85\xf9\xf2\x02\xfc\x78\xe1\xf6\x63\x98\xff\x6e\x18\xdb\x16\xa6\xe3\x86\x70\x6d\x61\x1c\x1f\x01\xd3\x36\x88\x67\xeb\x22\xbf\xc2\x2c\xdd\x30\x2c\x5b\x24\xc4\x6b\x30\x86\xed\x71\xf0\x6b\xc3\xd8\x35\x94\x2e\x21\xc6\x45\x1f\xb7\x16\x8e\x3c\x7b\x12\xa6\xc5\x63\xa0\xcd\x76\x91\x66\x6e\xb2\xc2\xbc\xd8\x0d\xca\x2c\x1e\x4a\x2c\x12\x42\x2c\x06\x3a\x2c\x18\x19\x16\x8e\x0a\x8b\x85\x08\x8b\x81\x06\xdb\xe9\x02\x1a\x61\x07\x41\xdd\xb8\x31\x0a\xbe\x3a\x96\xf7\x38\x0a\xfa\xeb\x71\xa7\x2b\x06\xea\x2b\xc2\x7c\x85\xa1\xbd\x1e\x07\xe9\x15\x13\xe5\x15\x63\x8a\x82\x62\x74\x8f\x83\xec\x1a\x44\x75\x81\x77\xfe\x3b\x6c\xbb\xbb\xa6\xdd\xc8\x5a\x00\xd3\x2d\x34\x57\x37\xaa\x16\xc0\xb5\x41\x72\xc5\x8d\xa8\x05\x46\xd3\x62\x45\xd2\x22\x45\xd1\x1e\x09\x7b\x15\x8a\xbb\x1a\xc6\x5c\x19\x1b\x24\x60\x43\xec\xe0\xad\x5a\xc4\x54\x00\xd7\xae\x4f\x22\x0c\x2d\x15\xb8\xa0\x8c\x33\xcd\x48\xf1\x9a\x16\x64\x73\x43\x33\xc1\x73\x4f\x6b\x62\xab\x57\xb5\x43\x0b\xcc\x41\x59\xa6\x9e\xef\x67\x3d\x41\xfd\x5a\x17\x4b\xa2\xc0\x3f\x76\x09\x6d\xe1\x94\x3a\x3c\xea\x0c\x53\x20\x18\x7c\x34\xf3\xe1\x19\xbe\x84\x27\x17\xc2\x84\x27\xe1\x72\xb2\x25\x3f\xe2\x6d\xaf\x3f\x8a\x7b\x10\x73\x4d\x39\x9c\x32\x5e\xef\xb0\x33\x5f\xef\x53\xe3\x6c\x6a\xfd\x99\x8d\xd3\xd0\x9f\xe7\x8b\xe7\xf5\xc0\x1a\x97\x63\x90\x61\xf6\x25\xbb\x1c\xd1\x19\xab\xd4\xd3\xf4\x68\xbb\xc1\x3d\x96\x4b\xdb\xb1\x9f\x57\x85\x15\x66\xbe\xfe\x1b\x74\x86\x3b\x07\x79\xdf\xa7\xed\xb9\x2d\x00\xde\x39\x33\xe7\x05\xbe\x79\x23\x0d\x09\xcf\xc1\x95\x3b\xf3\xe6\xdc\xdd\xf0\x5f\xf4\xd6\x0d\x44\x11\x3f\x16\x82\x78\x2f\x7a\xd8\x62\x80\x3d\xb9\xee\x20\x87\x5b\xfc\xaf\x2f\xc7\x3e\x6a\xb8\x8b\xfd\x0d\x18\x63\xdb\x95\xd9\x1f\xf7\x9b\x62\x04\x7e\xdf\xdd\x8b\xef\xc5\x70\x41\x80\x49\xbc\x85\xed\x8d\x95\x06\xdf\x4f\x81\x0f\xc5\x88\x3f\x99\xdb\x7e\x8d\xc6\x0d\xf5\x8d\xa5\xdb\x7e\xba\xed\x1f\xa0\x47\xb8\xed\x6b\xb6\xa2\xa2\xd2\x4f\xf6\xc2\x79\xbf\x64\xd9\xb2\x6b\x0b\xb2\x95\xb7\xaa\x16\x95\xde\xb2\xd7\xdc\x10\x23\x42\x11\xd2\xad\x73\x8b\xfc\x62\x1a\x03\x0e\xd5\xf0\xea\xb7\x0d\x42\x16\x88\x02\x02\xaf\xdf\xdf\xfc\xf8\xf6\xf2\x3f\xdf\xbc\x9d\xc2\x1b\x92\x2d\x83\x58\x33\x0e\x04\x35\x1b\x8a\xb0\x25\x59\x53\x20\x50\x71\xf6\xb7\x8a\xfa\xea\x85\xd3\x66\x7c\x67\x51\x30\xdd\x01\x12\xc8\xe8\x24\x0f\xd9\xd0\x5b\xc4\xb7\x4c\x69\xb3\x88\xc8\xcb\xd5\x19\x13\x5e\xfe\xc0\xb9\x14\xab\x6d\xd5\xf6\xc6\x30\xb3\xa6\xb7\xa7\x35\xb7\xa4\x92\xc2\x82\xad\x1d\xf2\xd9\x62\x40\x81\xe4\x01\x55\xe5\x8c\x14\x30\x07\xc7\x5c\x0e\xc8\x0c\x01\x85\x4b\x0a\x9c\x6a\x73\xe8\x1b\x57\xa6\x1f\xba\xb2\x53\xfc\x1b\x2a\x45\xd5\x39\xcc\x2a\x04\x87\x96\x92\xad\x88\x64\x5e\x10\x8c\xce\x80\x49\x31\x85\xf7\xa2\xbe\x1e\x6d\x70\x6a\x7d\xfc\x4d\xc6\x9a\xc1\xa9\x7d\xfd\xe1\xcd\x0d\xbc\xff\x70\x0b\xa5\xc4\x3a\xc1\xbe\xc8\x4a\xe4\x88\x5b\x60\x46\xcd\xa8\xec\x36\xca\xa7\x70\xc9\x37\xbe\x6b\x6f\x95\x0c\x53\x60\xee\x43\x94\x1b\xb6\x2e\x3c\x95\x7b\x3b\x9f\x9e\x3d\x9f\xe2\xff\x9e\x99\x3d\x24\x8d\x29\xd7\xc0\x75\x43\x04\x4d\x9d\x34\x62\xcd\x43\x36\x2b\x68\x7b\x1e\xdc\xce\xf2\xb1\x96\xa2\xc9\x17\x3f\x54\x86\x37\x1a\x63\x0b\x62\xef\xe6\xf5\xda\xec\x11\x49\x4b\x49\x15\xe5\x9e\x77\x16\xd2\x1c\x54\xdc\x71\x28\xe0\x8d\x84\x29\x02\x13\xdb\x02\x6f\xbb\x21\x77\xdd\x49\x3b\xf2\x6b\xbf\x83\x12\x7a\xe1\xed\x3d\xdf\xd7\x2c\x1f\xbc\x7e\xcd\xc3\x32\x76\x1b\x7d\x54\x1f\xfc\x52\xe4\x27\x0a\xae\xfc\x71\x4f\xee\xd4\x4f\xe1\x76\xc9\x54\x7b\xb3\x31\xb6\x22\xf3\x2f\xf7\x84\x7b\xd1\x06\x96\xcf\xe1\x39\xfc\x01\x3e\xc1\x1f\xf0\xf2\xf5\x7b\xdf\x3b\x52\x8c\x0b\x4e\xa8\x6b\xcf\xfa\x41\xae\xae\xa3\xec\x88\x3f\x2f\x89\x46\x7e\x70\x75\x1d\x02\x6e\x9c\x31\x9e\xe3\x56\xa0\x9f\x34\x95\x9c\x14\xf5\xd5\x3c\x6c\xa6\x03\xae\x80\xe6\xa5\x9e\xfc\xc1\xb1\x15\x2c\xae\xe6\xde\x1c\x1b\x2b\xfd\x1c\x74\xef\xe8\x78\x73\xc4\x23\x37\x78\x74\xbc\x59\xda\x23\x07\x57\x73\xf4\xb5\xbd\x77\x9a\x82\xa9\xce\xe8\xfd\xa7\xb4\x79\xeb\x15\xd1\xd9\xb2\xaf\xd6\xfc\x5d\x21\xef\xcc\x91\x68\x4b\xef\x43\x2e\xd0\xb7\x1c\x54\x34\xd8\x0c\xf5\xcb\x16\x3c\x21\x90\xbb\xde\x79\xba\x9a\x6f\xef\x5c\xef\x59\xdd\xe7\x06\x0b\xaa\x48\xec\x2e\xa3\x9d\xc6\x1a\xa5\xc8\xed\xcd\xd7\x9b\xa7\x99\xbc\xbc\x63\x1f\xf5\x2e\xc0\xfe\x9a\xb3\x7b\x71\x76\x15\x9d\x42\x93\x07\xad\xe8\x36\x9a\x21\x23\xdc\x26\x5d\xcf\xa9\x94\x21\x5b\x5f\xc0\x6c\x83\xc8\x35\x96\xd1\xc0\x43\x10\xa0\x13\x4a\x29\xb4\xc8\x84\x77\x51\x8f\x3e\xb8\xcf\x31\xc3\xe9\x0e\x09\x5f\xb5\x11\xcd\x6f\x5f\x5f\x9f\xc3\xed\xab\xeb\x73\x10\x12\x6e\x5e\x85\xe0\x6b\xba\x9e\xbb\x67\xb7\xaf\xae\x9f\x7d\xb6\x49\x87\xfa\x5e\xf8\xd2\xab\x4c\x50\xcf\x8d\x6b\xae\x9c\x93\x15\x29\x27\x77\x74\xe3\x61\x55\x87\xda\xf4\x93\x66\x07\x45\x78\x0d\x3b\xb1\x2b\x52\x8e\xe4\x25\x29\xc9\xd9\x13\xad\xdc\xe0\x4e\x78\x3b\xc6\xed\x12\x0e\x1e\x3c\x51\xfe\xac\xc4\x9a\xe6\xf6\xf2\x5e\x3f\x83\xf2\xbc\x14\xcc\xef\xc6\x9a\x2a\x41\x1c\xa6\x54\x09\xe2\x38\x4a\x95\x20\xfa\x94\x2a\x41\x04\xf0\x4c\x95\x20\x52\x25\x08\x4b\xa9\x12\x44\xaa\x04\xe1\x49\xa9\x12\xc4\xe1\xc1\xa5\x4a\x10\x5f\x2c\xb6\x35\x55\x82\x38\x4c\x09\xe5\x99\x2a\x41\xa4\x4a\x10\x3b\x94\x2a\x41\x7c\x6e\xd3\x22\x55\x82\x48\x95\x20\x6a\x4a\x95\x20\x46\x50\xaa\x04\x31\x8e\x52\x25\x88\x83\xf4\xc4\x72\x43\x52\x25\x88\x94\x1b\x72\x2c\x9f\xa7\x97\x1b\x02\xa9\x12\x84\x1f\xa5\x4a\x10\xe3\x29\x55\x82\x18\x47\xa9\x12\xc4\x78\x9e\xa9\x12\x44\x4b\xa9\x12\x44\xaa\x04\xf1\x85\x6e\xdd\x54\x09\x22\x55\x82\x18\xa6\x14\x23\x48\x95\x20\xc6\x51\xaa\x04\xe1\xcf\x34\xdd\xf6\xfd\xf9\x3c\xbd\xdb\x7e\xaa\x04\x91\x2a\x41\x1c\xa4\x10\xd3\x4d\x52\x25\x2a\x99\xf9\xa8\xc8\xfe\xbe\x7a\x25\x56\x65\xa5\x29\x7c\xac\x19\x36\x7a\xdf\xe3\x9d\x66\x1b\x9b\x70\xd5\x91\x8e\x9f\x03\x36\x9d\x09\x3e\x67\x8b\x4a\x62\xf2\xfd\xc5\x8a\x70\xb2\xa0\x93\xcc\xbe\xe8\xa4\x99\xb9\x49\x33\xca\x8b\x2f\x0a\x3a\x5d\xb0\x15\xf3\xa9\x20\x01\x3b\x6b\xff\x16\x39\xb5\xf1\xd1\x00\x78\xcb\x8a\x7c\xc2\x0b\x11\x59\x89\x8a\x6b\x9b\x27\x80\xf3\xed\xc9\xb3\x59\x25\x1b\xe7\x36\x57\xc2\x76\x13\x04\x40\x04\x9e\xc0\xd6\x81\x18\xc6\x79\x5b\x4b\xe3\x3a\xd8\x5a\x2e\x89\xd6\x54\xf2\x97\xf0\x5f\xa7\x7f\xfd\xf5\x4f\x93\xb3\xaf\x4e\x4f\xbf\x7f\x3e\xf9\x8f\x1f\x7e\x7d\xfa\xd7\x29\xfe\xe3\x5f\xcf\xbe\x3a\xfb\xa9\xfe\xe1\xd7\x67\x67\xa7\xa7\xdf\xff\xe9\xdd\x37\xb7\xd7\x6f\x7e\x60\x67\x3f\x7d\xcf\xab\xd5\x9d\xfd\xe9\xa7\xd3\xef\xe9\x9b\x1f\x8e\x64\x72\x76\xf6\xd5\xaf\xbc\x2f\x87\x01\xe6\x47\x1c\xe3\x23\x8a\xe9\xf1\x08\x86\x87\x43\x97\x44\x11\x0f\x1f\x1d\xaf\x38\x02\xc2\x79\x4c\xe2\x0b\x88\x5a\x5f\x61\x06\x71\x3d\x66\x7f\x27\xa4\x58\x31\xad\x69\x8e\x2e\xa3\x4e\x79\x11\x5f\x1c\x38\xd3\xbd\x66\xdc\x4e\xe4\x62\x82\x91\x37\x04\x9a\xa9\x2e\xae\xba\x93\x29\x2b\xf4\x92\xca\x7b\xe6\x1d\x0f\x32\x17\x24\xde\x7a\x33\x50\x08\x4e\x72\x3a\x67\xdc\xdb\x41\x82\x46\xdc\x68\xfb\x2d\x89\xe1\x24\x86\xc7\x70\x79\x4a\x62\x58\xd1\xac\x92\x4c\x6f\x5e\x09\xae\xe9\x27\x0f\x87\x48\x5f\x0a\xdf\x38\x76\x20\xf0\x37\xbe\x79\x4e\xa5\xc8\xeb\xac\x36\x59\x71\x4c\x5d\x0f\x34\xa9\x8e\x39\xc7\xa5\x28\x58\xb6\xb9\xa8\xa7\x04\x0f\x2c\xfd\xa4\x2f\x1e\xed\x0e\xa0\x89\xba\x6b\xc5\x07\x9d\x98\x9b\x5f\x2b\x25\x76\xc6\xf1\x45\x19\xfe\x68\x09\x5f\x4b\xb6\x66\x05\x5d\xd0\x37\x2a\x23\x05\xca\xc7\x18\xba\xfe\x72\x0f\x6f\xff\xf8\x90\x96\xa2\x50\x70\xbf\xa4\x46\x27\x01\x31\xef\x8e\xae\xb7\x8c\xf8\x32\x5d\x10\xc6\x61\x65\xb6\x41\x59\x0f\xd4\x9c\x06\xa3\xb1\xbc\x15\x7e\x49\x24\xe5\xba\x1e\x9c\x2b\x30\x34\x13\xa2\x70\x29\x76\xde\x98\xeb\x66\x06\x5c\x2e\x31\x17\x3f\x72\x7a\xff\xa3\x19\xb9\xef\x58\xe7\x05\x59\x34\x35\xcb\x14\xd5\x35\xd8\x2b\x24\x23\x1b\xec\xae\xb4\x2f\x1f\x79\x13\x60\x4e\x55\x45\x81\x14\xf7\x64\x83\x5b\x21\xce\x78\x99\x7a\x09\x2f\xce\x50\x8c\x11\x05\xcd\x78\x73\xf8\x8d\x6f\x88\x7c\x49\x14\xbc\xba\xbc\xfe\xf1\xe6\x2f\x37\x3f\x5e\xbe\x7e\x77\xf5\x3e\xc4\x9c\x30\xbb\x87\x7a\x6d\xf2\x8c\x94\x64\xc6\x0a\xe6\x6f\x45\xec\xe0\x2e\xbb\x2c\x03\x8c\xc2\x3c\xbf\xc8\xa5\x28\xed\x1a\xca\x8a\x63\x59\xbf\xb6\xfe\x8d\xaf\x27\xb9\xeb\x35\xec\x54\x08\x34\x9b\xdb\xd7\x19\x39\xef\xbd\x32\x2c\x24\xe1\xc6\x9a\x47\xcf\x54\x40\xb4\xdb\x41\x73\x64\xc5\x35\x5b\x7d\xb9\xc9\xd7\x24\x8f\x95\x78\x7d\x99\xe7\x34\x8f\xb1\xbd\x9e\x62\xe2\xc1\xab\xfa\xb5\x42\x32\x6e\xa0\xad\x9a\x08\xd7\x1f\x6e\xae\xfe\x77\x9c\xd9\x02\x37\x63\x21\x01\xac\x08\x35\x5b\xa4\x28\x23\xed\xa4\x8f\xae\x7a\x47\xda\x4b\x0f\xd1\xcf\x74\x2f\x35\x96\x5c\x0c\xcc\xd4\xc7\x8a\x77\x64\xb5\x77\x01\x83\x76\x4c\xb0\x12\x39\x9d\xc2\xb5\x35\x90\xa8\x8a\xc2\xb3\x53\x36\x8e\x48\x0a\x86\x31\xd7\x8c\x14\xde\xa6\x26\xfd\x5b\xc5\xd6\xa4\xa0\x36\xc1\x0f\x4b\x38\x74\xeb\x07\x46\xd0\xcd\x73\x52\xa8\x20\xa5\xe7\x6f\x13\x19\xe3\xf4\x9d\xa8\x78\x0c\x7c\x52\xc3\x0b\x72\xca\x85\x0e\xf2\x67\x9a\xf7\xc2\x82\x8f\x52\x64\x60\x7d\x9a\x41\x50\xec\x1a\x9b\xd7\x31\xaa\xd0\x80\xf3\x2f\x9a\x0c\xd6\x04\x77\xeb\x78\xdd\xbc\xbb\x8d\xfd\x56\x2a\xe8\xf5\x77\x4c\xa2\x50\x28\x8b\x79\x7f\x49\x49\x8e\x95\x7c\x4a\xa2\x97\x16\xa7\xb7\x22\xea\xce\xdb\xf7\x88\x6c\xdc\x9d\xce\x79\x89\x6d\x01\x9e\x66\x32\x6e\xfd\x85\xdf\x9c\x12\x5d\x49\x6a\x6f\x65\x36\x19\x90\x72\x32\x2b\x7c\x91\xd5\x81\x82\xd4\xcc\xdd\x07\x5e\x6c\x3e\x0a\xa1\xbf\x6e\xaa\xad\x44\x38\x34\x7f\x76\x37\xf8\x7e\x60\x37\xe0\xa2\x85\x10\xb9\x7c\x82\x0b\x8d\xc2\x2a\xbc\x38\x8c\xdb\xe3\x66\xbb\x7f\x46\x51\x25\x2b\x7e\xa9\xbe\x91\xa2\xf2\xb4\x8c\x76\x2e\x6f\xdf\x5c\xbd\x46\x89\x5e\xf1\x80\xcb\x0b\xe5\x5a\x6e\xb0\x12\x5a\x8c\xb6\x0f\xd0\xf5\x17\x7c\x6b\x54\xe2\xd6\xf9\xf7\x15\x54\x73\xa8\xb8\xa2\x7a\x0a\xef\xc8\x06\x48\xa1\x44\xed\xe4\xf0\x56\xb9\xd7\x88\xc8\xef\xba\x62\xa7\x80\x95\x45\xbd\x2f\x97\x8c\xc3\x4c\xe8\x25\x6c\xb1\x0d\x28\x25\xba\x3b\x46\xac\x10\x15\x04\xa4\x6f\x3b\x73\x30\xbe\x3d\x54\x5f\x89\x4f\xee\xa8\x82\x52\xd2\x8c\xe6\x94\x67\x41\xe7\x2b\x12\x62\xe6\xf7\xff\xe6\x7b\x42\xdf\x0b\x6e\x84\x64\x84\x33\x7a\xc5\x73\x96\x11\x6d\xbd\x90\x3a\x8a\x83\x01\xb1\x7a\xce\xb3\x45\xb0\x78\x90\x11\x91\x9e\x6c\x2b\x45\x25\x46\x45\xb5\xac\xa8\xdd\x58\x7f\xaa\x66\xb4\xa0\xda\xb7\xd8\x22\xd4\x15\xa0\x89\xb6\x95\xcd\xd8\x8a\x2c\x28\x10\x5d\x8b\x01\x7f\x1f\x13\xe5\xca\xa8\x53\x9c\x49\xa6\x21\x17\xb4\x29\xc9\xe5\xeb\xec\x50\xf0\xed\xd5\x6b\x78\x0e\xa7\x66\x0e\xcf\xd0\x9e\x98\x13\x56\xf8\xd7\xe6\xc0\xac\x81\x2d\xfb\x87\xcd\xeb\xe1\xfa\x6a\xaf\x2b\x27\xfb\x40\x48\xab\xbe\xce\x81\x0b\x50\x55\xb6\xac\xe7\xda\xdf\x07\x5b\xbb\x8b\x5d\x06\x10\xe2\x68\x9c\x80\xf5\xe4\xd8\x88\xe5\x7d\x02\xd6\x77\x6e\x2d\xd3\x21\x01\xeb\x1d\x9f\xcc\xf7\x09\xd8\x20\x44\xe2\x13\x17\xb0\x81\x06\xcc\xb7\x8a\xca\x48\xf6\xcb\xb7\x4f\xdc\x7e\xe9\x5e\x71\x8d\xac\x6c\x57\xd6\xdf\x40\xb0\x02\x71\x45\x35\xc9\x89\x26\xce\xae\x09\xad\x21\xba\x6b\x13\xa5\xc3\xf7\x34\x0f\xdf\xe7\xb4\x6e\x14\x7d\xcb\x78\xf5\xc9\x26\xac\xc4\x0a\x20\xdd\xbc\x41\xa6\x90\x85\x4d\x31\x6e\x5d\x52\x96\x05\xc3\x8a\x92\x5b\x39\x14\x41\x8a\xb3\xdb\x28\x20\x5c\x38\xd4\xd7\x19\x54\x9c\xa4\x28\x84\x31\xf0\xcc\x9d\x95\xf0\x5c\xf8\x22\xd9\xb7\x26\x11\x9d\x1d\xb4\xd7\x26\x6f\x8a\x87\xdc\xf7\xac\x25\xd1\xf0\x05\x88\x86\xcf\x1a\xf8\x2b\xe8\x9a\x7a\xf7\x35\xd8\xee\x3e\x68\x78\x01\x53\xf5\xb6\x0e\x88\x1e\xe0\xb0\xa0\x20\x33\x5a\x58\xcb\xdf\x8a\x88\x08\xf9\x70\xc1\xc2\x25\x4a\x98\x4c\x8a\x22\x56\xbd\x8f\x8f\xa2\xc0\x64\x18\x12\x61\xda\xcd\xb0\x7e\xc6\xb3\x8e\x2c\xe2\xcc\xfa\xed\xa6\x8c\x36\xeb\x18\x32\xf8\xf9\xce\x7a\xe5\x7d\x71\x80\xed\x59\x37\x77\x90\x58\xb3\x8e\x86\xfd\xcf\x73\xd6\xef\x19\xcf\xc5\xbd\x8a\x6b\xf0\xfd\xd9\x32\xad\xb5\xa9\x6f\x1a\xbb\xa2\x5a\x33\xbe\x50\x5d\xa3\x8f\x14\x45\x04\xd0\xd0\x90\xd5\xe7\xb0\xb1\xbe\xa1\x9c\xba\xe9\xe7\xae\x55\x12\xe8\x76\xa9\x94\xcb\x4b\xe8\x58\x51\xbe\x36\xe4\xae\xd3\x79\xc8\x8a\x0a\x88\xe9\x25\x2b\xea\x10\x2d\x56\x8a\xbc\x92\xe6\x25\x34\x23\xc5\x4d\xe9\xdb\xc3\x04\xb6\x0f\xde\x37\xef\x6e\x2e\xfb\x8c\x03\xe4\x13\x43\xac\xa5\xb4\x0e\x5a\xc3\x19\x48\xbe\x62\x4a\xf9\x7b\x11\x0d\xdd\xd3\xd9\x52\x88\x3b\x38\xad\xd1\xd7\x0b\xa6\x97\xd5\x6c\x9a\x89\x55\x07\x88\x3d\x51\x6c\xa1\x2e\x9c\x60\x9a\x98\xf9\xf2\xc5\x64\xe2\x9b\xf0\x82\x71\x17\xb3\xc5\xbb\x13\xd7\x0a\x84\x7f\x3b\x44\x68\xa7\x24\x6b\x66\x1b\x77\x7c\x00\x4b\xdb\xb8\xcd\x02\x0c\x07\x16\xf2\x7d\x58\xfd\x02\xac\x78\xf9\x59\xf5\xfa\xee\xa6\x7f\x1f\x54\x50\xf5\xc0\xc6\x0f\x9c\x2f\xdb\x08\xc6\x16\xdb\x70\xfe\x42\xf3\x8c\x00\x8e\x5b\x3b\xc5\x39\x0b\x3f\xef\xb5\xa2\x76\xd4\x46\x5c\x09\x74\xd8\x3a\x96\x41\x47\xb6\xb1\x20\x5a\xd7\x6f\xc7\x89\x1b\xc0\x7a\xdb\xfd\xdb\x38\x72\x03\x78\x6e\x23\x90\xa3\xb8\x81\xe1\x11\x5d\xc1\x70\xb4\x3b\x38\xe0\x01\x7d\x83\x25\x92\x15\x00\xfb\x5d\x3f\x81\x02\xfd\xd1\x0c\x17\x88\x66\xbc\x40\xd8\xc1\x77\xe5\xca\xa2\xb4\xf4\xbb\xe9\xf0\x02\x56\x87\xb0\x3d\xde\xaa\x0e\x7a\x9b\x15\xb5\x45\x2b\x9b\x52\x70\xc5\xa6\x2e\xbc\xc9\xfe\xee\xb7\xd7\xfb\x2d\x60\xb9\xb0\xb9\xad\x9d\x4a\x96\x1e\x3c\x5d\x4f\xaf\x1c\x2a\xae\x59\x51\x23\x9a\x56\x65\x61\x2c\x97\xde\xe8\x3d\x47\x8c\x1c\x3b\x5d\x03\xcf\x9b\xe9\x09\x69\x6e\xe8\x6a\x81\x9e\xc3\x7f\x57\x4a\x03\x69\x52\x8a\xea\x82\x76\xb8\x92\x1e\xcc\xeb\x5a\x7b\x88\x8f\x73\xad\x5c\xb1\x9e\xbd\x16\xe6\x25\xd6\x2c\xf7\xe1\x9a\xb3\xf9\x9c\xd6\x49\x55\x33\x0a\x25\x91\x64\x45\x35\xc2\x5d\x7d\x31\x12\x33\xba\x60\x36\xe7\x44\xcc\x81\x98\x09\x3d\x39\x51\x6d\x95\x34\x1f\xf9\x81\x99\x2c\x4c\xc3\x8a\x2d\x96\x1a\x0f\x39\x10\x28\x04\x5f\x60\x2d\x1c\x3f\x88\x40\x21\x48\x0e\x28\xeb\x85\x84\x7b\x22\x57\x40\x20\x23\xd9\x12\xb1\x17\x5e\x11\xd9\xbc\x92\xd8\x8e\x50\x53\x92\x6f\x26\x4a\x13\x6d\xee\xba\xd4\xe6\x45\xdb\x95\xf3\xe0\x9a\xed\xd4\x64\xb1\x7b\x00\x3d\x2e\x33\xaa\x7d\xba\x83\xd7\x70\x48\x87\x81\xac\xed\xe1\xae\xb0\x09\xe0\x3a\x2f\xc8\xe2\xa9\x15\x01\x4a\xdd\x33\x1d\xa5\xee\x99\xc7\x52\xea\x9e\x79\x34\xa5\xee\x99\xa9\x7b\x66\xea\x9e\x99\xba\x67\xa6\xee\x99\x5b\x94\xba\x67\xa6\xee\x99\x0f\x50\xea\x9e\x79\x98\x61\xaa\x8c\xed\x49\xa9\x7b\x66\xea\x9e\xb9\x9f\x52\xf7\xcc\xcf\x6d\x5a\xa4\xee\x99\xa9\x7b\x66\x4d\xa9\x7b\xe6\x08\x4a\xdd\x33\xc7\x51\xea\x9e\x79\x90\x9e\x58\x3f\x8d\xd4\x3d\x33\xf5\xd3\x38\x96\xcf\xd3\xeb\xa7\x01\xa9\x7b\xa6\x1f\xa5\xee\x99\xe3\x29\x75\xcf\x1c\x47\xa9\x7b\xe6\x78\x9e\xa9\x7b\x66\x4b\xa9\x7b\x66\xea\x9e\xf9\x85\x6e\xdd\xd4\x3d\x33\x75\xcf\x1c\xa6\x14\x23\x48\xdd\x33\xc7\x51\xea\x9e\xe9\xcf\x34\xdd\xf6\xfd\xf9\x3c\xbd\xdb\x7e\xea\x9e\x99\xba\x67\x1e\xa4\x10\xd3\x4d\xe9\x9c\x79\xb4\x4d\x79\x9c\xba\xa8\x0e\x2d\xdb\xa9\x35\x33\xab\xe6\x73\x2a\xd1\xec\xc6\x91\x7a\x39\x6e\x86\xcb\xf4\x4e\xeb\x34\x05\x1f\x9e\xd6\xf0\x53\x54\x9f\x63\x09\x57\x65\x13\xa7\x71\x88\x7e\x80\xc7\xfe\x10\x5d\xc9\x1d\x6c\x16\x22\xa9\xf2\xbb\x5f\x33\x0e\x6f\x3e\x7c\x3d\x8d\x50\x12\x36\xa4\x9a\x1a\xce\xc9\x07\x9e\x85\x26\xeb\xb4\x9b\x2c\xac\xb2\x51\x5d\xd5\xc8\xed\xb5\xac\x10\xca\x62\x6b\xed\xe2\x65\x4b\xc2\x39\xf5\x49\x50\xb1\x02\x91\x69\x74\xbb\xcd\x28\xe5\x20\x4a\xca\x2d\xfe\x9f\x80\x62\x7c\x51\xf8\x68\x00\xa2\x35\xc9\x96\x53\xf3\xfe\xbc\xde\x60\xae\x9b\x4c\x33\x6a\x9f\xa3\xa6\x25\x25\x2b\xbb\xd1\x24\x5d\x11\x66\x87\x0b\x24\x93\x42\x29\x58\x55\x85\x66\x65\xc0\x80\x41\x51\x4c\xb3\x56\x36\xe7\xbf\xde\x04\xe0\x75\xdc\x14\xb5\x60\x4f\xac\xdd\xd9\xcc\x81\x9b\x5e\x2f\x13\xac\x3d\x6a\x78\x81\x3f\xc7\x46\x82\xab\x52\x6f\x6c\x42\x94\xe7\x01\x9e\x33\xa9\x34\x64\x05\xc3\x1b\x1c\xce\x03\x45\x4d\x86\x63\xf6\x41\x00\x13\x9e\x1b\xce\xdc\xad\x91\x72\x8b\xc4\x73\x34\x40\x4b\x2f\x83\x1f\xd3\x72\xea\xbc\x2f\x5a\x0f\x37\x67\xca\x5d\x28\x94\xd7\x40\xeb\x6a\xea\xf6\x70\xd5\x6b\x84\xc7\x2b\xf7\x2c\x0b\x5c\xbf\xb3\x63\xd2\x19\x72\xc0\xf9\xc7\x02\xe8\xce\x2b\xde\xa8\x00\x5b\xba\xbc\x16\x90\x5e\xef\xbf\x9b\x8c\x5b\x17\xc3\x45\x05\xe1\xc1\xb2\xa3\x52\xf0\x98\x72\xba\x36\xda\x8b\x66\x94\xad\x8d\x11\xee\xc1\x72\x50\x1f\xfc\x43\xd5\x81\xa6\x72\xc5\x38\x26\x6d\xbd\xa3\x4a\x91\x05\xbd\xf6\x8a\x7e\xef\xbb\x5b\x63\x00\xbc\xde\x8c\xde\xc7\xb8\xc0\x0b\x76\x6b\xdc\xb6\x29\x08\x27\x5e\xe9\xa1\xed\x4b\xc3\xca\xbe\x75\x53\x17\xe5\x5e\x32\xad\xa9\x97\x61\xa3\x6c\xb7\x05\x04\x0e\x6d\x57\xe2\xf1\x1b\x68\x27\xbd\x02\xde\xd5\x03\xb5\x03\x34\x8f\x33\x46\x2a\xcf\xbd\x7c\x5c\x16\xe5\x34\x93\x8c\xce\x61\xce\x30\x8b\x01\xf1\xf6\xe7\xb6\xba\x2f\xf1\x19\x2d\xe1\x40\x94\xa2\x12\xe7\xd5\xe1\xad\xeb\xf9\x9d\xc2\x9f\xbd\xf3\x4c\xb5\xac\x78\x46\xda\x5e\x59\xc0\x45\x4e\x81\xcd\x61\x81\xc8\x7e\x1f\xa9\x83\xbd\xf9\xfe\xed\xf9\x7f\xfc\x1e\x66\x1b\x73\xd1\x40\x2c\x8b\x16\x9a\x14\xf5\x80\x3d\x98\x16\x94\x2f\xcc\x6e\xb7\x2a\xbb\x5f\x52\x28\x20\xcd\x16\xbb\xaa\xdb\xdc\xd7\x17\xbf\xb9\x9b\xf5\xee\x64\x1e\x1c\x2f\x72\xba\xbe\xe8\x9c\x80\x49\x21\x16\x9d\x66\xf8\x1e\x1c\xeb\x54\x4d\xdf\x44\x45\xaf\x6b\xfe\x80\xe0\xc2\x8e\x9e\x81\xa2\xab\x2e\x9c\x0e\x4b\x71\x6f\xbb\xa9\xb4\xcf\xf1\x98\x9a\x5a\xba\xb4\x79\x87\xa5\x28\xab\xc2\x66\xb6\x7e\xcd\xbc\x0c\x3a\x94\x54\x95\xa2\xdb\xb5\x67\xf6\xc8\x72\x3f\xe1\x50\x0f\x73\xeb\x22\x64\x85\x44\xc0\x44\x08\x57\xb8\xc1\x45\x97\x9a\xca\xe7\x95\xf4\xca\x7c\xfc\x9a\x14\xc5\x8c\x64\x77\xb7\xe2\xad\x58\xa8\x0f\xfc\x8d\x94\x42\xf6\x66\xc8\xe7\x1c\x13\x63\x35\x2e\x2b\x7e\x67\x9b\x81\xd7\x2f\x5f\x88\x05\x88\x4a\x97\x95\xd7\xed\x6f\xbe\xbd\x9d\x9a\x39\x99\xfb\xed\x83\xc6\x44\x76\x46\x69\x67\xa4\xf4\x13\xf3\x0b\x7d\xdc\x33\x23\xc0\x38\x50\x33\x8f\x56\x2a\xb6\x6f\xed\x77\x59\xe8\x88\xaf\xdf\x3c\xff\xb7\x7f\xb7\x02\x17\x84\x84\x7f\x7f\x8e\x49\x99\x5e\xe6\x2d\x9a\x02\x68\x7f\x31\x05\x6a\x45\x8a\x82\xca\x50\xc1\x68\x8e\x63\x47\x10\x36\x62\xed\x1f\x2a\xd5\x74\xa8\x00\x7b\x44\xe7\xcf\xed\xed\x5f\xd0\xf3\xc3\xb4\xa2\xc5\xdc\xcb\x2a\x2f\x94\x68\xfb\x1d\x9d\xa0\x31\x7d\xe2\x6c\x11\x73\x9b\xf4\x11\x01\x9f\xd7\x9d\xb2\x16\x45\xb5\xa2\xaf\xe9\x9a\x65\x3e\x61\xad\xde\xd2\xf5\x78\xf9\x67\x3e\x17\x4c\x61\x41\xfa\x59\x21\xb2\x3b\xc8\x1d\xbb\x16\xd6\xee\x63\x85\x6c\x42\xeb\x4a\x86\x24\x21\x78\x27\x1f\xec\x9d\xdd\x36\x75\xc0\xcb\xc1\x4b\x60\x45\xca\xb2\x29\xfa\x21\xc9\x7d\x6f\xb2\xbd\x78\x1a\xc9\xcb\x78\xf7\xde\xea\x73\x18\x02\x83\xc3\x21\xa1\xe1\x89\x7b\x7b\x4f\x9b\xc3\x3b\x2f\x21\x34\xaa\xdc\x8e\xda\x37\xf0\xd5\xdb\x66\x2d\xbb\xd0\xda\x05\x25\xf2\xb0\x49\xeb\x91\xfa\x4b\x74\x2a\x23\xd9\x71\x36\xd7\x5e\xb3\xa1\x03\xaa\x8a\x69\xe1\x1b\x74\x0c\x8e\xf4\x85\x64\x81\xf4\x56\x8e\x37\x31\xd5\x15\xd1\x5e\xce\x0a\x4b\xdd\x22\x7f\x04\x4a\x2a\x15\x53\xc6\x46\xff\x0e\x05\xd0\xab\x82\x30\xdf\xc0\x59\x13\x3c\x29\x85\xef\x52\x05\x4c\xb7\x15\xa0\xd8\x9c\x30\x54\xd3\x5d\x8b\xdc\xb1\x43\xc5\x84\x6e\x13\xaf\x88\xca\x8e\x9b\x25\xb4\x24\x45\x34\xf3\xef\x73\xaa\xba\xef\xda\x95\x0a\xd7\x74\x86\x4b\xa3\xea\x2c\x67\xa7\xac\x3c\x39\x7e\xb9\x0a\x0e\xe7\xe2\x4b\xd3\x6f\xcd\xa0\xa3\x08\x49\x54\x6c\xce\x56\x09\x51\x6e\xed\x5d\xb5\x8d\x54\x2c\xa9\x13\x0a\xde\x5c\x5b\x37\x8b\xf3\xc4\x4e\x1d\x58\x94\x7b\x77\xaa\x6b\x86\x0a\x27\x2f\x4f\x3e\x9b\x92\xb3\x8b\x28\x45\x49\x16\xe8\x3b\x88\xb2\x96\xdb\x4c\x03\x10\x5e\xd6\xad\x41\x15\xba\xcd\x90\xaf\x6f\x25\x44\x4b\xa5\x1b\x15\xcd\xdb\x12\xe8\x4b\x81\x15\x16\x62\x6c\x39\xe7\x30\xb1\x85\x1b\xef\x03\xf2\xa2\x89\x14\x15\xcf\x5d\x34\xb8\x81\x20\xbc\xdb\x9a\xd8\xf7\xfe\x15\xcc\xd0\xcd\x63\x6b\xb5\x63\x21\x3c\x9b\x28\xc9\x94\x6f\x31\x3c\xc7\x93\xc3\x8b\xe9\x8b\xe7\x5f\xbe\xcd\x86\x73\x12\xc9\x66\x7b\xdf\xd8\x6c\x56\xcb\x7d\xb6\xd9\xa9\x1b\x26\x47\x99\xa1\x77\x2e\x24\xd5\x74\x36\xf6\xdf\x34\x75\xb7\x4e\x64\x75\x2f\x99\x76\x27\xe8\x9e\x05\x24\xaa\x9d\xa2\xd3\x06\x84\xec\x96\x20\x3e\x6b\x7d\x79\x01\x57\x92\x90\x8e\xcb\xe1\x2d\x0b\x01\x54\x35\x7b\x72\x7a\xd7\x2a\x58\x2b\x54\x87\xe2\xa9\xfe\xf3\xed\x38\xef\xaa\x60\x6f\x8e\x5d\xec\xe1\xb3\x67\x70\x6a\x9f\x70\x62\xab\xd9\x9d\x7d\xb6\xe3\xe9\x96\xf5\xcd\xa7\xd2\xbb\xa9\x4c\x6f\x69\xdf\x7c\x2a\x09\xcf\x69\x6e\x2f\xfc\x01\xa6\x35\xd4\x45\xa7\x87\xd6\x38\x5c\x6d\x9e\xa8\xfe\x1a\x7b\x73\xec\x9a\x67\xff\x49\x97\x64\x4d\xb1\xe6\x1f\x2b\x88\x0c\x10\x4f\x5a\xc0\x8d\x5d\x19\x98\x55\x1a\x28\x5f\x33\x29\xf8\x8a\x06\x14\x76\x5f\x13\xc9\xc8\xac\xa0\x20\x29\x16\x0e\xce\xa8\x82\x5f\x9d\x7e\x77\xf9\x11\x61\xd6\xfe\xed\x23\x88\xa4\x40\xeb\x55\xaf\x14\xa6\xe7\x46\x3a\x85\x9d\xd7\x9e\x6e\x1d\x20\x7f\x11\xbd\x75\xf0\xea\x79\x36\x27\xc0\x7f\x0e\x78\xde\xac\x97\x99\x8f\x55\xa5\x2b\x52\x60\xd9\xc7\xac\xa8\x14\x5b\x7f\x0e\xfd\xeb\xca\x70\xbe\x66\x1e\x27\x7b\xab\x7c\x69\x7b\x68\x76\x6a\x7b\x7a\x96\xf0\x46\xf3\x32\x5e\x4b\x49\x07\xbc\x3c\x51\x75\xb2\x4a\xaf\x35\x90\x77\x50\xce\x95\xad\x9e\xe1\xe0\xe6\x6c\x51\x49\x5b\x48\xc7\x4f\x04\x75\x9a\x59\xaf\x10\x45\xf2\xb9\xc2\x73\x39\x57\xaf\xf0\x7d\xc6\x6c\x8c\x7e\x5e\x7f\xaf\x54\xf0\xeb\xf7\x37\x9d\xfa\xe3\xa3\xde\xc1\xba\x15\x45\x3e\x85\xeb\xb6\x80\x79\xdb\x62\x00\xfb\xeb\x8c\x46\x9b\x18\x99\x4c\xe5\xa2\x6d\x81\xba\xa0\x9c\x4a\xbc\x80\x99\xa1\xd6\x6b\x39\xfe\x9e\x38\x23\x0a\x41\xa1\x86\x8d\x45\x68\x8c\x59\x31\x4f\x77\x8f\xaf\xcf\xc4\xdc\x4b\x6c\x75\x95\xd1\xce\x96\xde\x5a\x5f\x36\x41\x38\x33\x79\xe8\x0c\xb6\x6c\x47\x6f\xd6\xab\x6b\x20\x79\x2e\x11\xbe\xe8\xae\x80\xf5\x31\x25\x65\xe9\x87\xfe\x72\x2b\x6c\x56\xa6\xfb\xc6\xed\x92\x8f\xe6\x88\xa6\x46\xbb\xc0\xf0\xba\x2a\x0b\x66\x21\x5b\x9d\x07\x8c\x66\x5b\xbf\xa9\xa4\x2b\xb1\x1e\x7f\xd4\xfd\x1d\xb1\x9e\x6e\x58\x6f\xcd\x23\xfc\xfa\xe4\x3d\xb0\xe7\x24\x55\xa2\xf0\xd9\x70\x6e\x28\x5b\x7b\xcd\xc9\x06\x63\x9c\x8e\x9f\x95\x7a\xaf\x39\xd6\x1d\xd1\xb2\xb5\x6f\x46\xb3\xee\xec\x33\xca\xb5\x34\xc2\x35\x70\xcf\x00\x7c\x34\x33\x57\x21\x40\xa7\x19\x30\x5b\x53\x6e\x94\xd8\x07\xcf\x66\x7e\x38\x28\xb1\xa6\x52\xda\xca\xe1\x36\xc7\xc1\xb6\x7c\xa4\x44\xfa\xa4\xa8\x34\xb3\xea\x3d\x7d\xff\xf0\xe3\xb1\x1d\x02\x7a\xfd\xfe\xc6\xea\x54\x3b\xad\xc6\x0e\x61\xdc\x2b\x50\xd1\xdd\xf1\xcd\xaa\x35\x7a\xd2\xf3\x1c\x7f\x96\xfe\x09\xfe\x9e\xb1\x7e\x4b\x5e\x17\xe7\x08\xa9\x5e\xe0\x7d\x45\x0e\xa8\x34\xe7\xfd\x64\x45\x89\xcc\x96\xe3\xe7\xfc\x01\x11\x6a\x59\x42\x2e\x30\xeb\x61\xbc\x4e\x14\x12\x5d\xd6\x13\x54\xff\x85\x10\x77\x55\xd9\x97\xaa\xa3\x59\xd6\x1a\xbf\xa7\xc1\xdd\x30\x4b\xa2\x97\xe3\x07\xb9\x57\x14\x77\x44\xeb\x68\xa6\xdd\x11\xfd\x73\xe8\xf0\x9c\xab\xf1\xe8\xe3\xfe\xed\x80\x6a\x7b\x27\x40\x36\x6d\x45\x97\xb1\xe2\xab\x77\xe5\x7f\x55\x54\x4a\x53\xf9\x35\x93\x4a\x3f\x9b\xc2\x77\xa4\x60\xae\xc8\xe2\xb8\x9d\x62\xee\xe7\x27\x5d\x66\x7f\x66\x7a\xf9\x47\xa1\xf4\x7b\xaa\x4f\xce\xfb\x7f\x3a\x19\x77\x73\x3c\x71\x03\x3e\x01\x21\xe1\xe4\xbd\xe0\xf4\x64\xba\x75\x39\xb2\xea\x77\x14\x57\x86\xd7\x0d\xab\x5c\x86\x6c\x18\x37\xb7\x66\xaa\x47\x4a\x99\x82\x66\xba\x66\xd2\x39\x2d\xb7\x02\x96\x64\x6d\xaf\x75\x3e\x1d\x7f\x15\xd5\x40\xb0\xc7\x13\x72\x5e\xda\xb9\xbd\x17\xf2\xce\x36\x6c\x40\xe6\x23\x63\x5f\xf6\x4a\xb8\xe9\x6e\xab\x4e\xd7\x06\x2d\xf6\x2f\xe9\xf8\x1b\xda\xc8\xf3\x62\x5b\x31\xdd\x50\xb9\x66\x19\x7d\xcb\xf8\xdd\xa8\x83\xda\xcf\x35\x7a\xb3\xc3\xcb\xb3\x75\xdc\xbd\x43\xce\x32\x6e\x13\xb8\x8d\x49\x42\x66\xa2\xd2\x78\x77\x43\x10\xa5\x87\xe3\x13\xeb\x3f\xfc\xb7\xdd\x35\x88\x57\x29\x6d\x8b\xb0\x8e\xa3\xae\xf1\x33\x8e\x84\x42\x63\xc8\xab\x76\x1e\xaa\x0d\xd7\xe4\x13\xea\x2e\x91\xdd\x51\x09\x85\x99\x8a\x29\x34\xa9\x58\xde\x62\x04\x81\xb9\x63\x72\x3b\xfc\x22\x27\xb4\x5c\xd2\x15\x95\xa4\x68\x7c\x67\xfe\x9b\xe2\xad\x53\xe3\x0d\xcf\x4e\x26\xce\xa8\x79\xb0\x7d\x63\x5c\xf7\x3c\x91\x4f\xe1\x4d\x28\xc7\x15\xd9\xa0\x3a\xb4\x8c\x09\x07\xfa\x89\x29\x04\xd8\x94\x22\xef\xd4\x74\x1b\xc5\xb4\x52\x54\x4e\x9a\x0a\x80\xae\xc2\x92\xaa\x53\xb9\x20\xa7\xb3\x6a\xb1\x60\x7c\x31\x4e\x97\xa0\xad\x82\x16\x51\xdb\x96\xad\xf5\x33\x61\x9b\xba\x4c\x52\xa2\xc7\xda\x6a\x68\x95\x9f\xa3\x07\x98\x75\x79\xaf\x44\x6e\x59\xcf\x36\xd6\xbb\x37\x96\x71\x5d\x2f\xc7\x0c\x72\x0a\x57\x1c\x84\xcc\xa9\xc4\xf2\x30\x79\x8e\x73\x5d\xaf\xde\x28\xb6\xad\x13\xd2\x70\xea\xaf\xd8\xb9\x57\x9e\x89\x91\x01\xaa\x1d\x4d\x27\x4d\x4c\x55\x33\x73\x91\xa9\xe4\xd8\x76\x9e\x7d\x74\x00\x29\xca\x25\x99\x14\x74\x4d\x0b\x70\x5d\x95\x46\xc7\x7e\x97\x82\x0b\x69\x57\xa3\xf6\x10\xe1\x9d\xd5\x0a\x6f\x9c\xec\x37\xbb\x67\x76\xd4\x23\x5c\x13\xbd\xf1\xfa\x66\xac\x41\xe8\x61\x0c\xf6\x6f\x06\x7c\xe0\x5d\xc7\xe7\xc3\x74\xb3\x92\x71\x2e\x9d\x34\x20\x39\x5a\xf5\x74\x55\x0a\x49\x24\x1b\x1d\x05\xdb\xdd\x97\x68\x41\xf6\xc5\xc2\xd8\xb1\x66\x9a\xad\x99\xb9\xc7\x0e\xc8\x91\x76\x36\x46\x72\xed\x6c\x75\xb4\x69\xb8\x80\x7a\xbf\x1b\x0b\x50\x65\x4b\x9a\x57\xc5\xf8\x7b\xe7\xa2\x22\x92\x70\x4d\xa9\x3a\xaf\xe1\x3d\x1b\x97\xa6\x6d\x85\x4b\x93\x64\x3e\x36\x24\x64\xc4\x1c\x72\xa3\x9f\x98\xc6\xf6\x99\xe6\x37\x28\xc3\x6c\xf2\x3a\xde\x6b\x46\x72\x15\x72\x2b\xeb\xbd\x2b\x9c\xbc\xc3\x3a\x19\xa9\x14\x76\x43\x70\xaa\x84\x7e\xca\xa8\x31\x3b\xb4\x6a\x26\x79\xec\x26\xb0\xd9\x3f\x4c\xf0\xf3\x46\xba\xba\x3d\x4b\xd7\x2c\xf3\x88\xbf\x0c\x29\x50\x64\xe9\xd6\x09\x8f\xc2\x48\x9e\xb3\x8d\x0b\xae\x15\xad\xe2\xd8\x52\x06\xb7\x4b\x3a\xf6\x50\x35\xe5\xb5\xf0\x70\xae\x19\xa9\x59\x0e\x8b\xee\x91\xdc\x3b\x82\x7e\x7b\xc7\xfa\x3a\x05\xbb\x6f\x0c\x82\x67\x6e\xe8\x9d\x16\xaa\x63\x39\xa2\x1a\xd9\xd7\x40\x35\x54\xf8\x6f\xf5\x50\x1d\xa7\xe9\x7d\x3d\x74\x7e\x00\x60\x0f\xf0\xae\xbf\x1b\x90\xc8\x45\xa8\x73\xf5\xe4\x52\x2e\xaa\x15\xe6\x05\x3b\x57\x51\xdb\xe6\xde\xc7\x25\x78\xbb\xa4\x90\xdb\x6b\x05\xc6\x61\xcd\x05\xe6\xd5\xbb\xd7\x35\x36\xd1\x83\x23\x73\x85\x3e\x5c\xe5\x26\xd7\xd4\x39\x9f\xc2\x77\xee\x2e\xe4\x13\xd1\x1e\x44\x69\xf4\xd0\x16\x1e\x5c\x87\xf0\x19\xfd\xfb\x9b\x67\x3c\x9f\xb4\xf8\x92\xd6\x06\x76\x5e\x6c\xaf\xf8\xbb\xed\x42\xe4\xe6\xa0\x4e\x15\x61\xbc\x34\x37\x58\x5f\x5f\x6e\x83\x09\xe0\xd9\x92\xf0\x85\x95\x26\x34\x10\x05\xe3\xee\xaa\xae\xb1\x37\x55\x19\x29\x6b\x9f\x0a\x81\x5c\x54\x7e\xcb\xff\xab\x5f\x9d\x03\xa3\x2f\xe1\x57\x9d\xc1\x4d\xe1\x8d\xe3\xde\x6e\x0e\xdf\x59\xb0\xf5\x5e\x66\xed\x66\x3a\x07\x49\x17\x44\xe6\x85\x5f\x6b\x0f\x31\x6f\x5c\x0e\x88\xda\xaa\x37\x03\x9a\x71\x0a\x84\x0f\xa8\x83\x0b\x3d\x84\x91\xe8\x94\xd9\xf3\x60\xfa\x40\x61\x3e\x4d\xd4\x9d\xba\xb0\x0e\x8e\x49\x4e\x34\x99\x90\xd2\xfa\x8d\x99\xe0\x17\x36\xa0\x33\x71\xad\x5d\x27\xc4\x09\xa5\x49\x73\x90\x2e\x7e\x29\x2b\xec\x9e\x3e\x21\xcd\xa7\x18\x9f\x90\x09\x36\x02\xf5\xad\x27\xf1\x0f\x4e\xbd\x09\x88\x96\x78\xf7\x4c\xde\x76\x81\xd5\xc2\xdd\xbe\xfb\x14\xde\x7b\xe5\x3b\xb8\xde\xc8\x79\x9b\x8c\xea\x1a\xb2\xb6\xf2\xdf\x47\xd4\xd7\x1a\xe3\xcd\xfb\xdb\x8f\x7f\xb9\xfe\x70\xf5\xfe\xb6\x56\x1c\xb5\x1a\xf0\xe1\xba\x4f\x71\x84\x9d\xf4\x7d\x8a\xa3\x55\x03\x21\x28\xa6\x6d\xc5\xd1\x57\x03\x3e\x9c\x77\x15\x47\x5f\x0d\xf8\xcc\xec\xae\xe2\x18\x50\x03\x9e\x56\x44\x77\x7e\x07\xd5\x80\x97\x74\xee\x28\x8e\x61\x35\xe0\xc1\x75\x57\x71\xf4\xd5\x80\xd7\xf9\xda\x55\x1c\x1d\x35\xe0\xa9\xf2\x77\x15\x47\x57\x0d\x78\x30\x1d\x56\x1c\x49\x0d\x1c\xf3\x50\x2f\x35\x40\xf9\x3a\x50\x05\x34\x0e\xef\xa1\xa8\x82\xcf\xcb\xf4\x5a\x5b\x76\x8a\x62\xc7\xd8\x54\x5f\xc6\x7a\xf6\x31\xfa\x7c\xfd\x1d\x91\x20\x69\x29\xa9\xc2\x7b\x95\x67\x4e\xc8\xd0\x02\x81\x63\xea\xdb\x9a\x9f\xb4\x70\xe3\x2f\x2e\xa5\xf6\x33\x25\xc5\x46\x4b\x40\xab\x93\xc6\xec\x1d\x3b\x5e\xca\xc1\xb4\x69\x72\x42\xe0\xd5\x8f\x57\xaf\xdf\xbc\xbf\xbd\xfa\xfa\xea\xcd\xc7\xcf\x96\xf5\x12\xd4\x3e\xb2\x6f\xae\xc6\xb1\xd4\x2c\x3d\x6c\xaf\x79\xb3\xb5\x15\xd4\xe9\x9a\x89\x4a\x39\x5c\x5a\x1e\x75\x7d\xd5\x8e\x6c\xf5\x66\x89\xd5\x67\xf9\xa6\x8e\x52\xc7\x1d\xe6\x74\xd0\x53\xe1\xcd\x37\xaa\xa1\x6a\xe9\x01\x73\xd5\x9b\x67\x54\x6f\x87\xa5\xfd\x3e\x0f\xff\x85\x8f\x6d\xf2\x5a\x7a\xd0\xf0\x0d\x59\xf9\x3d\xe6\xaf\x37\xcb\x07\xbc\x27\xde\x3c\x6b\xe3\xb9\x9f\x3a\xe5\xdd\x7e\x25\x8e\xd8\xfd\x5a\x8a\x55\x14\xd1\x7b\x63\x03\x6d\x0e\x5d\xe6\x3d\x49\x43\x46\xcc\x89\xb2\x63\xf5\xdf\x77\x1d\xb7\x95\x73\x0d\xd4\x8d\x22\xbc\x59\x1a\x7e\x58\x23\x31\x4c\x6d\x06\x35\xee\x8e\xd1\xed\xda\xa6\xdf\xbc\x23\xe5\x9f\xe8\xe6\x23\x0d\xe8\xd0\xb2\x83\x3a\x2c\x68\x66\x8c\x59\xb8\x1b\x1d\x1e\xeb\x13\x82\xad\x5f\xd5\xc3\x0c\x69\x6d\xf3\xa4\x7a\xa5\x87\x4d\x4b\xac\x46\xe7\x77\xd4\xbb\x16\x40\x4d\x3b\x8d\xbb\x43\x17\x1c\xea\x5b\xa2\xd9\x41\x21\xeb\x0d\x31\x9b\x9c\x47\x6f\x09\x7f\xe2\x0c\xfc\xf0\xb9\x6a\x8d\x1d\x6d\xdd\x2a\xc1\x2c\x8f\x6f\x9b\x23\xd6\xc6\x36\xa4\xf7\x17\x2e\x17\x75\x62\xec\x8e\x89\x3d\x63\xea\x02\x53\xb4\x2e\x7e\x89\xff\x09\x1e\x94\x6d\x9c\x77\x99\xe7\xae\xba\x4a\xa5\xe8\xbc\xf2\xa9\x7c\xdd\x27\x44\x36\xa9\x29\x90\x92\x7d\x47\xa5\x62\xc2\xab\x7d\x43\x9f\xee\x18\xcf\xcf\xa1\x62\xf9\x57\xfe\xdd\xd5\x2c\x45\xdb\xbf\xc2\x0b\xad\xb9\x4b\x03\x99\xa7\xe1\xc7\xbd\x6b\x6f\x35\xa2\x3e\x98\xab\x2d\x28\x6b\xe4\x51\x8d\xb8\x08\x66\xe9\x2e\x6c\x51\x16\x35\xa4\x00\x08\xd4\x1b\x37\xa6\xce\x3e\x69\x94\x76\xd0\xfb\x59\xa8\x60\xd3\x45\x2f\x7f\x59\xb7\xcc\x0c\x13\x01\x2b\xaa\x49\x4e\x34\x99\x1a\x69\x72\xde\xff\x51\x95\x24\xf3\x6a\xe6\x31\xc0\xbe\x20\x33\x5a\xa8\xce\x03\xd0\x78\x44\x7f\xb3\x57\x41\xe9\x96\x10\x2f\xc4\x45\x4e\xdf\xe3\x1b\xe0\x8f\xee\x6a\x7d\x99\x65\xa2\xe2\x1a\xff\x10\xf6\x0c\x2c\xa3\x3e\x5d\x0a\xa5\xaf\xae\xcf\xeb\x1f\x4b\x91\x5f\x5d\x47\x61\x8c\x9c\x54\x40\xd3\xc8\x27\x66\x86\xe1\x66\xf5\x2c\xbc\x57\x53\x2c\x63\xac\xd5\x40\x51\x85\xb4\xe3\x19\x2e\x4e\xed\x89\x56\xd9\x92\xae\x48\xd0\x2d\xaf\xa6\xaf\xeb\xc9\x07\xa6\x02\xda\xa3\xf4\x89\x71\x2c\x85\x6f\xee\xff\x51\xba\xa5\x5a\x32\x97\xf5\xf5\x8b\x67\x4f\xc6\x1c\x6d\xf6\x6d\xd4\xad\x82\x6b\x11\xc9\x24\xb5\x6a\xa0\x31\xe4\xa3\xac\xeb\xb2\x9b\x26\x70\x79\x7d\x15\xcc\x74\x6d\xcf\xc6\x93\x58\xd6\x1a\xb4\xf9\xf5\x13\xd5\xeb\x2d\x9a\x7a\xab\x64\x74\xd8\x16\x14\xbc\xd8\x34\xbc\x95\x6d\xea\x10\x76\x5e\x09\xcf\x51\x3b\x50\xa5\x15\x9c\x5a\x86\xd3\xac\xac\xc2\x14\xa0\xe3\xb3\xa2\x2b\x21\x37\xe7\xf5\x8f\x0d\x5c\x77\xa2\xb4\x90\x64\x11\xa8\xbe\xeb\x61\xe3\x70\xdb\x9f\xec\x43\xa3\x4d\xca\xee\xa8\xfd\xbd\xcf\xe0\xb2\x38\xb3\x4a\x9a\x0b\x68\xb1\x69\x1b\xa4\xff\x7c\xac\x04\x4f\x8c\x7b\x97\x62\x19\x09\xcd\xa9\x7b\x1f\xdd\x21\xf1\x2a\x38\x60\x54\x13\x3a\x4b\x9a\xb9\x87\xb9\x17\xe2\xb0\x4f\xae\xa8\xf7\x79\x73\x91\x0d\xbf\xf8\x0b\x09\x94\xaf\x61\x4d\xa4\x67\x43\xdf\x96\xa2\xe9\xf5\x9c\xad\x99\x12\x81\x22\x75\x5f\x7d\xa8\x28\x7a\xdd\x75\xec\xb1\x99\xac\xb1\x8c\x4a\xfa\xa9\xc4\xce\x8f\x8d\x1e\x08\xf7\xc1\xe4\xdd\x38\xcb\x0b\xff\x1a\x75\x96\x4a\xa2\x35\x95\xfc\x25\xfc\xd7\xe9\x5f\x7f\xfd\xd3\xe4\xec\xab\xd3\xd3\xef\x9f\x4f\xfe\xe3\x87\x5f\x9f\xfe\x75\x8a\xff\xf8\xd7\xb3\xaf\xce\x7e\xaa\x7f\xf8\xf5\xd9\xd9\xe9\xe9\xf7\x7f\x7a\xf7\xcd\xed\xf5\x9b\x1f\xd8\xd9\x4f\xdf\xf3\x6a\x75\x67\x7f\xfa\xe9\xf4\x7b\xfa\xe6\x87\x23\x99\x9c\x9d\x7d\xf5\xab\xc0\x81\x07\x36\x5e\xb7\x14\xab\xfd\x7a\x9f\x5b\x84\xe3\xf2\x28\xad\xd8\x5b\xaa\xb7\x63\x5c\x39\xfb\x31\x82\x4e\xea\x8f\xaf\x35\xb3\x9f\x84\x20\x53\x34\x93\x54\x3f\xed\x88\x92\x1d\x63\xa7\xed\x45\x40\x69\x4c\xa8\x0b\xbc\x95\x24\xc8\x46\x78\x52\x36\x4f\x0a\x50\x3d\x44\xb5\x33\xc4\xee\xa2\x78\xb7\xdc\xb9\x14\xab\xba\xb5\x00\x42\xb4\xd6\xa4\x60\xa1\xfe\xe6\xfa\x44\x9a\x37\x7f\x12\x57\x5d\x48\x01\xb5\x14\x50\x1b\x43\x29\xa0\x36\x8e\xba\x01\xb5\x1b\x3c\xfb\x29\x9a\x36\x44\x94\xaf\xfd\x20\x50\x83\x18\xf9\xda\x87\xd5\xe9\x72\xeb\xf1\x6e\x83\x48\xfb\x5d\xc0\xbc\x07\x67\xa7\xfc\x5a\xdc\x69\x9b\x8d\xe5\xeb\xde\x58\x0d\x63\x89\xe1\xb2\x28\x80\x71\x5f\xe5\x85\x83\x6c\xeb\xbb\x59\x77\x12\x10\x85\xc5\x0c\xd6\x7e\xf0\xd3\xba\xdc\x42\xb7\xf2\xb3\x02\xac\x94\x30\xba\x7e\x8d\xa5\x3f\xdb\x72\x0d\x77\xb6\x82\x83\xd2\xb8\x48\xab\xaa\xd0\xac\x2c\x28\x04\x5c\x64\x2d\xec\xb0\xa8\x28\x10\xa5\x44\x66\x4b\xef\x34\xd5\xc5\x0a\xa2\x7c\xde\xdf\xdd\x14\x70\x56\x35\xb9\x43\x14\x72\x46\x73\xca\x33\x8a\x05\xdc\xc6\x96\x6e\xb3\x54\xef\xa4\xd9\xc6\xac\xcd\x1b\xbe\x6e\x72\xa6\xea\x2a\x7f\x7e\xcb\xbf\x67\x9c\xff\xbc\x49\x22\x46\x4c\x39\x90\x65\x9b\x2b\xe2\x25\x39\xd1\x6e\x6d\x3c\xf9\x04\xd3\x71\xc4\xbc\xc5\x5d\x78\x65\xf5\x84\xdd\x5c\x42\x6f\x0b\x0d\x8a\x31\xe0\xc2\xb9\x73\x4d\x68\x26\x24\xa4\x35\x94\xbd\x16\xa0\x59\xef\xc9\xe3\x89\x00\x45\x43\xcd\xf5\x41\x53\x3d\x38\x8a\xdc\x37\xd3\x9f\x9e\x99\xfd\x08\x26\xf6\x80\x79\x6d\xcd\xe3\x20\xae\xa1\xa6\x75\x14\xb3\x3a\x86\x49\x3d\x64\x4e\x07\xa4\xc1\xb6\xd4\xc3\xa6\x45\x31\x81\xc3\xcd\xdf\x70\x20\x59\x29\xe9\x9c\x7d\x8a\x22\x33\x2f\x79\xb3\x80\xc0\x72\xca\x35\x9b\xb3\x90\x7e\xc2\xc2\x0c\xae\xa4\xdc\x16\x9c\x22\xd9\x12\xed\x82\xc0\x0e\x46\x2d\x90\xfc\xa9\xa5\xc1\x59\x17\x4d\x4c\x05\x76\x13\xcb\x39\x95\xb4\x57\xd2\x5e\x49\x7b\x1d\xa2\x27\xaf\xbd\x9c\x3c\xa8\xaf\xec\x9f\x57\xfd\x60\xed\x96\xd0\xf2\x34\xaf\x3b\x95\xc3\xf0\x8c\x7b\xbb\x6b\x8f\x3f\x7b\x6d\x5d\xbe\x0b\x7c\xae\x07\x76\x20\x60\xbb\xe1\x23\xaf\xab\xa2\x18\x5f\x15\xde\x52\x7f\x02\xaf\x70\xe6\xca\xaa\x28\x5c\x21\xef\x29\x7c\xf0\xea\x28\x2b\xe6\x70\x59\xdc\x93\x8d\x3a\x87\xf7\x74\x4d\xe5\x39\x5c\xcd\xdf\x0b\x7d\x6d\x2f\xaa\x3e\x4a\xb5\x9b\x27\x69\x59\x03\x9b\xc3\xcb\x82\x68\xaa\x34\x68\xe2\x73\x50\x99\xea\xf6\x39\x13\xb2\x37\xc8\xb6\xe5\x68\x9c\xf6\xee\x63\x85\xfa\xce\xc6\xfa\x65\x5d\x71\x72\xf2\x19\x36\x5a\xc1\xe6\x34\xdb\x64\x45\xe8\x19\x7d\x5b\xf3\xa9\xeb\x2a\x91\xa2\x10\xf7\x5e\x62\x07\x01\x3b\x03\x45\x3e\xbf\xa8\x36\x2c\xa5\x50\xfa\x46\x13\xa9\x23\xf4\x62\x39\xb9\xae\x99\x99\xc9\xcd\x48\x51\x78\x8b\x73\xb6\x5a\xd1\x9c\x11\x4d\x8b\x0d\x90\xb9\xa6\xb2\x5b\x51\xd8\x97\xa7\xb2\x55\xbc\x5d\x21\x5a\xec\xb4\x4d\x78\x5e\x50\x09\x73\xc2\x0a\x6f\x8c\xcf\x8e\x13\xd7\xf6\x08\xf7\xea\x28\x62\xc9\x82\x23\x5d\xd5\x5c\x20\x59\x26\x64\x8e\x45\xb9\x04\xf8\x83\x51\x1d\xc3\x56\xb0\xa2\x0d\xb5\x22\x9c\x2c\x68\x40\x09\x85\x6d\xf4\x2d\xcc\x0a\x91\xdd\x29\xa8\xb8\x66\xbe\xb6\x99\x6d\x82\x2e\xee\x20\x13\xab\xb2\x40\xf1\x14\x56\xd8\x0f\x1e\x2e\xee\x37\x24\xf3\x9a\x7f\x4e\x1a\xd1\x33\x31\x63\x52\x17\xbf\x6c\xff\x84\xbf\xf0\xb3\xf4\x82\x6f\x22\xe1\xf7\x10\xfa\x89\x66\xfe\xd6\x61\xef\xe8\x7f\xe0\x14\x77\x6d\x50\xdf\x6d\x00\xc1\x1b\x38\xf7\x5c\x18\xc1\x6c\x76\x7d\x60\x13\x5e\xe8\x55\xf3\x9f\xc2\x9b\x4f\x34\x6b\x7e\x0e\xb9\x90\x98\x51\xda\x06\x04\x58\x7b\x96\xdc\x05\x94\x04\x88\x02\xb5\x89\x03\x72\xf1\x2e\xd5\xd8\xa5\xad\x1e\xb1\xc8\x31\xa4\xbe\x81\x25\x2b\x68\x2c\xb3\x82\xf1\xd1\x8d\x62\x76\xc9\x15\x82\x04\xc6\x95\x6d\x58\xd7\x91\x64\xa1\x30\x01\xc3\x6c\xa7\x25\x6e\x20\xcf\xba\x5d\x52\x3d\x0b\xe1\x73\x2a\x85\xd0\x70\x7a\x72\x71\x72\xb6\x13\xd3\x0d\x84\xa0\x99\xdb\x75\x41\xd5\x46\x69\xba\xb2\xe5\x65\xdc\xa8\x03\xb9\x32\x6c\xa2\x5d\x62\x07\x65\x9a\x9d\xe4\xe7\xc0\x42\xe1\x04\xce\x16\xb4\xbd\x4a\x70\x27\x84\xe5\xa6\x80\xad\x27\x7a\x0e\x4a\x80\x96\x24\x67\x51\x30\xe2\xc8\xd3\x0c\x50\xcb\xca\x35\x3e\x39\x3d\xf9\x69\x64\x1f\xaa\x5d\xa2\x3a\x3b\x83\x7b\xc1\x4f\x34\x6e\xd7\x29\xdc\x86\x9e\xaa\x4a\xd1\xba\xa4\xaa\xed\xea\xc4\x69\x38\xac\x42\x74\x9b\x3a\x19\xe3\x12\x44\x15\xba\xee\x58\x33\x9c\xe8\xba\xfa\xeb\x9b\x4f\xc1\x3b\xc9\xe6\xa5\x1a\x25\xf6\x1c\x4d\x41\x6b\x70\x06\x32\x25\x0a\x0a\xb6\xa6\x17\x4b\x4a\x0a\xbd\xdc\x40\xf8\x19\xe2\x82\x4f\xfe\x4e\xa5\xc0\xfa\xb4\xdc\xf1\x0d\xc3\xe2\x85\x84\xa5\xbb\xe4\x1d\xa2\xde\x1d\x4c\x90\x07\xcd\xd8\x8b\xdf\x50\xcf\x7b\x11\x6c\xeb\xc0\x3f\xde\xde\x5e\x7f\x43\x75\x34\xc3\xc3\x8c\xae\x4e\xa0\xea\x34\x53\xfa\xcc\x16\x48\x38\xd4\x77\x02\xa5\x90\x9f\xdb\x04\x5a\x0a\x15\xb0\xee\xb0\xb3\xf6\x42\x69\xdf\xfa\x8f\x5d\xd2\xc2\xe8\x66\x4e\x33\xb3\xe2\xd1\x92\x89\x5d\xdf\x84\x52\xe4\x70\x75\x3d\x85\xbf\x88\xca\xcc\xe2\x8c\xcc\x82\x2c\x79\x43\xf7\x84\xeb\xba\xc0\xea\x33\x33\x09\xcf\x42\xc2\x65\x96\xcc\xbe\xff\x23\x25\x39\x95\x0a\x35\x21\x25\x9e\xad\x5f\x6b\x8a\x04\xc0\xec\x8c\x2b\xa6\xe5\x5c\x29\x2d\x56\xb0\xb4\x8c\xc3\x17\xba\x53\xea\xd6\xc9\x8e\x50\xfc\xb5\x91\x6b\xd6\x87\xa6\x40\xd2\x32\x86\xb6\x73\x6f\xfb\x33\xd2\x46\x3b\x9a\xc0\xee\x94\x40\xae\x35\xdf\x19\x76\x42\xca\x70\xab\x04\xb3\xb4\x93\x6f\xf6\x8a\x2b\x4f\x17\xcc\x91\x71\xbb\x49\x8c\x50\x09\x46\x89\x47\x4a\x49\x81\x48\x69\x29\x10\x52\xda\xb7\xcf\x04\x01\x96\x81\x5c\x62\x65\xb9\x40\xa4\x7c\x08\x18\x80\x01\x44\x60\xd9\xec\x52\x5b\xd3\x21\xc2\xf4\x43\x4c\x24\x3e\x84\x16\x11\xee\xd2\xe3\x4f\x5f\x8c\x8d\x07\xf1\xe6\xaf\x0c\x2e\x22\xb2\x5b\x42\x44\x0b\x20\x59\xe6\xd7\xbc\xa6\x4b\xc2\xaa\x4e\x14\x67\xb6\x53\xe4\x93\xb0\x3d\x8c\xc5\x1c\x71\xca\x2c\x9c\x44\x02\xaf\x56\xb3\x60\x25\xd5\xd4\xdd\x92\x3a\xf6\x32\x74\x8a\xf5\xbf\x8f\x31\xd4\x1a\x88\x50\x1b\x48\x84\x2f\x42\xcf\xc5\x0b\xf3\xce\xbf\xff\xdd\xef\x7e\xfb\xbb\xa9\x9d\x56\xf3\x8c\x40\x9e\x33\x0a\x84\xc3\xd5\xe5\xfb\xcb\x1f\x6f\xbe\x7b\x85\x35\x90\xc3\x76\x61\x84\x94\xec\x98\x09\xd9\x11\xd3\xb1\x1f\x31\x19\x1b\xcb\x4e\x05\x4a\xf8\x3e\xba\x06\x19\x86\x7b\xb4\x2b\x65\xcb\x1e\xbb\x9b\xa2\x0d\x1b\x46\xf0\x64\x9b\x3b\x71\xaf\x5a\x74\x84\x8b\xc3\x67\x97\x9e\x3a\x2b\x6f\x44\x76\x17\xcd\xcb\x73\x72\xfb\xea\xda\x32\x8c\xe2\xe8\x21\xbc\x0e\x30\x31\xbe\x16\xc5\xda\x2c\x26\x81\xdb\x57\xd7\x81\xca\x62\x6a\x78\x60\x84\xd5\xfa\xbd\x37\x41\xf9\x78\x4d\x81\x1d\x07\xd0\x63\xab\xb2\x08\x89\x28\x03\x56\x7c\x97\x94\x14\x4c\x69\x96\xe1\x58\x9b\x18\x6c\x90\x57\x47\xdc\xf9\xa3\xf2\x92\x7f\xac\xa5\xc8\xfe\xb1\x13\xbf\xd6\xfd\xbb\xd4\x38\xda\x3a\xae\xb2\x60\xa7\xc9\x79\xaf\x74\x4b\x78\x9d\x41\xe7\x68\x0b\x4b\x1c\x7e\xa2\x96\x23\x9a\x61\x7e\x0d\x1d\xbb\xc4\x3b\xbd\x66\x9c\xe5\x18\x1a\x41\x41\xbb\x73\xd7\x72\x0c\x64\xeb\x5e\xb8\x6f\x39\x86\xfa\x25\x8c\xdd\xb9\x63\x39\x46\xb2\x6d\x93\xe5\x78\x1c\x3d\x82\xe5\x58\x4a\x7a\xa3\x45\x19\x05\x67\x67\x59\x45\x45\xd9\xcd\xe8\x5c\x48\x1a\x07\x66\xd7\x02\xe0\x20\xaf\xa8\x6b\xda\xef\x5f\x1f\xb3\x0e\x73\x89\x2e\x5c\xcd\x3b\xf1\x1a\xd0\x64\xb1\x7d\xfe\x0b\xb6\xa6\x9c\x2a\x75\x81\xd0\xb8\xaa\xb4\x4e\x4a\x4f\xa6\x73\xc2\x8a\x4a\xd2\x73\xb3\xd2\x74\x55\xda\x5e\xf2\x81\xa5\xfa\xcc\x62\x50\x6e\x59\x51\x6d\xdb\xbb\xd7\xa8\x45\xff\xf5\x31\x36\x9f\xdd\x38\xb6\x2f\x69\x78\x73\xa6\x4c\x12\xb5\xa4\xd8\x92\x91\x7e\x62\x5a\xd9\x81\x4a\x4a\x94\x77\xa5\x5f\x84\xba\xb8\x8d\x84\x26\xb0\x82\x92\x28\x45\x73\x7f\x6d\xd0\x81\x7c\xda\x01\x5e\x8b\xfc\xe4\x44\x75\x1f\xe3\xc9\x79\x21\x49\x46\xa1\xa4\x92\x89\x1c\xb0\x76\x76\x2e\xee\x39\xcc\xe8\x82\x71\xdf\x1b\x80\x3b\x91\x66\xd0\xf5\x81\x37\x26\x2c\x0d\x00\x52\xd5\x7d\x6f\xa7\xf0\xb1\xd7\x97\xd3\x5f\x6b\x89\x4a\x67\xa2\xd5\xd6\x6e\x76\xcf\x03\x38\xb6\x48\x52\xcc\xb9\xc7\x63\x5e\x91\xa2\xd8\xb4\x62\xc5\x93\xb3\x2b\x2f\xa1\x1f\x6b\xe1\xbf\x30\x4c\xad\x39\xac\xa1\x1c\xbb\x07\xb4\x3b\x15\xfe\xb2\x49\x52\x92\x2d\xc3\xd2\x15\x12\x74\xf7\x00\x25\xe8\x6e\x82\xee\xee\xa5\x04\xdd\x4d\xd0\xdd\x04\xdd\x4d\xd0\xdd\x04\xdd\x4d\xd0\xdd\x91\x94\xa0\xbb\x87\x28\x41\x77\xf7\xd2\x93\x0c\x4d\x24\xe8\x6e\x82\xee\x1e\x4d\x09\xba\x9b\xa0\xbb\xe3\xf8\x26\xe8\xae\x17\x25\xe8\xee\x83\x94\xa0\xbb\x21\x94\xa0\xbb\xbe\x94\xa0\xbb\xa3\x29\x41\x77\x13\x74\x37\x80\x12\x00\xc3\x83\x12\x74\x37\xc2\xc5\xe1\xb3\x4b\xcf\x04\xdd\x4d\xd0\xdd\x23\x29\xf9\xc7\x5a\x4a\xd0\xdd\x00\x4a\xd0\xdd\x83\x94\xa0\xbb\x09\xba\x1b\xc0\xeb\xe9\x59\x8e\x35\x44\xf4\x5a\x8a\x59\x68\xf1\x51\xe4\xa1\xb0\x3f\x75\x2a\x3d\x1a\x80\x61\xda\x8b\x5f\x02\xe1\x55\x2d\x18\xda\xdb\xee\x36\x76\xa9\x8f\x40\xf2\xe4\xdd\xc7\x2d\xf5\xd1\x47\xbe\xe6\xaf\x37\x66\xe9\x09\xa0\xd7\x82\x71\x4a\x7b\x30\x4a\x81\x22\x7c\x0b\x9f\x54\x23\x8c\x02\x38\x0e\x62\x93\x02\x47\xb9\x83\x4b\xaa\x91\x45\x11\xde\x1c\x01\x98\x5d\x54\x51\x60\xa8\xbb\x83\x47\xea\x22\x8a\x02\xb8\x76\xb0\x48\xbb\x68\xa2\x90\x95\xd2\x43\x48\x22\x07\x84\x09\xb9\x61\xf5\x50\x44\x03\x38\xa0\x00\xde\x88\x20\x8a\x8c\x01\x1a\xc4\xff\x84\x19\x71\x03\xd8\x9f\x1a\xbd\x13\x32\xb1\x2d\xee\xa7\x8b\xdc\x09\xd9\x02\x0d\xe6\x67\x1b\xb5\x13\xe4\x07\xc8\x63\x23\x76\x62\xc4\x47\x83\x63\xa3\x81\xe6\x9a\xcb\x95\xb9\x5d\x4a\xaa\x96\xa2\xf0\x54\x05\x3d\x35\xf0\x8e\x71\xb6\xaa\x56\x46\xe6\x28\x23\xb7\xd9\x3a\x30\x91\x47\x35\x90\x4d\x8c\x7f\xda\xc0\xaa\xb7\xc6\x43\x89\x22\x69\x8e\xdc\xcd\x16\xc3\xaa\xe6\x4b\xb2\xf6\xb7\x77\x55\x95\x65\x94\xe6\x34\xef\x39\xf7\xe0\xb7\xd3\x7a\x2e\x3c\xf9\xda\x5e\x8f\x4c\xc1\x8b\x10\x0b\x23\xe4\x5a\x30\x17\x72\x45\x34\xf2\xf8\xed\x6f\x3c\x38\x04\x01\xc0\x1e\x05\xfc\x15\x1d\xf8\x15\x6c\xc6\x85\x39\xb4\x02\x9c\x59\xe1\xf6\x63\x98\x13\x6b\x18\xe0\x15\xa6\xe3\x86\xc0\x5d\x61\x1c\x1f\x01\xd8\x35\x08\xea\xea\xc2\x9f\xc2\x2c\xdd\x30\x40\x57\x24\xd8\x67\x30\x90\xeb\x71\x40\x5c\xc3\x00\x2e\x94\x2e\x21\xc6\x45\x1f\xbc\x15\x0e\xbf\x7a\x12\xa6\xc5\x63\x40\xae\x76\xe1\x56\x6e\xb2\xc2\x5c\xb9\x0d\xd4\x2a\x1e\x54\x2a\x12\x4c\x2a\x06\x44\x2a\x18\x1e\x15\x0e\x8d\x8a\x05\x8b\x8a\x01\x89\xda\x69\x68\x18\x61\x07\x41\xdd\x83\x2e\x0a\xc8\x38\x96\x0b\x35\x0a\x04\xea\x71\xa7\x2b\x06\xf4\x29\xc2\x7c\x85\x41\x9e\x1e\x07\xee\x14\x13\xea\x14\x63\x8a\x82\x02\x55\x8f\x03\x6f\x1a\x84\x36\x81\x77\x12\x38\x6c\xbb\xbb\xa6\xdd\xf0\x52\x00\xd3\x2d\x48\x53\x37\xb4\x14\xc0\xb5\x81\x33\xc5\x0d\x2b\x05\x86\x94\x62\x85\x93\x22\x85\x92\x1e\x09\x80\x14\x0a\x3e\x1a\x06\x1e\x19\x1b\x24\x60\x43\xec\x80\x8e\x5a\xd8\x50\x00\xd7\xae\x4f\x22\x0c\x32\x14\xb8\xa0\x8c\x33\xcd\x48\xf1\x9a\x16\x64\x73\x43\x33\xc1\x73\x4f\x6b\x62\xab\xed\xae\x0b\x99\xcf\x41\x59\xa6\x9e\xef\x67\x3d\x41\xfd\x82\x0f\x4b\xa2\xc0\xf5\x7f\xf3\xe4\xea\xaa\x87\xd4\xe1\x4b\x67\x98\x62\xec\xd1\xce\x87\xf6\x8f\x67\x8d\x2c\xcd\x70\x2f\xe4\x5d\x21\x48\xae\x2e\x4a\x61\xff\xaf\x2d\xcc\xd0\xa9\xc8\x60\x47\x18\x52\x92\xe1\x73\xba\x9c\x6c\xdd\x8b\x78\xdb\xeb\x8f\xe2\x1e\xc4\x5c\x53\x0e\xa7\x8c\xd7\x3b\xec\xcc\xd7\xfb\xd4\x38\x9b\x5a\x7f\x66\xe3\x34\xf4\xe7\xf9\xe2\x79\x3d\xb0\xc6\xe5\x18\x64\x98\x7d\xc9\x2e\x47\x74\xc6\x2a\xf5\x34\x3d\xda\x6e\x70\x8f\xe5\xd2\x76\xec\xe7\x55\x61\x85\x99\xaf\xff\x06\x9d\xe1\xce\x41\xde\xf7\x69\x7b\x6e\x0b\x68\xba\xea\xbf\xc0\x37\x6f\xa4\x21\xe1\x39\xb8\x9a\x5f\xde\x9c\xbb\x1b\xfe\x8b\xde\xba\x81\x50\xda\xc7\x82\xd1\xee\x85\xd0\x5a\x20\xac\x27\xd7\x1d\xf8\x6c\x0b\x82\xf5\xe5\xd8\x87\xce\x76\x01\xb0\x01\x63\x6c\x34\x64\x00\xf8\x35\xc5\x08\xfc\xbe\xbb\x17\xe4\x8a\xe1\x82\x00\x93\x78\x0b\xe0\x1a\x2b\x17\xbc\x9f\x07\x1e\x0a\x94\x7e\x32\xb7\xfd\x1a\x92\x1a\xea\x1b\x4b\xb7\xfd\x74\xdb\x3f\x40\x8f\x70\xdb\xd7\x6c\x45\x45\xa5\x9f\xec\x85\xf3\x7e\xc9\xb2\x65\xd7\x16\x64\x2b\x6f\x55\x2d\x2a\xbd\x65\xaf\xb9\x21\x46\x84\x22\xa4\x5b\xe7\x16\xf9\xc5\x34\x06\x1c\xaa\x56\x3c\x36\x78\x62\x8f\x17\x69\x1d\x17\x0d\x56\x16\x88\x02\x02\xaf\xdf\xdf\xfc\xf8\xf6\xf2\x3f\xdf\xbc\xf5\x11\x34\xb7\x4b\xa6\xac\xca\xac\xc5\x57\xc5\xd9\xdf\x2a\x0a\x64\x25\x8c\x2d\x58\x04\x0d\x55\x9d\xa3\x23\xa4\xf3\x0b\xcf\xe2\x4c\x31\x81\xd8\x5e\x62\xcc\x28\x36\x0f\x01\xd3\x8f\x3e\x18\x1e\x4f\x10\x99\xee\x17\x8b\xf6\x8e\x41\x6f\x01\x8b\xdd\xe8\xcd\xe4\x80\xa4\xa5\xa4\x8a\x72\x4f\x4b\x8d\x00\xa7\xda\xc8\x24\x6b\x87\x30\x0e\x04\x14\xe3\x8b\x22\x30\xa7\x25\xd0\xc6\x0f\xb1\xf0\x27\xed\xc8\xaf\xfd\x0c\xfd\x50\x33\xbf\xf7\x7c\x5f\x63\x64\xd0\xe8\x9c\x87\x25\xeb\xd9\x92\x77\x42\xd1\x3a\x1a\x57\x8a\xfc\x44\xc1\x95\x3f\xda\x83\xe4\xb9\xa4\x0a\x0b\x6b\x33\xd5\xda\x73\x46\x43\x32\xff\x4a\x2f\xb8\x17\x6d\x38\xed\x1c\x9e\xc3\x1f\xe0\x13\xfc\x01\x4d\xce\xdf\xfb\x5a\x86\x31\xcc\xba\x50\x87\x86\xbd\xfd\x5d\x5d\x47\xd9\x11\x7f\x5e\x12\x8d\xfc\xe0\xea\x3a\x04\xd2\x35\x63\x3c\xb7\x8a\xf6\x93\xa6\x92\x93\xa2\xbe\x90\x84\xcd\x74\x80\xe1\x6b\x5e\xea\xc9\x1f\x1c\x9b\xbc\x7e\x35\xf7\xe6\xd8\x58\x24\xe7\xa0\x7b\x47\xc7\x9b\x23\x1e\xb9\xc1\xa3\xe3\xcd\xd2\x1e\x39\xb8\x9a\xa3\x87\xe1\xbd\xd3\x14\x4c\x75\x46\xef\x3f\xa5\xcd\x5b\xaf\x88\xce\x96\x7d\xb5\xe6\x7f\x01\x7c\x67\x8e\x44\xc7\x78\xca\x05\x9a\x0e\x41\xf5\x42\xcd\x50\xbf\x6c\xc1\x13\x02\x34\xea\x9d\xa7\xab\xf9\xf6\xce\xf5\x9e\xd5\x7d\x97\xff\xa0\x62\xa4\xce\x14\xef\xd4\xd4\x2f\x45\x3e\x85\x37\x24\x5b\x7a\xf3\x34\x93\x97\x77\xec\xa3\x52\xe4\x76\xf0\x4b\xe2\x1d\xfa\x30\x96\x97\x1b\xab\x61\xef\x8a\xb9\x84\xa6\x4c\x59\xd1\x6d\x34\x43\x46\xb8\x99\x5b\x49\xe7\x54\xca\x90\xad\x2f\x60\xb6\x41\xbc\x0e\xcb\x68\xe0\x21\x08\xd0\x09\xa5\x14\x5a\x64\xc2\x3b\x9f\x7f\x3b\xdf\x15\x99\xe1\x74\x87\x38\xed\xdb\x38\xce\xb7\xaf\xaf\xcf\xe1\xf6\xd5\xf5\x39\x08\x09\x37\xaf\x42\x50\x05\x5d\x7f\xc5\xb3\xdb\x57\xd7\xcf\x3e\xc3\xa4\x4b\x4a\x72\x96\xd2\x8b\x87\x29\xa5\x17\x1f\x47\x29\xbd\xb8\x4f\x29\xbd\x38\x80\x67\x4a\x2f\x4e\xe9\xc5\x96\x52\x7a\x71\x4a\x2f\xf6\xa4\x94\x5e\x7c\x78\x70\x29\xbd\xf8\x8b\x05\x4c\xa5\xf4\xe2\xc3\x94\xa0\x43\x29\xbd\x38\xa5\x17\xef\x50\x4a\x2f\xfe\xdc\xa6\x45\x4a\x2f\x4e\xe9\xc5\x35\xa5\xf4\xe2\x11\x94\xd2\x8b\xc7\x51\x4a\x2f\x3e\x48\x4f\x0c\x70\x9c\xd2\x8b\x13\xe0\xf8\x58\x3e\x4f\x0f\x70\x0c\x29\xbd\xd8\x8f\x52\x7a\xf1\x78\x4a\xe9\xc5\xe3\x28\xa5\x17\x8f\xe7\x99\xd2\x8b\x5b\x4a\xe9\xc5\x29\xbd\xf8\x0b\xdd\xba\x29\xbd\x38\xa5\x17\x0f\x53\x8a\x11\xa4\xf4\xe2\x71\x94\xd2\x8b\xfd\x99\xa6\xdb\xbe\x3f\x9f\xa7\x77\xdb\x4f\xe9\xc5\x29\xbd\xf8\x20\x85\x98\x6e\x92\x2a\x51\xc9\xcc\x47\x45\xf6\xf6\xd5\xc7\x9a\xcf\x63\x02\x93\xe1\x4d\x8c\xec\x65\x85\xf8\x34\x55\x9a\x81\xca\x76\xd8\x85\xa4\x24\xf7\x89\x58\x9a\x17\xcd\x30\x74\xda\xaa\xd0\x2f\x0a\x43\x5d\xb0\x15\xf3\x49\x2d\x86\x1d\xe1\xf2\x16\x39\xb5\x81\xd2\x00\x9c\xcb\x8a\x7c\xc2\x9b\x11\x59\x89\x8a\x6b\x23\xaf\x32\xb1\x2a\xfd\x91\xb4\xdd\x95\xc6\x8d\xd9\x95\x05\x01\x58\x81\x43\x12\x24\x13\x7c\xce\x16\x95\x24\x66\x8a\x2e\x56\x84\x93\x05\x9d\xb8\x57\x99\x34\x83\x9a\x34\xbb\xf3\xe2\x33\x59\xe9\x24\xaf\xf1\xa5\xd7\xc1\x66\x73\x49\xb4\xa6\x92\xbf\x84\xff\x3a\xfd\xeb\xaf\x7f\x9a\x9c\x7d\x75\x7a\xfa\xfd\xf3\xc9\x7f\xfc\xf0\xeb\xd3\xbf\x4e\xf1\x1f\xff\x7a\xf6\xd5\xd9\x4f\xf5\x0f\xbf\x3e\x3b\x3b\x3d\xfd\xfe\x4f\xef\xbe\xb9\xbd\x7e\xf3\x03\x3b\xfb\xe9\x7b\x5e\xad\xee\xec\x4f\x3f\x9d\x7e\x4f\xdf\xfc\x70\x24\x93\xb3\xb3\xaf\x7e\xe5\x7d\x4b\x0c\xb0\x43\xe2\x58\x21\x51\x6c\x90\x47\xb0\x40\x1c\xcc\x24\x8a\x78\xf8\xe8\x78\xc5\x11\x10\xce\x75\x12\x5f\x40\xd4\x17\x56\xcc\xd4\xac\xc7\xec\xef\x8d\x14\x2b\xa6\x8d\x76\x30\x6a\x8d\x74\x20\xfc\xbe\x1c\x75\xaf\xdf\xa9\x13\xb9\x6c\x1e\x82\x85\x66\xaa\x0b\xb0\xee\x64\x24\x0a\xbd\xa4\xf2\x9e\x79\x07\x86\xcc\x4d\x89\xb7\x6e\x0d\x14\x82\x93\x9c\xce\x19\xf7\xf6\x94\xa0\x35\x37\xda\x90\x4b\x62\x38\x89\xe1\x31\x5c\x9e\x92\x18\x56\x34\xab\x24\xd3\x9b\x57\x82\x6b\xfa\xc9\xc3\x33\xd2\x8f\xf7\xf6\xb9\xb9\x8c\x15\x4f\xbb\xf7\xde\xc9\xb5\x2f\x3e\x8f\x10\x5f\xe6\x5a\xb2\x35\x2b\xe8\x82\xbe\x51\x19\x29\x50\x54\xc4\x50\x7b\x97\x7b\x78\xfb\xc7\x4c\xb4\x14\x85\x82\xfb\x25\x35\xe2\x19\x88\x79\x77\x74\x47\x65\xc4\x97\xe9\x82\x30\x0e\x2b\x23\x53\xcb\x7a\xa0\xca\x68\x14\x0e\xcc\x5b\xf7\x99\x1b\x16\xd7\xf5\xe0\x5c\x4d\x93\x99\x10\x85\x4b\x3b\xf3\xc6\x21\x37\x33\xc0\xac\x53\x8e\x8b\x1f\x39\xbd\xff\xd1\x8c\xdc\x77\xac\xf3\x82\x2c\xe0\x9e\x15\x05\xe6\x6a\x52\xbd\xd3\x89\xda\x77\x0e\xea\x97\x8f\xbc\x09\x30\xcf\xa8\xa2\x40\x8a\x7b\xb2\xc1\xad\x10\x67\xbc\x4c\xbd\x84\x17\x67\x98\xbf\x46\x14\x34\xe3\xcd\xe1\x37\xbe\x61\xe3\x25\x51\xf0\xea\xf2\xfa\xc7\x9b\xbf\xdc\xfc\x78\xf9\xfa\xdd\xd5\xfb\x10\xcd\x6a\x76\x0f\xf5\xda\xe4\x19\x29\xc9\x8c\x15\xcc\x5f\xa1\xee\x60\x11\xbb\x2c\x03\xec\xa3\x3c\xbf\xc8\xa5\x28\xed\x1a\xca\x8a\x73\xc6\x17\x41\x62\xd4\xd2\xeb\x7e\x53\xfc\xda\x68\x34\x9b\xdb\xd7\x41\x37\xef\xbd\x32\x2c\x24\xe1\xc6\xb0\x9d\x6d\x02\x32\x47\x5b\xb8\x8a\xac\xb8\x66\xab\x2f\x37\x21\x99\xe4\xb1\x92\x91\x2f\xf3\x9c\xe6\x31\xb6\xd7\x53\x04\xe3\xbf\xaa\x5f\x2b\x24\x0b\x05\xda\x42\x6d\x70\xfd\xe1\xe6\xea\x7f\xc7\x99\x2d\x70\x33\x16\x12\xd4\x09\x37\x1f\x8d\x34\x88\xb4\x93\x3e\xd2\x95\x58\xa7\xbd\x74\x80\x7e\xa6\x7b\xa9\xb1\xe4\x62\xe0\x88\x3e\x56\xbc\x23\xab\xbd\x93\xfa\xdb\x31\xc1\x4a\xe4\x74\x0a\xd7\xd6\x40\xa2\x2a\x0a\xcf\x6e\x99\x4f\x49\xc1\x30\xe6\x9a\x91\xc2\xdb\xd4\xa4\x7f\xab\xd8\x9a\x14\xd4\x26\xbd\x61\x59\x83\x6e\xc9\xb2\x08\xba\x79\x4e\x0a\x15\xa4\xf4\xfc\x6d\x22\x63\x9c\xbe\x13\x15\x8f\x81\xd9\x69\x78\x41\x4e\xb9\xd0\x41\xae\x3d\xf3\x5e\x58\x63\x4e\x8a\x0c\xac\x7b\x2f\x08\x9e\x5c\xe3\xd5\xba\xa1\xa4\xdb\xd6\x24\xf2\x37\xc1\xdd\x3a\x5e\x37\xef\x6e\xe3\xa1\x95\x0a\x7a\xfd\x1d\x93\x28\x14\xde\x61\xde\x5f\x52\x92\x63\x75\x9b\x92\xe8\xa5\xc5\xae\xad\x88\xba\xf3\x76\xc3\x21\x1b\x77\xa7\x73\x0e\x53\x5b\x94\xa6\x99\x8c\x5b\x7f\xe1\x37\xa7\x44\x57\x92\xda\x5b\x99\x4d\x90\xa3\x9c\xcc\x0a\x5f\xb4\x71\xa0\x20\x35\x73\xf7\x81\x17\x9b\x8f\x42\xe8\xaf\x9b\x0a\x24\x11\x0e\xcd\x9f\xdd\x0d\x1e\x8b\xf7\x85\x5e\xdd\x96\x58\x8b\xd9\x8c\x75\x82\x0b\x8d\xc2\x2a\xbc\x60\x8a\xdb\xe3\x66\xbb\x7f\x46\x51\x25\x2b\x7e\xa9\xbe\x91\xa2\xf2\xb4\x8c\x76\x2e\x6f\xdf\x5c\xbd\x46\x89\x5e\xf1\x80\xcb\x0b\xe5\x5a\x6e\x4a\xc1\x6c\xfc\x21\xaa\xbf\xe0\x5b\xa3\x12\xb7\xce\xbf\xaf\xa0\x9a\x43\xc5\x15\xd5\x53\x78\x47\x36\x40\x0a\x25\x6a\x27\x87\xb7\xca\xbd\x46\x94\x7a\xd7\x8f\x38\x05\x2c\x66\xe8\x7d\xb9\x64\x1c\x66\x42\x2f\x77\xdc\x93\xfe\xd5\x0b\x77\xc7\x88\x55\x93\x82\xc0\xe5\x6d\xe1\x73\xc6\xb7\x87\xea\x2b\xf1\xc9\x1d\x55\x50\x4a\x9a\xd1\x9c\xf2\x2c\xe8\x7c\x45\x42\x91\xfc\xfe\xdf\xfe\x3f\xf6\xde\x85\x39\x8e\xdb\x5a\x17\xfd\x2b\x28\x26\xa7\x48\xc6\x9c\xa1\xe4\xe4\xe4\xa1\x93\x8a\x8b\x21\x29\x87\x15\x8b\xe2\x15\x25\xfb\xee\xeb\x78\xa7\x30\xdd\x98\x19\x6c\x76\x03\x1d\x00\x3d\xe4\xe4\xea\xfe\xf7\x5b\x58\x00\xfa\x31\x33\xb4\xd4\x0b\xa0\x48\x3a\x8d\x53\x75\x6c\x29\xdb\x6b\xd0\x78\xac\x17\xbe\xf5\x2d\xec\x0d\xbd\x94\xc2\x2a\xc9\x04\x77\xf4\x42\xe4\x3c\xa3\xc6\x65\x21\x4d\x92\x04\x03\xe0\xd7\x7c\x66\x8b\x02\xa1\x8e\x55\x91\x48\xb1\xb5\x66\x0a\x1e\x08\x8d\xaa\x99\x3b\x58\x7f\xaf\x67\xac\x60\x06\xd2\x88\xf8\xc7\x2d\x9e\x53\xe3\xd8\xbe\x78\x49\x17\x8c\x50\x13\xd4\x00\x3e\xc7\xc4\x84\xb6\xe6\x14\x56\x92\x1b\x92\x4b\xd6\xd0\x54\x61\x93\x1d\x9a\x7c\xb8\x38\x23\x2f\xc8\x81\x5d\xc3\x43\xf0\x27\xe6\x94\x17\x78\xbe\x0a\x40\xd2\x6f\xf8\x3f\x7c\x1e\xa6\x8b\xb5\x5e\x17\x5e\xf7\x11\xa9\x9c\xf9\x3a\x22\x42\x12\x5d\x67\xcb\xb0\xd6\xf8\x1c\x6c\x48\x17\xfb\xaa\x18\x80\x94\x78\x05\x8b\x94\xd8\xa8\xe5\xfb\x14\x2c\x76\x6d\x9d\xd0\x5d\x0a\x16\xfd\x54\x97\xdf\xa7\x60\xa3\x50\x7a\x4f\x5c\xc1\x46\x3a\x30\x1f\x34\x53\x89\xfc\x97\x0f\x4f\xdc\x7f\xe9\x86\xb8\x56\x57\xb6\x3b\x8b\x77\x10\x9c\x42\x2c\x99\xa1\x39\x35\xd4\xfb\x35\xb1\xbc\x9a\xdb\x3e\xd1\x78\xf9\x9e\xe6\xe5\x7b\x4c\xef\x46\xb3\xef\xb8\xa8\xef\x5c\x11\x47\xaa\x07\xa4\xeb\x73\x10\x0a\x97\x2e\x62\x89\xe1\xe8\xd2\xaa\x2a\x78\x8b\x41\x8d\xea\x36\x42\x1a\xc3\xd9\xe5\x26\x8f\x57\x0e\x21\x9c\x01\xc3\x19\x60\xb3\x36\x66\xa5\x22\x97\x58\x74\xf7\xc6\x22\x3a\x38\x02\xcd\x96\xdd\xd2\x0a\x7b\xc9\xb1\x77\x6d\x54\x0d\xcf\x40\x35\x3c\xea\xc3\x5f\xc1\x56\x0c\x4d\xa5\xbe\xa1\x16\xbe\xb3\xb2\x08\xd7\xe1\x58\x47\xbc\x1e\xc0\xb4\x48\x41\x67\xac\x70\x9e\xbf\x53\x11\x09\x6a\xc4\xa2\x95\x4b\x92\x67\x32\x25\x8b\x54\x1c\x18\xef\x64\x01\x05\x22\x34\xc1\xb2\xdb\x69\xfd\x82\x57\x1d\x44\xa4\x59\xf5\xf7\xeb\x2a\xd9\xaa\xc3\x93\xc1\x2f\x77\xd5\x6b\x74\xe0\x40\x36\x57\xdd\xc6\x20\xa9\x56\x1d\x1c\xfb\x5f\xe6\xaa\xdf\x72\x91\xcb\x5b\x9d\xd6\xe1\xfb\xc1\x09\x0d\xd6\x14\x5b\xda\xad\x99\x31\x5c\x2c\x74\xd7\xe9\xa3\x45\x1c\xf6\xd2\x8d\x5d\x5e\x9f\xac\x62\x38\xc6\xe7\x4a\x3a\xbe\x90\x6d\xaf\x24\x32\xed\x52\x6b\x0f\xd1\xef\x78\x51\x58\x1f\x72\x3b\xe9\xbc\xcb\x8b\x8a\x78\xd3\x1b\xbd\xa8\x4f\x8d\x45\xa9\xe9\xa9\xb2\x1f\x61\x38\x2d\xae\x2b\x6c\x5f\x0f\xb2\x79\xf1\xbe\x7d\x73\x7d\xd2\x17\x1c\xa1\x9f\x38\x60\x2d\x95\x4b\xd0\x5a\xc9\x84\xe6\x25\xd7\x1a\x9f\x45\xb4\xe3\x96\xcd\x96\x52\xde\x90\x83\x50\xca\xb0\xe0\x66\x59\xcf\xa6\x99\x2c\x3b\x55\x0d\x13\xcd\x17\xfa\xd8\x2b\xa6\x89\x5d\x2f\x2c\x26\x13\xbe\x44\x14\x5c\xf8\x37\x5b\x88\x9d\x84\xd1\x44\xe2\x3b\xb0\x91\x76\x49\xb2\x66\xb5\xe1\xc4\x47\x88\x74\xbd\xa2\x1c\xc0\x70\xc7\x46\x5e\xc6\xd5\xf4\x03\x0b\xe4\xa3\xda\xf5\xed\x43\x7f\x19\x45\x32\xfa\x89\x83\x1f\xb9\x5e\xae\x39\x8a\x23\xa0\xf0\xf9\x42\xfb\x1b\x11\x12\x37\x4e\x8a\x4f\x16\x3e\x6e\x58\x11\x12\xb5\x09\x77\x02\x12\xb6\x5e\x64\xd4\x95\x6d\x3c\x88\x36\xf5\xdb\x49\xe2\x46\x88\xde\x4c\xff\x36\x89\xdc\x08\x99\x9b\x08\xe4\x24\x69\x60\xf2\x80\xa9\x60\xf2\xd9\xe9\xe0\x88\x1f\xe8\x3b\x2c\x89\xbc\x00\x72\x7f\xea\x27\x52\xa1\x3f\x98\xe3\x42\x92\x39\x2f\x24\xee\xe2\x7b\x0a\xaf\xb1\x37\xdb\xf6\x18\x7b\xb3\x7d\xde\x18\x7b\xb3\xf5\xc7\xd8\x9b\x2d\x26\x18\x18\x7b\xb3\x8d\xbd\xd9\x60\x8c\xbd\xd9\xc6\xde\x6c\xc8\x31\xf6\x66\xfb\xf4\xe4\xc6\xde\x6c\xcf\x96\x6d\x76\xec\xcd\xf6\xe9\x31\xf2\xae\x8e\xbd\xd9\xc6\xde\x6c\x5b\x63\xec\xcd\xf6\xd8\xae\xc5\xd8\x9b\x6d\xec\xcd\x16\xc6\xd8\x9b\x6d\xc0\x18\x7b\xb3\x0d\x1b\x63\x6f\xb6\x4f\x8e\x27\xc6\xd6\x3e\xf6\x66\x1b\xd9\xda\x3f\x57\xce\xd3\x63\x6b\x27\x63\x6f\x36\xdc\x18\x7b\xb3\x0d\x1f\x63\x6f\xb6\x61\x63\xec\xcd\x36\x5c\xe6\xd8\x9b\xad\x1d\x63\x6f\xb6\xb1\x37\xdb\x33\x3d\xba\x63\x6f\xb6\xb1\x37\xdb\xee\x31\xbe\x11\x8c\xbd\xd9\x86\x8d\xb1\x37\x1b\x5e\xe8\x18\xed\xe3\xe5\x3c\xbd\x68\x7f\xec\xcd\x36\xf6\x66\xfb\xe4\x88\x71\xdd\xb4\xc9\x39\xa2\x01\xc1\xc3\x30\x0c\x7a\xb4\x6c\x87\xb5\x61\x56\xcf\xe7\x4c\x81\xdb\x0d\x33\x45\x25\x6e\x76\x13\x5e\x3a\x62\xad\x25\xc7\x1c\x57\x8f\xf2\xd3\xcc\x1c\x01\x19\xa2\x76\x25\x88\x30\x45\x1c\xe0\xb1\x3f\x45\x4f\x5e\x01\xb4\xfb\x8a\x69\x5c\x7c\xcd\x05\x39\x7f\xfb\x7a\x9a\x80\x5c\x31\x86\x97\x08\xd6\xe4\xad\xc8\x62\x61\xef\xed\x21\x8b\xe3\x08\x09\xfc\x20\xfe\xac\x65\x85\xd4\x0e\x5b\xeb\x36\x2f\x5b\x52\x21\x18\x86\x5a\xcd\x29\x44\x6e\x20\xed\x36\x63\x4c\x10\x59\x31\xe1\x2a\xcb\x28\xd1\x5c\x2c\x0a\x8c\x05\xa0\xc6\xd0\x6c\x39\xb5\xdf\x2f\xc2\x01\xf3\x7d\x19\x9a\x59\x63\xae\x9a\x51\x8c\x96\xee\xa0\x29\x56\x52\xee\xa6\x4b\x68\xa6\xa4\xd6\xa4\xac\x0b\xc3\xab\x88\x09\x13\xcd\xa0\x60\x51\xbb\xea\xd9\x70\x08\x08\xea\xba\x69\xe6\xc0\x9e\xc0\x82\xd7\xac\x81\x5f\x5e\x94\x0b\xd6\x5e\x35\x08\xe0\x8f\xa0\x3b\x55\x59\x99\x35\xb1\xc7\x03\xb3\xfd\x80\xfb\xe7\x4a\x1b\x92\x15\x1c\x22\x38\x58\x07\x06\x96\x0c\xe6\x8c\x41\x00\x53\x91\x5b\xc9\xc2\xef\x91\xf6\x9b\x24\x72\x70\x40\x2b\x94\xc3\x0f\xc5\x4c\xf0\x99\xee\x32\xb9\xe9\xe6\x5c\xfb\x80\x42\xa3\x26\x1a\x78\x89\xdd\xe5\x0a\x7b\x04\xd7\x2b\x47\x12\x6c\x86\x6f\xf6\x42\x3a\x53\x8e\xb8\xff\x40\x25\xec\xb3\xe2\x8d\x09\x70\x24\xc0\x41\x41\xa2\xbe\x7f\xbb\xac\x2d\xd0\x4a\x82\x81\x40\x88\xec\x98\x14\xb8\xa6\x82\xad\xac\xf5\x62\x19\xe3\x2b\xeb\x84\x23\x44\xee\xb4\x07\x5f\xd4\x1c\x18\xaa\x16\xcc\x9c\x86\xb5\xc2\xd5\x3f\xf6\x49\x3c\xe7\xce\x0e\x6f\x54\x8d\x46\x29\x05\x58\xfa\x2b\x99\x5f\x43\xbd\xa8\xe3\x06\x45\x69\xae\x1d\xf5\x55\x7e\x09\x1c\x3d\x78\x22\x91\x81\xae\x00\xc7\xb5\xe9\x3d\x24\xbb\x78\xba\xa2\x19\xd3\xe4\xe0\xe2\xea\xf4\x88\x5c\x5d\x9c\xb9\xca\x00\x84\x4c\x39\xdf\x70\x07\xe1\xae\x79\xa7\x09\x54\x1a\x52\xc7\xee\xfa\x7c\xae\x7d\xc1\x05\x42\xe6\xed\x92\x1a\xb8\x58\x9d\xcf\xa7\xca\xfa\x07\x54\xb9\xc6\x63\xc8\x89\x56\x32\x9f\x92\x4b\x69\x58\x43\x2e\x9b\xc4\x6f\x81\x20\xdc\x67\x1b\xbd\xee\x72\x44\xe6\x58\xb7\x0e\x15\xf4\x1a\xa6\x4a\x2e\x80\xd8\xf4\x0d\xd3\x9a\x2e\xd8\x15\x0a\xc4\x72\x5f\x8a\x0c\x70\x2c\xc1\xa6\xa0\xad\x71\x01\x79\xb2\x36\x46\x6d\x2b\x89\xf6\x31\x97\xb9\xf3\xd1\xa4\x74\x5f\xdd\xdc\xbc\x5b\xc5\x8d\x41\x1d\x6a\xae\x5d\xfb\x01\xc0\xff\x6d\x52\xd3\xe0\x26\xda\xa9\x92\x22\x6f\xc2\x44\xdd\x04\xed\xcf\xd9\x58\x53\xe4\xa8\x54\xb5\x03\x2b\xce\x14\x67\x73\x32\xe7\x50\x8c\x04\x65\x33\x47\x8e\xee\x96\x62\x66\x4b\x05\xa1\x5a\x33\x05\xeb\xea\xcb\x26\xc2\xfa\x4e\xc9\x0f\x38\xa2\xe3\x19\xb3\xee\xa2\x70\x3d\xb3\x3d\xb7\x83\x90\x39\x23\x7c\x4e\x16\x50\xa0\x83\xbb\xd7\x54\x90\xdf\xbd\xf8\xd3\xef\xc9\x6c\x6d\x98\xef\xf0\x60\xa4\xa1\x45\x98\x30\x42\x68\xc1\xc4\xc2\x9e\x76\xe7\x79\xf7\x39\x76\xb0\x3c\xcf\x33\xe6\x3a\x6e\x3b\xde\x9e\x97\x5f\xdf\xcc\x7a\xa9\x15\x84\xc4\xe3\x9c\xad\x8e\x3b\x37\x60\x52\xc8\xc5\x94\x9c\x52\x61\x75\x3a\xea\xfd\xaf\xae\x72\xc0\x0f\x0c\x4f\x9b\xa4\x55\x5c\xb2\xe0\xd9\x3a\xd6\x09\xf1\x4c\xe2\x64\x29\x6f\x5d\x7b\x91\xf6\x77\x10\x4b\x13\xb4\x4b\x5b\x3e\x5c\xc9\xaa\x2e\x60\xb9\xc8\x6b\x8e\x8a\xcb\x40\x53\xd5\x9a\x6d\x92\xb1\xdc\xa3\xcb\x71\xca\x21\x4c\x73\x23\x9f\xe1\x94\x44\xc4\x42\x48\xcf\x64\xe0\x1f\x89\x1b\x2a\x70\x94\xdd\x23\xe4\x35\x2d\x8a\x19\xcd\x6e\xde\xcb\xef\xe4\x42\xbf\x15\xe7\x4a\x49\xd5\x5b\x21\xcc\x3d\xa6\x36\xf8\x5b\xd6\xe2\xc6\x35\x8a\x0e\x1f\x5f\xc8\x05\x91\xb5\xa9\x6a\x54\x12\x67\xbe\x79\x9c\x9a\x35\x99\xe3\xce\x41\x13\xe9\xfa\xd8\xb2\x33\x53\x76\xc7\x71\x2f\x98\xb7\xdc\x2a\x30\x41\x98\x5d\x47\xa7\x15\xdb\xaf\xc6\xc5\xfc\x1d\xf5\xf5\xf5\x8b\xdf\xfd\xd1\x29\x5c\x22\x15\xf9\xe3\x0b\xa8\xad\x46\x45\xa9\xe0\x0a\x80\xb7\xc7\x35\xd1\x25\x2d\x0a\xeb\x98\xc6\x29\x46\x7b\x1d\x3b\x8a\xb0\x51\x6b\x5f\x54\xab\x99\x58\x05\xf6\x80\x39\xdc\xf7\xef\xff\x0b\x12\xb8\xdc\x68\x56\xcc\x51\xc1\x75\xa1\x65\xdb\x00\x68\x1f\x62\xe2\x7d\xef\x8b\x18\x55\xa3\x54\xc0\xe3\x66\x45\x57\xb2\xa8\x4b\x76\xc6\x56\x3c\xc3\xbc\x4e\xf7\xb6\xae\x27\x0b\x4f\x60\x50\x70\x0d\x0c\xed\xb3\x42\x66\x37\x24\xf7\xe2\xda\xea\x14\x8c\x17\xb2\x8e\x25\x5a\x8c\xa9\x25\x42\xd7\x10\xdd\xbb\xba\x6d\x05\x10\xea\x9d\x86\x92\x92\x56\x15\x17\x0b\xbb\xcc\x94\x28\x7a\xdb\x5b\x6c\x94\x4c\xab\x79\xb9\xe8\xa6\x9f\x30\x97\x21\x12\xe3\x11\x83\xf0\x98\xf8\xaf\x47\xfa\x1c\xe8\xf2\xa2\x58\x70\x48\x3b\x6b\xec\xfb\x75\xef\x98\xb5\xe2\x62\x29\x48\x2a\x90\xe1\xb8\x27\x12\x35\x5c\x20\x6d\x0a\xc3\xcd\xb3\x09\x7b\xed\x81\x8e\xa0\xd9\x32\x12\x8b\x1d\x88\x7e\xb0\x8f\x29\xe6\xea\xed\x9c\x68\xa0\x11\x25\x35\xa8\x64\x85\x1b\xdd\xfc\x25\x25\x15\x53\x9a\x6b\xeb\xa3\x7f\x0f\x0a\xe8\xb4\xa0\x1c\xfb\xfe\xdd\x64\xf8\x2a\x89\xdd\xaa\x88\xe5\x76\x0a\x14\xba\xf5\xc5\x5a\xba\x2b\x99\x7b\x71\x60\x98\x20\x6d\x82\xca\x77\x6e\xa5\x59\x62\x99\x65\x92\xb9\x7f\x8f\x69\xea\xbe\x6f\x77\x2a\xde\xd2\x59\x29\x8d\xa9\x73\x92\xbd\xb1\x42\x4a\x7c\xbe\x06\x0e\xd6\xe2\xb9\xd9\xb7\x66\xd2\x49\x94\x24\x18\x36\xef\xab\xc4\x18\xb7\x36\x56\x6d\x1f\x1c\x97\xcc\x2b\x05\xb4\xd4\x36\xcd\xe2\x33\xb1\x53\x8f\xf9\x16\xe8\xd6\x6d\xcd\x54\xc9\xfe\xab\xfd\x47\x33\x72\x6e\x13\x95\xac\xe8\x02\x72\x07\x49\xf6\x72\x53\x28\x7a\x85\x72\xe6\xd2\x1a\x4c\x43\xda\x0c\xe4\xc2\xe3\x0b\xde\xf7\xf1\xb3\x62\x79\xcb\x09\xbe\x94\x40\x94\x92\xe2\xc8\xf9\x84\x89\x84\x48\xf9\x36\x82\xde\x80\x2a\x59\x8b\xdc\x83\x3a\x1a\x24\xd1\x9b\x8d\x85\xbd\xc4\x13\x11\x42\x9a\xc7\x91\x97\x43\xf7\x5c\x57\xef\xcc\x35\x99\x31\x43\x63\xdc\x88\x97\xd3\x97\x2f\x9e\xbf\xcf\x06\x6b\x92\xc8\x67\xbb\x6c\x7c\x36\x67\xe5\x1e\x6d\x75\x42\x07\xe1\x24\x2b\xf4\xc6\x3f\x49\x35\xad\x7e\xf1\x87\x26\xb4\xaf\x04\x51\xb7\x8a\x1b\x7f\x83\x6e\x79\x44\xbd\xe9\x01\x24\x6d\x88\x54\x5d\x4e\xde\xc3\x36\x97\x17\x11\x92\xc4\xb4\x20\x8e\xef\xe1\x47\x88\xae\x67\x4f\xce\xee\x3a\x03\xeb\x94\xea\xae\xf7\x54\xfc\x7a\x7b\xc9\xdb\x26\x18\x2d\xb1\x0b\x21\xde\xdb\x23\x07\xee\x17\xf6\x1d\x29\xe5\xe1\xa3\x5d\x4f\xbf\xad\xe7\x77\x15\xba\xcb\x4a\x6f\x6b\xcf\xef\x2a\x2a\x72\x96\xbb\x80\x3f\xc2\xb5\x26\x81\x85\x79\xd7\x1e\xc7\x9b\xcd\x7d\xdd\xdf\x63\xb4\xc4\xae\x7b\xf6\x57\xb6\xa4\x2b\x06\xd4\x9d\xbc\xa0\x2a\x42\x3d\x19\x49\xae\xdd\xce\x90\x59\x6d\x08\x13\x2b\xae\xa4\x28\x59\x04\xd3\xf9\x8a\x2a\x4e\x67\x05\x23\x8a\xcd\x99\x62\x22\x63\x9a\xfc\xfa\xe0\xfb\x93\x77\x50\x2d\x81\xef\xa7\x40\x15\x23\x2c\xec\x7a\xad\xa1\xca\x3e\xd1\x2d\xec\x7c\xf6\x74\xe3\x02\xe1\x55\xf4\xc6\xc5\x0b\xeb\x6c\x6f\x00\x7e\x0d\x44\xde\xec\x97\x5d\x8f\xb2\x36\x35\x2d\x80\xbd\x35\x2b\x6a\xcd\x57\x8f\x61\x7f\x3d\x9b\xee\x19\x47\xdc\xec\x0d\x16\xe2\xf6\xd2\x6c\x51\xf4\x62\x3e\x2c\x60\xae\xd2\xf5\x58\xf4\x38\xa4\x7d\x1d\x6a\xce\x7a\xbd\x72\xd0\x8f\x72\xa4\xe4\x8b\x25\x24\x50\x32\x29\xe6\x7c\x51\x2b\xc7\x87\x15\x8b\xe4\x03\x0e\xff\xc7\x7b\x9e\xb3\xc1\xc7\x49\xc1\xa9\x1e\x16\x86\x6f\xb1\x0b\x7a\x19\xd0\x53\x4b\xf8\x6e\x49\x74\x18\x30\x24\xbc\xef\xd8\x29\xb9\x07\xf4\x8b\x2b\x8f\x50\x0d\x3b\xc8\xc5\xff\xb0\x6c\xe8\x0b\x70\x93\x4d\xab\x64\xbe\xaf\xbd\x78\xc0\x5e\xf1\x39\x96\xf5\x1c\xfc\x73\xae\x1d\x1d\x3b\xf4\xd0\x86\x17\x44\x21\xc5\xc4\xca\xbf\x64\xc6\xde\x8e\x41\x22\x2b\x99\x0f\xe2\xb4\xc3\xa5\xe3\x10\x89\xb8\xdd\x7b\x4d\x96\xb2\xc8\x1d\xcb\xbb\x7f\x34\x1a\x78\x60\x67\xcc\xdc\x32\x26\xc8\xc5\x15\xec\xb5\x5d\x36\x40\x38\xf6\x76\x7c\xa0\xcc\x70\x3e\xa0\xb9\xbd\x70\x4d\x41\x3a\xb9\xe5\xb0\xfb\x03\xa5\xda\xb3\x32\xec\x78\xa0\xb3\x79\xf8\xa4\x58\xb3\x7e\x91\x1a\xfe\x6f\xcd\x3e\x04\x12\x05\x3a\x93\x28\x4a\x06\xbb\xb1\x79\xae\x50\xfd\x53\x1e\x25\xd7\x1c\x61\x60\x79\x15\x8b\xcf\x6a\x16\x2b\xbc\x89\x2d\x71\x45\xd8\xa0\xd8\xe0\xe0\x7f\x41\x0b\x72\x71\x75\x8a\xb6\x1e\xfb\x1f\x3c\xe4\xcb\x0a\xda\xdf\xd7\x84\x57\x59\x8b\x75\x1e\xf6\x11\x2d\x3e\x37\xa0\x27\x9a\x68\x79\x08\x88\x0f\x17\x22\x77\x14\x7f\x94\x29\x25\xc2\x09\xb1\xbe\x95\xe7\x50\x45\xe0\xbc\x01\x27\x03\x10\xef\xde\xfa\xea\x20\x1d\xbb\xc4\xa1\x20\xc5\x99\x78\x80\x29\x85\xe2\x86\x4a\x2a\xa3\x87\x33\xde\x77\xdd\xb3\xa6\x84\xbb\xb5\xcb\x28\x02\x1f\x4c\x92\x04\xbf\xeb\x57\x17\x67\xe9\x8e\x7f\xc5\xf3\x67\x7b\xfc\x87\xe6\x3f\xfb\x3c\x6f\xbd\xd6\x31\x41\x1c\xa6\x5a\xe6\x4a\xe6\xf7\x04\x16\xad\x13\x30\xf8\xd5\x2a\x1c\x53\x5f\xeb\x47\x89\x7b\x8c\x9d\xe4\x6c\xce\x05\xf3\x5c\x9d\xc3\xcf\xdb\x40\x6d\x0b\xe1\xc2\x55\x5d\x14\xd7\x2c\x53\x6c\xd8\x83\x75\xff\xdc\x5d\x6c\x48\x4a\xe1\xba\x77\xf2\x09\xc0\x05\xed\x05\x3b\x07\x4c\x0f\x5d\xf1\xe6\x16\x78\xee\x3f\xf0\x48\xaa\xba\x28\x80\x23\x47\xac\x31\x47\x03\xd6\xcf\xbd\x3c\x38\xf4\x17\xd7\xa1\x8e\xca\x15\x82\x36\xe7\x65\xa0\xb6\x65\x9a\x35\x1f\x1c\x8e\x4a\x45\xb5\x76\x08\x51\x2e\x72\xbe\xe2\x79\x3d\x70\x5d\xed\xc7\x42\x8c\xe8\x59\x77\xe0\xd5\xa5\xf1\xcc\x4a\x54\xa7\xc0\xd7\x52\x11\x76\x47\xad\xc8\xa3\xa6\xf6\x9c\x6a\xb8\x68\xb9\xcc\x6e\x98\x3a\x22\x83\xf3\xe9\x67\xf0\x1f\x9e\x42\x64\xec\xda\x50\x87\xb5\xa0\xca\xde\x65\x21\xd5\xd0\x10\x6b\x20\x11\x42\x5b\x92\x70\xec\xf6\xf8\x57\x6e\x2b\xd7\x5c\x2c\x26\xf0\x37\x76\x31\xfd\xac\x26\x52\x4c\xe8\xc4\x2a\x83\x27\x1f\x70\x7d\x27\x33\x5a\xbc\x85\x48\xe2\x5d\xb8\x5d\x21\x7d\x30\x34\x90\x61\x42\xd6\x8b\x25\x2c\xaa\x2a\xa9\x6f\xcd\x45\x0a\x66\xa0\x07\x8e\xc3\xc3\x0e\x14\xe9\x88\xde\xfd\xbc\x72\x1f\xf2\x74\x3b\x42\x0d\xbe\xf5\x04\x6b\xfd\x1e\x21\xe8\xc2\xbd\xf7\x6d\xf0\x9d\x74\x1a\x89\xfa\x95\x44\xd1\x7e\x0d\xbc\x2f\x72\xc5\xd4\x8a\xb3\xdb\x63\xef\x6a\x4e\x6e\xb9\x59\x4e\xdc\xea\xe9\x63\xd8\x82\xe3\x5f\xc1\x3f\x10\x73\x71\x64\x61\x27\x79\xee\x9f\xa2\x6b\xcd\xe6\x75\xe1\x1e\x79\xf5\x94\xd0\x8a\x7f\xcf\x94\xe6\x12\x55\x72\x7e\xc3\x45\x7e\x44\x6a\x9e\x7f\xf3\x85\x0a\x73\xb8\xe0\x6d\x41\x70\x84\xc5\xfd\xce\x5b\x49\xcf\xd4\xca\xff\xed\xae\x60\xab\xb9\x06\x7d\xce\x8c\x15\x52\x2c\x3a\x4c\xb6\xe0\xec\x5f\x08\x6e\xb0\x12\x5d\xfa\x1e\xba\xc1\x41\x6a\x53\xaa\x1c\x8a\xc5\xb9\x35\x37\x12\x3f\x4f\xe8\x33\xd8\x29\x68\xb7\xa6\x9b\xf7\xe6\x09\xa5\x32\x03\x0b\x26\x02\x17\x98\x2b\x07\x08\x24\x8d\x46\x92\x25\x5d\xb1\xa6\xff\xd0\xc0\xba\x7e\xae\xc9\x92\x8a\x1c\xfe\xd3\x2c\x93\x2a\xf7\xeb\xcb\x4d\x53\x95\xef\xca\xb1\x86\xa6\x0b\x3d\x74\xd2\x5a\x6e\x2a\x36\xbf\x1e\x32\x87\xaa\x1c\xe8\x1c\xb4\xff\x7d\x08\x9a\x6a\xc1\xff\x55\x33\x42\x4b\x69\x1d\xa4\x88\x5e\xf8\x1b\xa7\x88\x94\x74\x0d\xde\x34\x2c\xed\x77\x81\x5f\x68\xd8\xe1\x72\x8d\xe0\x8e\xc8\x3b\x46\x73\xde\x21\xeb\x3d\x22\xdf\xf5\xd9\x7b\x87\x1d\x03\xa9\xc8\xb5\xa3\xb8\xf4\xff\xb9\xab\xee\x51\x4c\xcb\x5a\x65\xec\x9d\x03\xc6\x59\xe7\x69\xd8\xb1\x95\xf3\x1d\x1b\x65\x6f\x88\xa1\x37\x4c\xb8\xa4\xb2\x3d\x22\x43\x11\x9e\x79\xad\xe0\x3e\x64\x4b\x96\xd7\xe0\xc9\xce\xd6\x64\x6e\xfd\x43\xff\x5a\xb6\xe4\x8b\x25\x1b\x98\xfa\xf1\x69\x82\x63\xa8\x49\x72\x7d\x53\x69\xb6\x6c\x16\x01\xd4\xde\xb0\x65\x6d\x78\x3d\xda\x67\xbc\x92\xde\xd9\x55\x01\x53\x45\x0d\x82\x02\xd7\xe7\x13\x75\x5d\x06\x7b\xe7\x4e\x7d\xf7\x98\x92\xef\xec\x27\x0c\xd7\x5b\xb4\xaa\x0a\x1e\x7c\xed\xfe\xe1\x85\xea\x03\xff\x0e\x3b\x48\xee\x9c\xea\x25\x97\x62\x4b\xa9\x92\xcc\x3d\xd6\x64\xb5\xb2\xc6\x7a\xa0\xab\x3c\x63\x84\xe6\xb9\xf5\x95\x14\x51\xac\x94\x2b\xab\x15\x23\x9f\x7f\xe2\x48\xc3\xec\x82\x4d\x3a\xfe\xf3\xd3\x77\x8a\x4f\x3c\x5d\x91\xdb\xf6\x6c\xc3\x8e\x0e\x76\x61\xa9\x73\x80\x43\xe7\x28\x55\x8b\xb6\x6c\xc5\x5a\xd5\x2f\xe3\x86\xe2\x30\xbc\x08\xfc\x2d\xde\xdf\xa5\x6a\x11\xfb\xbe\xb0\x7f\xa2\x16\x35\xa8\xe3\xe0\xb7\xb4\xad\xdb\x31\x6e\xaf\x55\xf6\x2e\x6c\x75\xb1\xfd\xfe\xbe\x26\xa7\x6f\xce\x02\xbc\x10\x21\x91\xfb\x0c\xa7\xe7\x50\xab\x94\x5c\x71\x68\x3f\xf8\xbd\x87\x4d\x60\x1e\xa5\x77\x02\x2d\x7a\x80\x09\x84\xd4\x5d\x10\x8b\x7d\xdd\xc3\x4a\xe0\x9e\xe4\x69\x0b\x11\xc9\x1a\xcd\x64\xad\x49\xb1\xc2\x3d\xa1\xf7\xc2\xc4\x90\x75\xe0\xa2\xaa\x0d\x1e\xb1\xd4\xe4\x8d\x45\xb6\xa4\x62\xe1\xa0\xa4\x2c\x12\xc8\xa2\xd7\xc2\xd0\x3b\xfb\xd5\x56\x34\xd3\x19\xad\x58\xee\xcb\x87\x49\x2e\x6b\xdc\xf6\xff\xfa\xd7\x47\x84\xb3\x57\xe4\xd7\x9d\xc9\x4d\xc9\xb9\x97\xde\x1e\x0e\xec\x2a\x38\xe6\xa5\x59\x7b\x98\x8e\x88\x62\x0b\xaa\xf2\x02\xd7\x64\x47\xce\xc9\x6d\x87\xce\xae\x39\x0c\xec\x8e\x6b\xa3\x09\x8a\x72\x46\x48\xb3\xcb\xce\x75\x6c\x17\x42\xe8\xcf\x58\x3b\x43\xf5\x8d\xb5\x6d\x56\x0f\x4f\x72\x6a\xe8\xa4\x63\x2c\x8e\x5d\xd6\x76\xe2\x9b\x2c\x4f\xa8\x57\x4a\xad\x19\x3c\xfe\x95\xaa\x85\xb0\x81\x31\x6d\xfe\xaf\xb8\x98\xd0\x09\xb4\xe4\xc5\x46\x9e\xcf\xe7\x45\x13\xdd\xbd\xbc\xaf\xed\xcf\x1b\xe5\xee\xbe\x1d\x18\x87\x10\x5f\xd2\xc4\xa5\x8d\x61\xf6\xad\x91\x5b\xfd\x8f\x51\xf5\xc1\x62\x9c\x5f\xbe\x7f\xf7\x5f\x57\x6f\x2f\x2e\xdf\x07\xc3\x11\xcc\x00\x46\xea\x7d\x86\x23\xee\xa6\xdf\x67\x38\x5a\x33\x10\x03\x44\xda\x34\x1c\x7d\x33\x80\x91\xbc\x6d\x38\xfa\x66\x00\xb3\xb2\xdb\x86\x63\x87\x19\x40\x7a\x11\xdd\xf5\xdd\x69\x06\x50\xda\xb9\x63\x38\x76\x9b\x01\x84\xd4\x6d\xc3\xd1\x37\x03\xa8\xfb\xb5\x6d\x38\x3a\x66\x00\x69\xf2\xb7\x0d\x47\xd7\x0c\x20\x84\xee\x36\x1c\xa3\x19\xf8\x9c\x1f\x45\x99\x01\x26\x56\x91\x26\x20\x64\x3d\x3b\xca\xa5\x39\x17\x28\x92\xb3\x5e\x93\xd9\x0e\x7d\x5f\x8a\x43\xf5\x3c\xf6\xb3\x0f\xb3\x17\xab\xef\xa9\x22\x8a\x55\x8a\x69\x88\xab\x90\x65\x1d\xbb\x36\x88\x78\xa1\x38\xea\x42\x42\x68\x8b\x18\x7e\x76\x55\xb1\x8f\x54\xd7\x9a\xac\x86\xac\xfb\xb0\x94\xb2\x6a\x60\xda\xb4\x1b\xa2\xe4\xf4\x9f\x17\x67\xe7\x97\xef\x2f\x5e\x5f\x9c\xbf\x7b\xb4\xc2\x95\xa8\x46\xae\x7d\x77\x35\x8d\xa7\xe6\xc6\xcf\xfb\x6b\x68\xb1\xae\x97\x01\x5b\x71\x59\x03\xc4\x1d\xc0\x27\x29\xf7\x57\x6f\xe9\x56\xb4\x48\xe0\x81\x16\x6b\x68\xd0\xca\xb3\xb4\xc7\x50\x4f\x77\x66\x2a\xd0\x72\x93\x3a\xaa\x6e\xfc\x8c\xbb\x8a\x96\x99\x34\xdb\xe1\xc6\xfd\x39\x0f\xfc\xc6\xa7\x76\x79\xdd\xf8\x59\xc7\x37\x66\xe7\xef\x71\x7f\xd1\x22\x7f\x26\x7b\x82\x96\x19\x9c\xe7\x7e\xf5\x13\xba\x11\x52\x1a\xb5\xfb\x5a\xc9\x32\x89\xea\xbd\x76\x2f\x55\x1e\xda\x84\x5e\xa4\x5d\x4e\xcc\xbe\x1e\x0e\xce\xeb\x8f\x4e\xda\xca\xa7\x06\x42\xcb\x16\xb4\x48\x2b\x0f\x68\x0e\xe3\xcc\x66\x54\x0b\xfd\x14\x7d\xe7\x5d\x35\xd4\x1b\x5a\xfd\x9d\xad\xdf\xb1\x88\x5e\x49\x9b\xe7\x81\x15\x2c\xb3\xce\x2c\xb9\x61\xf8\xe2\x49\xe2\x5f\x72\xc9\x69\x98\x66\x4c\x93\xa9\x04\x4b\x4e\xa2\xfb\xcd\xb9\x31\x89\x5c\x96\x14\x5b\x6f\xc7\x0d\x43\x97\xf3\x87\xb1\xd5\x42\x3f\x76\xc3\x49\x88\x12\xed\x09\x8a\xd9\x6f\x92\xa6\x5b\x9c\x1b\x31\x7e\x7d\x18\x3b\x91\x63\xf1\x6b\xd5\x45\x9e\x41\x5a\x25\x5a\xe4\x13\xc1\xa1\xf5\xc7\x6e\x54\x5a\xb4\xd8\x34\xa8\xb6\xfe\x88\xc1\xb8\xf5\x47\xb2\xf3\x1b\x80\xe1\x49\xcf\xb0\xc3\xfc\xc7\x5f\xf7\xae\xbf\xd5\xa8\xfa\x68\xa9\x8e\x13\xd6\xea\xa3\x00\xb1\x8a\x16\xe9\x03\xb6\x24\x9b\x1a\xc3\xe1\x41\xc2\xc1\x4d\x69\xb3\xf7\x1b\xa3\x1d\xf5\x7d\x8e\x0b\xa8\xe9\x67\x99\xbf\x0a\xed\x24\xe2\x54\x40\xc9\x0c\xcd\xa9\xa1\x53\xab\x4d\x8e\xfa\x7f\x04\xb8\x71\xdc\xb5\x6d\xe4\x15\x74\xc6\x0a\xdd\xf9\x01\x70\x1e\x1d\x74\x3f\xee\x27\x74\xc5\xb2\xa9\x90\x39\xbb\x84\x2f\x80\x3f\xfa\xd0\xfa\xc4\x41\xd1\xe0\x7f\x88\xfb\x0d\x60\x42\x9f\xba\xaa\xbe\xa3\xf0\xc7\x4a\xe6\x17\x57\x49\x04\x83\x24\x1d\xd1\xbe\xf5\x89\xb9\x61\x70\x58\x91\xdc\x79\x61\xa4\x72\xc6\x5a\x0b\x94\x54\x49\x7b\x99\xf1\xea\xd4\xdd\x68\x9d\x2d\x59\x49\xa3\xa2\xbc\x30\x5e\x87\xc5\x27\x5c\x47\x74\x38\xe9\x0f\x2e\x80\xcd\xde\xc6\xff\x49\xfa\x16\xbb\x61\x83\xf5\xd5\xcb\xbd\x27\xe3\x8e\x36\xe7\x36\xe9\x51\x81\xbd\x48\xe4\x92\x3a\x33\xd0\x38\xf2\x49\xf6\x75\xd9\xa9\x2c\x25\x27\x57\x17\xd1\x42\x57\xee\x6e\x3c\x89\x6d\x0d\x70\xdf\xd7\x4f\xd4\xae\x37\x70\xe4\x4d\xd6\xe7\xb8\x23\x08\x1c\x1c\x41\xb6\x76\x7d\x19\xe2\xee\x2b\x15\x79\x80\x54\x6b\x72\xe0\x04\x4e\xb3\xaa\x8e\x33\x80\x5e\x4e\xc9\x4a\xa9\xd6\x47\xe1\x8f\x4d\xbb\xb0\x89\x36\x52\xd1\x45\xa4\xf9\x0e\xd3\x86\xe9\xb6\x7f\x72\x3f\x9a\x6c\x51\xb6\x67\x8d\xcf\x3e\x13\x8f\xe0\x6e\xd0\xd4\xc1\xdb\x43\x75\xde\x69\xc7\x93\xf2\x12\xc2\xf1\x7c\x02\x4e\x42\x16\xd7\xda\xb0\x3f\xfa\x6a\xe2\x34\xfa\xc1\x28\x0c\x48\x96\x34\x6b\x8f\x6c\x72\xd7\x1f\x9e\x97\xfb\x08\x57\xe1\xbc\x6b\x40\x9d\x85\x58\x91\x15\x55\xc8\xd6\xda\xed\x48\x66\xd7\x73\xbe\xe2\x5a\x46\xaa\xd4\xfb\x2a\xf3\x93\xd8\x75\xdf\x74\xc7\xd5\xa0\xa6\x72\x2a\xd9\x5d\x05\x3d\x58\x1b\x3b\x10\x9f\x83\xc9\xbb\xef\x2c\x2f\xf1\x34\x73\x6e\x54\xd4\x18\xa6\xc4\x2b\xf2\xdf\x07\xff\xf8\xea\xe3\xe4\xf0\x9b\x83\x83\x1f\x5f\x4c\xfe\xf4\xd3\x57\x07\xff\x98\xc2\xbf\xfc\xe6\xf0\x9b\xc3\x8f\xe1\x0f\x5f\x1d\x1e\x1e\x1c\xfc\xf8\xf7\x37\xdf\xbe\xbf\x3a\xff\x89\x1f\x7e\xfc\x51\xd4\xe5\x8d\xfb\xd3\xc7\x83\x1f\xd9\xf9\x4f\x9f\x29\xe4\xf0\xf0\x9b\x5f\x47\x4e\x9c\x8a\xf5\xdb\x28\x57\x82\x80\x06\x8c\xef\x22\xbf\x2d\x2d\xc1\x75\x21\xe4\x6e\xd2\xa6\x27\x27\x5c\x98\x89\x54\x13\x27\xf8\x15\xf0\xc2\x26\x71\x79\xd2\xea\xd9\x77\x09\x6c\x52\x7f\x7e\xad\x9b\xfd\x24\x14\x99\x2b\xd3\x7f\xda\x2f\x4a\x6e\x8e\x3d\x76\xb1\xe8\xf7\x01\x48\x43\xfd\x52\x7c\x9e\xf1\x81\xea\xe7\x46\x48\x86\xb8\x53\x94\x2e\xca\x9d\x2b\x59\x86\xee\x00\x00\xd1\x02\x76\xc2\x68\xb1\x7e\x9e\x37\x0c\xfd\x5e\x1d\xc6\xf8\xa0\x86\x19\xe3\x83\x5a\xdc\x18\x1f\xd4\x86\x8d\xee\x83\x9a\x23\x88\x1a\x5f\xd3\x76\x0d\x26\x56\x38\x08\xd4\x4e\x8c\x7c\xc8\x61\x75\x1a\xd5\x22\xbe\x6d\x27\xd2\x7e\x1b\x30\x8f\x90\xec\x8d\x5f\x8b\x3b\x6d\xab\xb1\xb0\xe9\x8d\x72\x37\x96\x98\x9c\x14\x05\xe1\x02\x6b\xbc\x60\x92\xa1\x32\x48\x31\x97\x4e\x0a\xac\xb0\x2b\x1c\xfc\xf4\x76\xc9\x36\x96\x10\xd8\x0f\x0d\x55\x86\x8b\x05\x66\x39\xa1\xbb\x0a\xb8\xa3\xa1\x40\x86\x0b\x52\xd6\x85\xe1\x55\xc1\x48\x44\x20\xeb\x60\x87\x45\xcd\x08\xd5\x5a\x66\x9c\x86\xca\x39\xf8\x5f\x0a\x8a\x62\x16\xf5\x91\x02\xac\xaa\xa1\x37\x80\x42\xce\x58\xce\x44\xc6\xa6\xe4\x7b\xfb\x6b\x18\x8b\x12\x4e\xd2\x6c\x6d\xf7\xe6\x5c\xac\x9a\x9a\xa9\xda\x95\xe9\x60\x0e\x95\x5d\xd1\xdd\xf3\xfc\xcf\x2d\x12\xb1\x6a\xca\x83\x2c\xdb\x5a\x11\x94\xe6\x04\xbf\xb5\xc9\xe4\x53\x28\xc7\x91\xf3\x16\x77\x81\xaa\xea\x89\x8b\x5c\x62\xa3\x85\x06\xc5\x18\x11\x70\x6e\x85\x09\xcd\x82\xc4\x74\x77\x72\x61\x01\xb8\xf5\x48\x19\x4f\x04\x28\x1a\xeb\xae\xdf\xcb\x9a\x16\x99\xa0\xe9\xba\xe9\x4f\xcf\xcd\x7e\x00\x17\x7b\x87\x7b\xed\xdc\xe3\x28\xa9\xb1\xae\x75\x12\xb7\x3a\x85\x4b\xbd\xcb\x9d\x8e\x28\x83\x6d\x47\x0f\x9b\x96\xc4\x05\x8e\x77\x7f\xe3\x81\x64\x95\x62\x73\x7e\x97\x44\x67\x9e\xb4\xec\xb3\x84\xe7\x4c\x18\x3e\xe7\x31\x2d\x81\xa5\x9d\x5c\xc5\x04\x80\x08\x80\x10\xcb\xfa\x05\x91\x4d\x88\x5a\x20\xf9\x53\x2b\x83\x73\x29\x9a\x94\x06\xec\x3a\x55\x72\x6a\xb4\x5e\xa3\xf5\x1a\xad\xd7\xa7\xc6\x93\xb7\x5e\x5e\x1f\x84\x90\xfd\x71\xcd\x0f\x70\xb7\xc4\xd2\xd3\x9c\x75\x98\xc3\xe0\x8e\xa3\xd3\xb5\x11\x4c\xd5\xa8\x44\x4c\xb7\x67\x6a\x63\x35\x8d\x24\xb4\x28\xe4\x2d\x42\x22\xd0\x4e\x2a\x52\xb0\x15\x2b\x7c\x38\x44\x4a\x2a\xe8\x02\xb8\x33\x71\x11\x4c\x68\xc0\x25\x15\xb1\x0a\x47\xf1\x9c\x6d\x76\xbe\x42\xf1\xeb\x08\x12\x18\x0c\x41\x9c\x92\x45\xc1\x94\x26\x05\xbf\x61\xe4\x8c\x55\x85\x5c\x0f\xe7\xfb\x74\x03\xba\xb7\x19\x6a\xac\x9a\xba\x66\x06\x83\x53\x8e\xe9\x22\x13\x28\xf9\x1d\xc7\x6c\xec\xe1\x06\x86\x7f\xe0\x90\x27\x95\x23\xad\x25\x6f\x51\x0d\x7b\xe5\x9c\x9c\x14\xb7\x74\xad\x8f\xc8\x25\x5b\x31\x75\x44\x2e\xe6\x97\xd2\x5c\xb9\x24\x02\xc6\xe1\xe9\xd6\xb0\x3a\xd1\x84\xcf\xc9\xab\x82\x1a\xa6\x0d\x31\x14\xa3\x44\xb9\xee\x76\x7b\x90\xaa\x37\xc9\xb6\xa3\x6b\x9a\xee\xf9\xf1\xf4\xf4\x20\xa9\x21\xa7\x47\x00\x88\x22\x0e\x5a\x11\x28\x7c\x23\x8f\xd8\x89\x23\xf5\x75\x14\x9a\x8e\x23\x36\x68\x0c\x4c\x82\x11\x1a\x6a\x84\x4e\xab\x90\xba\xe3\x82\x28\xa6\x2b\x29\x34\xc3\xa9\xa0\x56\xdd\x34\xdf\xec\x12\xc0\xfa\x51\x73\x81\x48\x7f\x36\xce\x93\xad\xa4\x36\xc0\x95\x8c\x73\x30\xfa\xca\xe5\x2a\x08\x03\x02\x6e\x5a\x14\x68\x47\x80\x97\x25\xcb\x39\x35\xac\x58\x13\x3a\x37\x4c\x11\x1a\x4d\x3d\x61\xe7\xa4\x18\x0d\x8c\xe3\xc0\xab\x0c\xbc\xde\x28\xaa\xf1\x76\x6c\xa5\xff\x5d\x83\x78\x3a\xb4\x27\x61\x3b\x1c\xac\xd6\xd3\xa3\x6f\x91\x8e\x23\x85\x7a\x81\xad\xda\x07\xef\x3b\xea\x72\x92\x16\xb3\xd0\x2e\xc0\xac\x90\xd9\x8d\x26\xb5\x30\x1c\xeb\xd5\xbb\x5e\x3f\xf2\x86\x64\xb2\xac\x0a\x50\x9e\x71\x94\x90\xe4\xe7\x69\x21\x77\x69\xe4\xe6\x5f\x27\x8d\x92\x98\xd8\x39\xe9\xe3\x5f\xb5\xff\x13\xfc\x05\x2e\x46\x88\x8e\x61\xe3\x23\x58\x76\xc7\x32\x7c\x5c\xd1\xbb\xfa\x6f\x05\x83\x53\x1b\xd5\x74\x9d\x10\x29\x9a\x42\x80\xb9\xb4\x4e\x2b\xd0\xa2\xc7\x75\x60\x26\x1b\xad\xc3\xce\xef\x58\xd6\xfc\x39\x26\x94\x85\x3e\x88\x59\xe8\x98\x62\x4d\x13\x1e\x06\x93\x04\xa4\x95\x06\x1e\x85\x26\xf9\xec\x8e\x8d\x06\xc1\x20\x31\x86\x19\xc3\x0d\xa7\x68\x9c\xb0\x82\x0b\xa4\xf9\xef\x0e\x4f\x21\xda\x6d\x4e\xd3\xdc\xee\x58\x80\x89\x15\xb6\xd5\x0f\x39\x52\x66\xe8\xbf\x19\x56\x21\x7e\x4d\x95\x94\x86\x1c\xec\x1f\xef\x1f\x6e\xa1\x01\x22\xc1\x8b\xae\xef\xa4\x73\xe0\x1c\x31\x91\x9f\x75\xa4\x54\x0e\x1d\xd4\x2b\x68\x9f\xcd\xb2\xfd\xfc\x88\xf0\x58\x20\x8a\x67\x67\x55\xb5\x08\x27\x21\xae\xaa\x89\x38\x26\xda\x23\xa2\x25\x31\x8a\xe6\x3c\x49\x75\x01\xc8\xb4\x13\x34\xaa\xf6\x4e\xf6\xc1\xfe\xc7\xfd\xd8\x73\xca\x4c\x76\x48\x6e\xa5\xd8\x37\x70\x5c\xa7\xe4\x7d\xec\xad\xaa\x35\x0b\x64\xbc\x47\xc0\xa2\x2f\x58\x3c\x20\x47\x12\x76\x57\x15\x3c\xe3\xa6\x58\x83\x73\x49\x64\x1d\xbb\xef\xc0\x36\x4f\x4d\xe0\x0d\x3e\xbf\x8b\x3e\x49\xae\xa2\xd9\x1a\xb1\x17\xe0\x0a\x3a\x87\x33\x52\x28\xd5\xa4\xe0\x2b\x76\xbc\x64\xb4\x30\xcb\xf5\xe0\x0e\x36\xdb\x43\x48\x31\xf9\x37\x53\x12\x98\x8d\x85\x97\x1b\x87\xe2\x8c\x01\x34\x74\x07\x1a\xdc\xb0\x3d\x99\xa8\xdc\xab\xf5\x17\xbf\x65\xc8\xb8\x88\x6c\x35\x71\x7d\xff\xfe\xea\x5b\x66\x92\x39\x1e\x76\x76\xa1\xf4\x0e\x5e\xb5\x98\x9a\x4b\x55\x3e\xb2\x07\x12\x0f\x12\x9f\x40\xc7\xd8\x47\x76\x81\x96\x52\x47\xec\x3b\xd9\xdd\xc0\x17\xc7\x1c\xda\x1d\xae\xdf\x96\x60\x99\xdd\xf1\x64\x65\xe8\x6d\xa7\x30\x72\x71\x35\x25\xff\x25\x6b\x68\x9a\x44\x67\x51\x9e\xbc\x1d\xa1\x77\x8a\x66\x86\xec\xd9\x45\xd8\x8b\x79\x68\x75\xc3\x9e\xfb\xbf\x31\x9a\xbb\x26\x3e\xda\x30\x8a\xe2\xf6\x6e\x47\x22\xe8\x6e\x67\x5e\x29\x3d\xe7\x5a\x1b\x59\x92\xa5\x13\x1c\xbf\xd1\x1d\x92\x64\xaf\x3b\x62\x91\xfb\x56\xaf\xb9\xf7\x05\x4d\x14\xab\x52\x58\x3b\xff\xb5\xbf\x20\x6b\xb4\x65\x09\xdc\x49\x89\x94\x1a\xe4\xce\x98\x26\x94\x64\x70\x54\xa2\x45\xba\xc5\xb7\x67\xc5\x13\x1b\x46\x4b\xe4\xc2\x1d\x12\xd7\x89\x2d\x89\x5d\x8f\x2e\x66\x22\x89\x0a\x9a\x48\x0c\x29\x74\x5f\xc8\xf0\xd6\x69\xdb\x23\x55\x7d\x14\x49\x54\x49\x43\x76\x00\x48\x12\x88\x6c\x4e\xa9\x7b\xec\x4c\xb0\xfc\x24\x65\x0d\x07\x89\xa5\x9f\xee\x8e\x87\x5f\xbe\x14\x07\x8f\xa4\x5b\xbf\x2a\x9a\x7e\x66\x9b\x7c\xc6\xb5\x65\xc4\xb5\x3d\xea\x0e\xe9\x4c\x27\xa8\x33\xcd\xd4\x0a\x57\x30\xd1\x8e\x54\x4b\x26\xb1\xcf\x37\x61\xec\xe0\x88\x57\x44\xd4\xe5\x2c\xda\x48\x35\x8c\x6d\xca\xa4\xde\x86\x4e\x9b\x87\xcb\x14\x53\x0d\x10\x96\xe0\x20\x51\xb1\x88\xbd\x17\x2f\xed\x37\xff\xfe\x7f\xff\xef\xdf\xfe\xef\xa9\x5b\x56\xfb\x1b\x91\x32\x67\x8c\x50\x41\x2e\x4e\x2e\x4f\xfe\x79\xfd\xfd\x29\xb0\x67\xc7\x9d\xc2\x04\xc5\xfc\x29\x4b\xf9\x13\x16\xf2\x3f\x60\x19\x3f\x10\x96\x45\x6a\xf8\x3e\x2e\x0b\x04\xc6\x67\xb4\x6b\xed\x08\xb3\x7d\xa4\xe8\x9e\x0d\x13\x64\xb2\x6d\x4c\xdc\xe3\x19\x4f\x10\x38\x3c\xba\xf6\x34\x59\x75\x2d\xb3\x9b\x64\x59\x9e\xfd\xf7\xa7\x57\x4e\x60\x92\x44\x0f\x15\xe1\x81\x89\x8b\x95\x2c\x56\x76\x33\x29\x79\x7f\x7a\x15\x69\x2c\xa6\x56\x06\xbc\xb0\xba\xbc\xf7\x3a\xaa\x92\xb3\xa1\x66\xf2\xd0\x4e\x5e\x56\x45\xcc\x8b\x32\x81\x5e\x01\x8a\xd1\x82\x6b\xc3\x33\x98\x6b\x81\xea\x2f\xdd\x1f\xf6\x7b\xf1\x78\xce\x31\x3f\xd6\x8e\xc4\xf9\xb1\xfd\xb7\x89\xaa\x9e\x9b\x44\x5b\x27\x55\x16\x9d\x34\x39\xea\x91\xfe\xc4\x33\x54\xfa\x44\x5b\x5c\xc9\xf9\x13\xf5\x1c\xc1\x0d\xc3\xb5\x02\xed\x0e\xd1\xe9\x52\xe4\x3d\xc7\xd8\x17\x14\xf0\x3b\xb7\x3d\xc7\x48\xb1\xfe\x83\xfb\x9e\x63\x6c\x5e\xc2\xfa\x9d\x5b\x9e\x63\x22\xdf\x76\xf4\x1c\x3f\x6f\x3c\x80\xe7\x58\x29\x76\x6d\x64\x95\x04\x67\xe7\x44\x25\x45\xd9\xcd\xd8\x5c\x2a\x96\x06\x66\xd7\x02\xe0\x48\x5e\x83\x32\xa6\x22\x82\x59\x35\x3c\x73\xc9\x2e\x5c\x0d\x5d\xb2\x4f\xc0\x65\xc9\x96\xe1\x55\x55\x30\xad\x8f\x01\x1a\x57\x57\x2e\x49\x89\x14\x3a\xa7\xbc\xa8\x15\x3b\xb2\x3b\xcd\x4a\xd8\xab\xa3\x58\x92\x47\xbb\x19\x4c\x38\x51\xcc\x64\x0e\x46\xe1\x51\x8b\xf8\xfd\xb1\x3e\x9f\x3b\x38\xae\xa3\x6d\x7c\x5b\xaf\x4c\x51\xbd\x64\xd0\xcc\x93\xdd\x71\xa3\xdd\x44\x15\xa3\x1a\xcd\x11\x0d\x50\x17\x7f\x90\xc0\x05\xd6\xa4\xa2\x5a\xb3\x1c\x6f\x0d\x3a\x90\x4f\x37\xc1\x2b\x99\xef\xef\xeb\xee\xcf\x20\x25\x2f\x14\xcd\x18\xa9\x98\xe2\x32\x27\xc0\xba\x9e\xcb\x5b\x41\x66\x6c\xc1\x05\x36\x02\xf0\x37\xd2\x4e\x3a\x5c\x78\xeb\xc2\xb2\x08\x20\x55\xe8\x98\x3c\x25\xef\x7a\x1d\x5d\xf1\x56\x4b\xd6\x26\x93\xad\xb5\xf6\xab\x7b\x14\x21\xb1\x45\x92\x02\x5b\x03\x5c\xf3\x9a\x16\xc5\xba\x55\x2b\x48\xc9\x9e\x98\xc4\x3c\xd4\xc6\x3f\x33\x4c\xad\xbd\xac\xb1\x12\xbb\x17\xb4\xbb\x14\x78\xdd\xa4\x18\xcd\x96\x71\xc5\x14\x23\x74\xf7\x13\x63\x84\xee\x8e\xd0\xdd\x7b\xc7\x08\xdd\x1d\xa1\xbb\x23\x74\x77\x84\xee\x8e\xd0\xdd\x11\xba\x3b\x70\x8c\xd0\xdd\x4f\x8d\x11\xba\x7b\xef\x78\x92\x4f\x13\x23\x74\x77\x84\xee\x7e\xf6\x18\xa1\xbb\x23\x74\x77\x98\xdc\x11\xba\x8b\x1a\x23\x74\xf7\x67\xc7\x08\xdd\x8d\x19\x23\x74\x17\x3b\x46\xe8\xee\xe0\x31\x42\x77\x47\xe8\x6e\xc4\x18\x01\x18\x88\x31\x42\x77\x13\x04\x0e\x8f\xae\x3d\x47\xe8\xee\x08\xdd\xfd\xcc\x31\xe6\xc7\xda\x31\x42\x77\x23\xc6\x08\xdd\xfd\xe4\x18\xa1\xbb\x23\x74\x37\x42\xd6\xd3\xf3\x1c\x03\x44\xf4\x4a\xc9\x59\x34\xb5\xf4\x15\x80\xa3\x78\xe6\x32\x6a\xf6\x9e\xc4\x00\x2f\xc3\xd4\xa6\xe4\xb4\x8f\x99\x83\xfe\x56\x9e\x3e\x12\x21\xd7\x63\x42\xdd\x1c\x81\x1a\x73\xba\x83\xed\x16\x21\x78\x20\xa4\x2b\x10\x3a\xeb\xe3\x4a\xba\xff\xaf\x05\x74\x75\x90\x5c\x2e\x3b\x89\xe5\xca\x7d\x14\xd6\x55\x3c\x7c\xeb\x5e\xe8\x16\x91\x28\x1a\x67\xd2\x06\xfa\x9b\xb0\xad\x3e\xf8\x0a\x29\xbb\x0f\xd9\xea\x03\xaf\xb0\x9e\x3f\x1a\xae\xf5\x04\x80\x7b\xd1\x10\xad\x7b\xe0\x59\x91\xd6\x6b\x03\x9a\x15\xc0\x55\x11\x12\x77\xc2\xb2\x22\x67\xb9\x05\xc9\x0a\xa0\xaa\x04\x5f\x0e\xd8\xd3\x2e\xa0\x2a\xf2\x95\xbf\x03\xc5\xea\x82\xa9\x22\xa4\x76\x60\x58\xdb\x40\xaa\x98\x9d\x32\xbb\x40\x54\x1e\x03\x14\x13\x5c\xf6\x00\x54\x3b\x20\x50\x11\xb2\x01\x3c\x95\x18\xfe\xb4\x13\xfa\x14\xe7\xbf\xee\x80\x3d\x05\xe0\x52\xcc\xc2\xb6\x90\xa7\x2e\x68\x29\xe6\x08\x34\x70\xa7\x4d\xc0\x52\x54\x0a\x24\x4f\x0d\x56\x4a\xf1\x34\x1c\xfd\x2c\x1c\xe9\xa9\xfa\x32\xa1\xf7\x4b\xc5\xf4\x52\x16\x48\x53\xd0\x33\x03\x6f\xb8\xe0\x65\x5d\x5a\x9d\xa3\xad\xde\xe6\xab\xc8\x1a\x26\xdd\xa0\x55\x9d\x13\x08\x6f\xca\x68\x8b\x07\x1a\x45\xb1\x1c\xa4\xdb\x23\x06\x84\xee\x4b\xba\xc2\xbb\xfa\xba\xce\x32\xc6\x72\x96\xf7\xf2\x9a\xe4\xb7\xd3\xb0\x16\x48\xb9\xae\x41\x2a\xd7\xe4\x65\x8c\x87\x11\x13\x11\xcd\xa5\x2a\xa9\x01\x19\xbf\xfd\x1a\x21\x21\x0a\xfb\xf6\x20\xb8\xb7\xe4\x98\xb7\x68\x37\x2e\x2e\x97\x17\x91\xc7\x8b\xf7\x1f\xe3\xf2\x77\xbb\xb1\x6d\x71\x36\x6e\x17\xae\x2d\x4e\xe2\x03\x60\xda\x76\xe2\xd9\xba\xc8\xaf\x38\x4f\x37\x0e\xcb\x96\x08\xf1\x1a\x8d\x61\x7b\x18\xfc\xda\x6e\xec\x1a\x68\x97\x18\xe7\xa2\x8f\x5b\x8b\x47\x9e\x3d\x09\xd7\xe2\x21\xd0\x66\xdb\x48\x33\xbf\x58\x71\x59\xec\x06\x65\x96\x0e\x25\x96\x08\x21\x96\x02\x1d\x16\x8d\x0c\x8b\x47\x85\xa5\x42\x84\xa5\x40\x83\x6d\x75\x01\x4d\x70\x82\x48\x68\xdc\x98\x04\x5f\x9d\x2a\x7b\x9c\x04\xfd\xf5\xb0\xcb\x95\x02\xf5\x95\x60\xbd\xe2\xd0\x5e\x0f\x83\xf4\x4a\x89\xf2\x4a\xb1\x44\x51\x6f\x74\x0f\x83\xec\xda\x89\xea\x22\xe8\xfa\x77\xb2\x99\xee\x9a\x76\x5f\xd6\x22\x84\x6e\xa0\xb9\xba\xaf\x6a\x11\x52\x1b\x24\x57\xda\x17\xb5\xc8\xd7\xb4\x54\x2f\x69\x89\x5e\xd1\x1e\x08\x7b\x15\x8b\xbb\xda\x8d\xb9\xb2\x3e\x48\xc4\x81\xd8\xc2\x5b\xb5\x88\xa9\x08\xa9\xdd\x9c\x44\x1c\x5a\x2a\x72\x43\xb9\xe0\x86\xd3\xe2\x8c\x15\x74\x7d\xcd\x32\x29\x72\xa4\x37\xb1\xd1\xab\xda\xa3\x05\xe6\x44\x3b\xa1\xc8\xef\x73\x99\xa0\x3e\xd7\xc5\x92\x6a\x82\x7f\xbb\x24\x2d\x71\x4a\x78\x1e\xf5\x8e\x29\xa1\xf0\xf8\x68\xd7\x03\xf9\x7c\x49\x9e\xdc\x13\x26\x79\x12\x29\x27\x47\xf9\x91\xee\x78\xfd\x4d\xde\x12\x39\x37\x4c\x90\x03\x2e\xc2\x09\x3b\xc4\x66\x9f\x9a\x64\x53\x9b\xcf\x6c\x92\x86\x78\x99\x2f\x5f\x84\x89\x35\x29\xc7\x28\xc7\xec\x39\xa7\x1c\x21\x19\xab\xf5\xd3\xcc\x68\xfb\xc9\x3d\x54\x4a\xdb\x8b\x9f\xd7\x85\x53\x66\xd8\xfc\x0d\x24\xc3\x7d\x82\xbc\x9f\xd3\x46\x1e\x0b\x42\xde\x78\x37\xe7\x25\x7c\x79\xa3\x0d\xa9\xc8\x89\xa7\x3b\x43\x4b\xee\x1e\xf8\x67\x7d\x74\x23\x51\xc4\x0f\x85\x20\xbe\x17\x3d\xec\x30\xc0\x48\xa9\x5b\xc8\xe1\x16\xff\x8b\x95\xd8\x47\x0d\x77\xb1\xbf\x11\x73\x6c\xbb\x32\xe3\x71\xbf\xe3\x1b\x01\xee\xbf\xbd\x17\xdf\x0b\xcf\x05\x11\x2e\xf1\x06\xb6\x37\x55\x19\x7c\xbf\x04\x3e\x16\x23\xfe\x64\xa2\xfd\x80\xc6\x8d\xcd\x8d\x8d\xd1\xfe\x18\xed\x7f\x62\x3c\x40\xb4\x6f\x78\xc9\x64\x6d\x9e\x6c\xc0\x79\xbb\xe4\xd9\xb2\xeb\x0b\xf2\x12\x6d\xaa\x65\x6d\x36\xfc\x35\x3f\xc5\x84\x50\x84\x31\xea\xdc\x18\xb8\x37\x8d\x1d\x09\xd5\x78\xf6\xdb\x06\x21\x4b\xa8\x26\x94\x9c\x5d\x5e\xff\xf3\xbb\x93\xbf\x9e\x7f\x37\x25\xe7\x34\x5b\x46\x89\xe6\x82\x50\xb0\x6c\xa0\xc2\x96\x74\xc5\x08\x25\xb5\xe0\xff\xaa\x19\xd6\x2e\x1c\x34\xf3\x3b\x4c\x82\xe9\x8e\xd0\x40\xd6\x26\x21\x74\x43\x6f\x13\xbf\xe3\xda\xd8\x4d\x04\x59\x9e\x67\x4c\xa2\xf2\x81\x73\x25\xcb\x4d\xd3\x76\x6e\x85\x39\xd7\x1b\xe9\xcd\x2d\x99\x62\x64\xc1\x57\x1e\xf9\xec\x30\xa0\x84\xe6\x11\xac\x72\x56\x0b\xd8\x8b\x63\x83\x03\x3a\x03\x40\xe1\x92\x11\xc1\x8c\xbd\xf4\x4d\x2a\x13\x87\xae\xec\x90\x7f\x93\x5a\x33\x7d\x44\x66\x35\x80\x43\x2b\xc5\x4b\xaa\x38\x0a\x82\xd1\x99\x30\x2d\xa6\xe4\x52\x86\xf0\x68\x0d\x4b\x8b\xc9\x37\x59\x6f\x06\x96\xf6\xec\xed\xf9\x35\xb9\x7c\xfb\x9e\x54\x0a\x78\x82\xb1\xc8\x4a\x90\x08\x47\x60\xc6\xec\xac\xdc\x31\xca\xa7\xe4\x44\xac\xb1\x7b\xef\x8c\x0c\xd7\xc4\xc6\x43\x4c\x58\xb1\xfe\x79\x2a\x47\x27\x9f\xf6\x5e\x4c\xe1\xff\xed\xd9\x33\xa4\xac\x2b\xd7\xc0\x75\x63\x14\x4d\x28\x1a\x71\xee\x21\x9f\x15\xac\xbd\x0f\xfe\x64\x61\xbc\xa5\x64\xfa\x05\x87\xca\x40\xa3\x31\x36\x20\xf6\x7e\x5d\xaf\xec\x19\x51\xac\x52\x4c\x33\x81\x8c\x59\x68\x73\x51\xe1\xc4\x81\x82\xb7\x1a\xa6\x88\x2c\x6c\x8b\x8c\x76\x63\x62\xdd\x49\x3b\xf3\x2b\xdc\x45\x89\x0d\x78\x7b\xbf\x8f\x75\xcb\x77\x86\x5f\xf3\xb8\x8a\xdd\xc6\x1e\x85\x8b\x5f\xc9\x7c\x5f\x93\x0b\x3c\xee\xc9\xdf\xfa\x29\x79\xbf\xe4\xba\x8d\x6c\xac\xaf\xc8\xf1\x74\x4f\x70\x16\xdd\xc3\xf2\x11\x79\x41\xfe\x4c\xee\xc8\x9f\x21\xf8\xfa\x3d\x36\x46\x4a\x11\xe0\xc4\xa6\xf6\x5c\x1e\xe4\xe2\x2a\xc9\x89\xf8\x61\x49\x0d\xc8\x23\x17\x57\x31\xe0\xc6\x19\x17\x39\x1c\x05\x76\x67\x98\x12\xb4\x08\xa1\x79\xdc\x4a\x47\x84\x80\xf6\xa3\x9e\xfc\xc5\x71\x0c\x16\x17\x73\xb4\xc4\xc6\x4b\x3f\x22\xa6\x77\x75\xd0\x12\xe1\xca\xed\xbc\x3a\x68\x91\xee\xca\x91\x8b\x39\xe4\xda\x2e\xbd\xa5\xe0\xba\x33\x7b\xfc\x92\x36\x5f\x5d\x52\x93\x2d\xfb\x66\x0d\x9f\x0a\x79\x63\xaf\x44\x4b\xbd\x4f\x72\x09\xb9\xe5\x28\xd2\x60\x3b\xd5\xe7\xad\x78\x62\x20\x77\xbd\xfb\x74\x31\xdf\x3c\xb9\xe8\x55\xbd\x2f\x0d\x16\xc5\x48\xec\x83\xd1\x4e\x63\x8d\x4a\xe6\x2e\xf2\x45\xcb\xb4\x8b\x97\x77\xfc\xa3\x5e\x00\x8c\xb7\x9c\xdd\xc0\xd9\x33\x3a\xc5\x16\x0f\x3a\xd5\x6d\x2d\x43\x46\x85\x2b\xba\x9e\x33\xa5\x62\x8e\xbe\x24\xb3\x35\x20\xd7\x78\xc6\x22\x2f\x41\x84\x4d\xa8\x94\x34\x32\x93\x68\x52\x8f\x3e\xb8\xcf\x0b\x83\xe5\x8e\x79\xbe\x6a\x5f\x34\x3f\x9c\x5d\x1d\x91\xf7\xa7\x57\x47\x44\x2a\x72\x7d\x1a\x83\xaf\xe9\x66\xee\xf6\xde\x9f\x5e\xed\x3d\xda\xa2\x93\x10\x17\xbe\x42\xd1\x04\xf5\xd2\xb8\x36\xe4\x9c\x94\xb4\x9a\xdc\xb0\x35\xc2\xab\x8e\xf5\xe9\x27\xcd\x09\x4a\xf0\x19\x6e\x61\x4b\x5a\x0d\x94\xa5\x18\xcd\xf9\x13\x65\x6e\xf0\x37\xbc\x9d\xe3\x26\x85\x03\x42\x26\xe8\x9f\x52\xae\x58\xee\x82\xf7\xf0\x1b\x4c\xe4\x95\xe4\xb8\x88\x75\x64\x82\xf8\xf4\x18\x99\x20\x3e\x6f\x8c\x4c\x10\xfd\x31\x32\x41\x44\xc8\x1c\x99\x20\x46\x26\x08\x37\x46\x26\x88\x91\x09\x02\x39\x46\x26\x88\x4f\x4f\x6e\x64\x82\x78\xb6\xd8\xd6\x91\x09\xe2\xd3\x63\x44\x79\x8e\x4c\x10\x23\x13\xc4\xd6\x18\x99\x20\x1e\xdb\xb5\x18\x99\x20\x46\x26\x88\x30\x46\x26\x88\x01\x63\x64\x82\x18\x36\x46\x26\x88\x4f\x8e\x27\x56\x1b\x32\x32\x41\x8c\xb5\x21\x9f\x2b\xe7\xe9\xd5\x86\x90\x91\x09\x02\x37\x46\x26\x88\xe1\x63\x64\x82\x18\x36\x46\x26\x88\xe1\x32\x47\x26\x88\x76\x8c\x4c\x10\x23\x13\xc4\x33\x3d\xba\x23\x13\xc4\xc8\x04\xb1\x7b\x8c\x6f\x04\x23\x13\xc4\xb0\x31\x32\x41\xe0\x85\x8e\xd1\x3e\x5e\xce\xd3\x8b\xf6\x47\x26\x88\x91\x09\xe2\x93\x23\xc6\x75\x53\x4c\xcb\x5a\x65\x18\x13\xd9\x3f\x57\xa7\xb2\xac\x6a\xc3\xc8\xbb\x20\xb0\xb1\xfb\x88\x6f\x9a\xad\x5d\xc1\x55\x47\x3b\x3e\x06\x6c\x3a\x93\x62\xce\x17\xb5\x82\xe2\xfb\xe3\x92\x0a\xba\x60\x93\xcc\x7d\xe8\xa4\x59\xb9\x49\x33\xcb\xe3\x67\x05\x9d\x2e\x78\xc9\x31\x0c\x12\x64\x6b\xef\xbf\x03\x49\xed\xfb\x68\x04\xbc\xa5\xa4\x77\x10\x10\xd1\x52\xd6\xc2\xb8\x3a\x01\x58\x6f\xa4\xcc\x66\x97\xdc\x3b\xb7\x0d\x09\xdb\x43\x10\x01\x11\x78\x02\x47\x87\xa4\x70\xce\x5b\x2e\x8d\xab\x68\x6f\xb9\xa2\xc6\x30\x25\x5e\x91\xff\x3e\xf8\xc7\x57\x1f\x27\x87\xdf\x1c\x1c\xfc\xf8\x62\xf2\xa7\x9f\xbe\x3a\xf8\xc7\x14\xfe\xe5\x37\x87\xdf\x1c\x7e\x0c\x7f\xf8\xea\xf0\xf0\xe0\xe0\xc7\xbf\xbf\xf9\xf6\xfd\xd5\xf9\x4f\xfc\xf0\xe3\x8f\xa2\x2e\x6f\xdc\x9f\x3e\x1e\xfc\xc8\xce\x7f\xfa\x4c\x21\x87\x87\xdf\xfc\x1a\x1d\x1c\x46\xb8\x1f\x69\x9c\x8f\x24\xae\xc7\x03\x38\x1e\x1e\x5d\x92\x44\x3d\xbc\xf3\xb2\xd2\x28\x08\x9f\x31\x49\xaf\x20\x82\xbd\x82\x0a\xe2\x30\x67\x7c\x12\x52\x96\xdc\x18\x96\x43\xca\xa8\x43\x2f\x82\xc5\x81\x73\xd3\x6b\xc6\xed\x55\x2e\x14\x18\xa1\x21\xd0\x5c\x77\x71\xd5\x9d\x4a\x59\x69\x96\x4c\xdd\x72\xf4\x7b\x90\x0d\x90\x44\x9b\xcd\x00\x25\x38\xc9\xd9\x9c\x0b\x74\x82\x04\x9c\xb8\xc1\xfe\xdb\xa8\x86\x47\x35\x3c\x44\xca\x53\x52\xc3\x9a\x65\xb5\xe2\x66\x7d\x2a\x85\x61\x77\x88\x84\x48\x5f\x0b\x5f\x7b\x71\x44\xc2\xdf\x60\xeb\x9c\x2a\x99\x87\xaa\x36\x55\x0b\x28\x5d\x8f\x74\xa9\x3e\xe7\x1e\x57\xb2\xe0\xd9\xfa\x38\x2c\x09\x5c\x58\x76\x67\x8e\x1f\x2c\x06\x30\x54\xdf\xb4\xea\x83\x4d\x6c\xe4\xd7\x6a\x89\xad\x79\x3c\x2b\xc7\x1f\x3c\xe1\x2b\xc5\x57\xbc\x60\x0b\x76\xae\x33\x5a\x80\x7e\x4c\x61\xeb\x4f\xee\x91\x8d\x7f\x1f\x32\x4a\x16\x9a\xdc\x2e\x99\xb5\x49\x84\xda\x6f\x87\xd4\x5b\x46\xb1\x42\x17\x94\x0b\x52\xda\x63\x50\x85\x89\xda\xdb\x60\x2d\x16\xda\xe0\x57\x54\x31\x61\xc2\xe4\x3c\xc1\xd0\x4c\xca\xc2\x97\xd8\xa1\x31\xd7\xcd\x0a\xf8\x5a\x62\x21\xff\x29\xd8\xed\x3f\xed\xcc\xb1\x73\x9d\x17\x74\xd1\x70\x96\x69\x66\x02\xd8\x2b\xa6\x22\x9b\xb8\x53\xe9\x3e\x3e\xf1\x21\x80\x9a\xaa\x9a\x11\x5a\xdc\xd2\x35\x1c\x85\x34\xf3\xe5\xfa\x15\x79\x79\x08\x6a\x8c\x6a\xd2\xcc\x37\x27\x5f\x63\x9f\xc8\x97\x54\x93\xd3\x93\xab\x7f\x5e\xff\xd7\xf5\x3f\x4f\xce\xde\x5c\x5c\xc6\xb8\x13\xf6\xf4\x30\xd4\x21\xcf\x68\x45\x67\xbc\xe0\x78\x2f\x62\x0b\x77\xd9\x15\x19\xe1\x14\xe6\xf9\x71\xae\x64\xe5\xf6\x50\xd5\x02\x68\xfd\x5a\xfe\x1b\x6c\x26\xb9\x9b\x35\xec\x30\x04\xda\xc3\x8d\x4d\x46\xce\x7b\x9f\x4c\x16\x8a\x0a\xeb\xcd\x43\x66\x2a\xe2\xb5\xdb\x43\x73\x54\x2d\x0c\x2f\x9f\x6f\xf1\x35\xcd\x53\x15\x5e\x9f\xe4\x39\xcb\x53\x1c\xaf\xa7\x58\x78\x70\x1a\x3e\x2b\xa6\xe2\x86\xb4\xac\x89\xe4\xea\xed\xf5\xc5\xff\x9d\x66\xb5\x88\x5f\xb1\x98\x07\xac\x04\x9c\x2d\x4a\x56\x89\x4e\xd2\x3b\xcf\xde\x31\x9e\xa5\x9f\x1b\xbf\xd0\xb3\xd4\x78\x72\x29\x30\x53\xef\x6a\xd1\xd1\xd5\x68\x02\x83\x76\x4e\xa4\x94\x39\x9b\x92\x2b\xe7\x20\x31\x9d\x44\x66\x87\x36\x8e\x2a\x46\xac\x60\x61\x38\x2d\xd0\xae\x26\xfb\x57\xcd\x57\xb4\x60\xae\xc0\x0f\x28\x1c\xba\xfc\x81\x09\x6c\xf3\x9c\x16\x3a\xca\xe8\xe1\x7d\x22\xeb\x9c\xbe\x91\xb5\x48\x81\x4f\x6a\x64\x91\x9c\x09\x69\xa2\xf2\x99\xf6\xbb\x80\xf0\x51\xc9\x8c\xb8\x9c\x66\x14\x14\x3b\x60\xf3\x3a\x4e\x15\x38\x70\x78\xd2\x64\xe2\x5c\x70\xbf\x8f\x57\xcd\xb7\xbb\xb7\xdf\x5a\x47\x7d\xfe\x96\x4b\x14\x0b\x65\xb1\xdf\xaf\x18\xcd\x81\xc9\xa7\xa2\x66\xe9\x70\x7a\x25\xd5\x37\xe8\xdc\x23\x88\xf1\x31\x9d\xcf\x12\x3b\x02\x9e\x66\x31\xde\xe3\x95\xdf\x9c\x51\x53\x2b\xe6\xa2\x32\x57\x0c\xc8\x04\x9d\x15\x58\x64\x75\xa4\x22\xb5\x6b\xf7\x56\x14\xeb\x77\x52\x9a\xd7\x0d\xdb\x4a\x82\x4b\xf3\x83\x8f\xe0\xfb\x0f\xbb\x11\x81\x16\x40\xe4\xf2\x09\x6c\x34\x28\xab\x78\x72\x18\x7f\xc6\xed\x71\x7f\x44\x55\xa5\x6a\x71\xa2\xbf\x55\xb2\x46\x7a\x46\x5b\xc1\xdb\xb7\x17\x67\xa0\xd1\x6b\x11\x11\xbc\x30\x61\xd4\x1a\x98\xd0\x52\xb4\x7d\x20\xdd\x7c\xc1\x07\x6b\x12\x37\xee\x3f\x56\x51\xcd\x49\x2d\x34\x33\x53\xf2\x86\xae\x09\x2d\xb4\x0c\x49\x0e\xb4\xc9\xbd\x02\x44\x7e\x37\x15\x3b\x25\xc0\x2c\x8a\x0e\x2e\xb9\x20\x33\x69\x96\x64\x43\x6c\x04\x95\xe8\xf6\x1c\x81\x21\x2a\x0a\x48\xdf\x76\xe6\xe0\x62\x73\xaa\x58\x8d\x4f\x6f\x98\x26\x95\x62\x19\xcb\x99\xc8\xa2\xee\x57\x22\xc4\xcc\xef\x7f\x87\xbd\xa1\x97\x52\x58\x25\x99\xe0\x8e\x5e\x88\x9c\x67\xd4\xb8\x2c\xa4\x49\x92\x60\x00\xac\x9e\xcf\x6c\x51\x20\x0f\xb2\x2a\x12\x29\xb6\xd6\x4c\xc1\xab\xa8\x51\x35\x73\x07\xeb\xef\xf5\x8c\x15\xcc\x60\xc9\x16\x49\x60\x80\xa6\xc6\x31\x9b\xf1\x92\x2e\x18\xa1\x26\xa8\x01\x7c\x8e\x89\x09\x6d\xcd\x29\xac\x24\x37\x24\x97\xac\xa1\xe4\xc2\x26\x3b\x34\xf9\x70\x71\x46\x5e\x90\x03\xbb\x86\x87\xe0\x4f\xcc\x29\x2f\xf0\xdc\x1c\x50\x35\xb0\xe1\xff\xf0\x79\x98\x2e\xd6\x7a\x5d\x78\xdd\x47\xa4\x72\xe6\xeb\x88\x08\x49\x74\x9d\x2d\xc3\x5a\xe3\x73\xb0\x21\x5d\xec\x2b\x80\x00\x47\xe3\x15\x2c\x52\x62\xa3\x96\xef\x53\xb0\xd8\xb5\x75\x42\x77\x29\x58\xf4\xfb\x64\x7e\x9f\x82\x8d\x42\x24\x3e\x71\x05\x1b\xe9\xc0\x7c\xd0\x4c\x25\xf2\x5f\x3e\x3c\x71\xff\xa5\x1b\xe2\x5a\x5d\xd9\xee\x2c\xde\x41\x70\x0a\xb1\x64\x86\xe6\xd4\x50\xef\xd7\xc4\x72\x88\x6e\xfb\x44\xe3\xe5\x7b\x9a\x97\xef\x31\xbd\x1b\xcd\xbe\xe3\xa2\xbe\x73\x05\x2b\xa9\x1e\x90\xae\xcf\x41\x28\xc9\xe2\x96\x18\x8e\x2e\xad\xaa\x82\x03\xa3\xe4\x46\x0d\x45\x94\xe1\xec\x36\x0a\x88\x57\x0e\x21\x9c\x01\xc3\x49\x8b\x42\x5a\x07\xcf\xc6\xac\x54\xe4\x12\x8b\x64\xdf\x58\x44\x48\x76\xb0\x5e\x9b\xbc\x29\x5c\x72\xec\x5d\x1b\x55\xc3\x33\x50\x0d\x8f\xfa\xf0\x57\xb0\x15\x43\xf7\x35\xd8\xec\x3e\x68\x65\x11\xae\xc3\xb1\x8e\x78\x3d\x80\x69\x91\x82\xce\x58\xe1\x3c\x7f\xa7\x22\x12\xd4\xc3\x45\x2b\x97\x24\xcf\x64\x4a\x16\xa9\xf8\x3e\xde\xc9\x02\x8a\x61\x68\x82\x65\xb7\xd3\xfa\x05\xaf\x3a\x88\x48\xb3\xea\xef\xd7\x55\xb2\x55\x87\x27\x83\x5f\xee\xaa\xd7\xe8\xc0\x81\x6c\xae\xba\x8d\x41\x52\xad\x3a\x38\xf6\xbf\xcc\x55\xbf\xe5\x22\x97\xb7\x3a\xad\xc3\xf7\x83\x13\x1a\xac\x29\xb6\x8c\x5d\x33\x63\xb8\x58\xe8\xae\xd3\x47\x8b\x22\x01\x68\x68\x97\xd7\xe7\xb1\xb1\xd8\xa7\x9c\xd0\xf4\x73\xdb\x2b\x89\x4c\xbb\xd4\xda\xd7\x25\x74\xbc\x28\xac\x0f\xb9\x9d\x74\xde\xe5\x45\x45\xbc\xe9\x8d\x5e\xd4\xa7\xc6\xa2\xd4\xf4\x54\xd9\x8f\x30\x9c\x16\xd7\x15\xb6\x87\x09\xd9\xbc\x78\xdf\xbe\xb9\x3e\xe9\x0b\x8e\xd0\x4f\x1c\xb0\x96\xca\x25\x68\xad\x64\x42\xf3\x92\x6b\x8d\xcf\x22\xda\x71\xcb\x66\x4b\x29\x6f\xc8\x41\x40\x5f\x2f\xb8\x59\xd6\xb3\x69\x26\xcb\x0e\x10\x7b\xa2\xf9\x42\x1f\x7b\xc5\x34\xb1\xeb\x85\xc5\x64\xc2\x97\x88\x82\x0b\xff\x66\x0b\xb1\x93\x30\x9a\x48\x7c\x3b\x44\xd2\x2e\x49\xd6\xac\x36\x9c\xf8\x08\x91\xae\x71\x9b\x03\x18\xee\xd8\xc8\xcb\x38\xfe\x02\x60\xbc\x7c\x54\xbb\xbe\x7d\xe8\x2f\xa3\x08\x55\x3f\x71\xf0\x23\xd7\xcb\x35\x82\x71\x64\x1b\x3e\x5f\x68\x7f\x23\x42\xe2\xc6\x49\xf1\xc9\xc2\xc7\x0d\x2b\x42\xa2\x36\xe1\x4e\x40\xc2\xd6\x8b\x8c\xba\xb2\x8d\x07\xd1\xa6\x7e\x3b\x49\xdc\x08\xd1\x9b\xe9\xdf\x26\x91\x1b\x21\x73\x13\x81\x9c\x24\x0d\x4c\x1e\x30\x15\x4c\x3e\x3b\x1d\x1c\xf1\x03\x7d\x87\x25\x91\x17\x40\xee\x4f\xfd\x44\x2a\xf4\x07\x73\x5c\x48\x32\xe7\x85\xc4\x5d\x7c\x4f\x57\x96\xa4\xa5\xdf\x75\x47\x16\xe1\xe1\x09\x1b\xf1\x55\xe1\xd1\xdb\xee\xa8\x23\xad\x6c\xa8\xe0\x8a\x75\x20\xde\xe4\xff\xc6\x9d\xf5\x7e\x0b\x58\x21\x5d\x6d\x6b\x87\xc9\x12\x21\xd3\xf7\xf4\xca\x49\x2d\x0c\x2f\x02\xa2\xa9\xac\x0a\xeb\xb9\xf4\x66\x8f\x9c\x31\x48\xec\x74\x0d\x3c\x6a\x96\x27\xa6\xb9\xa1\xe7\x02\x3d\x22\xff\x53\x6b\x43\x68\x53\x52\x14\x08\xed\x60\x27\x11\xc2\x03\xd7\x1e\xe0\xe3\x7c\x2b\x57\xe0\xb3\x37\xd2\x7e\xc4\x8a\xe7\x18\xa9\x39\x9f\xcf\x59\x28\xaa\x9a\x31\x52\x51\x45\x4b\x66\x00\xee\x8a\xc5\x48\xcc\xd8\x82\xbb\x9a\x13\x39\x27\xd4\x2e\xe8\xfe\xbe\x6e\x59\xd2\x30\xfa\x03\x2a\x59\xb8\x21\x25\x5f\x2c\x0d\x5c\x72\x42\x49\x21\xc5\x02\xb8\x70\x70\x10\x81\x42\xd2\x9c\x80\xae\x97\x8a\xdc\x52\x55\x12\x4a\x32\x9a\x2d\x01\x7b\x81\x7a\x91\xcd\x6b\x05\xed\x08\x0d\xa3\xf9\x7a\xa2\x0d\x35\x36\xd6\x65\xae\x2e\xda\xed\x1c\x42\x6a\xb6\xc5\xc9\xe2\xce\x00\x64\x5c\x66\xcc\x60\xba\x83\x07\x38\xa4\xc7\x40\x06\x7f\xb8\xab\x6c\x22\xa4\xce\x0b\xba\x78\x6a\x24\x40\x63\xf7\x4c\x3f\xc6\xee\x99\x9f\x3b\xc6\xee\x99\x9f\x3d\xc6\xee\x99\x63\xf7\xcc\xb1\x7b\xe6\xd8\x3d\x73\xec\x9e\xb9\x31\xc6\xee\x99\x63\xf7\xcc\x9f\x19\x63\xf7\xcc\x4f\x0b\x1c\x99\xb1\x91\x63\xec\x9e\x39\x76\xcf\xbc\x7f\x8c\xdd\x33\x1f\xdb\xb5\x18\xbb\x67\x8e\xdd\x33\xc3\x18\xbb\x67\x0e\x18\x63\xf7\xcc\x61\x63\xec\x9e\xf9\xc9\xf1\xc4\xfa\x69\x8c\xdd\x33\xc7\x7e\x1a\x9f\x2b\xe7\xe9\xf5\xd3\x20\x63\xf7\x4c\xdc\x18\xbb\x67\x0e\x1f\x63\xf7\xcc\x61\x63\xec\x9e\x39\x5c\xe6\xd8\x3d\xb3\x1d\x63\xf7\xcc\xb1\x7b\xe6\x33\x3d\xba\x63\xf7\xcc\xb1\x7b\xe6\xee\x31\xbe\x11\x8c\xdd\x33\x87\x8d\xb1\x7b\x26\x5e\xe8\x18\xed\xe3\xe5\x3c\xbd\x68\x7f\xec\x9e\x39\x76\xcf\xfc\xe4\x88\x71\xdd\xb4\xc9\x39\xa2\x6d\xca\xc3\xf0\xa2\x7a\xb4\x6c\x87\x6b\x66\x56\xcf\xe7\x4c\x81\xdb\x0d\x33\x45\x25\x6e\x76\xd3\xf4\x4e\x43\x99\x02\x46\xa6\x73\xfc\x34\x33\x47\x40\xe1\xaa\x5d\xe1\x34\x4c\x11\x07\x78\xec\x4f\xd1\x53\xee\x40\xb3\x10\xc5\x34\x2e\xbe\xe6\x82\x9c\xbf\x7d\x3d\x4d\x40\x09\x1b\xc3\xa6\x06\x6b\xf2\x56\x64\xb1\xc5\x3a\xed\x21\x8b\x63\x36\x0a\xac\x46\xfe\xac\x65\x85\xd4\x0e\x5b\xeb\x36\x2f\x5b\x52\x21\x18\xa6\x40\xc5\x29\x44\x6e\x20\xed\x36\x63\x4c\x10\x59\x31\xe1\xf0\xff\x94\x68\x2e\x16\x05\xc6\x02\x50\x63\x68\xb6\x9c\xda\xef\x17\xe1\x80\xf9\x6e\x32\xcd\xac\x31\x57\xcd\x28\x46\x4b\x77\xd0\x14\x2b\x29\x77\xd3\x25\x34\x53\x52\x6b\x52\xd6\x85\xe1\x55\xc4\x84\x89\x66\x50\x66\xad\x5d\xcd\x7f\x38\x04\x04\x75\xdd\x34\x73\x60\x4f\xe0\xee\x6c\xd6\xc0\x2f\x2f\xca\x05\x6b\xaf\x1a\x04\xf0\x47\xd0\x48\xb0\xac\xcc\xda\x15\x44\x21\x2f\xf0\x9c\x2b\x6d\x48\x56\x70\x88\xe0\x60\x1d\x18\x58\x32\x98\x33\x06\x01\x4c\x45\x6e\x25\x0b\xbf\x47\xda\x6f\x92\xc8\xc1\x01\xad\x50\x0e\x3f\x94\xe5\x84\xba\x2f\x16\xa6\x9b\x73\xed\x03\x0a\x8d\x9a\x68\x60\x53\x77\x97\x2b\xec\x11\x5c\xaf\x1c\x49\x0b\x1c\xbe\xd9\x0b\xe9\x4c\x39\xe2\xfe\x03\x01\xba\xcf\x8a\x37\x26\xc0\x51\x97\x07\x05\x89\xfa\xfe\xed\x62\xdc\x40\x86\x0b\x06\x02\x21\xb2\x63\x52\xe0\x9a\x0a\xb6\xb2\xd6\x8b\x65\x8c\xaf\xac\x13\x8e\x10\xb9\xd3\x1e\x7c\x51\x73\x60\x98\x2a\xb9\x80\xa2\xad\x37\x4c\x6b\xba\x60\x57\xa8\xd7\xef\xfb\x62\x6b\x78\x00\x0f\x87\x11\x7d\x8d\x0b\x08\xb0\x5b\xe7\xb6\x2d\x41\xd8\x47\x95\x87\xb6\x1f\x4d\x4a\xf7\xd5\x0d\x2f\xca\xad\xe2\xc6\x30\x94\x63\xa3\x5d\xb7\x05\x00\x0e\x6d\x32\xf1\xe0\x26\xda\x29\xaf\x20\x6f\xc2\x44\xdd\x04\xed\xcf\x59\x27\x55\xe4\xa8\x1c\x97\x43\x39\xcd\x14\x67\x73\x32\xe7\x50\xc5\x00\x78\xfb\x23\xc7\xee\x4b\x31\xb3\xa5\x82\x50\xad\x99\x82\x75\xf5\x78\xeb\xb0\xbe\x53\xf2\x03\xba\xce\xd4\xa8\x5a\x64\xb4\xed\x95\x45\x84\xcc\x19\xe1\x73\xb2\x00\x64\x3f\x46\xeb\x40\x6f\xbe\xdf\xbd\xf8\xd3\xef\xc9\x6c\x6d\x03\x0d\xc0\xb2\x18\x69\x68\x11\x26\x8c\x10\x5a\x30\xb1\xb0\xa7\xdd\x99\xec\x3e\xa5\x50\x44\x99\x2d\x74\x55\x77\xb5\xaf\x2f\xbf\xbe\x99\xf5\x62\x32\x84\xc4\xe3\x9c\xad\x8e\x3b\x37\x60\x52\xc8\x45\xa7\x19\x3e\x42\x62\x28\xd5\xc4\x16\x2a\xa2\xc2\xfc\x1d\x8a\x0b\x3a\x7a\x46\xaa\xae\x40\x9c\x4e\x96\xf2\xd6\x75\x53\x69\x7f\x07\xb1\x34\x41\xbb\xb4\x75\x87\x95\xac\xea\xc2\x55\xb6\xbe\xe6\x28\x87\x0e\x34\x55\xad\xd9\x26\xf7\xcc\x3d\xba\x1c\xa7\x1c\xc2\x34\x37\x02\x21\xa7\x24\x22\x16\x42\x7a\xe2\x06\xff\xba\xd4\x30\x9f\xd7\x0a\x55\xf9\xf8\x9a\x16\xc5\x8c\x66\x37\xef\xe5\x77\x72\xa1\xdf\x8a\x73\xa5\xa4\xea\xad\x10\xe6\x1e\x53\xeb\x35\x2e\x6b\x71\xe3\x9a\x81\x87\x8f\x2f\xe4\x82\xc8\xda\x54\x35\x2a\xfa\x9b\x6f\x1e\xa7\x66\x4d\xe6\xb8\x73\xd0\xb8\xc8\xde\x29\xed\xcc\x94\xdd\x71\xdc\xd3\xc7\x2d\xb7\x0a\x4c\x10\x66\xd7\xd1\x69\xc5\xf6\xab\x71\xc1\x42\x47\x7d\x7d\xfd\xe2\x77\x7f\x74\x0a\x97\x48\x45\xfe\xf8\x02\x8a\x32\x51\xee\x2d\xb8\x02\xe0\x7f\x71\x4d\x74\x49\x8b\x82\xa9\x58\xc5\x68\xaf\x63\x47\x11\x36\x6a\xed\x8b\x6a\x35\x13\xab\xc0\x1e\x30\xf9\xf3\xfe\xfd\x7f\x41\xe6\x87\x1b\xcd\x8a\x39\xca\x2b\x2f\xb4\x6c\xfb\x1d\xed\x83\x33\xbd\xef\x7d\x11\x1b\x4d\x62\x54\xc0\xe3\xa6\x53\x56\xb2\xa8\x4b\x76\xc6\x56\x3c\xc3\x3c\x6b\xf5\xb6\xae\x27\x0b\x5f\xf9\x5c\x70\x0d\x84\xf4\xb3\x42\x66\x37\x24\xf7\xe2\x5a\x58\x3b\xc6\x0b\x59\xc7\xf2\x4a\xc6\x14\x21\xa0\x8b\x0f\xee\x5d\xdd\xb6\x74\x00\x95\xe0\xa5\xa4\xa4\x55\xd5\x90\x7e\x28\x7a\xdb\x5b\x6c\x94\x4c\xab\x79\xb9\xe8\xc6\xad\x98\xcb\x10\xf9\x38\x1c\xf3\x34\x3c\xf1\x5f\x8f\xf4\x39\xd0\x75\x09\xb1\xaf\xca\xed\xac\xb1\x0f\x5f\xbd\x63\xd6\x8a\x8b\xe5\x2e\xa8\x40\x86\x2b\x5a\x4f\xd4\x5f\xa2\xc3\x8c\xe4\xe6\xd9\x84\xbd\xf6\x40\x47\xb0\x8a\x19\x89\x7d\x74\x8c\x7e\xe9\x8b\xa9\x02\xe9\xed\x9c\x68\xde\x54\x4b\x6a\x50\xc9\x0a\x37\xba\x24\x7f\x94\x54\x4c\x69\xae\xad\x8f\xfe\x3d\x28\xa0\xd3\x82\x72\xec\xc3\x59\xf3\x78\x52\x49\xec\x56\x45\x2c\xb7\x53\xa0\xd0\x9c\x30\xd6\xd2\x5d\xc9\xdc\x8b\x03\xc3\x04\x69\x13\xd4\x8b\xca\x56\x9a\x25\x96\x92\x22\x99\xfb\xf7\x98\xa6\xee\xfb\x76\xa7\xe2\x2d\x9d\x95\xd2\x98\x3a\x27\xd9\x1b\x2b\xa4\xc4\xe7\x6b\xe0\x60\x2d\x9e\x9b\x7d\x6b\x26\x9d\x44\x49\x82\x61\xf3\xbe\x4a\x8c\x71\x6b\x63\xd5\xf6\xa5\x62\xc9\xbc\x52\x40\x4b\x6d\xd3\x2c\x3e\x13\x3b\xf5\x60\x51\x81\xee\x54\xd7\x4c\x95\xec\xbf\xda\x7f\x34\x23\xe7\x36\x51\xc9\x8a\x2e\x20\x77\x90\x64\x2f\x37\x85\x46\x20\xbc\x5c\x5a\x83\x69\x48\x9b\x81\x5c\x2c\x13\xa2\x1b\x95\x9f\x15\xcb\x5b\x0a\xf4\xa5\x04\x86\x85\x14\x47\xce\x27\x4c\x1c\x71\xe3\x6d\x44\x5d\x34\x55\xb2\x16\xb9\x7f\x0d\x6e\x20\x08\x6f\x36\x16\xf6\x12\xcf\x60\x06\x69\x1e\xc7\xd5\x0e\x44\x78\xae\x50\x92\x6b\x2c\x19\x9e\x97\x29\xc8\xcb\xe9\xcb\x17\xcf\xdf\x67\x83\x35\x49\xe4\xb3\x5d\x36\x3e\x9b\xb3\x72\x8f\xb6\x3a\xa1\x61\x72\x92\x15\x7a\xe3\x9f\xa4\x9a\xce\xc6\xf8\x43\x13\xba\x75\x82\xa8\x5b\xc5\x8d\xbf\x41\xb7\x3c\xa2\x50\xed\x00\x92\x36\x44\xaa\x2e\x05\xf1\x61\x9b\xcb\x8b\x08\x49\x62\x3a\x2e\xc7\xb7\x2c\x24\x44\xd7\xb3\x27\x67\x77\x9d\x81\x75\x4a\x75\xd7\x7b\x2a\x7e\xbd\xbd\xe4\x6d\x13\x8c\x96\xd8\xc5\x1e\xee\xed\x91\x03\xf7\x0b\xfb\x8e\xcd\xee\xf0\xd1\xae\xa7\xdf\xd6\xf3\xbb\x0a\xdd\x54\xa6\xb7\xb5\xe7\x77\x15\x15\x39\xcb\x5d\xc0\x1f\xe1\x5a\x93\x40\x3a\xbd\x6b\x8f\xe3\xcd\xe6\xbe\xee\xef\x31\x5a\x62\xd7\x3d\xfb\x2b\x5b\xd2\x15\x03\xce\x3f\x5e\x50\x15\xa1\x9e\x8c\x24\xd7\x6e\x67\xc8\xac\x36\x84\x89\x15\x57\x52\x94\x2c\x82\xd8\x7d\x45\x15\xa7\xb3\x82\x11\xc5\x80\x38\x38\x63\x9a\xfc\xfa\xe0\xfb\x93\x77\x00\xb3\xc6\xb7\x8f\xa0\x8a\x11\x16\x76\xbd\xd6\x50\x9e\x9b\xe8\x16\x76\x3e\x7b\xba\x71\x81\xf0\x2a\x7a\xe3\xe2\x85\x75\xb6\x37\x00\xbf\x06\x22\x6f\xf6\xcb\xae\x47\x59\x9b\x9a\x16\x40\xfb\x98\x15\xb5\xe6\xab\xc7\xb0\xbf\x9e\x86\xf3\x8c\x23\x6e\xf6\x06\x7d\x69\x7b\x69\xb6\xb8\x3d\x91\x14\xde\xe0\x5e\xa6\x6b\x29\xe9\x81\x97\xfb\x3a\x14\xab\xf4\x5a\x03\xa1\x1f\xe5\x3c\x6d\xf5\x0c\x26\x37\xe7\x8b\x5a\x39\x22\x1d\x9c\x0a\xea\x34\xb3\x2e\x01\x45\xf2\x58\xcf\x73\x42\xe6\x6c\x68\x4b\x8b\x7e\xe1\x8b\x17\xe0\xa8\xac\x3b\x84\x71\x3a\x5b\xb2\xbc\x1e\xf8\x02\xec\xe8\xdc\x65\x4e\xa4\x30\x92\xd0\xa6\x25\x16\xcc\x13\x60\x74\x7c\xf0\x73\xad\x90\x62\x02\x0f\xca\xee\x6c\x85\x79\xa9\xc0\xc7\x1a\xfe\x62\x98\xd4\xfe\x4c\x21\xfd\x6c\xe7\x78\x44\xa8\xd6\x75\xe9\x54\xdf\x40\xce\x50\x6e\xc8\x9c\x1b\xc0\x0d\xca\x5a\x65\x2c\x64\x75\xac\xd2\x1b\xc4\x93\x85\x3e\x09\xd7\xac\x80\xab\x8c\x3e\x0d\xfb\x97\x1d\x29\xee\x48\x68\xff\xa7\x41\x4b\xe1\xaf\x9c\x2f\x04\x02\x14\x72\x53\x0c\x2c\xe1\xcd\x7d\xce\x87\x2d\xae\x14\xd0\xdd\xdf\x9e\xa2\x66\x7e\x9d\x5f\x81\x30\x8b\x0c\x8b\x3c\xad\x34\x60\xc5\xa7\x33\x56\xe8\xcd\x09\xce\xda\xa3\x36\xcc\xa5\x00\x4a\x1c\x7f\x9c\x06\x17\x92\x04\xe5\x04\xf1\xf9\x31\xd5\x9a\x2f\xc4\xa4\x92\xf9\xc4\x4a\x3b\x1e\x82\x64\x42\x66\x24\x69\x1e\xf8\x83\xaf\x90\x09\x3e\xd4\xe9\x95\x2b\xa6\x96\x8c\x0e\x4a\x80\x6e\x60\x3b\xbd\x04\xa2\x58\xa5\x98\x06\xf0\x91\xe3\xbf\x73\xb7\x71\xd8\x1e\x06\x61\x54\x6b\x99\x01\x7f\x85\xc3\xa0\xa8\xda\x75\x55\xa0\x83\xdf\x3a\xec\xf1\xa2\x64\xc1\x57\x4c\x90\x77\xce\xc6\x9d\x16\x54\xeb\x5e\x02\x65\x30\x1a\x6f\xc6\x08\xad\x8d\x6c\xd0\x5b\x84\x9a\xb6\x77\x99\x03\x59\xcf\x86\xf9\xae\x76\xcd\xba\xf3\xeb\x88\xb3\x56\x4f\x49\xc0\xb4\x0c\x12\x79\x31\xff\x3c\xa9\xc3\xb4\xad\x0e\x9d\x13\x8e\xda\xed\x2a\x7d\x52\xb5\xed\xf3\x33\x48\xe6\x95\xcc\x49\x06\xe0\xcd\x60\x09\x3d\x04\xb3\x3b\xf5\x41\x12\x77\x7d\x66\xa8\xa6\xb0\x37\xb3\xf3\x93\x83\xe4\x86\xe9\x79\x1d\x68\x83\x15\x97\x3a\x6c\x0e\x6e\xa1\x18\xcd\x87\x6d\xbd\x66\x06\x6c\x74\x6f\xa3\x1c\x5c\x27\x78\x4c\x43\x11\xfa\xce\x7a\x34\xae\x16\xb4\x32\xaa\x58\x76\x44\x9a\xeb\x8a\x39\xf2\xa1\xd0\xa3\xe9\x64\x94\xb3\x39\x17\xed\xaf\x64\x52\x29\xa6\x2b\x29\xf2\xa1\xbe\x76\xf7\xd3\x8f\xda\x34\x92\xb5\xed\x9d\x1a\x98\x41\x22\x6b\x61\xa7\x0b\xb9\xdd\x96\xf1\xfb\xdf\x4c\xc9\xae\x71\x18\x24\xb1\xd3\x4f\x70\x7a\xf3\x47\xb0\x22\x4c\x2c\xa9\xc8\x9c\xab\x71\x7c\xc3\x2a\x7d\xac\xf9\xc2\x19\x8d\xaf\x5f\xbc\xfc\xd3\x8b\xaf\xbf\xfe\x3d\x98\x91\x70\x3e\xa6\xe5\xb0\x7d\xec\x27\x79\x69\x51\x2d\xe9\xc4\xb5\xa2\xa6\x80\xf1\xfc\x7b\x63\xd3\x06\x89\x5d\xbd\x9c\xbe\xfc\xfd\x11\xf1\x04\xfb\xd0\x55\x63\x29\x85\x54\x0e\x53\xed\x08\xe5\x86\xfa\x75\xd4\x78\xc5\x10\x0e\x5c\x73\xd4\x7c\x6f\x94\x41\x80\xe0\x47\x33\xa3\x15\x35\x86\x29\xf1\x8a\xfc\xf7\xc1\x3f\xbe\xfa\x38\x39\xfc\xe6\xe0\xe0\xc7\x17\x93\x3f\xfd\xf4\xd5\xc1\x3f\xa6\xf0\x2f\xbf\x39\xfc\xe6\xf0\x63\xf8\xc3\x57\x87\x87\x07\x07\x3f\xfe\xfd\xcd\xb7\xef\xaf\xce\x7f\xe2\x87\x1f\x7f\x14\x75\x79\xe3\xfe\xf4\xf1\xe0\x47\x76\xfe\xd3\x67\x0a\x39\x3c\xfc\xe6\xd7\xc3\x14\xdc\xf0\xd2\xec\x98\x72\xec\x88\x12\xec\x64\x65\xd7\x95\x62\x36\x1e\xe1\x52\x0c\x87\x76\xf7\x93\xa7\x1b\x82\x42\x2b\x46\xf7\xa7\xc1\xde\x45\x98\x97\x58\x58\xe7\x44\x3b\x87\xa5\x90\xb7\x50\x6a\xc4\xa5\xe2\x66\x60\x88\xff\x56\xc0\xc3\xc3\x25\x5b\x31\x75\x14\x66\xfb\x9d\x15\x78\x15\xe4\xe1\xf2\xe1\x46\xee\x94\xe6\x1b\xfe\x59\x2b\x34\xb8\x4f\xd3\x6e\xdd\xb4\xad\x57\x86\x99\x9a\x46\x07\x6d\xe9\x95\x4b\x29\xae\x9a\xf5\x0e\x1f\x30\x6c\xc6\x5e\x1b\x3d\x74\x60\x18\xf6\x1e\x7d\x4c\xdf\x43\xd9\xbe\xdf\x22\xb0\xb7\x53\xf2\x3d\x55\x5c\x0e\x44\xdc\x3b\xf4\x0b\xf4\x8f\x93\x02\xfc\x73\x87\x85\x6f\x2c\x0b\x84\x85\x03\x1d\x0c\xd3\x9d\x5c\x43\xbe\x11\x9e\x3e\x51\x1b\x73\xd2\xf8\x6c\xa7\xad\xcf\xd6\x75\x37\xb9\xb1\x77\x6d\x65\x3f\x61\x98\x27\xa0\xed\x49\x72\xf5\x7a\xae\xd9\x77\xe7\xeb\x9d\xa3\x89\xeb\x3b\xdc\xf1\x2d\x43\x24\xa0\xbb\x0b\x0b\x3f\x19\xd6\x02\x7c\x9b\x4b\x3a\xf4\x21\x11\x58\x75\xf9\x22\xd4\x56\xc3\x39\x70\x19\x99\xce\xdf\x62\xf4\x0c\xd6\x18\xe0\xe8\x0c\xaa\xcd\x55\x40\x5f\x8b\x7e\xbf\xc5\xa6\x2d\xe4\xe0\x8c\x62\x25\xf3\x7d\xdd\xae\x1c\xd9\x73\xf7\x04\x9c\xb7\x49\xa6\xb8\xe1\x19\x2d\x86\x65\xc9\xad\xde\x0b\x62\xb2\xa2\xd6\x86\xa9\x56\x12\xa4\xb5\xcd\xed\x30\xc0\x02\x7c\x29\x2d\xc8\x0d\x5b\xdf\x4a\x95\x87\xb8\x23\x7c\x75\x7b\x0e\x06\x92\xd2\xf8\xcf\xe6\xcc\x9b\x2b\xd7\x16\x4d\x95\x4c\x91\x19\x0b\x0f\x10\x11\x82\xd7\x53\x72\x22\xd6\x1e\x51\x21\xba\xec\x34\x3e\x64\x18\x6a\x0f\x20\x56\x73\x19\x80\xde\x85\xf2\x2e\x22\x7c\xc5\x70\x87\xd5\xce\x6c\x7a\x4f\x32\xbd\x92\x79\xf3\x35\xc3\x92\x70\x3e\x6f\x1e\xf2\xe8\x52\x11\xd7\x19\x08\xb4\xa4\x62\x8e\x9e\x62\x90\x48\x2f\xea\xc1\x6d\x96\x8d\x5d\xb9\x60\x5a\x7f\x6b\xaf\x14\x3e\x29\xd4\xbf\xa3\x14\x02\x38\x2f\x79\xd0\x77\x2f\xe0\x66\x87\x05\x65\x56\xf9\x39\x10\x90\x75\xbb\x64\xde\x4a\x1d\xa6\x53\x4f\xe0\x3f\x86\x52\x73\x9a\xaf\x5d\x87\x4d\x3b\x49\x6e\x3a\x35\x32\x03\x13\x0e\x8a\x79\x69\x27\x97\x67\xa1\xd8\xd3\xc5\x22\x1a\xd9\xa6\xb9\x69\x24\xe1\xbf\xd1\xaf\x06\xe4\x1c\x7c\x37\x2c\xf6\xaf\x9a\x0e\x8b\xe2\x8d\x24\x7b\xef\x55\xcd\xf6\x76\x65\x48\x3f\x1d\xd8\x32\x73\x2b\xd5\xcd\xf1\x8b\x17\x2f\xfe\x00\x71\x2d\x7c\xf2\xff\xfa\xfa\xaf\xff\xeb\xeb\xbf\x4e\xcb\x7c\x78\x80\x37\x14\x16\x8b\x00\xc4\x6e\x22\x8d\xdf\x75\xcf\x78\xd8\xee\xa1\x2f\xac\x6e\x63\xfc\x2b\x30\x10\x8e\xc1\x91\x6a\xf6\x1c\x91\xb9\x45\x80\x58\x71\xf0\xd5\x49\x3b\xcd\xf7\xeb\x6a\xa0\xd1\x44\xa3\x4f\x7b\xbf\x19\xff\x9c\xda\xca\x72\xfb\x80\xaa\xfb\x97\x0e\x7e\xec\x64\x75\xc0\xf4\xfb\x1a\xb9\x93\x6e\x40\xc5\x15\x98\x55\x78\x1e\x01\x73\xba\xae\xd0\x95\x68\x83\x75\x38\xd0\x67\x44\xc6\xc8\xfb\xef\x9c\x18\x52\xb9\x10\x19\xd2\xe8\xbd\x12\xf6\x81\x36\x31\x40\x95\x5c\x94\xe0\x43\xdc\x13\xe0\x50\x3a\x22\x6f\xc5\x6b\x57\xf4\x3b\xec\x9d\x19\x22\xe4\x96\x31\xc3\x48\x2f\x30\x29\x8f\xd8\xf1\xaf\xfc\x8a\x4e\xdc\x52\x0c\x57\x72\x43\x37\xb0\x93\x0b\x8d\xf2\x94\xf7\xdf\x6d\x48\xf2\x57\x65\x28\x6a\x96\xf6\x33\xd3\xde\xe3\xf2\xdb\x09\xcf\x6d\xce\x68\x0c\x33\xed\x4a\xd6\xd5\x91\xf7\x67\x5b\x94\x58\x68\xeb\xad\x6a\x31\x9c\xfd\x0b\x8e\x96\x73\xe7\xfa\x53\x6e\x9e\x86\xe1\x42\x0e\x7e\xb2\x76\x05\x3c\x39\xc9\x5c\x7a\x3a\x78\x87\x8e\xf6\xc5\xbd\x7a\xa8\x5a\x0c\x7e\x9c\x71\x19\x6a\xa9\x48\xe7\x99\x7d\xaf\x60\x0b\x9a\xad\xf7\xf0\x4f\x1f\x3d\xd8\x46\x88\x17\x34\xa1\x02\xe8\x6b\x79\xc6\x8d\xfb\x8e\xc1\xf7\x17\x0a\xc1\xa1\xc2\x1c\x7c\x78\xa7\x34\xc1\x8d\xae\x35\x22\xfe\x0a\xee\x71\x60\xfc\x5a\x52\x91\x43\xd9\x36\xca\x31\x91\x39\x3b\xf6\x92\x26\xf0\x79\xa8\x4c\x7b\xd3\x57\xbc\xe9\xe7\x1d\x9d\x66\xff\x1d\x22\xed\x3d\x50\x61\x34\xd0\x8c\x84\x71\x75\xf7\x8c\x0f\x7d\x26\xca\xb9\xae\xe0\x9e\xb9\xd7\x84\x20\xb4\x9d\xe7\xe0\x9b\x72\x4f\x78\xd6\x44\x5a\xcd\x0f\x0e\x0d\x2b\xc3\x21\x44\x4d\x0d\xb7\x59\x2c\xab\x21\x7a\x95\xc2\xb0\xbb\x41\x3c\xba\x7d\xe5\x7e\xdd\x17\x44\x96\xb2\xc8\x01\x5a\xe3\x92\xb0\x03\x9f\x0b\x9d\x2c\x42\x8d\x51\x7c\x56\xdb\x38\x83\x8a\x1c\xba\x30\xfb\x37\xd4\xe1\xb8\x32\x9f\x6b\xd3\x53\xd2\xf2\x3f\x75\x21\x88\xa0\x4b\xa6\x84\x5c\xb3\x81\x60\x27\xeb\xf4\x75\xd6\x02\x7c\x93\xb0\x91\x90\x1f\xb3\x77\x76\x90\x48\x46\xb3\xa5\x4f\x07\x7e\x81\x47\x2a\xac\x13\x3d\xd7\xdf\x5a\xa3\x39\xd4\x79\xee\x1d\x9b\xbd\x93\x26\xa7\xa4\xeb\xca\xd3\x99\x0f\x8c\x21\x49\x30\xdf\x4e\xfb\xd3\xaa\x2a\xb8\xab\xdc\x8c\xf0\x10\x89\x8b\x78\xa9\x33\xe2\xd7\xb2\x6c\x80\xcb\x76\x95\xb5\xeb\x83\x38\xdc\x83\x5e\x32\x50\xde\x85\x7b\xb9\xce\x96\x40\xba\x0c\x2f\xf6\xb7\x76\x8a\x4b\x5e\x0d\x96\x09\xd9\x6e\x6a\x9a\xe9\x01\x66\xc9\x8a\x0b\x84\x54\x83\x25\x56\x32\x7f\x45\xfe\x21\xc8\x4b\x97\x8c\x96\xb7\x80\x75\xf9\xf6\xe2\x2c\x68\x38\xd4\x77\xbf\xbe\x86\xe3\x42\xbe\x76\x52\x35\x33\x0b\x9e\x93\x99\xeb\x82\xae\xd9\x70\x1c\xf4\x81\x60\xb7\xae\x9e\xd6\x43\x27\x9a\x87\xff\x55\xa8\x03\x45\x90\x5a\x75\x17\xcf\x4f\xf9\x90\xfc\xd6\xcd\xb9\x62\x0a\x93\x97\x07\xb1\xdc\xd5\x9c\x91\xb7\xef\xf6\x03\x88\xe8\x76\xa2\x6e\x27\x93\xc9\xc4\xae\xf5\xc5\x30\x0d\x41\x02\xa2\xe0\xa8\x77\xa6\x1a\x17\xb0\x94\x39\x9f\x0f\x47\xab\xf7\x4e\x22\xa8\xdc\xf6\x93\xc1\xf3\xa0\x62\xb8\x50\xb7\x1b\xd3\xa1\x08\xef\x18\xa6\xe3\xce\xa3\xc0\xef\x7f\x87\x51\x6a\xa7\x70\x33\x71\x9c\x5d\x7d\xbb\xb8\x43\xa0\x4f\x3a\x0f\x57\x48\x33\xb6\xa4\x2b\x2e\x81\x8f\x1b\x74\x07\x54\x3e\x77\xf7\x6b\xf8\x5d\x6f\xf6\x37\x3c\x9b\xf9\xcb\xe3\x9b\x39\x41\xfa\x7d\xb0\x54\x76\x57\x49\xd7\xa2\x14\xf8\x21\xae\x64\x1e\x87\x6f\x23\x00\xa8\x2c\xd6\xa0\xdc\xd7\x56\xc7\xf5\x94\xb1\x8f\xda\x5c\x53\x8d\xc1\x82\xfd\x0e\x91\x19\xb5\x53\x6e\x96\xf3\x60\xe3\xf8\x23\x4a\x7a\x2e\xfc\x8d\x84\x1c\xa9\x90\x84\xcd\xe7\x36\x54\x95\x82\xb0\x6a\xc9\x4a\xa6\x10\x96\xae\xf7\xe1\x9e\x0d\xf1\x95\xf5\x98\x94\x55\x06\x0e\xa3\x55\xd2\x6a\xf8\xe1\xb2\x9f\x0b\x3e\x50\xce\xd5\x94\x7c\x4f\x0b\x9e\x07\xf7\xc5\xea\xad\xbd\xb7\xe2\x9d\x94\xe6\x0d\xd7\x10\xb4\x0e\xaf\xd7\x80\xd7\x28\x97\x10\xd9\xdb\x7e\xe4\xc0\xf7\xa4\x30\xb2\x15\x3b\x94\xe3\x0f\x8d\x22\x51\xb5\x38\x49\xe0\xfe\x58\xa3\x62\xed\x6a\x93\x61\x60\x84\x09\xa3\xd6\x95\xe4\x88\xc2\xa0\x4d\x1a\x96\x40\x2d\x3b\x25\x1f\x6c\x44\xec\xe3\x51\x44\xae\xd3\x53\x58\x35\xb0\x8c\x37\x74\xed\xc8\xb2\x1c\x08\x0f\xe3\x58\x6d\x84\x0b\x2e\x4f\xe2\xfb\x55\xcf\x24\x82\xc3\x60\x33\xfe\xb0\xc7\xed\x0a\xba\xa3\x75\xff\x7a\x78\xe1\x48\x8b\x2e\x6c\xcf\xea\xf6\xfc\x87\x8b\xa5\x37\x4c\x93\x4a\xb1\x8c\xe5\x90\xb4\x77\xb8\x73\x6a\xf0\x04\x14\x8f\x63\x30\xe1\x26\x5c\x4a\x50\x0e\x51\x77\xe1\xa2\xf3\x74\xee\x59\x80\xf0\x05\x44\xf0\xbc\x6b\xaf\x14\xd5\x50\x30\x20\x26\x4a\x4a\xc8\x0c\x29\x47\xe3\xac\x6a\x04\x71\xf3\x96\xab\xb5\xb2\x5a\x32\x3c\x7c\x43\x0d\xd0\x70\xb5\xd8\xa6\x9c\x6c\x10\x2a\x74\xad\x98\x5b\x01\x6e\x48\x2e\x11\x5e\x82\xd5\xab\xfe\xd3\x3f\x5c\x9c\x91\x17\xe4\x00\x0a\xe3\x1a\x32\x4b\x0c\x4b\x81\x4b\xbe\xf7\xb5\x0b\x9f\x87\x29\x4e\xd1\xee\x2b\x91\xca\xb3\x68\x5b\xfb\x08\xe6\xcc\xaf\x29\xc6\xc9\x0e\x09\x18\xdf\x78\x90\xe5\xa3\xaa\x7a\x00\x55\x85\xd3\x4b\x98\x52\x75\xd0\x2d\x1f\x34\x1b\x5c\xef\xb8\x65\x64\x3f\x7c\x01\x23\x8b\xe6\x04\x70\xcd\x74\x55\x7f\xd7\x40\x9b\x90\x92\x19\x9a\x53\x04\x97\x86\x33\xd6\x41\xe0\xd6\x3d\xc0\xb4\x1d\xf9\xd4\x3d\x88\x3e\x68\xf7\xdc\x83\xf6\x5c\x0f\x57\x5b\x3f\x73\x0f\xdc\xb9\x1e\x1e\x30\x3d\x7f\x93\xad\xd9\x77\x5c\xd4\x77\x2e\x0d\x3a\xf8\xe5\x7c\xeb\x6e\x5d\x9f\x83\x38\x47\xf6\x7c\x87\x22\xc1\x99\x31\x9f\xb6\xcb\xb7\xd3\x76\x53\xff\x36\xd5\xe4\xdb\x51\x7a\x71\xab\xa1\x4f\xe8\x9a\xe3\xf8\x63\x87\x9f\x55\xa2\xa8\xc8\x65\xb9\xf5\xf5\xf6\x50\x30\x8a\x20\x7b\xe9\xf4\x76\xdb\x71\x5b\x77\xde\xbe\xe1\xf7\xe1\xfe\xdb\xfa\xdc\xac\x50\xb2\xdb\x87\x62\x6b\x8b\xa1\x3d\x83\xf7\x90\x68\x16\xbd\xef\x00\xda\xce\x75\x73\x00\x87\x3f\xb3\x34\x13\xa2\x33\x56\x6c\x25\xcf\x23\x29\x75\x23\xa9\x4c\x94\x2c\x50\x1c\x4c\xbd\x35\x7a\x27\x0b\x5f\xd1\x1e\x16\xc9\x8a\xfd\xc5\xac\x91\x41\x41\x97\x36\x35\xf8\xba\xda\x58\x23\x33\x14\x85\x15\xc6\x53\x5c\xa3\x1a\xe1\x3d\x92\xcd\x35\xb2\x2e\x68\x7f\x8d\xac\xd8\x5f\xc4\x1a\x75\x5f\xdd\x20\x9f\x15\xe7\x0f\x9c\x34\xfc\xde\xf0\x22\xa7\x83\x59\xc7\xf8\xc4\x6d\x8f\x2c\xef\x62\x83\xfb\xce\x85\x7b\x1e\x6d\x96\x6b\xb8\x85\xe2\xa2\x29\xcc\xdb\x5a\x7c\x87\xc1\x2f\xa9\x1a\xfe\xce\xf1\xed\xc5\xd9\x94\x6c\x3a\x2b\x36\xac\xf5\x4b\x81\x7d\x8e\xa2\x79\xee\xfd\x22\xb1\x8e\x35\x76\x18\xde\x57\x24\xeb\x6b\x5c\xa7\xca\x08\xef\x76\xad\x33\x53\xc4\x1d\xe3\x6b\x27\x03\x40\x0c\x84\x86\x33\x3d\x3c\x13\x43\x4b\xa6\x2b\x9a\xb1\x3c\xcc\xca\x01\xca\x3a\x1c\x13\xc3\x2f\xfb\x55\x53\xd4\x57\x8b\xa6\x8f\x78\x23\xff\x60\x60\x9d\x3f\xb9\xcf\x3f\x3e\xf4\x54\x39\x73\x8a\x68\x70\x67\x24\x29\x68\x2d\xb2\xe5\x93\x3f\xa5\x3b\xb6\x3d\x3c\xcf\x11\x4a\x6e\x98\xc2\xb5\x77\xac\xa8\xa2\x25\x33\x4c\x05\x0e\x11\x44\xea\x29\x8a\x4c\x18\x4f\x25\x8c\xa4\x02\x9e\x20\x43\xf4\x38\x02\x61\x3c\x55\x67\x9f\xfe\xa8\x25\x44\x77\xd3\xc1\x12\xbd\x19\x89\xda\x6a\x12\xcf\xfc\x07\xab\x9f\x60\x29\xbe\x87\xd0\xed\xb9\xae\xc5\x2d\x17\xb9\xbc\xd5\xa9\x52\x1b\x3f\x38\x71\x2d\x81\x55\x00\x91\x0d\xcf\x17\x3c\x6c\x7a\x43\xba\x0f\xde\xd1\xa7\x63\x5f\x47\x87\xde\x5d\x08\xef\xf4\x3f\x3c\xe9\xf7\x4c\x72\x0c\x8b\x52\xd3\x53\x65\xa7\x6c\x38\x2d\xae\x2b\x96\x45\x07\x41\xdf\xbe\xb9\x3e\xe9\x8b\x44\x5d\x6d\xae\xc9\x2d\x94\x1d\xda\x0d\xb6\x32\x3b\xe4\x38\xb7\x6c\xb6\x94\xf2\x06\x25\xf7\xa0\x03\xce\x5e\xd6\xb3\x69\x26\xcb\x4e\x8d\xc5\x44\xf3\x85\x3e\xf6\xda\x61\x62\x57\x07\xc7\x8f\xc9\x05\x34\x05\xdb\x6e\x6e\xe7\x3f\x06\x25\x34\x6b\x56\x15\xce\xae\x47\xf7\xfb\xae\x46\xdb\xcb\x7e\x89\x63\xea\xf7\xe4\x08\x5f\x3c\x02\xdf\x3e\x8a\x43\x71\xe1\x61\x7c\xe2\x38\xa2\xd7\xc5\xf3\x6d\x84\xae\x28\xcd\xc1\x6c\xf7\x05\x25\x16\xf6\xd2\xbd\xed\x7c\xf9\xf4\x59\x78\x39\x4b\xb2\xd6\xf0\x82\xe6\x85\x59\xa5\xea\xcd\x22\xce\xb4\xef\x7a\x85\x4b\xd3\x41\x68\xeb\x25\x2e\x44\xf7\xe8\x6c\xcd\xcf\xbc\xc8\x11\x3e\x3c\x1e\x24\xee\xd9\x3b\xe9\xab\x1c\x71\x21\xe1\xd6\xf3\x40\x63\xa6\x51\x12\x1f\xf4\x85\x80\x3c\xdc\x2b\x01\x49\xf0\x5e\x4d\xf0\xb5\x14\x6a\xc5\x33\x76\x92\x65\xb2\x16\x11\xa5\x14\x67\xcc\x4e\x9e\x1a\x96\x5f\xf7\x24\x0e\xa5\x4c\xa5\x24\x07\x49\x8e\xb8\x90\x16\x9c\x3a\x7a\xcb\xbe\xd4\xe1\x1c\x20\xed\xfc\x20\x35\xba\xf1\xdd\x5e\x49\x68\xc3\x28\xa6\x7c\x21\x6a\xcd\xe3\xea\x13\xb7\xd7\x05\xd3\x24\xad\x6b\x46\x36\xf6\xcf\x19\x03\xaf\x02\x07\x09\x0d\x3c\xb5\x9f\x5b\x4a\x6a\xa8\xbe\x69\x69\x44\x19\x14\xc7\x37\xca\xb5\xf3\xf7\x7e\xf9\x26\xd4\xcd\x10\x41\x2d\x3a\x74\xbf\x96\x54\xb1\x2b\xa7\xa8\x2f\x43\x7a\x2c\x62\xcb\xac\x38\x42\x89\xe6\x62\x51\xb0\x26\x51\xdc\x24\xde\x06\x2d\xf2\x8c\x99\x5b\xe6\xb9\x17\x36\x0d\x92\x6e\xab\x41\x06\xc9\x04\xfe\x21\xe3\x8b\xf9\xac\x42\xde\x68\xba\x0d\x09\xde\xd9\x50\x7e\x65\x49\x56\x9c\xdd\x82\x42\xd6\x7c\x21\x68\x11\xbe\x9c\x79\x62\x21\x60\x3a\x19\x24\xb3\xff\xa5\x40\xb1\x6c\x0f\x72\x25\xf3\xa3\xa6\x23\x0d\x64\xe3\x07\x49\x0d\x1b\xb2\x95\xb5\xef\x56\xab\x0e\x53\x6a\x40\x86\xcb\x72\x72\x75\x71\x46\x5e\x4e\xc9\xdf\xa4\x36\xf6\x5f\x81\xb1\x7d\xd7\xe1\x1a\xb6\x0a\x9e\xc0\xdb\x9a\x3f\x67\x93\x77\x94\x8b\x0d\xdd\x2b\xd7\xe8\x63\xf8\xd5\x1a\x0a\x99\xd2\xf5\x2c\x97\x25\xe5\x83\xfa\x2f\x7d\xa2\xe8\x72\x5e\x17\xc5\x9a\xfc\xab\xa6\xc5\x70\xc6\x90\x2b\x99\x43\x5b\x24\xd0\x88\xe1\xb0\xef\xfd\x39\xfc\xd5\x5f\xa6\x7f\x6e\x66\xfc\x97\xe9\x9f\x87\x32\xe9\x36\x77\xfc\x2f\x53\xbd\xca\xa6\x7f\xf6\x0c\x47\xc4\x0b\x6c\x30\xe6\xc3\x1e\x0f\xee\xa9\xea\xb4\x87\x02\x50\xfc\xd4\xcb\x1f\x9c\x23\xa5\xc6\xea\x95\x07\xaf\xe7\xec\x74\xf0\xfe\x56\xd1\x8c\x5d\x31\xc5\xc1\x65\x93\x22\xc7\x33\xe8\x84\x2b\x40\x72\xcf\x49\x6d\x2f\xb4\x76\x42\x07\xda\x31\xb7\xa8\x82\xb1\xdc\xb9\xe7\x7e\xbe\x8c\x2c\xec\x74\xe1\xb8\x0d\xd3\xb0\xd6\x87\x06\x7a\xa3\x4c\x31\xea\x8a\x4e\x48\xce\x0a\xd6\xb2\xf7\x4e\x5d\x52\x73\x90\xd4\xc0\x0f\x25\xa4\x98\x08\xb6\xa0\x86\xaf\x58\x78\xcc\x72\xc5\x60\xc3\x93\x53\x8e\x76\xa9\x81\x39\xfb\x49\xf2\xb2\x64\xb9\x75\xd1\x8a\xf5\x60\x1c\x2d\x18\x16\xe7\x46\x73\x4d\x04\x2f\x8e\x7c\xf7\x54\x87\xd8\x87\x25\x25\x15\x1c\x81\x81\x69\xd4\x36\xe3\xd7\xf8\x72\xf0\xd5\x68\x91\x3e\xc8\xde\x71\x80\x08\x9d\x9b\x86\x38\xce\x5b\xb1\x41\xa2\x03\x1b\x77\xcb\xe8\x01\x15\x2b\x9a\x09\x43\x68\xf7\x46\x0c\x53\x05\xce\xb0\x06\xdb\xe7\x30\x63\xce\x9a\x63\x27\x6a\x67\x35\x97\x2a\xe3\xb3\x62\x4d\x96\xb4\x68\xf8\xc4\x29\xb9\xb1\x2b\xee\x7e\x72\xd8\xf1\xbf\x66\xa6\x7b\x0c\x0a\x29\x16\xb0\x98\xd4\xc7\xd8\x77\x15\x30\x2f\x0f\xb3\x82\xd6\xec\xd4\x95\xfb\x66\x1b\x31\xac\x65\x1d\x0b\x74\x35\x92\xfc\xf6\x45\xd8\xf2\x2f\x4c\x0c\x38\xe0\x05\xd9\xc8\x82\xb9\x13\x8a\xd7\x96\x3b\xa9\x0b\xf6\x75\x57\xf6\xf0\x05\xf8\xd2\xd4\x54\xef\x43\x0f\x04\x7b\xb6\xde\x37\x33\x1f\x1a\x83\x5a\xc3\x67\x28\x90\x2f\x58\x6d\xef\xe4\x40\x39\xff\x9a\x58\x4f\xd0\x0c\x6f\xb0\x41\x02\x6d\x8a\xbb\x97\x8a\x57\x05\x23\x7f\xbe\x61\xeb\x23\xc7\x46\xe9\xaa\xec\xfe\x32\x50\x66\xdb\xe8\xa8\x61\x49\x92\x95\x9d\xac\x54\xe4\xcf\xe1\xdf\xfe\x32\xec\x6e\xa2\x93\xff\xf8\xd4\xbf\xfb\xf8\xc8\x77\xf0\x73\x57\xa7\x88\x27\xb3\x74\xc3\xed\xaf\x2f\x7a\x34\xd2\x2d\xec\x94\x9c\x03\x69\x4b\xc9\xe8\x60\x9a\x33\x12\xf6\x1e\x42\xb4\xae\x78\xed\x99\x5e\x23\x9e\xd1\x88\xab\xe9\x67\xbd\xaa\xc7\x4b\x79\xed\xa9\x38\x80\xf9\x78\xce\x54\xfb\x37\x98\x5f\x10\x39\xb9\x94\xe7\x77\x2c\xab\xcd\x97\x22\xe0\x72\xe3\x86\x21\x1a\x36\xf6\x0e\xc5\xdf\x59\xc3\x4c\xed\x56\xfe\x86\x61\x5e\x86\x9b\xe2\xae\x56\x1b\x76\x90\x70\x98\x5c\x5d\xe7\x3c\x6d\x9d\x8e\x1b\xb6\x1e\x48\xc6\xe8\x86\xef\x55\x71\xe3\xbe\xd9\x13\x22\x35\xfa\xc0\x3a\x87\x08\xa1\x33\x46\xce\xef\xb8\x36\xfa\xff\x38\xad\x9a\xc9\x72\xe6\x3d\x13\xf4\x75\x08\xd7\x0a\xbe\x39\x1c\x5c\x91\xc3\x1f\x71\x1f\x1f\x71\xc8\xc2\x02\x45\x9e\xb4\xb7\x61\x9d\x3b\x3d\x5c\x30\xdd\x64\x6f\xd8\x7a\x5f\x13\xc5\x0a\x67\x73\x97\xbc\xea\xb5\x8b\xc0\x9c\x0b\x57\x16\x1d\xbe\xd3\xe9\x08\xb7\xa7\xb0\xea\xe7\x36\x50\xc6\xc8\xed\xbe\x58\x38\x21\x41\x2c\x07\x5a\x4d\xbe\xa2\x05\xae\x57\xa0\x91\xd6\x9b\xcf\x33\xaa\x1c\xee\xcc\x33\x36\x6b\xdf\xed\x0a\xb3\xae\x40\x2d\x69\xfd\x4b\x6f\xcd\xdb\xfb\xe6\x38\x22\x70\x78\x29\xc3\xb3\xba\xa0\x8a\x58\x8b\xb3\x40\xf5\xa1\x8b\x38\xb9\xad\x32\x42\x84\xca\x6e\xf4\xbd\xa7\x4d\x79\x9d\xb3\x8c\x52\x9a\x21\xe6\x82\xc4\x24\x14\x8b\xf6\x54\x28\x42\xe6\x41\xbf\x3b\x97\x9c\x07\x4b\xdd\x18\x28\x8c\x0d\x6d\x7b\xa5\x98\x5e\xaf\x10\xbe\x00\xde\x7d\xcc\xab\x7b\xeb\x34\x36\xb6\x67\x4a\xfe\xda\x90\x65\x61\x66\xe9\x48\x67\x9a\x8e\xd8\x7e\x25\xc0\x82\x84\x5f\x43\xee\x92\x33\x3b\x73\xa9\xd8\x8a\x29\x72\x90\x4b\xf8\x15\xb6\xe2\x19\xae\x27\xec\xff\xc3\x94\x04\xd5\xd2\x24\x21\xbc\x92\xc7\x52\xf1\x90\x6e\xff\x99\x17\xe4\x00\xa6\xd6\x4d\x42\x60\xb6\xc8\x63\x15\x1c\xd7\x38\xf6\xe2\x7e\x79\xa8\x30\x1a\x35\xb7\x03\x31\xd7\x73\x8d\x70\xc0\x25\xb2\xe9\x17\x35\x71\x8e\x9c\x7a\x8f\x04\x73\x23\x83\x35\xe5\xda\xdb\x94\xa3\xee\xeb\x2b\xb6\x59\xee\x8c\x35\x6e\x51\x73\xe5\xff\xc7\xea\x12\x4a\x14\x5b\x58\x4d\x8e\x10\xea\x74\xf7\x17\xd2\xfc\x46\x56\xb2\x90\x8b\xf5\x75\xa5\x18\xcd\x4f\xa5\xd0\x46\x81\x11\xc3\xb7\xc8\xb8\x4f\xa2\xff\x3f\x9b\x0d\xcc\x17\x2d\xe5\x2d\xa1\x9e\xdb\x4c\xce\x5d\x3b\x17\x59\x2f\x96\xae\x33\x27\xfc\x08\xa1\x99\x92\x03\xd9\x33\xc3\x87\xfb\x54\xb6\x9e\x92\xeb\xa6\x9b\x26\xa8\x15\x54\xd3\x4f\x98\x1d\x3c\x92\xdd\xd2\xb5\x57\xa9\x74\xc6\x73\xa6\x83\x7a\xc8\xda\x05\x19\xda\x74\xa2\x6b\x4a\x36\xfb\x43\xf9\xc4\x7f\x5c\x83\xa8\xf3\x15\x13\x57\x32\xd7\x6e\xeb\x30\x5d\x59\x08\x39\xb1\x6e\xd0\xbd\x47\xc0\xba\x8a\x27\x97\x67\xc3\x7a\xc2\x3e\x52\xee\xe7\x9e\x8f\x18\x78\x2f\x43\x30\xae\xe1\x20\xb7\x47\xb6\x49\xb0\xd8\x23\x33\x34\x9b\x54\x4a\x9f\xa6\x71\x3d\x14\xc3\x7a\x7f\xa1\xc4\x0c\x96\xe2\xbc\xa4\x77\xd7\x37\x6c\x18\x61\xe0\xa4\xf9\xb8\xbf\x0f\x8c\xb4\x27\x90\xa8\xfe\x20\x34\x35\x5c\xcf\xf9\xe0\xf7\x65\x7c\xfa\x09\xca\xdb\x30\xfd\x67\xdd\xe8\x57\xb8\x76\x65\xd9\x8b\x5f\x6b\x44\x21\x19\x09\xfd\x84\xfa\xc7\x6e\xea\xea\x68\x10\xc9\x47\xd2\x24\xa1\xc0\xc3\x75\x05\x7d\xa1\x3d\x2e\xdc\xf2\xcc\xb5\x8f\xc7\x4d\x35\x67\xee\xc1\xc2\xa9\x25\x51\x97\x33\xa6\x82\xf2\xc7\x78\xba\xf0\x0c\xc0\x55\xbf\x19\x62\x73\xb2\x10\x12\x9d\xd1\xc0\xda\x68\x64\x39\x4b\x5c\x95\x08\x6c\xd7\xf9\x9d\x0d\xc0\x34\xa6\x2e\xc0\x8d\xde\xe1\xdc\x14\x89\x92\x48\x5c\x51\x69\x28\x99\xec\x1f\x25\xa4\xc4\x5e\xb7\x69\xc8\xe2\x77\xff\x06\x29\x14\x65\xbb\xda\x81\xaf\xea\x72\x03\x59\xdb\xe5\xc6\x66\x7d\x6a\x8a\x45\xee\x2d\x73\x44\x83\xec\xee\xe8\x72\x19\xf8\xd7\x3c\x7d\x04\x35\x68\x6b\x1c\xc4\x92\xf8\x84\x33\x15\x6d\x0c\x00\x3f\x02\x19\x31\x44\x15\x44\x3b\x53\x97\x19\xb5\xc2\xdd\x3c\x71\xc7\x22\x52\x27\xb8\x81\x2f\x74\x73\x63\x82\xcc\x63\xbb\xff\x36\x2c\x2c\x52\x40\x9c\x5a\x73\x03\x95\xd9\x6f\x47\xef\x7a\xdc\x34\x39\xfe\x08\x89\xa1\xc8\xdd\x0a\x6b\xb2\xfd\xd1\xd7\x83\x34\x45\x54\xd8\x77\x82\x30\x22\x0b\xed\xdc\xc0\xa7\xba\xdb\xd1\x5b\x7a\xb9\x9d\xf4\x8e\x5b\xab\xdd\xe9\xef\x48\x99\x40\xd9\x36\x0f\xb7\xde\xa5\xc3\xa3\x44\xf6\x53\xe9\x17\xe2\x88\x5c\x4a\x73\x21\xf0\x1a\xcf\x8e\x4e\x46\xfe\x4c\x32\x7d\x29\x0d\xfc\xcd\xa3\x1f\x1a\xb7\x6c\xc9\x8e\x8c\xcf\x04\x42\x37\x8d\xb8\x7d\xb5\x96\xd9\xee\xab\xfb\xbe\x48\xa5\xee\x86\x7f\x41\xeb\x66\x9f\x2e\xe2\x66\x29\x95\x3f\x1b\x6d\xfa\x4a\x47\x38\x15\x61\x74\x91\x5e\xbe\x07\x00\x82\x59\xa9\x3b\x36\xbf\xdb\x1d\xc7\xd8\x6f\xef\x9e\xe4\xee\x12\x24\xd8\xf9\xb0\x04\xfe\xf3\x07\x77\xdd\xdd\x2d\x15\x1a\xda\x55\x05\xd0\x1f\xe4\x75\xd4\xc5\x21\x4e\xf9\x18\x45\x0d\x5b\xf0\x8c\x94\x4c\x2d\x18\x81\x26\x1b\xf1\x97\x3a\xf6\x08\x45\x79\xa7\xdd\x89\xa0\xb5\x0b\x04\x23\x10\x2e\x27\x0b\x6d\x9c\x34\xd0\x2d\xc8\x2f\x2b\x29\x24\x2d\xff\xdf\x06\x98\xf3\xff\x91\x8a\x72\xa5\xa7\x04\x57\x25\x49\x02\xc8\xbf\x2b\xd1\x43\xfe\x3a\x53\x8e\x98\x6d\xef\xa9\xd5\x11\xae\x10\xe6\xc8\x71\x90\x52\xe5\x7c\x2b\x50\x3c\x22\xb7\x4b\xa9\x59\x84\xd7\xd9\x24\x42\xf7\x6e\xd8\x7a\xef\xa8\xa7\x6e\xf0\x61\xe8\xde\x85\xd8\x6b\x91\xfe\x09\xb4\x6b\x13\xca\x40\xbe\x76\x0f\x24\xee\x3d\xad\x88\x34\x22\xf0\x88\xef\xec\xbf\x39\x19\xd4\xed\xf7\x79\xc5\xc8\x4c\xdb\xfe\x1b\x27\xa6\x7d\xa6\x40\x86\x00\x39\x5b\x28\x06\x05\x4e\x2e\xff\x0f\x6f\x02\xa5\x03\x68\xd7\x82\xad\x98\x28\x50\x29\x27\xae\x7d\x1f\xa0\x7c\x4a\x2e\xcc\xfe\xbe\xf6\xb7\xfe\x8e\x97\x75\xe9\x48\xfa\x0d\x2e\xe3\x96\xf3\x79\x68\x9b\x19\xca\x7f\x7a\x79\x37\xac\x36\x6e\xda\xef\x73\xe1\xb0\x8e\xb7\x32\x3e\xe9\xe6\xe0\x15\x1b\x99\x6f\x64\x33\x47\x42\x5e\x4b\x45\xd8\x1d\x2d\xab\x82\x1d\xb9\x87\x9b\xdf\x4e\xfe\x2d\x05\x0b\x0f\x2a\x18\x1f\x3c\x1c\x24\x5f\xec\x64\x24\x79\xe9\x94\x4a\x15\x58\x8b\x90\xaf\xa2\x50\x8c\xd4\xcb\x2e\x37\x0f\x60\x18\x15\xf2\xf2\xf8\xe5\xf1\x8b\x57\xe4\x23\xb1\x1f\xfc\xd2\xff\xf3\x6b\xff\xcf\xdf\x92\x8f\x08\x91\x1f\x09\x21\x57\x1b\xff\x74\x7f\x3f\x21\x7c\x1e\x56\x06\x93\xc2\xd5\x76\x11\xb9\xc8\x64\xe9\x4f\x15\xa0\x6f\x40\xad\xce\x58\xf3\x58\x87\xcc\x37\xbb\x0f\x06\x96\xa2\x4c\x96\x0c\x56\xe6\xe5\xff\x09\x52\x71\xfe\x08\x37\x44\x0a\x2f\xfb\xe5\x01\x2c\xed\x21\xb9\x85\x9e\x8a\x25\xbd\xc1\x3e\x8c\x9f\x64\xa6\xa6\x85\x5d\xc4\x83\xaf\x27\x2f\x0e\x89\x14\xbd\x1f\x40\x48\x5d\x71\x59\x50\xc3\xc2\xde\x1c\xbc\x3c\x9c\x26\xd8\xac\xaf\x77\x6c\x56\xe4\x3e\xc1\x6a\x5a\x35\x62\x3f\x35\xa8\x40\xda\xe4\xbe\x10\x12\x1d\x17\x44\xd3\xab\xb4\xa9\x21\x79\x09\xb7\xf5\x05\xee\xcb\x85\x34\x01\x44\x3b\xb8\x15\x47\x42\x14\xc8\x6f\xbf\x1e\x8c\xfe\x6a\xde\xd9\xa2\x71\x5f\x8d\xa4\x80\x08\xc1\x39\x7a\x72\x0e\xad\x4c\x9d\xca\xd3\x53\x72\x29\xf3\xd0\x19\x61\x49\x57\x28\xec\xb1\x4f\xcb\xf9\x06\xfb\x5c\x37\x39\x5c\x0e\x2c\x17\x19\x8a\xe6\xa2\x83\x95\xce\x24\x74\xfb\x51\x0e\xea\x3f\x63\xde\x39\xc7\xc0\x40\x28\x74\x43\xf0\x2f\xbb\xe4\x87\x56\x36\x8e\x5a\x99\xb8\xf2\x00\x37\xd9\xbf\xb8\x9e\x10\x7b\xb3\x3a\xbb\x61\xc6\xf9\xbc\x28\x14\x15\xf4\x21\xaa\x6a\x43\x66\xb4\xa0\xc2\x46\xb9\x09\x5e\xeb\x8c\x74\x85\xb2\x6e\x76\x70\xd5\x93\xdc\xf4\x2f\x03\xa9\x71\x63\xeb\xf1\x39\xd6\x3d\xfd\x61\x53\x60\x5b\x9a\x80\x58\x10\x0f\x46\xc8\x19\x2d\x42\xf5\x15\xf4\xdf\x6f\xda\x59\x88\xfd\x7d\x4c\x50\xe0\xe6\xe7\x91\x70\xce\x37\x69\x11\x2f\x53\x32\x41\x88\x3c\x93\x97\xd2\x04\x70\x0e\x39\xf0\x88\xc7\x43\x62\x58\x51\x60\x7d\xf4\xa6\xb7\x28\xa8\x6b\x23\x9b\xbf\xb0\x9f\x3f\x69\xa0\x40\x27\x62\x7d\x8b\x8a\xfd\x9a\xb9\x75\x7e\xc9\xfe\x8a\x41\x23\x8b\xdc\xe0\xc6\xdb\xbd\x8e\x9e\xa1\x9a\xec\xf5\x0e\xc6\xf0\xb6\x54\xd0\x2a\xc1\x6a\x41\xf0\xa7\xf8\x9c\x54\x05\xcd\x5c\x35\xa1\xb3\xe1\x08\x89\xf6\x38\x49\xef\xf7\x07\x2f\xdd\xfb\x1a\x9a\xec\x79\xe7\x62\x6f\xf4\xd9\x87\x8d\xdf\x5a\xcf\x34\xb5\xcf\x7e\x05\xff\x6f\xdb\x77\xbf\x98\x93\x2d\xad\x83\x73\x8a\xfc\x9a\xf6\xae\xf2\x51\xec\xe9\xda\x19\x00\x04\x77\xfe\x6b\xf0\x88\x7f\x8b\xc3\x5a\x87\x38\xe0\xb7\xc7\x5f\x1f\xbf\x3c\xb0\x6b\xfe\xf5\xa1\xbd\x67\x3d\xef\xfb\x25\x46\xb6\xf7\xd7\xc3\xec\xbc\xbe\xe4\x4c\x77\xfd\x6f\x84\xdc\x0b\xe1\x20\xa8\xe4\x56\xaa\xdc\x83\x5b\x03\x19\x40\x86\x7a\x19\x71\xba\xca\x7a\x30\x65\xb0\xed\x47\x64\x56\x77\xfa\x32\x23\x84\xde\x4a\x6b\x57\x20\x00\xb2\xba\xec\x37\xa5\x54\xec\x37\x9d\x5f\x40\x7d\xfa\x46\x20\x80\x68\x1a\xec\x06\xd2\xda\xdf\x4d\x3a\x14\x7b\x05\xd7\x66\x52\xd2\x6a\x72\xc3\xd6\x83\x72\x61\x58\xa0\x5b\x1c\xcc\x6d\x7b\xee\x6e\x11\x4a\xfa\xf9\x3d\x78\x5d\x33\x46\x3c\x60\x78\xff\x3b\x0f\xfd\xf1\x82\x3c\x08\x04\x02\xc6\x41\x7b\x58\x3a\xc8\x19\xc0\x61\x5b\x22\x97\x19\x2b\xa4\x6b\x12\xea\xea\x9e\x06\x89\x1c\xc0\x36\x94\x49\x91\xb1\xca\xe8\x63\x6d\xa4\xa2\x0b\x76\xec\x3f\x67\x38\xe5\xc9\x97\x46\xba\x7e\xef\xba\x69\x76\x0b\xcd\x1c\xfd\xe2\xc0\x1b\xe4\xbb\x72\x06\x8e\x20\xb7\x8f\x3e\xf1\x49\x33\xa0\x0a\x18\x2a\x72\xb6\xee\x13\xbe\x77\xe8\x0d\x9e\x38\xd8\x75\x30\x37\x0a\x1e\x06\x43\x6f\xf5\x79\x41\xb5\xe1\xd9\x5f\x0b\x99\xdd\x5c\x1b\xa9\xa2\xa3\x8d\x93\x1f\xae\xb7\x64\x22\x74\x73\xf7\x4c\x09\x72\xf2\xc3\x35\x39\xe3\xfa\x86\x28\xa6\x65\xad\x06\xd2\x12\xb9\xe1\xba\x02\xea\x5e\x45\x3d\x25\x37\xae\x21\xe1\xfe\x3e\x2e\x16\xd2\xf6\x9c\x66\x4b\x2e\x58\x78\xfc\x11\x4d\xfb\x5e\x14\x5c\x24\x9c\xd1\x48\xdd\xf1\x2b\x7a\xab\x99\xdb\x86\x99\xdd\x06\xfb\x3f\x33\xac\x61\x7b\x04\x12\x75\xf7\x19\x17\x67\x83\xff\xd3\x38\x4c\xd8\x5c\xbf\x47\x76\x85\xd9\xbc\x06\xaf\x79\xc1\x5c\x41\x17\xbe\x23\x0c\xd9\x68\x2a\x0d\x27\x78\x2d\x6b\x72\x4b\xd1\x6f\xaa\x46\x3a\x6b\x37\x25\xef\x79\xf5\x8a\x9c\x77\x3a\x66\xe2\x71\x6b\xf3\xfe\xc7\x82\xdf\x1e\x7a\x2b\x20\x45\xfa\xa2\x17\xb8\x61\xee\x79\xd6\x1a\x62\x6c\x89\x9c\x1b\xe7\x2e\xf4\xd3\xaf\xc8\x1e\xbb\x33\xbf\xdb\x3b\x22\x7b\x77\x73\x6d\xff\x21\xcc\x5c\xa3\x22\x4a\x3b\x2e\xca\xaa\xe0\x19\x37\x36\x00\x16\x73\xa6\xda\x14\x9e\xfb\x19\xec\xab\xf2\x66\x0f\xc2\xf4\x0a\x01\x39\xb3\xf7\x6f\xcf\xde\xbe\x82\x44\x50\x2e\xc9\x2d\x23\x95\x62\x2b\x26\x0c\x61\x4a\xc9\x81\x85\x44\x9d\xcf\x15\x9e\x24\xaf\x39\x4a\x40\xc5\x97\xc9\xb2\x52\xb2\xe4\x1a\x0f\x80\x71\x8f\x9d\xa0\xa4\x87\x6b\x40\x12\x8f\x2f\x81\xea\x6c\x50\x0b\x09\xf4\x0a\x10\xcb\x04\x81\x58\x7e\x5a\x72\xaf\x56\xc1\x63\x1c\xbd\x56\xb9\x98\x13\xe9\x9e\x93\x7b\x64\x5a\x78\x64\x45\x50\x58\x56\x23\xf8\x19\x8b\xc1\x9c\xab\xed\x68\x75\xc0\x6b\xa9\x82\xc0\xe3\x9c\xad\x8e\x75\x4e\x5f\x62\x81\x93\x76\xf9\xdc\x55\x75\x6a\xab\xdd\x21\x54\xae\xc6\x8e\xbd\x97\x7b\x53\x72\xcd\x4b\x5e\x50\x55\xac\x8f\xba\x3b\xd6\x48\xc7\xaa\x6b\xa9\x9a\x4f\x06\xf0\xca\x8b\x3d\x72\xe0\x78\xaa\xb0\x68\x15\x2a\x48\xc1\xe8\x8a\x05\x7a\x2f\xe8\x7c\xe1\x10\x71\x87\x88\x80\x9a\x44\x3f\x68\x91\xc8\x47\x2d\x02\x0e\x0c\xcd\xdf\x8a\x02\x09\x10\xdf\xa0\x5a\xf5\xa7\x63\xcf\xa8\x9a\xed\xe1\xaf\xd9\x5c\xaa\xcc\xf9\x9a\x90\x19\x5b\x32\xf2\xce\xcf\x32\xb6\xe1\x08\x17\x3e\x9e\x7b\x63\xaf\x1b\x5c\x3c\x37\xd9\x08\x44\xe7\x2e\x55\x00\x27\x0e\x48\x3d\xd1\x16\xf7\x49\xf8\xc6\x24\xaa\x39\xb3\x1b\xc1\xcd\x4d\x71\xc2\x3e\x08\xfe\xaf\x9a\x91\x8b\x33\xef\x35\x22\xd7\xb6\x62\x4a\x73\x6d\xac\x3d\xcf\xbb\x11\x17\xde\xd6\xd8\xe0\xed\xe0\xa4\xa4\xff\x96\x82\x9c\xff\xf5\xda\x7f\xf4\xa1\xf3\x68\xd0\x87\xf5\xa9\x6c\x3e\xca\x2d\xa0\xff\xae\x15\xb3\x01\x6d\x64\xb4\x7d\x12\xe4\xc4\xd5\x3d\xd8\x08\xdb\x4a\x22\x67\xd4\x50\x17\x68\x3b\x9b\x2b\xb1\x6f\xd0\xe0\xb7\x5b\x2d\x35\x83\xda\xd1\xc0\xdf\x8d\x6e\xdb\xf6\x68\x81\xa8\xbd\x03\xa8\xd6\x18\xee\x3f\xfd\xf0\xee\xe2\x0b\x87\xb0\x19\x78\xba\x8b\x37\x32\x4f\x12\xc7\xfe\xcd\x6e\xe4\xa9\x93\x49\x4a\xb4\x50\x42\x2e\xa5\x60\x47\x60\xac\x88\xb5\x56\xfe\x5f\x7f\x50\xdc\x0c\x23\x77\x6e\x47\xa4\x5b\x1e\x76\x36\xc1\x2a\x59\xa7\xfc\xb2\x43\x5c\x8f\xea\x39\xdf\xce\x2a\xc4\x42\xb3\x42\xce\x88\xd7\x5f\x8f\xb5\x42\x1f\xde\x5d\x24\x5a\xa0\x0f\xef\x2e\x7e\x49\x8b\x93\x2c\x55\xb4\x91\x29\x8a\x8e\xc0\xde\xf8\x72\x14\xda\x89\xa5\xb1\x51\xa2\x9d\x4f\xdb\x25\x73\x67\x4e\x06\x29\xda\x67\x72\xc8\xf9\xdd\xf4\x39\x66\x63\x1e\xe3\xc4\xdd\x70\x81\xac\xd3\xed\xab\xf4\x73\x4f\x6a\x1c\x57\x01\x05\xdd\x02\xf2\x57\xa4\xac\x0b\x03\x1c\xb2\x70\x21\xed\x0d\xc5\x4a\xac\x98\x0a\x17\x9a\xf8\x8e\x1a\x84\x9c\x31\x07\x55\x42\x57\x28\xfb\xb2\x97\x66\x76\xdd\x9f\x41\x8a\x6c\x26\xf7\x86\x0a\xba\xb0\x8b\x00\xfe\x1c\x29\xdd\x1f\xb1\xca\xcd\xfa\x5e\x30\xc3\x03\x07\xa6\x11\x41\x20\xa1\x2b\xca\x0b\x3a\xe3\x05\x47\x47\x77\x9a\x99\xc3\x69\x08\xc1\x20\xb8\x83\x5e\x22\xf9\xa3\x98\xde\x84\x81\x75\x97\xfa\x11\x82\x4a\xe4\xfa\x1c\xd8\x39\x1d\xdf\x5a\x77\xe4\x70\xda\xc6\xd4\x4b\x86\x0e\x51\x80\x0b\xca\x85\xeb\xbd\x30\xdd\x37\xc1\x4c\x13\xa5\xc7\x28\x22\x5c\xd8\x0a\x47\xdd\xda\xac\x14\xa1\x8b\x95\x93\x28\x74\x01\x51\xbe\x63\xd0\x18\xbd\xc0\x98\x10\xcd\x32\xc5\x0c\x32\x7e\x01\x05\x81\xfa\x6f\xe3\x22\x98\x51\x3b\x3c\x5f\xed\x40\xc0\xd4\x84\x43\x97\x60\x07\xbb\xad\x25\x9d\x60\xf4\x8b\x47\x97\x20\xc6\xe9\x8c\xeb\x28\x37\x20\xf4\x25\x83\xc8\xcf\x6a\x8b\xa1\x44\x63\xcd\xd4\xe2\xac\x69\x73\x4f\x13\x2c\xb7\xeb\x08\x86\xee\x05\x1a\xf1\x25\x19\xab\x96\xf3\x58\xe2\xe0\x53\x56\x2d\x5f\x5f\xf7\x01\x49\xf6\xef\x10\x1f\xf3\xfa\xba\x67\x45\x9c\x4d\x80\x43\x04\xeb\x8d\xb2\x55\xbe\x93\x45\xc1\xe7\xcc\x70\xc4\x12\x3f\x9a\x1d\x29\xa5\xe0\x06\xf3\xb6\x1b\xc9\x3c\xe6\x7f\x36\x45\xd4\xf3\x2e\x7c\x3e\x79\x83\xfd\x18\x37\x80\xaf\x2a\x93\x45\xc1\x32\x78\xe1\x93\x73\x38\x62\xf8\x35\x72\x63\xc7\x9b\x86\x87\xaa\xeb\xe9\xcd\x1f\x21\xb1\xed\x53\xd8\xc7\xee\xaa\x1c\xbf\x3b\x3f\x39\x7b\x73\x3e\x2d\xf3\x5f\x2d\xe5\xed\xc4\xc8\x49\xad\xd9\x84\x9b\x18\x8f\xfe\x91\x48\xc6\xa2\x1f\xd8\xcd\x32\xc5\x11\x69\x5b\xd5\x7d\xd0\x0c\x09\xb3\x27\x01\x70\xe0\x21\xa5\x4a\x4a\x73\x44\x14\x05\x88\xb5\x59\xa2\xa9\x66\x42\x37\x39\x77\xd6\x8c\x62\xec\x28\xfe\x6d\x7d\x50\xc3\xca\xce\x5c\x9e\x4c\xf4\xb7\xbf\xd5\x5d\x10\xbd\x67\xde\x41\xbc\xc7\xd5\x43\x4a\x85\x56\xed\xf7\xb8\x7a\xf8\x40\xde\xf8\x76\x5d\x3d\x57\x2f\xdd\x6b\xda\x97\x57\x3b\xb1\xbe\x26\x2e\x1c\x25\x3f\x73\x9a\xae\x1b\xb9\x11\xc8\x15\x00\x82\x98\xa5\x3d\x5b\x37\x6c\x4d\x80\x1c\x6a\x8e\x66\x19\xf9\xa0\x99\x3a\xea\x3e\xa2\x1f\x33\x93\xc1\xa6\x1c\xd7\x9a\xa9\x69\x94\x77\xfc\x24\xac\x0f\xde\x03\x86\x4f\x7f\xc7\xe6\x0f\x71\x08\xde\x31\x2c\xfa\x01\x28\x9c\x02\x3f\x86\xcf\x1f\xd0\xda\x2c\x5d\xbd\x70\x04\x80\xc7\x7d\x2f\xe0\x78\x36\x4f\x05\x52\xa2\xe7\xae\x7a\x12\xc7\x20\x82\x57\x26\x9e\x11\x52\xa0\xe3\x28\xb2\x75\x92\x3a\x4f\x82\x68\x89\x24\x1c\x21\x33\x18\x01\x2a\x57\x4c\xad\x38\xbb\x3d\xbe\x95\xea\x86\x8b\xc5\xe4\x96\x9b\xe5\xc4\xad\xae\x3e\x86\x06\xb0\xc7\xbf\x82\x7f\x44\xcc\xce\x61\x41\x4f\xf2\xdc\x57\x91\xd5\x9a\xcd\xeb\xc2\x55\x52\x45\x71\xe0\xd1\x8a\x7f\xcf\x94\xe6\x52\x1c\xc1\xcb\xc7\x11\xa9\x79\xfe\x0d\xee\x5c\x91\x78\x15\x63\x55\x6c\x72\x1f\x53\xe1\x2f\xac\xd5\x25\x8a\xe6\x12\x78\xbd\x15\x1c\xdb\x04\x0e\x21\xcd\x4b\x2e\x9e\x86\x16\xc0\x25\x11\xb8\xc8\x31\xfb\xd4\xdf\xa3\x53\x90\x12\xdb\x3f\xcb\xcd\x25\x60\x36\x9b\xaa\x13\x1a\x32\xca\x48\x2a\x93\x50\xb1\xa2\x7b\xd5\x27\x5d\xe5\x80\x49\x78\xdf\xb3\xcd\xe5\x5a\xff\xab\x98\xb8\x2f\x99\x54\x79\xbb\xcf\x63\x29\xc9\xa7\xc6\x53\x2b\x25\x69\x0b\x3f\x9e\x1b\x40\x60\x77\xd1\x06\x52\xac\x07\x17\xec\x82\x09\xe0\x17\xb6\x01\x17\x24\x81\x09\x7c\x96\x37\x9e\xf0\x66\x92\x31\xa4\x1f\x30\x7e\x11\x21\xfd\x83\x9c\x9e\xd8\x28\x3e\x79\xfc\x56\x49\x8e\xa7\xc8\x84\xea\x50\x1f\x68\x39\xab\x15\x5e\x8f\xf0\x3a\xad\xa2\x8a\x96\xcc\x30\xe5\xba\xb1\xd8\xdf\xc8\xa4\x10\xae\xc1\x2f\x52\xe6\xdb\x8a\x89\x6b\x43\xb3\x9b\x28\x14\xe5\x18\x73\xf5\xc6\x18\x73\x3d\x85\x98\x2b\x65\x75\x44\xa0\x18\xc8\xc3\xcd\xc3\xea\x55\x60\x7b\xf3\x65\x5e\x2d\x6f\x81\x53\xa5\xff\x11\xf6\x3e\x93\x62\xce\x17\x6f\x68\x15\xfb\x56\x1b\xe4\x44\x02\x80\xda\x09\x85\xe7\x59\xa0\xca\xac\x64\x55\x17\xd8\x4e\xa4\x5c\xfb\xbd\xfd\xb2\x61\x4e\x9c\x2a\xf5\xd1\x7f\x2a\xe4\x7f\x6b\x47\x4b\x99\x33\x32\xe3\x31\xa6\xb4\xd6\xcc\xc6\xae\x99\x6f\x9e\x0a\x81\x87\x0d\x17\xfc\x9c\xd1\x17\xa7\x09\x65\x1c\x05\x67\x20\x21\x7e\x81\xa4\x25\xb4\xe3\xc5\x1f\xfe\xf0\x87\x69\x0f\x39\xf4\xe2\xf7\xbf\xfb\xdd\x94\x9c\x71\x05\x2c\x5c\x1c\xad\xbb\xad\x2d\x08\x34\x24\xd4\x2c\x81\xf6\x11\x48\x3f\xa1\x73\x70\x5c\xa9\xbc\xa3\xca\xb2\x6e\xa4\xeb\x40\x40\x4a\xbe\x58\x62\x33\x41\x8e\x7d\xd2\xde\xab\x82\x67\xc6\xd1\xfc\x39\x53\x23\xe1\x50\xe0\x93\x56\x34\x7c\x6d\x53\xec\x0d\xa7\xeb\x88\x14\x1c\xc5\x6c\x4b\x20\xd2\xfe\x56\xc9\xba\x6a\xe9\xd7\x15\xd3\x75\x61\x90\xec\x55\xc4\x7d\xbf\xfb\xdc\xe6\xe4\xdb\xc5\x7d\xb6\x75\xac\x11\x6f\xf3\x3d\x95\x70\xd1\x0b\x6e\x8f\xb0\x6c\xa2\xc4\xb5\x5d\x9a\xb8\x2b\x5b\x51\xde\x90\xf3\x40\xf9\x19\xb8\x31\x48\xb1\xbe\xfe\xa6\x79\x75\xc9\x5b\x2b\x83\xbe\xb3\x8e\xcb\xac\x52\xf2\x7f\x1c\x6a\x1e\x58\x46\x5b\xeb\x8f\x94\x0b\x2c\xaa\x70\xfe\x5d\x43\x03\xc0\xb8\x45\x35\x8f\x0a\x7c\xb4\x36\x4a\xf1\x7d\xd5\xa2\x9a\xf5\x13\xd7\x86\xa6\xb3\xdf\x56\x5c\xc1\xb5\x5d\x84\x1b\xb6\xc6\x6b\xc1\x7b\x57\xb4\xf9\x2d\x74\x7c\x65\x96\xda\xe9\x81\x5a\x74\x66\x0a\xbf\x89\x0d\x4e\xa4\x71\xb3\x05\x0f\x05\x08\x0e\xa8\xef\xf4\x85\x0d\xf7\xc3\x57\x7a\x9a\x7f\x4f\xfd\xec\x7f\x01\x1d\xef\xc3\x0a\x36\xc7\xfd\x28\xfe\x88\x6a\x66\xea\xca\x6d\x17\x30\x7b\xd8\x35\x65\x5a\xbb\xf6\xef\x48\x99\x25\x55\x37\x2c\xf7\x66\x84\x16\x53\x72\x65\xb7\x0c\x5a\xe8\xe0\x75\xb5\x6b\xd2\xb5\x72\x20\xcc\x92\xae\x61\x39\x7d\xb0\x1e\xf1\xbc\xb2\x3f\x9d\xee\x3b\x43\x2d\x15\xd1\x86\x2a\x83\xa5\xf3\xb4\xc3\x4a\x7b\xee\xfd\x1f\xdf\xd0\x4a\xbb\x4e\x42\x5c\x2c\x22\x7a\xb0\xf8\xec\x0a\xac\xad\x77\x8a\xa8\x3f\xab\xff\xb1\xbd\x10\xed\x62\x60\xd5\xde\x13\xeb\x83\xf8\xde\x77\xb8\x8c\xec\x97\xe7\x0d\xc4\xa3\xf7\x9d\x8b\xa9\x7a\x26\xf7\x87\x55\x51\x6b\xd3\x3a\xa6\x6d\x70\x65\x62\x1b\x8f\x59\x77\xe4\xa8\x69\x67\xe6\x63\xaa\x28\x89\xbd\x78\xcc\x47\x56\x91\xed\xe1\xac\x6e\xdf\xf0\x49\xa2\xac\x9c\x1b\x9d\xd8\xb9\x71\x50\x6a\x8d\x7f\xc1\x71\xa3\x0d\xc4\x36\x42\xaa\x28\xa9\xdb\xe1\x18\xb6\x11\x77\x3b\x76\x06\x65\x51\x12\x6d\x40\xb7\x15\x9a\x45\x49\x6c\xc3\xba\x7e\x80\x16\x77\x42\xe3\x82\x3b\x37\xe2\x43\x3c\x37\x62\x03\x3d\x37\xf0\x70\x68\x37\xb6\x74\x79\xf0\xaf\xe2\xb4\x39\x38\x52\xf3\xf6\x88\x19\x39\x88\x2c\x78\xd7\x30\x8d\xa1\x99\x92\x37\xde\xef\x1b\x48\xfd\xbb\x39\xa8\x20\x74\xa6\x65\x51\x1b\x97\xa4\x01\xc1\xd1\x0a\xcb\x3b\xa3\x6d\xea\x27\xae\x31\x9e\x1b\xe0\x51\x36\xdf\x1d\xed\xa0\xba\x01\x61\x98\xf3\xef\xf0\x1e\xab\x17\x15\x67\x7c\xf1\xaf\x42\xf7\xbe\x08\xb5\xef\x3a\xe9\x12\xf5\x8f\xfa\x1a\xf4\x20\x2f\x41\x29\x5f\x81\x22\xcf\x80\x8c\x72\x96\xfa\x95\x6d\x9e\x80\xed\x76\xc9\x7c\x2d\x06\x56\x51\xb4\x0f\x17\x52\x11\x6b\x3e\x20\xc5\xe0\xdd\x26\x74\x98\x35\xe7\x02\x99\xf7\x88\x79\x7d\xcf\x34\x8f\x7d\xc6\xb9\xbe\x20\x07\xa7\x0d\xcd\x36\xbe\xa4\xf2\x42\x18\xa6\xe6\x34\x63\x87\x5d\xe4\x5d\x20\x84\x40\x7a\x38\x5c\x93\x25\x15\x79\xe1\xc0\x49\x54\x10\x76\x67\x98\x12\xb4\x80\x79\xe7\x8a\xaf\x50\x06\xfb\xe0\xa4\xa8\x96\x94\xcc\x19\x35\xb5\x62\x88\xbe\x0b\x8f\xc7\x67\x85\xfb\xe4\xc8\x97\x29\xf8\xd1\x14\xf5\xdc\x20\x28\xa4\x36\x07\x33\xa5\xb7\xc3\xdb\x83\xf6\x10\x84\xe6\x60\xf6\xac\xe0\x9f\x37\x9a\x77\xc3\xa9\xd5\x12\xe0\xae\x82\xb7\xbe\x96\x35\xd6\x2f\x74\x90\xdc\xb9\x54\xae\x33\x87\x54\xca\x3a\xea\x90\x2e\x46\x17\xa8\x29\xb6\xe0\xda\x40\x0f\x20\xef\x94\xf8\x8e\x1f\x8f\xc2\x6b\xf3\x64\x99\x94\xd2\x73\x13\xcd\x7d\xa6\x57\xae\x78\x1e\xa2\x57\x28\xbd\x88\x8a\xb5\xb9\x26\x15\xd5\x1e\x50\x04\x45\x26\x5a\xcb\x8c\x53\xfc\x93\x62\xe7\x5e\xb8\x1c\x35\xc4\xc4\x39\x33\x4c\x95\x5c\xa0\x21\xa8\x1d\x12\xd0\x2e\x65\xb8\x24\xb4\xaa\x8a\xf5\xa3\x1c\x3e\x21\x73\x76\x55\xcf\x0a\xae\x97\xd7\x09\x51\x68\x97\x3b\xc4\xe2\x77\x97\x6e\xd7\x11\x45\x55\x7b\x6d\xe1\xd9\x88\x66\x42\xf3\x88\x18\xcf\xfa\xc4\x36\x76\xe5\x52\x40\x5f\x3f\xaa\x75\x98\xe9\xe9\xf5\x70\x0a\x44\x37\x82\x66\x96\xc0\x02\x5e\x30\xc3\x1a\xa5\xdd\x59\xdf\xef\xa3\x9e\xe1\x44\x0e\xb2\x3e\x88\xaa\x2b\x8d\x64\xb4\x28\xd0\x0e\x34\xa4\x7d\x9a\x3e\xe3\xc1\x87\x75\x49\x10\x52\xa2\xc3\xc9\x59\xd0\x15\xdc\xaa\x91\x80\x4d\x84\x22\x33\xe7\x0f\x44\xa8\xa5\xf6\x48\x6d\x1c\x0e\xf4\x43\x8f\x74\x6d\x05\x04\x91\x22\x88\x3e\x22\xb4\x28\xe2\x4e\x6e\x73\x0f\x5c\xd3\x4c\xa7\xf6\x1e\xa9\x89\xf9\x08\x7c\x1c\x81\x8f\xf7\x8c\xa7\x03\xa7\xbf\xf6\xa9\x72\x67\x44\x68\x3e\x91\x78\x9c\xba\x03\xda\xd5\xca\xa9\xf9\xe0\x92\xc6\xbd\xdb\x6d\x31\x34\xf5\xd1\xfa\x5f\x3c\x20\x26\x0d\xee\xf4\xc4\xf8\xae\xf9\x29\xa0\x33\xdf\x6f\x88\xc4\x3e\xc9\x1b\xa9\x98\xf6\x86\x71\xe2\x9f\x41\xb2\x8e\x26\x8a\x02\x66\x35\x0a\xb5\x63\xba\xfd\x6f\x61\xb7\x37\x44\x41\x36\x00\xf2\xa2\xf6\x35\xc9\x65\x56\x97\x4c\x98\x98\x1a\x68\x7b\xfc\xda\xca\x23\x47\x65\xf9\x48\x86\x80\xe6\x39\x77\x36\xfe\x2a\xda\x24\x44\x68\x8e\x5c\xde\x8a\x5b\xaa\xf2\x93\x2b\x04\x65\x6f\x3f\xcc\x6e\x25\xc5\x81\x73\xc3\x94\x88\x95\x44\x67\xb2\x36\x81\x44\x0f\x9b\xd0\xd9\x40\xf7\x8e\x58\xdd\x11\xab\x3b\x62\x75\x47\xac\xee\x88\xd5\xdd\xc4\xea\x5a\x39\x2e\x77\x50\xb8\x2e\xa9\xd8\x20\xbc\xab\xc2\x7d\xc1\xcb\x1c\xcb\x8b\xf3\x74\xa0\x6c\x1d\x13\xe7\x7c\xb3\x08\xae\x9f\x5e\xb7\xca\x7e\x26\x04\x2d\xd1\x69\xdf\xf6\xe6\x45\xd7\x1e\x36\xad\x25\xa3\x00\xd6\x4f\x02\x66\xf7\xc8\x50\x39\x58\x3f\x74\x9a\xd0\x8d\x7b\xb8\x09\xa3\x9e\xee\x5d\x9b\x78\x87\x2b\x67\x45\x1e\x9f\x0c\x80\x2e\xc6\xaf\x5c\xa7\x74\x2a\x84\x74\xfe\xba\x8e\xc4\x05\xd1\x19\x2b\xf4\x91\x7f\xc1\x10\x39\xfc\x8b\xae\x28\xaa\xa7\x6b\x3b\xac\x7d\x6e\xc2\x81\x04\x60\x9e\xa8\x23\x4e\x12\x1c\x73\x02\x47\x1d\x76\xf2\x0a\x7f\xde\x49\xa2\x33\x4f\x7a\x49\x92\x38\x39\x9b\xa1\xb1\x93\x19\x29\xb2\x79\xd2\xd3\xd9\x92\x95\x34\xfa\xe4\xdb\xf1\x3a\x2c\xbe\xb5\xa3\xb7\x8a\x1b\xc3\xe2\xa7\x69\x9d\x4a\xa6\x4a\x4d\xe4\xbc\x21\xec\x89\x83\x6d\x12\xe7\xb6\xef\xad\x5e\xa2\x1f\xa6\x1a\x31\x29\xf0\xb2\x24\xe8\xc8\xab\x48\x20\x1a\xd9\x3c\x2a\x57\x0e\x43\x16\xbf\x5a\x60\x55\xad\x8e\x34\x92\x68\x50\x9b\x49\xf6\xb5\x5b\xc2\x62\xfd\xa5\x68\xa1\x2b\x77\x37\x9e\xc4\xb6\x8e\x30\x68\xf4\x18\x61\xd0\x23\x0c\x7a\x84\x41\x7f\xf6\x78\x82\x30\xe8\x44\x2e\x7a\x70\x26\x7c\xea\x23\x15\xac\x5a\x74\x20\xae\xe8\xd8\x3c\x0c\xc7\x67\xe5\xb3\x7f\x9e\x2d\x4c\xc8\xb8\x7b\x65\xf5\x68\x40\x55\x4b\x15\x59\x9b\xe7\xa7\xb9\x64\x64\x7f\x7f\x3a\xdd\xdf\x0f\x38\x6d\x7c\x0d\x61\x33\xc9\xda\xcc\x27\x7f\x24\x4c\x64\x32\xb7\xdf\xfe\x3e\xf2\xaa\xce\xb9\xd2\x06\x92\x16\x2d\x00\x39\xd5\x9e\x97\x7e\x5f\x52\x01\xbf\xdd\x5a\xc6\x5f\xff\x48\x2f\x23\xb4\x9b\x7d\x9d\x3c\xc8\x6e\xc2\xe3\x58\xed\xeb\xda\xe1\xfa\x0d\xcd\x02\xf2\x35\x4e\x31\x40\x8c\x1d\x64\x6b\x52\xf0\x12\x9f\xc2\x77\xc3\x9a\x1a\x1b\x83\x32\x6d\x34\x39\x70\x02\xa7\x59\x55\xc7\x9a\x33\x90\x53\xb2\x52\xaa\xf5\x51\xf3\x03\x56\x70\xb2\xd9\x7a\xe9\x87\x36\xa6\x8f\x12\x9a\xd5\x4a\x31\x61\x8a\xf5\x2f\x31\x33\x10\x0e\xcb\x13\x48\x0c\x34\x77\x00\xdf\x84\xa6\x1d\x1b\x54\xac\x41\x74\x74\x28\x05\x58\x9b\x66\xed\x23\x78\xd8\xdb\xe1\x49\x70\x8f\x1a\x88\x57\xb4\xc4\xb9\x54\x84\x89\x15\x59\x51\xa5\x63\x4e\x2a\x49\x19\xcb\xe7\x7c\xc5\xb5\x8c\x54\x70\xf7\xc1\x52\x92\xc4\xf2\xb2\x36\x55\x6d\xbc\xdf\x98\x2a\x91\xc4\xee\x2a\xa9\x59\xde\x6a\xe5\x38\xcd\x49\xda\xf0\xca\xf5\xd6\x7f\x89\x6d\x45\x1a\x46\x45\x8d\x61\x4a\xbc\x22\xff\x7d\xf0\x8f\xaf\x3e\x4e\x0e\xbf\x39\x38\xf8\xf1\xc5\xe4\x4f\x3f\x7d\x75\xf0\x8f\x29\xfc\xcb\x6f\x0e\xbf\x39\xfc\x18\xfe\xf0\xd5\xe1\xe1\xc1\xc1\x8f\x7f\x7f\xf3\xed\xfb\xab\xf3\x9f\xf8\xe1\xc7\x1f\x45\x5d\xde\xb8\x3f\x7d\x3c\xf8\x91\x9d\xff\xf4\x99\x42\x0e\x0f\xbf\xf9\x75\xe4\xc4\xa9\x58\xbf\x8d\x32\xec\x04\x34\x60\xaa\x70\xa3\x2b\x2d\xc1\x75\x21\xe4\x6e\xd2\x22\xe5\x26\x5c\x98\x89\x54\x13\x27\xf8\x15\x31\x2a\x32\x97\x10\x8e\x63\x5a\x3d\x9b\x26\xbc\xe9\xce\xaf\x4d\xad\x3d\xa2\x22\x03\xbc\xec\x19\x8f\x66\x04\x3f\xf7\x72\x62\xa9\xea\x0c\x2b\x2b\xa9\xa8\x5a\x93\xdc\x23\x14\xd6\x49\x7a\x8a\x75\x9a\x8a\x0d\x46\x6e\xfa\x0a\xab\x40\xe9\xfe\x2b\x58\xb3\x9c\xab\x2f\x4c\xf1\x1d\xd9\x29\x8c\xe5\xbc\x2e\x53\x40\x69\x7e\xb0\xdb\x01\xe5\x23\x72\x1e\xd9\x27\xd8\x4d\x2a\x40\x96\x66\x34\xbb\x71\xe0\x8f\x66\xef\xf1\x00\x73\xd6\x6d\x04\xb3\xb7\xe7\xab\x34\x4a\x46\xf1\x78\x0f\x97\x40\x85\xba\x2a\x99\x33\x7b\xa4\xc2\x4f\xb8\xef\x88\xc6\xfd\x08\x0f\x5f\xf7\xe5\xc5\x07\x5e\xfc\x21\x52\xae\x54\xe4\x0d\x04\x0a\x8f\x78\xe2\x49\x82\xde\x35\xfc\xdf\xec\x3b\x1b\x55\xa5\x38\xbc\xef\xa5\xa1\x05\xa1\xbe\x71\x21\x36\xc3\x5c\xc8\x8c\x16\x4d\xe5\x65\xd7\x65\x8e\x49\xae\x37\x3a\x34\x54\xc8\xd9\x53\x6c\xbf\xde\x05\x95\x48\xa9\x5c\x13\x5a\x68\x57\x41\xc4\x33\x3a\x2b\x18\xcc\xd3\x85\x90\x51\xf7\xd6\x4d\xb0\xa4\x77\xbc\xac\x4b\x52\x6b\xbb\x16\xe8\x67\x4a\x37\x9f\xa0\x11\x9a\xa5\xb8\xb5\x9a\x01\x0f\x7c\x82\x46\x73\x5c\xc0\x04\x7b\xa0\x3a\x34\xe6\x8b\x91\xeb\x70\x1e\x3b\x4f\x59\x11\x7d\x6e\x03\xce\x4b\xd7\x90\x03\xf3\xeb\x10\x95\xdf\x90\x73\xa8\x23\x69\xa2\x4e\x4d\x80\x3f\x0a\xd5\x99\xd9\x8d\x0d\x7d\x2a\x78\x91\x42\xa1\x82\x21\x59\xfa\xe3\x6d\xe5\xd6\xc2\x97\x79\x27\xa2\x1f\xd8\xad\xe6\x6a\xcd\xd4\x64\x51\xf3\x3c\x95\x82\x7b\x66\x71\x46\x44\x74\x91\x22\xa6\x48\x10\x49\x24\x8e\x1f\xe6\x59\xa4\xfb\xfb\xfa\xb4\xdf\x51\xf7\x35\x9f\xa1\xf4\xc1\xe9\x92\x0a\xc1\x8a\x4e\x88\x60\xaf\x88\xd5\xe0\xbe\x39\x0e\x42\x26\x10\xc9\xf9\x96\x38\xfb\xfd\x9e\x38\x48\x5c\xb1\x59\x32\xd1\x04\xff\x8f\xd6\xf5\x7d\x6c\x3e\xf3\x69\xa1\x5f\xa2\xf9\x4c\xea\x0a\xf0\xed\xb6\x33\xbd\x06\x32\x58\x2f\xa8\xdf\x76\xc6\x17\xca\x2d\xe5\x2d\xc9\xb1\x10\xd4\x5b\xe0\x3c\x5d\x31\x61\x1c\xfb\xa7\x0e\x08\x97\xe8\x7d\x9b\x2b\x59\x42\x45\xaf\x92\x25\xd7\x36\x14\x00\x3f\xc6\x5d\xda\x47\xf1\xc1\x8b\x1a\x09\x69\xbb\xaf\x0a\xe3\xf5\x29\x31\x54\x2d\xd0\x65\xae\x45\x2d\x88\xa8\xcb\x19\x8b\x8a\x49\x1e\x13\xc7\x3e\x76\x04\x7a\x88\x8e\x40\x8f\xd3\x9e\xc7\x1d\xe5\x1f\x7e\xb8\x4c\xd2\x88\x3d\xdd\x2d\xb9\x95\xaa\xc8\x6f\x79\xee\x98\x60\x34\x39\xb0\x53\x3c\xfc\xcf\xeb\x7f\x7e\x7b\xcb\xf3\xf4\x5b\x13\x05\x27\x83\xad\x21\xb0\x37\xbe\x63\x0a\xb7\x81\xda\x01\x4c\x15\x9b\xf1\x39\xe7\x00\x76\x02\x19\x0e\x46\x52\xce\xb8\x88\x29\x22\x95\xf3\xce\xe1\x86\x58\xd5\x6a\xde\x38\x2a\x2f\xcd\xcc\x11\x99\xd5\x0e\x9c\x31\x93\x66\x49\x34\x2f\xeb\xc2\x50\xc1\x64\xad\x8b\x75\xd4\x25\x7e\x7e\x07\x74\x5e\xb0\x3b\xa7\xc3\x62\xa3\x90\x46\x50\x6c\x16\x7e\xc1\x04\x53\x3c\x0b\xd5\x4c\x9b\xe1\x08\x42\x26\x30\xfa\x68\x2e\x05\xcb\x8f\x9b\x4e\x9f\x35\xf8\x36\xc0\x39\xc6\x32\x84\xd0\x19\xb5\x11\x48\x55\xd4\x0b\x8e\x40\x00\x8f\x0c\x63\x9f\xfd\xdf\x3e\x24\xc3\x58\xcb\x61\x53\x6b\x16\x9b\x42\x8d\xa1\x5a\xf8\xa5\x92\x74\xfd\x87\x07\x94\xef\x77\x73\x6a\xe5\xac\x62\x22\x47\x67\x58\x45\x57\xdb\xba\xcd\x7b\x94\x53\xe7\x81\xdd\x69\x7d\x9b\xf3\x3b\xa3\xb0\x20\xc0\x4c\x96\xa5\x75\x13\x02\xe2\x9c\xcf\x09\x15\x71\x26\xfd\xf9\x13\x4f\x90\x31\xde\xfb\x45\xc5\x7b\x0f\xd4\x8e\x35\x01\x11\xde\x3d\x34\x78\x71\x98\xcc\x5d\x34\x78\xdd\x32\x6e\xfc\xe1\xeb\xd2\xe0\x39\x3f\xce\x2b\xd3\x38\x6a\xb9\x92\xae\x77\x93\xc1\x61\xd5\xbd\x63\x7c\xe3\x9a\x74\x52\x88\x17\x31\xd5\xc3\xbb\xa9\xe4\x80\x14\x0e\xff\x9a\x76\x1f\x95\x1c\x56\x3b\x6c\xf3\x1d\x6d\xec\xd1\xd8\x50\x77\xe4\x95\xfb\xc5\xf0\xca\xcd\x0b\x99\xdd\x60\x42\xa4\x8d\x20\x1c\xa4\xf4\xde\x03\x11\x5f\x13\xc4\xf8\x08\xbc\x09\x99\xfb\xaf\x79\x08\xc1\xdd\xf7\x3f\x4f\xae\xe3\x5d\x61\x57\x1a\x8a\x39\xc3\x61\xb2\x56\x8d\x29\x69\xb5\x8e\x5a\xf1\x8c\x91\x19\xb3\x26\x43\xd5\x02\xc5\xca\xf1\x98\xe4\x53\xd4\x50\xcd\x0c\x1e\xad\xdf\xa7\xba\xed\x14\x9f\x79\xc9\x58\xab\x61\xa4\x62\x39\xa1\x9a\x94\xcc\x50\x2b\x8b\x4c\xfe\xe2\x8b\xdb\x62\x20\x2d\x7e\x56\x10\x7d\x87\xcd\x74\xa0\x3c\x3c\xf4\x26\x93\x42\xf3\x9c\xf9\xf9\xe6\xf6\x3a\x64\x68\xc2\xe5\x48\xdf\xdb\x7f\xdf\x87\x0f\x49\x5a\x65\x5b\x31\x1b\xfb\x19\xe5\xad\x00\xf0\x85\xff\xab\xee\x66\x82\xf1\xd8\x34\xda\xec\x60\xcc\x59\x8b\x58\xf0\x45\xc6\xae\xac\x4a\xd7\x86\x09\x73\xc6\xf5\x4d\x2c\xb6\xf8\xdb\xd3\xf3\xbe\xc0\xd8\xf4\xe6\xb7\xa7\xe7\xc4\xcb\x79\x20\x9c\xc5\xc3\x02\x2d\x3a\x2e\x02\xc6\x02\x20\x00\xa0\x8b\x8c\x55\xcd\x16\xe4\x5c\xdf\x7c\x61\xec\x73\x4c\xba\xb5\xca\x2f\x31\x49\xca\x5f\x16\xbe\xc4\xab\x2b\xef\x4e\xc0\x71\x5f\xcb\x9a\xdc\x52\x74\x8b\xa5\x16\xb1\xf2\x9e\x57\xaf\xc8\xb9\xd0\xb5\x62\x0d\xa6\x0f\x8b\x7c\xd8\xc8\x7d\xda\x88\x2b\xa4\x1b\xb1\xa6\x68\x57\x92\x32\xa4\x1b\xb1\xef\x6c\x77\xb4\xac\x0a\xa6\x5f\x3d\x4b\xec\x4b\x24\x18\x7c\x4b\x17\x60\x6d\x5f\x07\x82\xb3\x0d\xa6\xc1\x7e\xeb\x26\x04\x67\x1b\x4c\x13\xe1\x27\x3d\x26\x04\xa7\xa2\xca\x40\x2e\x33\x09\x0c\x1e\x58\x3b\xbd\x40\x12\xd5\x04\x78\x97\x4a\x89\x7e\xb3\xb8\x98\x13\x59\x72\x63\x02\x73\x8b\x4f\xe0\xe3\xf3\x62\x41\x5b\x59\x75\xe0\x67\x6c\xdd\xe6\x78\x05\xf0\x5a\x36\x41\xda\x71\xce\x56\xc7\x3a\xa7\x2f\xb1\x75\x90\x76\xf9\xb4\xef\xc2\x65\x7a\x3b\x84\x6e\x64\xb3\xf7\x72\x6f\x4a\xae\x79\xc9\x0b\xaa\x8a\x75\x97\x06\xa7\x95\x8e\xd5\xd5\x52\x35\x9f\x0c\x45\x36\x2f\xf6\xc8\x81\x54\xf6\x2b\xb0\x79\x46\x2a\x48\xc1\xe8\xca\x65\x8c\xbd\x01\x5e\xbb\x34\x1e\x92\xe9\x7c\x70\x47\xba\x07\xf0\x7c\xc8\x93\xc0\x9b\x39\x37\x28\x85\xf2\xf8\xe0\x82\x15\x11\x9d\xf7\xba\x3a\x6b\x3d\x70\x2e\xac\x5b\x3e\x25\x1f\x9c\xaf\x8b\xbd\xe9\x2e\x80\x72\xd7\xc7\xee\x56\x23\xf7\x0d\x3e\xb3\xfa\x44\x0e\xcf\x93\x78\x79\x0a\xcf\x38\xed\x1b\x0f\x5e\x7b\x6c\xbc\x0c\x75\xde\x78\x90\x32\x7b\x2f\x43\xdb\x8d\x13\x7e\x09\x1a\x04\xf7\x66\xb5\xe0\xe6\x1d\xab\x10\xd1\xe2\x46\x20\xee\xc4\xc4\xe6\x36\x17\xdc\x58\x11\x52\x73\x28\xef\xa5\x06\x3a\xdd\x2b\xc3\xb3\xba\xa0\x8a\x28\xe6\x90\x42\x98\xed\x3a\x3b\xbf\x7a\x77\x7e\x7a\xf2\xfe\xfc\xec\x15\x09\xb3\xe5\xdd\xec\x13\x46\xe8\x7b\xd9\xc2\x97\x08\x6d\xcb\xaa\x1c\xc1\x5a\xcc\x0a\x1c\x79\xa7\x84\x8a\xb6\xe2\x8d\x0b\x94\xf6\xa3\x82\x5c\x08\x6e\xda\x3e\x93\xe0\x90\x65\x85\x14\x4c\x23\x55\xb4\x9d\xa1\xc7\x68\x2d\xb8\x39\x72\xe9\x08\x37\x61\x7b\x6f\xc3\x8c\x11\x92\xed\x37\x82\x8c\x2b\x57\x9a\xdd\x2c\x29\xe2\x45\xe9\xd1\xf2\x0a\xed\x11\xfe\xd2\xd9\xe9\x50\x1d\x9d\x40\xa1\xbf\x07\x70\x67\x2b\x32\xe2\x3d\xad\x65\x42\x6b\xba\x39\x4b\xe5\xc8\xb7\x90\x52\xe1\x7e\xb9\x26\xce\x36\x22\xd8\x9f\xee\x87\x84\x40\xc1\x59\x8e\xf5\xb2\x3b\x2e\x70\xcb\x31\xe0\xb9\x1c\x23\x44\xf6\xb5\xda\x94\x90\xb7\x66\xc9\xd4\x2d\xd7\x68\x7e\x44\x3e\xdf\x4d\x60\x19\x63\x76\xbb\x7d\xb6\x37\xf4\x70\x54\x14\xa8\xeb\x59\x77\x31\xcd\xd2\xff\xc2\x0a\x5d\x6a\x8b\x0f\xcf\xa2\xdd\xa5\xb0\x24\x09\xee\xd7\xbb\x76\x7d\x3f\xbc\xfb\xee\x71\x3e\xc7\x59\xae\x04\x1f\x73\x2a\xcb\x92\x1b\xb2\xa4\x7a\x19\x9a\x5b\x61\x1f\xb2\x9a\xca\xe9\x18\x6b\x1f\xf7\x4c\xe1\x1a\xba\xce\x11\x2a\x78\xc3\x2b\x0a\x82\xa2\x9f\x25\x1a\x41\x9e\x9e\x40\xb4\x99\x4b\x74\x33\x20\xaa\xa0\xb3\xd9\xcf\x70\xa0\x44\x3c\x21\x30\x9f\x06\x99\xde\xfc\x11\x1c\x61\xef\xf2\x1e\x37\x6b\x7b\xfc\xee\xfc\xe4\xec\xcd\xf9\xb4\xcc\x9f\x91\x61\x67\x22\xaf\x24\xc7\xec\x22\xb2\xf3\x42\x9c\x3b\xd0\x4c\x37\x45\x7c\x77\x1e\x84\xc1\xa3\x35\x1a\x87\x0d\xf4\x60\x5e\x94\x4b\x14\x80\x3b\x9a\x33\x43\x79\x81\x15\xda\xde\x0f\x23\x2b\x59\xc8\xc5\x3a\xf2\x18\x13\xdc\x51\xfe\x95\xa3\x7e\x9d\xd0\x89\xbd\x55\x8f\x93\x0b\xc6\x32\xf7\xf6\x77\x3b\xb0\xed\xda\xed\x6a\x56\x17\xb9\x90\x4d\x56\x11\xa8\x66\xb7\x43\xe6\x67\xb5\xc0\x4f\x3c\x65\xd2\xde\x84\x90\x7d\xc7\x26\xcc\x66\xcc\x19\x1b\x96\x3b\xaf\xad\xe9\x80\x49\x2a\xa6\x4a\xae\xad\x69\x46\x03\xbc\xb6\x33\x30\xcf\xfb\xbe\xe2\x92\x2f\xd6\x7e\xe3\x1a\x3d\xf4\xcf\xd1\xdf\xbc\x9c\x58\x37\xa3\x52\x6c\xc2\xee\xb8\x86\x5c\x1b\x90\xb8\x4b\x15\x15\x00\x76\xfd\x94\x00\x78\x08\x80\x0a\x27\x17\x05\xfb\xde\x00\x3e\xb4\x39\x82\x80\x9a\xc1\x24\x5e\x98\x60\x8a\x16\xc5\x1a\x48\xfb\x5d\x8b\x4c\xf7\x4c\x48\x17\xc8\x05\x95\xca\x63\x22\x2b\xc5\x57\xbc\x60\x0b\x3b\xe5\x25\x17\x0b\x34\xdb\x3e\x55\x8c\xd0\xa2\x90\xb7\xcc\xb7\xdf\x60\x5b\xeb\x8b\xb9\x91\x6f\xec\x7f\xdf\xe1\x04\x82\x90\xf7\xf2\xed\x7b\x22\x98\x9b\x32\xea\x9e\x47\x26\x47\xed\x47\x21\xbb\x55\x4d\x26\x13\x78\x43\x3e\xf8\x1f\x29\x98\xce\x8b\x43\xf2\x03\xf3\xdf\x22\x89\x62\x56\xf7\xa3\xf0\xc5\xb7\x4b\x09\x2f\x51\xb5\xf6\x6b\xde\x06\xb6\xa0\x2a\x51\xb7\x4e\xe4\x41\xee\xb1\x95\x2d\xa4\xf1\x4e\x7e\xef\x17\x70\x74\xaf\x54\x93\xb6\x7a\xe3\x39\x65\xd0\x1e\xc1\x59\x4e\xea\x39\x05\x0c\x60\x64\xf2\xac\xa3\x3f\x43\x55\x81\x63\xb0\x47\xbb\xdf\x94\xe8\x75\x59\x70\x71\x73\x44\xb8\x09\x95\x38\x56\xa3\x44\x84\xec\x56\x5c\xd0\xc5\x8a\xd1\xa2\xe3\xe9\x7d\xf1\x77\xb5\xa0\x35\x1e\xc5\x37\x34\x89\x80\x5d\xef\xd7\x95\xab\x77\x0d\x86\x3d\xea\xd5\xab\xe7\x6c\xed\xed\xa5\x73\xb4\x9e\xc5\xbe\x70\x9d\x69\x1e\xeb\x60\x5d\x5c\x9f\x5e\x5f\xf4\x1e\xb7\x30\xb9\x4b\x27\x65\x84\x97\xde\xe7\xa0\xc3\x56\x3d\xcb\xbc\x10\xff\xd7\xf0\xf3\x30\x21\x45\x8d\xf9\xaf\x1c\xe9\xc6\x95\x54\x06\x41\x9a\x1f\x67\x22\xb3\x25\xad\x4e\x6a\xb3\x3c\xe3\x3a\x93\x2b\x96\x24\x0d\x7e\xbb\x64\xe0\x23\x7b\x30\x27\xe1\xf6\x92\x60\xa3\xca\x30\x2f\x72\xfa\xb7\x93\x2b\x42\x6b\x7b\x8e\x0d\xcf\xf0\xa5\x88\xb1\xe5\xa0\x61\xc5\xae\x99\x4e\x94\x69\x4f\xb9\x5e\x7e\x56\x4f\x66\xb5\x46\x68\x34\x6a\x8c\xd0\xe8\xa7\x0f\x8d\x06\xdb\x86\x9c\xca\x08\x87\x1e\x34\xb8\xe0\x86\x53\x23\x23\x5a\xea\xf4\xdf\x36\x6b\x6d\x64\xe9\x14\x2d\x20\x69\x40\x38\x72\x71\x2e\x01\x0e\x71\x31\xef\xcf\xb2\x57\x3f\x1e\x03\x89\x80\x63\x76\x21\x0c\x53\x73\x9a\xb1\x0d\xf6\x2c\x2c\xda\x40\xb0\x5b\xff\xf5\xbc\x91\xfc\xe7\x28\xf6\xb9\x0a\xbc\x97\xbf\xbc\xfa\x73\x07\x70\xfd\x97\x48\xa4\x85\xef\xba\x17\x9e\x9f\x49\x26\x85\x60\x99\x79\x8c\x07\x64\x3b\xf8\xbf\x52\x58\x7b\x0f\xc2\x71\xab\xff\x7f\xd5\xb4\x88\x39\x21\x97\x8f\x85\x9b\xe8\x9f\xca\x04\xcb\x12\xee\x62\x38\x8d\xa8\x32\x2e\x37\xc0\xf6\xd6\x9a\xd9\x98\xce\xcb\x35\x8a\x0a\x6d\x8f\x68\x8a\xd7\x8d\x7d\x5f\xa0\xb0\x4f\x0e\x4c\x56\x21\xb1\xea\x4f\x82\xa3\xd5\x2d\x8e\x3f\x91\xdf\x21\x62\x17\x37\x1c\x37\x6b\xcc\x3a\x3c\x2a\x56\x1e\x34\x57\x8a\x07\xf5\xde\x72\x22\xc3\x39\x37\xbe\xe3\xda\xb8\x8e\x0b\x6e\x76\xd6\x9a\x30\xc7\xf7\x88\x72\xc3\xed\xb8\xb8\x22\x52\x11\x5e\xfd\x93\xe6\xb9\x7a\xe5\x22\x0d\x9f\x7f\x94\x68\xd4\x1e\xd7\xfe\x41\x04\x18\x49\x02\xf5\xd6\x81\x59\x57\x3c\xa3\x05\x9a\x01\xe8\xfd\xe9\x15\xcc\x4a\x93\x3f\xfe\xde\xb5\x89\xfe\xed\xd7\xbf\x7f\x11\x75\xd5\x9e\x1f\x57\x24\x49\xfb\x36\xfd\x9f\x87\xe6\x7f\x4a\xcc\x4f\x10\x90\x3b\xce\x27\xf0\x67\x62\x82\x7c\xe7\xa8\xc1\xb5\x68\x7c\xce\x74\xc1\xfe\xc8\xd5\xd3\x1b\x23\x57\xcf\x63\x73\xf5\x90\xe6\xc8\x3b\x9b\xfa\x30\x96\x3a\x86\x72\xf2\x6a\xdb\x48\x3b\x73\x8b\xb5\xaa\xf7\x18\x69\xfc\x23\xe1\x33\x31\xd2\xa8\xf3\x81\xd3\x19\x7d\x5d\xe1\xec\xcf\xfe\xbe\xee\x54\x37\x20\xbe\x03\x98\x57\xcf\x2e\xaf\xff\xf9\xdd\xc9\x5f\xcf\xbf\x83\x35\xf1\x6c\x2f\xf6\xf2\xa3\xac\xe3\x8e\x87\x9a\xc4\xea\x07\xfb\x2a\x83\xdb\xac\x78\x0c\xf6\xe5\xeb\xeb\xfe\xc3\x1d\xb9\x7c\x7d\x8d\x58\xd9\xdd\xc0\xeb\x06\x46\x8d\x0a\x25\x7a\xc0\xeb\xd8\x0c\xa3\x98\xa3\xf7\xe6\xb9\x00\x3c\x26\xc0\x1f\xf6\xc5\x09\xb2\x93\x22\x43\xc2\x83\x2f\xbb\x4b\x91\xa0\xb7\xa7\xdb\xad\x49\x42\x00\xe5\x83\x9f\x3a\xf2\xa4\x42\x9d\x87\x80\xe1\xda\x7d\x71\x3b\xec\xdf\x22\x3c\x94\x36\x26\xb7\xfb\x6c\x00\xb8\x5f\xf0\xfc\xc4\x84\x6b\x2a\x0d\xeb\xfd\xfe\x35\x48\x0a\x60\x79\x6b\x1a\x62\xa8\xef\x95\xf5\x05\xad\x3f\xc7\xb4\x0e\x0f\x90\x9d\x5b\x8e\x14\xfb\x18\xb6\x85\xc4\xdd\xf2\xb6\x32\xde\xb9\x5b\xa7\x05\xe5\x88\x2e\xc5\x1b\x2a\x78\x97\x50\xf7\xaf\xd7\x00\xc8\x41\xa9\xa2\x4e\x7f\xbf\x1e\xcb\x32\x25\x3b\x7f\x0f\xf5\xa6\xe5\x6a\x29\xa9\x7f\x2c\xd1\x15\xcd\x52\x95\x6a\x7d\xce\x41\x68\x37\x63\x12\xce\x44\xfb\x57\xee\x6f\x32\xfb\x69\xcf\xc9\x05\x81\x09\x3f\x02\x01\x5c\xf3\xbb\x29\x94\xcf\x69\x10\xe6\xf5\x4f\x44\x26\x05\x9a\xc3\x26\x3b\xb1\xe4\xbe\x53\x4b\x68\xcc\x44\x2b\x19\x9a\xc3\x40\x3b\xf0\xd0\x0f\xf9\x8b\x62\x4d\x1f\xf0\x32\x90\x27\xe5\x19\xfd\xf0\x45\x88\xfa\x83\x2f\x82\x75\xba\x1e\x27\xe5\x5b\x2d\xa5\x91\x22\x29\x9d\xe9\xd5\x0e\x91\xb1\xf6\xc8\xc9\x3c\x75\xf4\xcb\x05\x53\x1d\xb3\x8a\x10\x0d\xbc\x49\x0d\xe3\x34\x15\x79\x53\x22\x26\x45\x80\xa0\xc6\x52\x4f\x3f\x1f\x03\x52\xe5\x17\x67\x5f\xd8\x76\x8c\xad\x84\x9e\x66\x2b\xa1\x2f\x03\x42\x7b\x0c\x73\x62\x0f\x79\x82\xf3\x76\x71\xe6\x33\x1f\x81\xc7\x1a\x9b\x9b\x76\x0a\x8d\xa4\xd2\x68\xc4\x6b\xb5\x2f\x1e\xdd\x48\x65\x6e\xa5\x4a\xd3\xde\xef\xaa\x27\x2c\xba\x0a\xd4\x4b\xdb\xea\x30\xd0\xd1\xf7\x08\xc1\x1d\x0b\xf1\x4c\xf5\xbd\x5b\x8f\x67\xac\xf3\xaf\xa1\xb0\x28\xea\x78\x10\xff\xc8\xb0\x89\x39\x0e\xc0\x66\x6c\x7e\x62\x87\xf9\xd8\x30\x04\x71\x89\xd2\xc4\x48\xe6\x0d\xf3\x31\xed\x18\x00\x7c\x18\xb2\x6d\x36\x9e\x82\x01\x48\x18\x4f\x6c\x25\x1d\x91\x6b\xb5\xbb\x25\x19\xa4\x6f\xd1\x09\xd6\x9d\x91\x4e\x88\x59\xf0\xf1\x6f\x2f\xd2\x79\x94\x44\x67\xd0\x5a\x09\xf6\xef\x7b\x2f\xca\x3f\x53\xe2\xcf\x7a\xe3\x04\xd8\x08\xa5\x6f\x6e\xbe\xb8\x21\x56\xd2\x1a\x12\x8c\x45\xe8\x3b\x38\x86\x95\x1a\xc0\x3a\xb4\x28\xec\xce\x4b\x84\x69\x23\x4d\x61\xa0\x0e\x0d\xba\x8e\x48\x26\xc5\x9c\x2f\x4a\x5a\xe9\x23\x64\x39\x5f\x2e\x6f\xc5\x2d\x55\x39\x39\xb9\x1a\x8e\x22\x7a\x34\x73\xeb\x17\xe2\x0b\x5b\x5b\x0f\x78\x78\x23\xf3\x14\x26\xd7\x8a\x21\x33\xee\x54\x5e\x8d\x56\x78\x52\xb4\xf0\x76\x6b\x1f\xad\x55\xf3\x13\x45\xbf\x08\x34\x16\x77\x45\x8b\x9a\x91\x19\x33\xb7\x8c\x09\xf2\x02\x79\xc6\xec\x78\xf1\x87\x3f\xfc\x61\x4a\xce\x5a\xca\x02\x0f\x64\x88\xc9\xf7\x51\xb3\x04\xda\x0b\x21\x0d\xa1\xf3\x39\x5c\x55\x67\xd4\xd1\xf0\x16\xaf\xd4\x3d\x5b\x48\xc9\x17\x4b\x58\x09\x2e\xe0\xaa\x15\x38\x6e\x08\x12\x9e\xe9\x1c\x78\x26\x34\x39\x85\xa0\xc7\xcd\x3b\xd2\xdb\x22\xa5\xcc\xd9\x11\x29\xf8\x0d\x23\x73\xfd\xad\x92\x75\x85\x2d\xe8\xb0\x8e\xbc\x2b\xd6\xd7\x75\x61\x80\xd2\x62\xc6\xdc\xc4\xd1\x59\x80\x70\xce\xd1\x2d\x8f\x1e\x1f\xdb\xed\x15\x4e\x82\x6b\x5f\x70\xeb\x6d\xce\x1b\xe6\x2b\x67\x63\xec\x81\x88\x58\x9a\x47\xc2\x24\xf7\x23\xcd\xe6\x4b\xb0\x14\x36\x6e\xf8\x36\x9c\x8d\xf1\x25\xb4\x90\x62\x01\x17\x08\x2d\x53\x76\xeb\x62\x59\xde\x94\x6d\xae\x2b\x74\xb2\x21\x1a\xe3\x9a\x02\xe5\x4a\xbc\x07\xf0\x86\x56\x78\x11\x9b\x90\xc6\xe8\x16\xad\x6e\xd0\x99\xac\x4d\x28\xb7\x72\x73\x84\xe6\x62\x51\x42\x8d\x0c\x07\x23\x42\x4c\x82\xad\x23\x89\xb6\x8f\xc4\x5e\xc1\x30\xfa\x0e\x67\x2f\x34\xc4\x9a\x82\x76\x30\x9a\x2d\xc9\x0d\x5b\x4f\x9c\x3f\x50\x51\x14\x7f\x77\x7f\xf8\x07\xc0\x33\x6a\xa8\x43\x19\x47\x4b\xf4\x88\x88\xe6\x99\x3d\x5e\xe2\x69\x73\x70\xe3\xea\x0f\xdb\xd1\x6a\xb5\xc0\x66\x1e\x2d\x32\xa4\xe2\xb4\xcf\x90\x90\xdb\xa5\x44\x7b\x93\xed\x10\xed\xc3\xb1\xdd\xfa\x08\xd7\xaf\x1d\x99\x14\x86\x09\x13\xc4\xc2\x69\x8a\xc1\x96\xbb\x71\xb1\xc9\x78\x1d\x2d\xd1\xda\x68\x96\xdb\xcf\xd6\x4f\x79\xe7\x5b\x3e\x64\xeb\x0a\xa3\x43\xc0\xfe\xa8\xc5\xe6\xd7\xc7\x1f\x25\x69\x9c\x45\x87\xd4\xe2\x94\x5c\x60\xbb\x54\xb6\x83\xc2\x99\x4c\x50\x1a\xdd\x8e\xdb\x25\xcf\x80\xd7\xd4\x4e\xd7\xcf\x35\x95\x96\x6b\x14\x49\xbc\x2e\xee\xb0\x4e\x68\x66\xea\x2a\xcd\x16\x01\x5f\x80\xdd\x7b\xa6\x35\xe1\x11\xf5\x01\xed\x28\xa9\xba\x61\xb9\x8f\x76\x68\x31\x25\x57\xf6\x90\xc6\x8b\xf5\xc1\xa9\x62\x05\x85\x96\xf2\x29\x0e\xbd\xf5\x39\xbb\x2d\x08\x52\xdc\xce\xfd\xe9\x74\xdf\xc5\xa8\x91\x0d\x0d\xda\xd1\xb6\x36\x88\x14\x15\x1b\x35\xb4\x23\x89\xf3\xb2\x99\x19\xa1\x55\xfc\x39\x01\x3e\x3b\xc8\xfa\x81\xaa\x40\x3f\x62\xf7\x25\xc2\x7e\xfa\xcc\x45\x9c\x27\xeb\x86\x07\x29\xc5\x6b\x85\x34\x2e\xad\x1b\xf8\xcc\xdc\xe6\x98\xd8\xb5\x4f\x20\x05\x49\xf6\xd9\x1f\xa9\xfc\x75\x37\x6e\x18\xf2\xd9\x63\x73\xf4\x49\x1d\x12\x28\x1e\x37\xdc\xa1\x0f\x6e\x47\xfc\x09\x23\xf1\xcf\x45\x9b\xa3\x44\x27\x52\x37\x47\x1f\xf8\xf8\xd6\x9b\x9c\x34\xb2\xbb\x19\xac\x24\x5a\xc4\x8e\x5a\x33\x57\x30\x94\xc0\xd0\xba\x61\x5d\xff\xa3\x60\x1d\x13\xc9\xdc\x48\x00\x27\x92\xea\x4a\xfc\x20\x21\x9c\x48\xe2\xc5\x1c\xac\x77\xc2\x88\xd7\x8d\x6e\xd3\x9f\x36\xf7\x9f\x48\xb8\x0f\x2c\x80\x53\x3a\xd5\x42\xf4\xb2\xd6\x89\x64\xc6\xe7\xbe\x37\xc7\x76\x2e\x3c\xd9\x7e\xc5\x66\xd4\xb7\x25\x76\x33\xec\x89\x84\xa6\xc8\xd3\x6f\x8e\x7e\xde\x3e\x91\xd0\x04\xd9\xff\xcd\xd1\x7f\x0d\xc0\x97\x81\x77\x47\xfc\xf3\xc0\xe6\x88\x7d\x2e\xd8\x1c\xf8\x32\xc1\xcd\xf1\x40\xde\x42\x13\x4d\x25\xf1\xb4\xdc\xf0\xf9\x38\x7b\x7d\x52\xdd\x46\x49\x4a\x5a\x85\x94\x54\x32\xa1\x53\xf2\xc6\xc5\x7f\x89\x24\xce\x6c\x50\x4a\xe8\x4c\xcb\xa2\x36\xa9\xbe\xdd\x13\x67\x27\x9d\x68\xca\x70\xd7\x0d\x88\x8f\x58\xc1\xca\x14\xc9\x13\x37\x5c\x2b\xbf\xb4\x1f\x0e\xe1\x78\xd3\x71\x2e\x99\x50\x88\x36\x53\xc4\xe7\x6e\x24\x73\xb7\xe3\xc8\x50\xdc\xd8\x49\x89\x92\x24\x9b\xd5\x27\x46\x49\x90\x72\x7b\x52\xc4\x2a\x6e\xec\xa6\x57\x89\x16\xeb\xe9\x59\xba\x24\x2b\xd1\x32\x53\x90\xb4\xb8\x91\xec\xfc\xca\x44\x01\x5d\xef\x0c\x5f\xbb\x9e\xf9\x09\xf2\xc6\xcc\x73\xa2\x74\xf2\xbc\xf1\x8f\x59\x8a\x58\x27\x09\x92\xf0\xa9\x82\xba\x9c\xcd\xb9\x88\xce\x94\xc7\x82\x0e\xfd\x5c\x3c\xee\xec\xe4\xea\xe2\x09\xbf\x5c\x77\x66\x19\x25\x31\xa7\x86\x8e\x6f\xd7\xf7\x8d\x1d\x60\xc9\x04\x69\x11\xda\x40\x6d\xce\xda\x5d\xfc\x1e\x0f\x24\xed\x8e\x04\x3e\xed\xd3\x4e\xc1\x6f\x2d\xd9\xeb\x34\x5e\x7c\xa7\x00\x31\xd5\x6d\x75\xc3\x48\x0f\x83\x4c\x19\x73\x78\xff\xd8\x95\x14\x03\x7b\x52\x02\xa1\x69\xc0\x0e\x4f\x36\xe1\xff\x04\x53\xf5\xb0\xe2\x68\xf6\xc5\xcd\xb1\x49\x10\x93\x6a\xe9\xdc\xb8\x66\x85\xf5\x3e\x49\x2a\x50\x8c\x1b\x32\x50\xbf\x25\x9b\x27\x90\xcd\x50\x21\xa4\x81\x1b\xac\x93\xe5\xc6\xe8\x8c\x15\xfa\x88\x44\xf0\xa4\x6c\x0e\x2a\xf2\x96\x62\x20\x95\x4c\xd5\x29\x3f\x4a\x9a\xc6\x4a\x74\xa5\x49\xd2\x6b\x4d\xe0\x6a\xc3\x89\x8c\xe8\x39\xd5\x1f\x69\xef\x38\xe9\x51\x4d\xa6\x92\xb8\x59\xe4\xe2\xa4\x27\x13\xde\x5c\x4c\x9d\x2d\x59\x99\xe2\x3d\x39\x0c\x2b\xf4\x75\xd2\xed\x72\x83\x6b\x72\xab\xb8\x31\xc9\x1e\x83\x88\x07\xc9\x30\x55\xa6\x7a\x05\x20\xb0\xae\x47\xe1\xc9\x26\xa5\x58\x23\xc9\xde\xea\x25\xba\x14\x7c\x87\xc0\xb4\x2f\xaa\x24\x58\x3b\x5c\xeb\xd8\xfb\x46\x1f\xe7\x9d\xf6\x44\x35\x59\xe2\x74\xd6\x8e\xb8\x9d\xd2\x60\x4a\x13\x9f\x53\x7b\x59\x93\x41\xce\xda\x71\x72\x75\x41\x56\x4e\xbb\x3c\xd9\xc3\x35\x3e\xd7\x8f\xcf\xf5\x49\xc6\xf8\x5c\xef\xc7\xf8\x5c\x3f\x3e\xd7\x8f\xcf\xf5\xf1\xe3\x99\x3c\xd7\x27\x4f\x16\x5c\xb9\x7e\xcf\x24\xe1\x23\xe6\x43\x00\x01\x44\x92\xfe\x09\xdd\x01\x77\xdc\xb1\x61\xf8\xe2\xe7\x54\x2a\x19\x6a\x9f\x5d\xc1\x42\xaa\xab\xee\x71\x00\x78\x16\xff\xcd\x91\xfe\xd9\x7e\x7f\x7f\x3a\xdd\x77\x68\xf5\xa4\x0b\x69\xed\xa5\x99\x4f\xfe\x98\x48\x26\x13\x99\xcc\x59\x3e\x4d\x08\x7c\x99\x73\xa5\x0d\xa4\xd0\x53\x3c\x67\xbb\xe1\x14\xbb\xbb\x47\x29\x71\x15\xa5\x3f\x9b\xe9\x41\x10\x6e\xff\x53\xaa\xf7\x64\x51\x47\x60\xbd\x78\xfd\x80\x49\x5c\x9f\x74\x4d\xe6\x86\x37\x2d\xbc\x93\x1e\x29\x7f\xed\xb1\xcc\xd4\xdb\x03\x72\xb8\x0d\xab\x48\x32\x6f\xa9\xe4\xd0\x4c\x21\x87\xfc\x23\xd3\xc9\xd6\xf5\xc0\x89\x9e\x66\x55\x9d\xce\xb5\x03\x89\x25\x2b\xa5\x42\xf7\xc0\xdc\x1c\xe1\xb3\xed\x44\x13\xba\x8b\x8d\x58\x37\xdb\xc3\x84\x99\xec\xac\x56\x8a\x09\x3c\x41\xd5\xe6\xf8\x8f\xcb\x8c\x87\x4b\xf4\x44\x13\xe3\x8d\xe6\xc0\x53\x4b\xef\x1a\x1b\x74\xd3\xe1\x47\x12\xa6\xc5\x00\xb8\xd6\xec\x56\x42\xc1\x73\xa9\x7c\xaa\x20\xd9\xcb\x15\xe9\x00\x95\x12\xcf\x94\x89\x55\x42\x89\x2b\xaa\x90\xf4\xd3\xbb\xc6\x03\x64\xb0\x73\xbe\xe2\x5a\x26\x33\x73\x3b\x71\x5f\x78\x96\xd1\x5d\xc3\x9a\x67\x59\x9b\xaa\x4e\x99\x6e\x76\x51\x6d\x3a\x1f\x82\xf8\x89\xb2\xbb\x4a\xea\xa4\xb7\xa9\xf1\x21\x52\xde\xa5\x07\x7a\xbe\x79\x89\x25\xdc\xdd\x1e\x15\x35\x86\x29\xf1\x8a\xfc\xf7\xc1\x3f\xbe\xfa\x38\x39\xfc\xe6\xe0\xe0\xc7\x17\x93\x3f\xfd\xf4\xd5\xc1\x3f\xa6\xf0\x2f\xbf\x39\xfc\xe6\xf0\x63\xf8\xc3\x57\x87\x87\x07\x07\x3f\xfe\xfd\xcd\xb7\xef\xaf\xce\x7f\xe2\x87\x1f\x7f\x14\x75\x79\xe3\xfe\xf4\xf1\xe0\x47\x76\xfe\xd3\xff\xcf\xde\xbb\x37\xc7\x8d\x23\xf9\xa2\xff\xf7\xa7\x40\x68\x26\x42\xf6\x1c\x55\xb9\x7b\xb6\x63\xce\x5c\x9f\x8d\xdd\x50\x5b\xea\x59\x9d\xb6\xdd\x5a\xcb\xf6\xc4\xb9\xbd\x73\xf7\xa0\x48\x48\x85\x15\x8b\x60\x13\xa0\xe4\x9a\xdd\xfd\xee\x37\x90\x09\x80\x60\x15\x49\x80\x0f\x3d\x3c\x53\xfc\xa7\xdd\xa5\x62\x16\x1e\x89\x44\x3e\x7f\x19\x49\xe4\xe5\xcb\x7f\xfe\xed\x6c\x53\xa0\xf9\xf6\xe7\x99\x54\x6a\x02\x37\xe1\xfc\xce\x1d\x9f\xee\xac\x62\x86\x90\x2f\x8b\x3a\x3d\x78\xc1\x73\xb5\x10\xe5\x02\x7f\xe2\x35\x51\x65\x35\x9f\x4f\x05\x8f\xc7\x43\xdd\xbc\x73\xbb\x95\x88\x37\xe6\x87\x08\xc9\x3d\xb3\xcb\x07\xd1\x14\x9f\x71\x16\x2a\x0e\xf0\x00\x9e\xd4\xf6\x1c\xc0\x93\x9e\x2b\x78\x92\xe9\x51\x6c\xe3\x66\x0e\xff\x66\x86\xc9\x23\x7e\x4e\x8d\x7c\x34\x99\xa4\x8f\x9c\x34\x4f\xea\x59\x13\x39\xc9\x22\x1f\xcd\x45\x16\x91\x93\x9a\xc8\x47\xd3\x53\x4a\xd7\x6c\x0f\xf9\x68\x32\xd1\x06\x92\x9f\xde\xb9\x59\x86\xb9\x8b\x7c\x34\x9d\x01\xa0\xc1\xaa\x37\xfb\xc9\x14\x81\xef\x77\x90\x8f\x26\x13\xbd\xb8\xfe\xda\x90\x8f\x50\x0a\xcc\x03\xcb\x75\x80\x3d\x3a\xc0\x1e\x4d\x7a\x9e\x77\xcd\xc5\x01\xf6\x68\xf0\xf3\x6c\xab\x20\x0e\xb0\x47\xa1\xe7\x00\x7b\x34\xfd\x39\xe4\x51\x1e\xf2\x28\x0f\x79\x94\x87\x3c\xca\x43\x1e\xe5\x21\x8f\x72\x0e\x8a\x5f\x49\x1e\xe5\x01\xf6\x68\x16\xa2\x07\xd8\xa3\x03\xec\xd1\x2c\x44\x0f\xb0\x47\x43\x9f\x03\xec\xd1\xa4\xe7\x00\x7b\x34\xe8\x79\x70\xd8\x23\x74\xf2\x4e\x8f\x41\x39\xcc\xa3\xbf\x49\xc8\x23\xa9\x8f\x5d\xc2\x4e\x93\x44\x54\xb9\xfa\x28\x6e\xd9\xa4\x3a\xf5\x07\x0f\x3a\xef\x8d\x76\x12\xe5\x67\x07\x81\x34\x87\xbb\x6f\xb2\x8b\x6e\x2e\xe7\x1c\xad\x52\xce\xf2\xe9\x29\x26\x0d\xa6\x3a\x35\x44\xe7\x8a\x5a\x6a\x53\x25\x4f\x59\xea\x46\x3b\x57\xd4\x5a\x69\xee\x5c\x92\x53\x52\xb2\x84\x17\x7c\x0e\x25\x4c\x5c\x13\x8a\x74\x51\x16\x99\xbe\xa4\xd3\xe5\x26\x57\x92\x65\xd7\xa8\x84\xd1\xbc\xee\x77\x3a\xdd\x82\xab\x83\xa2\x26\xf6\xf6\x20\xcb\x3c\x4f\x97\x19\x50\x07\xee\xb9\x64\x44\xae\x45\x95\xa5\xa4\x64\xb3\xf8\xf0\x3d\x6e\xf8\x38\xe7\x0a\xa4\x5e\x7b\x62\x60\xe5\xf9\xb6\xcd\x2c\x2e\x2d\xb8\x16\xb9\xac\x9c\x27\xc8\x35\x83\xfa\xc1\xbe\x14\xbc\x84\x2b\xe5\x8a\x25\x22\x4f\xe7\x4d\xb3\x39\xdf\xa5\x3e\x97\x94\x31\x75\x12\x2c\x25\x69\x55\xce\x03\x2f\x26\xae\xc9\x1d\xcd\x78\xca\xd5\x76\xae\x3a\x46\x73\xbd\x12\x8a\xf7\xab\x61\xda\xc9\x64\x4f\x65\x7d\x04\x08\x2d\x8a\x52\xd0\x64\x3d\x83\x22\x5f\xf3\xc2\x09\xfa\x21\xb0\x5d\xff\x5c\x21\xfd\x22\xab\x6e\x78\x3e\x4f\x4c\x1f\xe6\xac\xf8\x1d\xcb\xb6\xa4\x14\x8a\xce\xe0\x8a\xf0\xf4\x21\xbb\x61\xd3\x69\xd6\x52\x6a\xae\xc5\x04\xd7\x3a\xda\xf8\xaa\xdc\xce\x11\xac\x52\xc2\x2c\x61\xcd\x55\xd3\x8f\xa9\x77\x99\xe8\x33\x2b\xb2\x74\x06\x29\xaa\xd6\x34\x27\x7f\xfc\x96\x14\xac\x4c\x58\x3e\x4b\xd6\x3c\x44\xbe\xf8\x06\x0a\x8d\x33\x7e\x37\x4b\x01\xef\x03\x4e\xfe\xf7\xdf\x93\xb5\xa8\x4a\xb9\x3c\x9b\x2b\x71\x5e\x09\xf2\x1d\xd0\x04\x37\xbb\x56\x83\xe6\x48\x07\xa3\x8a\x64\x8c\x4a\x45\xbe\xfb\x96\x6c\x78\x5e\x29\x36\xb2\xfb\xbd\x37\xd0\x19\x3d\xe1\x9e\x0f\xfc\x0f\xdf\x4f\xa2\x35\x87\xf7\x7b\x0f\x79\x69\x8e\x14\x25\x80\x02\xd4\xb4\x66\x2b\x52\x36\x5a\xd1\x06\xae\xb2\x42\xf0\x79\x14\x70\x17\x85\x9a\xc5\x6c\x34\x23\xad\x4f\x5f\xae\xc4\x13\xea\x5a\xbf\x56\x62\xb5\x55\x23\x0c\xb6\x06\x4b\xfc\x2b\x52\xf1\x71\x55\xc7\xe4\xe7\x58\x32\xb8\x81\x02\xcd\x87\xb5\x90\x0a\x63\x8b\x72\x4d\xcb\x51\x4a\x04\x25\x85\x48\x8f\x25\xc9\xf8\x35\xd3\xa2\x74\x30\x89\x49\xb6\xfe\x78\x0b\x7f\x41\x4a\x76\xc3\xa5\x2a\x87\xdb\x7b\x0b\xa3\xd3\x0c\x7e\x71\x9a\x2b\xe0\xa6\x14\xd5\xc8\x1e\xd0\x0d\x86\x82\xe8\xac\x8d\x38\x8d\x9c\x09\x3e\x34\x49\x98\x04\x83\xc9\x5c\x48\x98\x61\x8a\x23\x1d\x45\x73\xa2\x65\x53\x32\x9a\xfe\x9c\x67\x23\xf3\x97\x1a\xab\xf4\xc1\x90\x22\x6b\x56\xb2\x29\x6a\xeb\xb5\x28\x13\x54\xae\xec\x11\xb4\xad\xc9\xc7\xa6\xdc\xac\xcc\x29\x66\x29\xfa\x18\xf4\xac\x17\x50\xe9\x5f\xb0\x72\xc3\xa5\xe4\x22\x1f\x7d\xe1\x9e\x79\x66\xf0\x35\xcd\xe4\xc8\x14\xbe\xa9\xfe\x54\x7b\x38\x67\xd9\x49\x24\xe5\x49\xd0\xb1\xfc\x4e\x24\xcf\x6f\x32\xad\x26\x92\x4d\x95\x29\x5e\x64\x6e\x57\x47\x92\x74\x83\x33\xc6\xc7\xf4\xa4\x6f\xe8\x12\x6d\x22\x76\x54\x82\x88\x7f\x5d\x88\x52\x4d\x29\x4b\x79\xe1\x66\xcb\x72\x55\x72\x26\x11\x1d\x97\x15\xb4\xa4\xe3\xeb\x3d\x80\x79\x13\xb1\xd9\x50\xf9\xd2\x64\xa8\x53\x00\x46\x96\x13\xec\x6f\x6d\x1a\x94\x34\x73\x0c\xe4\xd7\x81\x3f\x85\x48\x52\x2c\xa7\xf9\xc8\xd2\xb3\x66\x4a\x04\x10\x22\xe2\xde\x82\x95\x8f\x5c\xa0\x1b\x7e\xc7\xf2\x5d\x59\x34\x29\x54\xfe\x03\x4d\x6e\x59\x9e\x92\x4f\xd2\x4a\xa4\x74\x9b\xd3\x0d\x4f\x68\x36\x1a\x6f\xa2\x28\xc5\x1d\xd7\x82\x8c\xa5\x3b\x63\x1d\x5d\x0a\x82\x19\x7f\x1c\xf2\x73\xc8\x6a\x8b\x3a\x32\x78\x25\x9e\x82\x2f\x2a\x39\x16\xe5\xa5\xc1\x15\x9f\x24\x2b\x1f\xe6\x2e\x97\x58\xcd\x59\xf2\xbb\x84\x4d\xf3\x88\xe8\xa9\x3e\xc5\x12\xe3\x7a\xcc\xb0\xc8\x9f\xcd\x21\xa9\x25\xeb\xc8\x95\x00\x55\xdb\x15\xe0\x49\x48\xa6\xc9\xf4\xf5\xbd\xb5\x20\x67\x23\x09\xef\x1c\xe7\xd5\x16\x32\x23\xa6\x5c\xdd\xa3\xe6\x59\xae\x46\x68\xe2\x3b\x95\xce\x3f\x9c\x35\x4c\x1d\xf2\x81\xa6\x62\x8c\xe4\xfe\x21\x13\xc9\x2d\x39\x63\xe0\xd2\x6b\xb7\x7a\x46\x50\x45\x3b\xc9\x58\x3d\x9e\xd9\x83\x29\x1e\x98\xa2\x31\x82\xac\x4d\xea\x60\x5f\xe8\xa6\xc8\x98\x5c\xde\xfe\x11\xd2\x3a\x8c\xc8\x7b\x55\xae\xd2\x57\x1f\xce\x4f\xcf\xde\x9d\x2f\x37\xe9\xf0\xec\x85\x27\xb3\xb1\xf8\x86\xde\x0c\x97\x48\x0b\xb2\x11\x39\x57\xa2\x1c\xbe\xef\xd3\x4c\xac\x6b\xf9\x51\xaf\xd4\x74\x89\x71\xfc\x23\xcf\x98\xdc\x4a\xc5\x36\xb0\xf8\x23\x8f\xb5\xf1\x90\x58\x83\x41\x4b\x8f\xad\xa8\xc8\x3d\x1d\x2d\x8b\xf5\x55\xa1\xcf\xc2\x92\x7c\xe4\xc5\x6b\x72\x9e\xcb\xaa\x34\x94\xc7\x2b\x00\xd7\xcd\xc9\xc2\x1d\x6b\xf1\xa1\xc6\xda\x38\xdb\xfa\xa8\xea\x1d\xa5\x4a\x6b\x3d\xf8\x23\x63\x4d\x9b\x73\x73\xb8\x5e\x93\x23\xf6\x45\x7d\x7f\x74\x42\x8e\xbe\x5c\x4b\xfd\x9f\x5c\x5d\xcb\xd1\x90\xef\x17\x9b\x22\xe3\x09\x57\xd9\x56\x1f\x7f\x56\x96\x2c\x35\xc0\x95\xf8\x33\x23\xc9\xf2\x46\x91\xba\x2f\x5f\xa2\x52\xc0\xa4\x12\x25\xbd\x61\x56\x82\xfc\xa6\x5c\x8d\xdd\x0a\xcc\xf0\x5a\x8b\x7b\x92\x0a\x72\x0f\xa5\xae\x77\x2c\x57\x58\x59\x39\xd6\x94\x32\xf1\x6b\x8f\x73\xae\x4b\xb1\xd1\xd6\x40\x51\x8a\x0d\x97\x53\xee\x58\x46\x36\x34\x59\xf3\x9c\x8d\x4b\xf3\x9a\xa8\x75\x80\xc8\x9b\x43\x84\x7c\x5c\x33\x52\xea\xcb\x6f\xa4\x14\xc5\x07\xf4\x80\x36\xe6\x89\xba\x6a\x7e\xb3\x16\xf7\x0b\x25\x16\x95\x64\x0b\x3e\x12\xd5\x63\xe2\x7a\xde\xb2\x2d\xc0\xb5\xcc\xb0\xa2\x3f\x21\x29\x1b\x46\x9e\x90\xd8\xa3\x04\xe4\xb0\x01\x35\x6d\x60\x7e\xf8\xe1\x4c\x6b\xe2\x4b\xab\x3c\x8f\x3d\x15\x92\xbc\x62\x2a\x79\x95\xb0\x62\xfd\xca\x4c\x7c\xa2\x66\x41\x86\x6a\x17\xcf\x60\xcb\xed\xed\x3f\xc7\x9e\x9f\x92\x44\x64\x19\x4b\xf4\xff\x8e\x0f\x19\xbe\x61\xc5\xda\x0d\xeb\x39\x1c\xa7\xf1\x15\xce\x93\xea\x9a\x27\x6e\x6c\x21\xc4\xc8\x54\xd7\x2e\xd1\xa8\x29\x4e\xb0\x75\x88\xef\xb9\x2e\x57\xed\xd7\xec\xd7\x72\x6c\x66\xf4\x7e\x1f\x3f\x80\xfb\xdb\x91\x94\x4c\x81\x36\x37\xd2\xf1\x42\x8c\x3d\xfe\x4e\xeb\xb1\x72\x39\x97\xc7\x9a\x3c\x83\xad\x1f\xef\x2f\x47\x00\xa9\xd1\xe0\xc9\xbb\x60\xc9\x86\x18\xc4\x73\xc6\x63\xe5\xd8\xbc\xb7\x4a\xad\x59\xae\x78\x02\xd9\x45\x66\xa8\xe3\xd9\xa9\xbe\x6c\x2f\xae\xd1\x4f\x98\xb2\x94\x88\x3b\x56\x96\x3c\x1d\x9d\x08\xe5\x6e\x5b\x3f\x94\xc5\xb3\x49\xa5\x1b\x4f\xca\x4b\x13\xb2\xa7\xa7\xa7\x2c\x4f\xab\xcb\x69\xad\xc8\x99\x98\x93\xd7\xac\xc5\x79\x6e\xb5\x34\xed\x55\x34\xb6\x0a\x66\x02\x61\xaf\x7e\x66\x96\xfa\x97\xe7\xe1\xf5\xf6\x14\x00\x4d\x71\x2e\x05\x80\xa6\x1b\x9e\xff\x9d\xe9\xdb\x32\xa1\x19\xbb\xf8\x79\xa2\xdb\xf6\x0a\xa9\x4c\x4d\x52\xb1\x64\x0a\xcd\xb2\x52\xb1\x5c\x39\x04\x38\xa5\x68\xb2\x1e\xe5\x4e\x82\xcc\x36\x13\x2f\x17\x39\xf9\xc9\x9d\x75\x92\x8b\x74\x4c\x66\xda\x93\x79\x53\x6f\xa8\x62\xf7\x23\xd4\xfe\x45\xad\x1e\x8c\x79\x17\xfc\x33\x5f\xab\x27\x76\xc7\x11\x3b\x3e\xeb\xc2\xb8\x4d\x6d\xd3\x13\xea\xf9\xae\x26\x18\x53\xb5\xa3\xb4\xdd\xe5\x39\x92\xb4\x71\x94\x92\xf3\x2f\xcb\x79\x9d\x9d\x9e\xb4\x04\x7a\x8f\x1e\x62\xd2\x8f\x39\x07\x73\x04\xd5\xed\x82\xd3\x34\x2d\x99\x1c\x7b\x85\x1b\x45\xd7\x8a\xaf\xd3\xcb\x0b\xf2\x27\x1c\xe3\x93\xac\x4f\x51\x0a\x85\x1e\x8f\x33\xb1\xa1\x7c\x64\x0d\xe2\xde\x42\x79\x4d\x9e\xec\x54\x47\xae\xd7\xa5\x1b\x20\xc1\x11\x82\x5e\x6f\x3a\xa0\x5c\xf3\x9b\x6a\x7c\x2b\x00\xe3\xf7\x7e\x92\x75\x9f\xd1\x00\xdf\x33\x6a\xc7\x66\xee\xe8\x31\xbd\xba\x2f\xb9\x62\x2f\x97\xcd\xa4\xb6\xd1\x59\x3b\x59\xd6\x63\xd5\x8f\x8f\x07\x34\xac\xfa\xaf\xde\x88\xae\x6d\xe8\x3a\xde\x3f\xde\xd9\xec\x61\x44\xeb\x93\x62\x05\xcd\xe8\xcc\x0a\xd4\x8a\xd0\xd6\x90\x2c\x97\x1c\x20\x52\xbc\x12\xe3\xd1\xc1\xb0\x6b\x80\xfe\xaa\xa1\x46\xd1\x3c\x3f\x21\x6f\xc5\xd8\x44\x1b\x62\x6f\x43\x91\x1b\xe6\xa3\x3c\x9b\xc2\x20\x07\xcb\xb8\xf1\x1c\x2c\xe3\xe7\x60\x19\x4b\x99\x9d\xe7\x74\x95\x8d\xad\x56\x6f\x2a\xbd\x19\xbd\xd1\x62\x83\x01\xc5\x57\x29\x97\xfa\xbf\x23\xa7\x76\x75\xf5\x16\xb2\x34\xab\xdc\x7a\xf0\x20\xc7\xcf\x28\x38\x63\xb3\xf1\x4c\xb9\xed\x84\xcb\x6d\xb2\xb4\x47\x4d\xe1\xdd\x68\xac\xc6\x26\xa6\x7c\x9e\xea\xe5\x61\xd2\xc2\x66\x4c\x08\x5f\x9b\x91\x81\xa8\xa7\x0e\x13\x19\xaa\xa8\xc7\xa6\x53\x30\xf2\x71\xcd\x93\xdb\x4b\x2f\xad\x52\x94\xfa\xb3\xdc\xfb\x68\x06\xa3\x60\x16\x8a\x53\x8f\x12\x2e\xdf\xe5\x3c\xc1\xa6\x8f\x9e\x62\x7f\x85\x94\xc7\x6a\xbd\x42\x64\x84\x4a\x29\x12\x4e\x5d\xf2\x3e\x04\xa2\x9d\x3a\x3c\xf6\x30\x81\x12\xfd\x34\x8b\x0d\x96\xe6\x03\x58\x18\x72\xd2\x5a\x1b\x93\x9f\x4a\xcf\xa2\xd0\x4a\xa6\xd9\xc9\x27\x59\x2a\x3c\xc8\xe3\x1b\xb4\x75\x2e\x17\x9d\x98\xfa\xdb\x4c\x41\x75\xb8\xee\x93\x4c\x3c\xeb\x73\x59\x53\x74\xad\x36\xd9\x7e\xb4\x70\xe4\xd2\xc9\x43\x68\x5e\xf3\xe8\x1b\x39\xb6\x95\x4c\x5b\x84\x6d\xaa\xbb\xd4\x58\x04\xa6\x80\x0f\x40\x36\x0a\x51\x54\x19\x56\x73\x8f\x2a\x23\x35\xb0\xdd\x53\xb3\xcd\x70\x64\x8f\x9c\xa8\x3a\x4d\x39\xf7\x70\x70\xe7\x88\x50\x38\xa8\xe6\x1a\x18\x74\xbc\xf9\x67\x40\x95\xed\x01\x05\xcf\x23\x59\x6d\xed\x98\x47\x07\xbc\x9d\x2f\xb3\x81\x86\x8c\x38\xc6\x23\x69\x02\xfa\x71\xc3\x7d\xf1\xed\x1f\xbe\xff\x7e\x49\xce\x78\xc9\x12\x25\xca\xf1\x5d\xf9\x0c\x38\xbd\x2b\x6d\xa6\x25\x03\x1b\x13\x61\x71\xa7\x65\x9a\x62\x55\x88\x82\x00\x70\x0d\x35\x3c\x5e\xd9\xf2\xa0\x85\xe7\x03\x05\xf6\x40\x80\x77\xe0\x7b\x01\x78\x77\x6c\x44\xdd\xc0\xf5\xee\x00\xed\x92\x64\x34\x0e\x9a\x05\xd6\x9d\x05\x12\x77\x7a\xe1\xff\x54\xc8\xdb\x09\x09\x53\x7d\x5d\xa7\xa0\x6b\xd4\xf8\x64\x05\xaf\xd7\xd4\x6c\xbd\xa2\xf6\x3a\x44\xf9\x1d\x9e\xc6\x33\x43\xb3\x3b\x90\x97\xd1\x3e\x56\x5f\x91\xfb\xdd\x9c\x4c\x4e\xe7\xf8\xf5\xf4\x7b\x38\x35\x7b\x30\x8d\xf7\x84\x79\x9b\xbd\xd3\x79\x69\x8a\xef\xb5\x7d\x45\xa7\x96\x8d\x62\x97\xa5\xfd\x2e\x49\x53\xf6\x7e\xa7\x37\x92\xdf\xdb\x68\xac\x56\xe9\x00\xd0\x66\xec\x68\xb4\xdf\xc7\xa8\xd1\x87\x68\xca\x5e\xed\x77\x1f\x32\xdd\x83\x46\x7b\x42\x1b\x3d\x87\xf6\x7a\x06\x4d\x70\x06\xb7\x74\x0a\x02\xc4\xdf\x09\xfc\xe4\xfa\x03\x4d\xed\xef\xf3\xa4\x39\xaf\x7b\x1d\x7c\x1a\xfd\x77\xc6\xfb\x0b\xc5\x6e\xd7\x9d\x89\x3d\x73\x66\x00\xcd\x9c\x0a\x98\x39\xa5\x2b\xce\x24\xa0\xcd\x39\x40\x36\x27\xf6\xbd\xd9\xb3\xce\x67\x68\xce\x34\x43\x8f\x9b\x59\xb0\x02\xa7\xf6\xb3\x79\x88\x2e\x36\x7e\xef\x9a\xd9\xba\xce\x34\x7a\xcd\x58\xbb\x68\x12\xc5\x86\x4d\x65\xac\xa3\x8b\x69\xc8\x65\xcd\x8e\x30\xd3\xf5\x29\x7c\x3c\xfb\x77\xc6\x0e\x2e\x8d\xbe\x2d\xb3\x75\x5c\xd9\x37\xa9\xc6\xd6\xf3\xd6\x4f\xab\x61\x35\x89\x62\xa3\x1b\x8a\x35\xaf\x26\x51\xac\x4d\xb3\xa6\x91\x35\x8d\x43\xe7\xe8\x59\x32\x17\x3e\xdb\x3c\xfd\x49\xa6\xe2\xb2\xed\xc9\xf2\x59\x60\xd4\x50\x25\x6a\x82\x9e\x6d\xe8\x58\xfd\x12\x1f\xe5\x2e\x1a\xd7\x49\x62\x2a\xa8\xba\xd7\xe1\xa3\xee\xcd\x31\x59\x60\xf9\x6a\xe5\x6c\xbd\x34\x1a\x1d\x34\x3c\x55\x73\xf2\x92\xce\xd4\xf1\x62\xe2\xe5\x3b\xad\x3b\x40\x5b\x4f\x00\x1f\xd3\x7f\x6c\x38\x18\x5d\x02\x35\x92\x7f\x6d\x85\x4c\x81\xe2\x9f\x27\x77\x67\xa6\xe0\x8a\x9f\x59\x31\xad\x5e\xc5\x72\x3c\xa2\x45\x40\x32\x44\x41\x13\x66\x74\x96\x19\x2b\x95\x1e\xc3\x3b\x4f\x26\x86\x4e\x70\x18\x62\x84\x8e\xde\xe4\x65\xa4\xf3\xf3\xd5\x34\x44\x2f\xea\x11\xda\xc9\x32\x1f\xe9\xff\x7e\x3e\x59\xe6\x87\xe4\xeb\xd0\xf3\x35\x26\x5f\x3f\x0e\xd2\xc4\x53\x84\xc6\x0f\x99\xb3\x87\xcc\xd9\xfd\xcc\x59\xcb\x93\xe3\x03\x66\x2e\x6b\xd6\xf8\x08\xae\x45\x49\xc4\x4a\x2b\xa2\xd3\x00\x46\xea\x9b\xe3\xf4\xf2\x82\x24\x25\x83\x66\x11\x34\x93\x4b\x32\xde\xba\xdf\xb1\xeb\x6d\x86\x1c\xf8\x20\xa6\x46\x0c\xa8\x52\x6c\x53\xa8\x69\xc7\xfb\x90\x38\xdb\x78\x0e\x89\xb3\xcf\x21\x71\x76\xd6\xac\xaa\xcf\x8e\xd8\xb4\x80\xe2\xba\xda\xd0\x7c\xa1\x6f\x10\xba\xca\x76\x2a\x67\xac\xe8\x18\x49\xda\x66\xe8\x58\x54\x42\xe0\x13\x48\x86\x10\xf9\x68\xb8\xcd\x2a\xe7\xbf\x56\xac\x8e\x44\x38\x43\xe5\x89\x13\xe5\x60\x0c\xb3\xee\x2b\x9a\x5f\xb3\xdc\x2c\x89\x28\xd8\x0e\x44\x1b\x2e\xe0\x58\xcb\xda\x72\xc6\xd2\x34\xfe\xae\xb7\x61\xac\x6e\xe0\xc1\x09\xeb\x61\xa2\x31\x7a\x29\xd2\xe3\xb1\x13\xaf\x2d\xd8\x86\x8f\x18\x1d\xbd\x63\xa3\x8f\x59\x26\xee\x31\xe2\xee\x9b\x4d\xfa\xcc\xe8\x35\x9e\x70\x53\x83\x6e\xbc\xe1\x65\x29\x4a\x93\x78\xc8\xf3\xc9\x07\x10\x4a\xd5\xf8\xcd\x5a\xb1\x12\x1d\x9e\x58\x9b\xb2\x24\x57\xa3\xbd\x04\x9e\xd8\x51\x82\xd0\x1c\xe1\x3b\xf5\xbf\x2d\xac\xc5\x04\x3e\xb5\x7a\xc4\x8a\xad\xe9\x1d\x17\x55\x09\x23\x1d\x6f\x8b\x1d\x19\x82\x47\xda\x70\xd8\x8a\xca\x25\x62\x55\x13\x50\xdb\x1c\x5f\xc9\xbd\x6d\x1a\x7b\x57\xbd\xaf\x49\x42\xe6\x54\x2a\x6c\xae\xc0\x82\x7d\xe1\xa3\x3b\x9d\xec\x0e\xcf\x1d\x04\x93\x9d\xf7\xe8\x12\xf3\x4e\x16\xda\x28\xf9\x3c\x12\xed\xb6\x29\x27\x7d\x5a\x53\xdd\x2b\x77\x57\x40\xac\xcd\xb9\x62\x5d\x25\x63\x9c\xa2\xb9\xed\xa6\x84\xe0\xe6\x16\xec\xef\x71\x1d\x2c\x53\xca\xf8\x71\x3d\x2e\xc7\x44\xbb\x0f\x7e\x9d\xd0\x73\xf0\xeb\xb8\xe7\x19\xf8\x75\x5c\x29\x4e\xc6\x93\xed\xc5\xd9\x1c\xde\x01\x53\x1b\x85\x24\xc9\x0f\x54\x8e\x4e\xa6\x7a\x47\x73\x7a\x03\x41\x28\xf2\xe2\xea\xf2\x87\x77\x2f\xf5\xf1\x82\xc0\xdc\xc5\xd9\x58\x55\xa6\xa5\xba\xe7\xca\x5f\x83\xf7\x4f\x01\xcb\x4d\x76\x77\x62\x26\x6b\xe9\x51\xf6\xe2\x49\x80\xcc\x89\xb3\x42\x2e\x47\x87\x92\xf7\x1b\x7b\x61\x31\x8c\xed\x2b\x3a\x56\x5d\xde\xb9\x56\xef\x36\xe9\xed\x43\x2d\x8f\xd7\x4f\xa6\x7b\x0d\x62\x92\xf3\x82\x09\x78\x3b\x7c\x55\x52\xc5\x6e\xb6\x67\xac\xc8\xc4\x56\x33\xc5\x65\x3d\x10\xf3\xd5\x15\x0b\x9a\xe7\xe5\x8a\x26\xa4\xac\x32\x00\xda\x4f\xf7\xfa\x71\xe6\x8c\xa5\xf5\x0d\xc1\x73\xa9\x28\x34\x57\xc4\xdf\xee\xa1\x1c\xa9\x38\xc4\xa8\x08\x0b\x1c\x5f\xef\x37\x9a\x6d\xba\xdf\xf7\xc3\xf1\xc5\x2a\x08\xf0\xb3\x21\xbe\x8e\x4f\xbb\x8c\x4c\xb0\x6c\x1e\x09\x90\x1a\x1f\xaa\x4c\x5f\xcf\x59\x2a\x7d\xf8\x01\xa3\xb1\x9b\x9d\x8e\x39\x29\x94\x14\x28\x85\xf4\xcc\x4e\xc8\xaa\xd2\x0a\x3f\x93\x8d\xdc\x83\x61\x2d\xd4\xb1\x51\xfa\xfd\x1a\xf3\xab\x35\x59\x42\x8b\x22\xe3\x0c\x42\x0b\xa2\x34\x29\xc8\x43\x6c\xf4\x16\x42\x61\xd1\x36\x48\x4f\x8d\xd7\x4b\x17\xe4\x8e\x95\xab\xf0\xd2\x0e\x53\x39\x69\xc1\x21\xdf\x29\x52\x3f\x6d\x36\x23\xbf\xbc\xc0\x77\x6d\xfe\xbd\xef\x36\xb3\x7f\x8c\x14\x75\xc0\x3f\x66\xdf\x6d\xd3\x60\xac\x18\x44\x17\x7d\xdd\xbf\xe9\xf4\xf2\x22\x92\xe6\x0d\x0e\x0e\x5a\x1f\xd5\x6e\x7a\x6d\xad\x53\xc4\xb2\xa9\xfb\x12\xd3\x1b\xfd\xbb\xb1\x66\x85\xc8\xdd\x34\x59\x5e\x6d\x18\x34\x55\xaa\x07\x4c\x78\x0e\xbf\x72\x7a\x79\x31\xa8\xb5\x9a\xf3\xfd\x67\x99\xb8\x8f\x55\x00\x87\xa6\x5a\x0f\x4a\xad\x1e\x78\x23\xe7\x22\xff\x60\x16\xe1\xd3\x87\xb7\x63\x58\xea\x7d\x93\x82\x69\xe1\xc2\x94\x5e\xee\x82\x96\x8a\xd3\xd8\xda\x86\xaa\xcc\x8c\x1f\x81\x22\xe6\xa0\x29\xb8\x5c\xd3\x3b\x56\x37\xcf\x59\x12\xf2\xbb\xd8\x7b\x5d\xf3\x91\xd9\x1a\x94\x57\xd0\xc2\x0d\x9b\x5f\x91\xeb\x2a\xcb\x4e\xc8\x35\xcf\xa9\xbe\x92\x58\xec\x96\xfb\x09\x56\x57\x3c\x4f\x98\x5e\xc3\x85\xe5\x24\x02\x6b\x60\xdc\x35\x91\x14\x9d\x78\x83\x4c\x53\x2e\x31\x80\x00\x8d\x6d\x61\xb8\x5a\x90\x25\xe0\xe4\xbe\x8e\x6e\x9e\xfb\x26\xab\xa4\x62\xe5\x07\xa1\xaf\x66\xaf\xda\x08\x5a\x00\x50\xff\xcf\x3f\xf0\x3c\xe5\xf9\x4d\xac\xfe\xf7\x01\x2e\xfb\x84\xe6\x84\x71\x08\x7a\xe8\xe1\x6d\xb5\xb8\xd6\x67\xa7\x3e\x50\x2f\x64\x15\x5d\x7b\x45\x25\x39\x2a\x44\x2a\x8f\xb4\xc8\x3f\xc2\x70\xa2\x3c\x7a\xa9\xff\x6f\x77\x6d\x23\x29\x42\xa9\x0d\x8e\x01\xa8\xbf\xa2\x05\x3f\x7a\x79\x42\x80\x09\x20\x81\x4f\xa8\xf5\xd7\x77\x5a\xed\x4a\x80\xdf\x6d\xc4\x59\xfd\xe0\xbf\x0f\x27\x35\x77\x19\x70\xfa\xae\x8d\xee\xb1\x97\x71\x09\x07\x1c\x23\x23\xb6\xb7\xc9\xde\xc5\x4b\xc8\x69\xac\xa7\x9e\x6d\x0a\x05\x71\x7a\xb2\x61\xd4\x24\x1b\x13\x76\xc7\xca\xad\x5a\x9b\x86\x02\x5f\xad\x90\x75\xa7\x62\xc2\x96\x19\xc1\x6a\x17\xde\x91\x8c\xbe\xac\xb9\x6c\xd9\x1e\x4b\xfd\x34\xcb\x86\xbb\x22\x29\xbc\x64\xaf\xfc\xaf\x6e\x57\x40\x37\x1b\xb1\x23\x9f\xf5\x7b\xcd\xdd\xc0\x8f\xf0\xea\xd2\xe2\x30\x76\xc0\x82\x9c\xbe\x7d\x6b\x32\x55\x70\x1d\x7f\xe2\x79\x8a\xb6\xd4\xa9\x52\x25\x5f\x55\x8a\x7d\x60\x7a\x4a\xc9\x90\xb2\x66\xa3\x95\x59\xa0\x09\xb3\xf5\x4b\x02\x03\x1d\xbd\xd7\xb7\x7a\x6c\x5f\xd3\x3e\xef\x9b\x75\x71\xe6\x58\x27\x69\x6b\xb9\xb6\x93\xe9\x79\xd9\x98\xbe\xef\x44\xda\x26\x04\x76\x50\x8e\xea\xaf\x1a\x25\x78\xeb\x79\x5b\x0d\x25\x63\xc2\x6d\x8b\x16\x09\xd0\xb7\xf8\x9d\x0b\xdd\x35\x86\xda\xdf\x06\xb7\x85\xf7\x97\x8f\xdb\x02\xa3\xb1\x84\x92\xeb\x8c\xb6\x6f\x85\x63\x34\x90\xe1\xa8\x80\xbf\xb9\xfa\x6c\x27\x24\x09\x6f\xd3\x92\x02\xf6\x58\x9f\x05\xb6\xe8\xed\x8b\xb5\xe8\x6a\x15\x16\x32\xc1\x1c\xd1\x2e\x0e\x0a\xa7\x77\xa9\x9e\xc0\x40\xd7\xea\x7f\x34\xbd\xbe\xa8\xc7\x01\xe0\x7e\x17\xd7\x96\x13\x3a\x39\x1a\xaa\xb7\xae\x45\x09\xeb\xed\xb3\x4d\xef\x0c\x5a\xd9\xf7\x96\x6d\xef\x45\x99\xb6\xac\xcd\x28\x5e\xeb\xf9\xa5\x8c\xae\x58\x16\x3a\x22\xef\x68\xa1\x17\xa0\xae\x10\x45\x89\x89\x59\x5c\xc6\x2e\xc5\xfa\x9d\x4a\xa2\x9f\x5f\x94\x37\x34\xe7\x7f\x6d\xdb\x79\x28\x4a\xd7\xa7\x5a\x94\xfc\xaf\x8c\xbc\xc0\x9c\x03\xf4\x66\x65\x2c\x51\x2f\x0d\x1f\xb6\x48\xbe\x5e\x36\xa5\x69\xca\x51\xb3\xba\xec\xe5\xad\xbe\xc5\xe0\xf9\xed\xbc\x6b\xde\x79\xa4\x42\xfc\xdf\x97\x1a\x16\x94\xc7\x55\xd9\x59\x5f\xd1\xf3\xee\x86\x72\xbc\xc5\xda\xba\x14\x3d\xc5\x1a\xb0\x0d\xe5\x63\x26\x82\xcf\xc8\x15\xdc\x50\x55\x95\x5c\xb5\x5c\x39\x7d\x2f\xf1\xfc\xa7\x6a\xc5\x4c\x0e\xd9\xa0\x57\x73\x28\xc2\x3a\xbd\xbc\x98\x6b\xd1\xf7\x1b\xe3\x9b\x61\x69\x55\x87\x54\x39\xdd\xac\xf8\x4d\x25\x2a\x99\x6d\x3d\xc7\x3d\xa1\xa0\x6e\x2c\x09\xb9\x68\x37\xa3\x53\xc1\x64\x7e\xac\x08\xcd\x45\xbe\xdd\x98\xd7\xf3\x24\xab\x52\xd6\xf8\x15\xc8\xf6\xb8\x13\x3c\x25\xb4\x52\x62\x43\x15\x4f\x48\x22\xf0\x6f\x61\xea\x95\x64\x84\x76\xd0\x4b\x2a\xa9\xc4\x86\x6c\x68\x29\xd7\x34\xcb\xda\xf7\x7d\xd2\x4d\xd6\xe5\x89\x5a\xc0\xda\xb4\xfe\xe1\x0e\x47\x39\x82\xbb\xe1\xc7\x46\x73\xb7\x1e\xd0\xe8\x97\xef\xba\xf8\x34\xf8\xbe\x01\xbf\x6d\x69\x78\xd1\xbb\xf0\xfd\x6b\xd1\x7d\x52\x03\x33\xe9\x94\x73\x3d\xef\x95\xac\xc8\x68\xab\x69\xd8\x83\x45\xa7\x6f\x74\x50\xeb\x45\xce\x1c\x85\x25\xb9\x42\x7f\xd9\x86\xaa\x64\xdd\x11\xba\xf9\xbf\x1b\xa6\x68\x4a\x15\x5d\x6a\x75\xf8\xff\x1a\x57\x93\xf1\x8c\x8a\x2c\xd5\xa4\xbb\x2e\xba\xd6\xf1\xe3\x25\x29\x5a\x76\xa0\x31\xfe\xb7\xfa\x5e\x77\x5f\x06\xb5\x04\x0a\x3e\x7d\x27\xec\xc0\x0b\xb6\x7f\x13\x61\x11\xce\xbf\x68\xed\xb3\x27\xb8\xd6\x18\xe3\xee\x2b\x4d\x1b\x2f\x6b\xce\xc0\x9c\xdc\x0d\xeb\x29\x08\xc0\xb2\xd6\xfa\x7b\xe0\x17\x3c\x7d\x7f\xd6\xe5\xc3\x08\x59\x4d\xbd\x56\x52\xd3\xcf\xdf\x33\x5c\xeb\xa1\x35\x7f\xe9\xad\xea\x76\xee\x7d\xd4\xad\x4e\x10\x5c\x06\x2b\xad\xc1\x77\xc4\x4a\x6a\x89\x98\x0d\x95\xb6\x60\xb6\x93\x68\xad\xab\x75\x2d\x5c\x44\x3c\x26\x14\x85\xe9\xc3\xc9\x58\xb8\x81\x77\x7c\x21\x26\x20\x13\xc0\xb2\x68\x6c\x07\x02\xf2\x20\x42\x11\xec\x0b\xd4\x13\x5b\xaf\x99\xdb\x0a\xe3\x9a\xe9\xb5\x51\xfb\xc3\x59\x51\xa6\xb1\x9d\x7c\xf4\xf0\xdd\x36\x37\xba\x86\xdf\xb2\xed\xb1\x34\x65\xdb\x22\x97\x6b\x5e\x84\x92\x94\x5c\x5c\xc0\xec\x3e\xf9\x4c\x33\x9e\x3a\xf2\x78\x3e\x2e\xf2\x13\xf2\x5e\x28\xfd\x9f\xf3\x2f\x5c\x06\x3c\x14\x9a\x97\xce\x04\x93\xef\x85\x82\x6f\x4f\x5e\x1c\x1c\x5a\xf4\xd2\x18\x9b\x03\x5d\xa9\x70\x72\x3d\xcb\xc4\x4e\xf3\x22\x5c\x06\xe1\x96\x98\x4b\x72\x91\x13\x51\xda\x35\x70\x20\x59\xd2\x90\xb7\x95\xc0\xb9\xc8\x17\xe0\x34\xed\xf7\xc8\x5c\x18\xd1\xee\xd1\xc7\x65\xd5\xbf\xe1\xaf\x9c\xff\x53\xfd\x4b\xde\x18\x06\x0e\x01\x41\x28\xf0\x2f\x5c\xda\x2b\x29\x25\x69\x05\x0b\x41\xad\xe7\x84\x27\xbd\xa4\x37\xac\xbc\x81\xd0\x4a\xd2\xeb\x9c\x8f\xf3\x2e\x45\xf8\x94\x02\x1c\x01\x17\xc2\xdb\x0e\x8b\x94\xb4\x5e\x1f\xf8\x6d\x14\xb1\x1b\x34\x53\xff\x53\x4b\x4c\x58\xd7\xff\x06\x2c\x39\xb9\x24\xa7\x44\xf2\xfc\xa6\x13\x2e\xdc\x7f\xc3\x84\x9b\x7c\xe2\x9a\x2e\x97\x44\x0b\xc0\x3b\x9a\x69\x89\x0e\x19\xcd\x81\x72\x7f\x71\xbd\x77\xc1\x9d\x18\x74\x37\x2d\x8d\x5c\xcc\xe9\xe8\x96\x6d\x8f\x4e\x1a\x4c\xd3\x41\x51\x7f\xf9\x22\x3f\xaa\x61\x0d\x1b\x7c\xea\xae\x0e\x08\x62\x1d\xc1\xdf\x8e\x96\x7b\x77\x62\x07\xed\xa8\x9b\xb2\xe7\x82\x88\xb5\xbe\x49\x3f\x17\x74\x6a\xa6\x8d\x9d\xff\xd9\xac\x93\x35\x11\x60\xf7\xef\x4b\x5a\x14\xac\x24\xb4\x14\x15\x38\x13\x36\x77\xac\x5c\xda\xaf\x40\x62\x43\x9b\x87\xd1\xfa\xc5\x12\x51\x96\x2c\x51\xd6\xbc\xd0\xa7\x48\x09\xf2\x7f\x4e\xdf\xbd\x85\xe5\xfe\xdf\x57\x3f\xbf\x1f\xa4\xa7\xdd\xb3\xd5\x5a\x88\x5b\xc0\x0f\x80\x95\x79\x10\xfb\xee\xcf\xf8\x2b\x67\xf5\x67\x56\x45\x97\x24\x65\x8a\xf2\x0c\x32\x3b\x7e\x7e\xfb\xce\xe4\x7e\xd8\x6b\xbc\x75\x6b\xcc\x98\xdb\x78\x64\x92\x5d\x45\x53\x93\xe9\xf4\x81\xdd\x71\x76\x6f\xf6\xa4\xed\x67\x16\xe4\x86\xe5\x90\x2c\xd0\x91\x14\xb4\x20\x92\xa7\xec\x1c\x80\x6d\xda\x09\x8c\x74\x38\x76\x8c\xb1\x9f\x87\xfb\x44\x62\x40\x1c\x06\x2f\x47\x1b\x53\x28\x2f\x45\xd9\x09\xce\x1c\x83\x51\x13\xc6\x9f\x49\x5d\x52\x5a\x9f\xcf\x3e\x38\xe2\x6b\xca\xb3\xaa\x34\xf9\x98\xa3\xa9\xf8\x0c\x30\x9a\x08\x48\xde\xfe\x81\xec\x78\x38\xdd\xf7\xc1\x05\xec\x8a\xa9\x40\xce\x5a\x0f\x30\x1a\x7a\x98\x94\x35\x76\x64\x78\x84\xae\x3a\xad\xb8\x96\xc1\xed\x19\x17\x68\x27\xc1\x67\xbf\x56\xac\xdc\x42\x49\x8d\xd3\xf6\x3a\x59\xce\x4b\x17\xfa\x58\x83\xe2\xda\x79\x99\xcb\x0e\x71\x13\x9b\xf7\x56\xb7\x65\xe1\x6e\x0d\x72\x9a\x9b\x90\xf2\xce\x58\x81\x16\x83\x60\xb2\x73\xec\x92\xd3\x4e\x8a\x79\x95\x65\x5d\x24\x72\xd1\xed\x1a\xf6\x57\xbf\xd7\x8e\x89\x31\x35\xe2\x6c\x59\x7c\x46\x5b\xb4\xbd\x8a\x52\xc3\xda\x1d\x6c\xd7\xfa\x8b\x31\x83\xd6\x36\xd2\xd2\xed\xa5\xb9\x9b\xce\x36\xc0\xde\x0d\xd2\x65\x0e\xfc\xb6\xdf\xea\xf5\x97\x29\x22\x17\x31\x2e\x0f\x31\x8c\x17\x19\xb4\x86\xf1\x89\x4f\x52\x8c\x42\x79\x1c\x61\x1f\x07\x69\x92\x11\x49\x9f\x51\xe9\x02\x31\x16\x73\xcb\xb4\x62\xed\xe6\x88\x89\x01\x94\xe9\x20\xeb\x39\x82\xa8\x31\x04\x87\xd8\xd0\x66\x34\xf1\x4b\x17\xb6\xa7\xf1\x19\x6c\x55\x47\xcc\xaf\xc5\xf6\xed\xb5\xad\x23\x48\xee\x5b\xdf\xbd\x16\x76\x04\xc5\x2e\x1b\xbc\xdb\xce\x8e\x39\x07\x11\x96\x78\xac\xb5\x8d\xcf\x90\x8c\x8e\xe8\x6c\x8e\x28\x3e\x0a\x5a\xe1\xf8\x8c\xb4\xc5\x7b\x47\x69\xed\xf4\xc1\x16\x79\xc0\x85\xe7\x59\xeb\xb1\x76\x79\x2f\xc5\x16\x9b\x3d\xd2\x3a\xef\x77\x4a\xf5\x5a\xee\x43\x6e\xfd\xe0\x75\x36\xc4\x5e\xf7\x09\xf7\xf0\x4e\xc9\x78\x7e\x27\xb0\x9f\xda\x00\xd5\xfb\xc3\xde\x6b\x3b\x1a\xf8\x3d\xdc\x4b\x46\x05\xef\x55\xbe\xf1\xf2\x77\x96\x1c\xd1\xc6\x2c\xa9\x64\xc8\xef\xdd\x37\xa7\xbe\x9a\x92\xc9\x36\x60\x73\x1d\xaa\x8c\xfd\x99\xab\xf5\xcf\xb6\x33\xa4\x39\x49\xaa\x2a\x32\x98\xba\xf7\x87\x7e\x2c\xb7\x0f\xb5\x9e\x7f\xa1\x50\x28\x25\x62\xb3\x61\x79\x8a\xc9\x19\x1b\x7a\xcb\x88\xac\x4a\x66\x32\xe8\xb2\x0c\xad\x1c\xfd\x43\x3d\x64\xd9\x97\x82\xe6\xa8\xd6\x6a\x4e\xbc\xd3\xb7\x61\x37\x27\x46\xf1\x61\x9c\x8e\x13\x59\x80\xd1\x5f\x78\xe1\x2a\x0d\x76\x4a\x27\x02\x52\x73\xc5\x32\x01\xae\xa0\x25\x39\xfe\xdd\xb1\xc9\x8a\x35\x84\xe0\x2a\x32\x9f\x1a\x7d\xe3\x24\x02\x60\x25\x63\xf9\x4d\x8d\x9a\x2a\x33\x9e\x30\x77\xeb\x88\x9c\x2d\xc9\x07\xa3\x68\xc6\xe8\xad\xe1\x0b\x22\xea\x72\x88\x54\x30\x6a\x9c\x9c\x81\x7b\x61\xdf\xf2\x77\xe3\xce\x7e\x36\x7d\x3f\x2c\xa9\xbf\xbf\x1d\x71\x7d\x64\x87\x6c\x48\x53\xc4\xd4\xb7\x98\xdb\x0d\x27\x42\x03\x83\x04\x01\x9b\xd0\x52\x5f\x73\xe0\x5e\x5c\x90\x37\x1f\xce\x4f\x3f\x9e\x9f\x90\x4f\x97\x67\xf0\x5f\x51\x92\xdf\x61\xd7\xc7\x2c\xf3\x7e\x26\xa4\x00\xb5\xef\x63\x70\xa7\x02\x54\x9f\xef\x3e\x46\xa6\xac\x37\xb6\xf1\x28\x94\xab\x5e\xa7\x22\x07\x06\xe9\xe7\xa8\xff\x5b\x4e\x7e\x14\x25\x61\x5f\xe8\xa6\xc8\xd8\x6b\x72\x5c\x88\x54\x1e\x9b\x2a\x01\xfd\xef\x25\x7e\xf4\x2a\x13\x37\x21\x84\x2c\x5b\x5a\xc0\x48\x26\x6e\x88\xac\x56\xae\xb4\x04\xae\x72\xa0\xf5\x3b\x4b\xbb\x91\xde\x1e\x32\xa7\x6c\x5d\x89\x47\xd3\x0d\xac\x41\xd1\xff\x42\xc8\xea\xac\xc7\xf4\x4a\x26\x34\x63\x0d\x3a\xfa\x83\xdd\x9f\xfb\xdd\xab\xdf\xc5\x2d\x41\x63\x6e\x56\x43\xe4\xe5\x0e\xbd\x7f\xcb\x35\xdf\xdf\xf3\x2c\x4d\x68\x19\x2a\x3b\xdf\x3d\x1a\x70\x1f\x63\x9a\x32\xd4\x1d\x60\xb3\x96\x1c\xee\xf9\xd8\x15\x30\x78\x32\xe2\x8e\x95\x19\x2d\x30\xd9\x98\xd1\xc4\x00\xd3\xc3\x00\xcf\x58\xc1\xa0\x80\x09\x9b\x13\x84\x38\x8b\xe5\x49\x26\x24\x7c\x1d\x54\x81\x93\xc6\x94\x0d\x8c\xbe\x69\xaa\x13\x59\x6f\xe2\x0e\x71\x3f\x88\xc4\x53\x9c\x62\xc8\x65\x1d\x70\x82\x31\xf7\xb5\xe9\x6c\xf6\x30\xb8\x5c\x1d\x01\x78\x1e\xa2\x0c\x7f\x50\xcd\x8e\x4c\xb9\xd9\xd1\x09\x39\x72\x90\x41\xa9\x31\x4d\x8e\x7e\x77\x54\x7f\x21\xf2\xfc\x52\x53\xc9\x97\xe0\x6b\x0b\x18\xa3\x5f\xce\x09\xcc\x06\x66\x55\xd0\x3b\xe7\x26\x55\x43\x97\x69\x6d\xc0\x78\x76\x61\xfc\xcd\x9f\x09\xf1\x83\x3f\xc5\xbd\x11\xd7\xb5\x7e\x3b\xa3\x0d\xcd\xdc\xe4\x74\xb9\xd1\xea\x65\xf3\x88\x2b\xc0\x2b\xc0\xba\x43\xb3\x65\xa5\x57\x37\x12\x1a\xf3\x55\xe3\x10\xd8\xfc\xb1\x06\xfe\x1a\x2f\x49\x41\x4b\x6d\xb1\xda\x6f\x86\x88\x7a\x3d\x8b\x8f\x7e\x17\x40\x6e\x09\x32\xb4\x17\x66\x1b\x1d\x85\x51\x7c\xc3\x44\xa5\xae\x58\x22\xf2\xb6\x64\x76\x9f\xcc\xd4\x18\x56\x74\xb6\xbf\x09\x99\x9e\x5a\x15\xc7\xa6\xfc\xfb\x81\x9e\xda\x84\xec\x09\x89\xe2\xd3\xc0\xe5\xf9\xf9\xed\xbb\xb1\x6b\x45\xa0\x4e\xba\x3b\xbb\xea\xb3\x11\xef\xf9\x8d\x1b\xb9\x99\x49\xe7\x2b\xef\x2a\x15\xff\x82\x99\x68\x1f\x36\x48\xc7\x1c\xa4\xa2\xaa\xda\xd9\xdd\xc6\x8a\x1b\x61\x73\x85\xd5\x41\xc6\x14\xb8\x82\xb7\x7c\x4f\xad\x8f\x95\x00\xda\xe4\xce\x30\xb0\x89\x01\xbc\x05\x49\x99\x85\x48\x97\xc4\x90\xd9\xd0\x2d\x51\x25\xe5\x68\xc9\xd2\x44\x55\x50\x64\x4c\x95\x49\xe0\x34\x38\x47\xdf\xec\x4f\xa7\xc5\x42\xed\xb6\x4a\x13\x56\x2a\xf9\x96\x4a\xf5\xa9\x48\x69\x6b\x71\xca\x4e\x12\xa6\x54\x70\x08\x50\xc7\xbe\xcf\x59\xaa\x65\x9d\x59\x08\xa4\x46\xee\xb5\x20\xa9\x90\xde\x1e\xb9\x5e\xb6\xb1\x87\x42\xbf\xba\xd0\x3f\xd3\x36\xda\x0f\x42\xaf\xc2\x69\x4b\x04\xb9\x99\xef\x1a\x1a\xa5\x16\xf0\x25\xd0\x22\x39\xfb\xb2\x6f\xd2\x4f\x1b\xa9\xc8\xd3\xae\x24\x89\xe6\x8a\x1a\x15\xb7\x7e\xe1\x84\x50\xb2\xe6\x52\x89\xd2\xf8\xac\xa1\x53\x70\x49\x73\xc9\xdb\x2b\xf8\xa6\x27\x5d\xbc\x71\x3f\xae\x15\x67\x46\x5d\xb7\x4a\xc3\x9d\xd0\xcc\xb1\x64\x89\x28\x53\x37\xa4\x76\x99\x55\x0f\xd3\x68\x53\xed\x67\xa5\xe5\xe5\x89\xa5\x15\x19\x95\xea\xa3\xfb\x75\xbd\xf9\x51\xb2\xb3\xc9\xd0\x66\xba\xf5\x2c\x6c\xbd\xbb\xc8\xed\x1f\xbb\xdd\x43\x82\xd0\x1c\xb5\xca\xf1\x12\x33\xc4\x56\xf5\x5c\xf1\xbc\x8e\x98\xe7\xbd\x3b\x9b\xde\x94\x1f\x7a\xc4\x1b\x26\x25\xbd\x89\x1b\xea\x29\x02\xf3\x12\x07\xcc\x6b\x5e\x26\x3c\x4f\x79\x02\xf2\xdf\x65\x02\xb5\x49\xd5\xfa\xb9\x5f\x6f\xbb\x59\x50\xdf\x90\xb6\xb6\xd5\x1d\xbe\xd1\x5b\x57\xac\xa9\x8c\x9b\x9e\x3b\x6b\xd6\xe6\x8f\x3d\x20\x51\xe3\x28\x19\x95\xdd\x75\x10\x3b\xeb\xbc\x2a\x39\xbb\x26\x6f\xe8\x86\x65\x6f\xa8\x7c\x8c\x85\x06\xc9\xb1\x24\x6c\x79\xb3\x24\xc7\x1f\xbc\x50\xc0\x7b\xa1\xde\x75\x77\x3b\xe9\x2d\xf7\x0b\x9f\xfb\x69\x27\xbe\x3d\x27\xb9\xf3\xac\x4f\xba\x36\x42\x27\x7b\xd2\x99\x9e\x34\xb2\xce\x13\x3c\xed\xec\x6a\xd6\x69\xbb\x0c\x26\x9e\xda\xbe\x82\x9f\xf6\x93\xda\x3c\xa3\x55\x09\x76\x4a\x32\xee\xac\xf6\x16\xeb\xb4\x9f\xcf\x89\x27\x73\xca\x32\x0e\x3e\x93\xbd\xd3\x73\xaf\x5f\xb5\x28\xd1\x7b\x33\xfd\xd8\xd0\x80\xc1\x31\xe3\x67\xdf\x00\x8a\xb3\x1e\xe3\x9b\xab\xcf\xf3\xa8\x3d\x8f\x5d\x4d\x67\x36\xae\xf5\x6f\x79\x67\x42\x68\xd7\x9d\x3c\xa5\x3a\x2f\x05\x37\x97\xde\xd7\xc7\x89\xfe\x9d\xd9\xdf\x33\x06\x8d\x31\x48\xcd\x6e\x83\xff\xbc\x1e\x53\xaf\x1f\xb9\xe6\x87\x17\x4a\x90\xa2\x64\x77\x90\x99\x95\x43\x1e\xb2\x56\xde\xa5\x3e\x10\x2f\xbb\x35\xb3\x98\xc0\x5d\x38\x17\xaa\x7b\xff\xed\xdf\x3b\xb8\xc0\xfe\x39\xa0\x40\xf6\x6d\x2e\x3e\x71\xc1\xc5\xde\x32\x4c\x7c\x22\x9d\x7f\x7d\x25\x99\x83\x08\x05\xd4\xbf\x41\xb4\xda\x8c\xf3\xdd\x67\x07\xa8\x52\xbf\xf0\x01\x04\x2f\x86\x15\x12\x2d\x57\x13\x2a\xc1\x85\x06\x1f\xa3\xa0\x09\xb9\x7e\x7d\x5b\xfd\xc3\xae\xa4\x83\x6a\x98\x26\xcf\xcf\x31\xdd\xaa\xe2\xf3\xec\x41\xa0\x44\x36\x92\xd6\x13\xd6\xf8\x06\x98\xe8\xa1\xca\xe7\xf1\xe9\xe7\xba\xb1\xfc\x16\x12\x09\x53\x39\x2d\x8c\xab\xd0\xc3\x5d\xb3\x17\x5d\x4b\x56\xde\xb1\xf4\x35\x51\xa5\x69\xd7\x6c\xe0\x8e\xfd\x4f\x3c\x2f\xb2\xa5\x6b\x96\x9e\xfc\xe7\x7f\x7f\x53\xef\x02\x4d\x12\x56\x28\x96\x7a\x38\x66\xc0\x5c\xe4\x08\x23\x00\x45\x56\x95\x34\x33\xff\xeb\x39\x63\xc8\x2f\x7f\xf9\x06\x7f\x98\xa5\x2e\xf0\xaf\x3f\xfc\x66\xb1\x58\x7c\x53\x67\x03\xbc\x26\xb4\xe0\xec\x8b\x62\x98\x1f\xb2\xbc\xfd\x23\xb4\x08\xba\xfb\xee\x1b\xfc\x99\x37\x50\xba\x6f\xc3\x95\x67\xae\x26\xe6\x1b\x5b\x1d\x0d\x83\xcc\x73\xa1\xfc\x58\x76\x22\x72\x55\x8a\x2c\x63\xe5\xe2\x86\xe5\xcb\xdb\x6a\xc5\x56\x15\xcf\x52\x56\x02\x71\xfb\xd3\x77\xdf\x2e\xff\x61\xf9\xad\x1e\x78\xc9\xa8\x35\x6b\xa4\xa2\x9b\xe2\x35\xa4\x93\x7f\x63\x98\xd9\x62\xb2\x14\x19\xcd\xe5\xd2\xa5\x71\x2e\x13\x51\x32\xa1\xff\xb3\xf9\x46\x16\x2c\xd1\xbf\x8d\xe7\x96\xb4\x7e\xc7\xe0\x07\x9a\x21\x1a\x20\x13\xfb\xff\x0b\x22\xb2\x8d\xb7\xbe\x06\x5a\xe6\x32\x33\x18\x35\x19\x97\xea\xa7\xdd\xbf\xbc\xb5\x9d\x1b\xec\x36\xf8\x03\xc5\x8d\x5e\x8b\x52\x79\x9b\xb7\x20\x26\x89\x55\xf2\xfc\xa6\xca\x68\xd9\x78\xe7\x1b\x1b\x88\xaa\x43\x2c\xfa\xa2\xbd\xf3\x32\x37\x16\x8d\x04\x30\x9e\x2b\x56\xbe\x11\x59\xb5\xc9\xdd\x0f\xec\x29\x9e\xd7\xbc\x94\xca\x60\xdb\x60\x48\xd7\xfa\xe2\xda\x54\xe6\xf7\x5e\xab\xa7\xff\x90\x22\x07\xbf\x32\x59\xea\x05\x5e\x76\xbf\xf0\xcb\xb7\x7f\x31\xef\xe0\x8e\xd5\x8a\xec\xde\xf1\x68\x19\x21\x2d\x8a\x52\xdc\xd1\xcc\xef\x1f\xbd\xfb\xdb\xf6\x3b\x8d\x9f\x39\x6d\x7e\xd8\xf2\x5b\xed\x64\x9c\xc3\xd6\x27\xe3\x3e\xdc\x47\x28\xc2\xaf\xdd\x7d\x47\xb3\x62\x4d\xbf\xc3\x0d\x4c\xd6\x6c\x43\xed\xe1\x15\x05\xcb\x4f\x2f\x2f\x3e\xff\xc3\x55\xe3\xe3\x76\xbc\x22\xcd\x3a\xa6\x3f\xad\xf4\xf1\x9e\xa9\x35\xc1\x5c\x02\x73\xcd\xc7\xdf\x34\xc5\xcd\x8e\x96\xb7\xaf\xd5\x69\x95\x1c\x4f\xa8\xf7\x91\x5e\x01\xf7\xbf\xed\x5a\x96\x27\x1a\x1a\xf2\xae\xd9\xb3\xac\x4e\x0c\x6a\xcc\xc3\x30\x2a\x4b\xcd\xea\xd4\xc1\x50\x1b\x2c\x68\x83\x55\xd2\x13\xce\xcd\x8c\x96\x44\x33\x17\x2b\xa5\x85\x34\x4d\x44\x7e\xc7\x4a\x05\x5e\xd9\x9b\x9c\xff\xd5\xd1\x86\xf2\x38\xcc\x83\x57\x6c\x0f\xdd\x16\x0e\x46\x4e\x33\x0c\xae\x9e\x98\xe2\x98\x2d\x29\x99\xfe\x15\x52\xe5\x1e\x3d\x9b\x25\xde\xd2\x38\xed\x86\x2b\x2b\x12\x13\xb1\xd9\x54\x39\x57\xdb\x57\x20\xdd\xf8\xaa\xd2\xfb\xf2\x2a\x65\x77\x2c\x7b\x25\xf9\xcd\x82\x96\xc9\x9a\x2b\x96\xa8\xaa\x64\xaf\x68\xc1\x17\x30\xf4\x1c\xa3\x8a\x9b\xf4\x37\x4e\xe0\x37\x2d\xcd\x8e\xeb\x67\x5f\x85\x68\xee\x00\x60\xc2\x60\xd5\x86\x97\xec\xdd\x44\x11\x03\xb8\xbc\xf3\xab\x8f\x2e\x0e\x09\x9b\xb1\xbb\xfa\xb0\xee\x5e\x38\xa7\xde\x02\xbd\x60\xd0\x03\xc2\x80\xad\x96\x62\x63\x70\x81\xd3\x42\xf0\x1c\x6b\x0e\x92\x8c\xef\x1b\x36\xb2\x5a\x6d\xb8\x92\x16\x84\x18\xf3\x53\xde\xc0\x3d\x01\x60\x53\xe8\xc4\x59\x92\x8b\xbc\x36\xfe\x1f\x7c\x03\x00\x03\x6e\x01\xd8\x7c\x51\x5b\xe0\x5f\x71\xbb\x5f\xde\xb3\xb2\xec\x05\xd4\xb1\x5f\xde\xc9\xbf\x2a\x58\xe2\x4e\x8d\x3b\xe9\xa7\x88\x5d\x6b\xa0\x9b\x5d\x1a\xd0\xae\x4b\x6e\xe5\x84\xc5\x4e\xcc\xa9\xd3\xf8\x6b\x37\xf8\x16\x64\x47\x9e\x36\x3f\xde\x21\xbe\x08\x5f\x15\xf8\x74\x5b\x6e\xf6\xe7\x42\x2e\x21\x7b\x13\x18\x33\x1a\xd0\x8d\xdd\xf5\x60\x50\xd5\xc1\xa8\xce\xfd\x35\x1d\xe4\x19\xb3\x53\xec\x2a\xeb\x6d\x87\xa6\xeb\x5e\x81\x99\xca\x83\x7b\x46\x6c\x2a\x2b\x7b\x10\xaa\xda\x83\xf0\xc8\x46\x5d\xef\xb4\xa3\xd4\xd4\xb0\xb7\xed\xed\xee\xc6\xc6\x92\x8f\xfc\x23\xb0\x17\x42\xc6\x5b\x70\x27\x8c\xdc\x6d\x3a\x40\x70\x8e\x15\xd2\x71\xb7\xbe\x0c\x12\xb1\x29\x32\xa6\x9a\xd7\x29\xa4\x3e\xb5\xc5\x9a\x77\x99\xa2\x2b\xf2\x7c\x34\xed\x98\x25\x54\xd1\x4c\xdc\x5c\xb5\x64\x71\x2d\xd0\x47\x1b\x7b\x80\x94\x62\x79\xa5\xc5\xe6\x55\x03\xac\xb3\xb5\xcf\x6d\xf3\x4c\x75\xbf\x59\x03\x5e\x1b\xaf\x55\xb3\x2d\x45\x1b\x97\x42\xdb\x10\xe9\xf0\x02\x53\x93\x44\x93\x7a\xf5\x14\xb8\xfc\xb3\x82\x14\x75\xa9\x25\xed\x13\xae\x73\x94\xad\x43\xdb\xb5\x47\x6d\x7d\x3b\x60\x02\x42\x65\x49\x77\x7e\x45\xf3\x62\xbe\x30\x8b\x5a\x1a\x20\x02\x4a\x0a\xce\x30\x6f\xd2\x69\x39\xb0\x44\x8c\xa6\xdd\x35\xbf\x34\x27\xfa\xe6\x2a\x99\xcb\xbe\x33\x3e\x6c\x20\x5b\xeb\x46\xd0\x4a\x82\x62\x0a\x21\x40\x1d\xbc\xfa\x53\x17\xb2\x0c\xd6\xc7\x18\x74\x78\xe0\xf3\x0d\xa4\x20\x5a\xe8\xef\x94\x49\xcd\xc0\x57\xe0\x26\xdf\xd0\x9c\x5f\x33\xa9\x96\xae\x98\x5d\xfe\xf2\xfb\xbf\x74\x85\x0d\xbd\xb4\xd3\x13\x8b\x5d\xea\xf4\x0a\xc3\x60\x20\xd1\xf5\x72\x38\x8a\xfd\x0d\x2a\x21\x4d\xc4\x4c\xfb\x1e\xa6\xab\xe8\x2d\x23\xc2\x4c\xb7\xd2\x66\xcc\x2d\x7b\x4d\x8e\xd0\x32\x71\xc3\xfc\x4f\xad\xab\xff\x77\x57\x7e\xdc\x8b\x7b\x48\xff\x3a\xd2\x5f\x3a\xc2\xc1\x39\x45\xd2\xef\xf0\x50\x0f\x12\x93\xc6\x4a\x7e\x73\xc3\xba\xd0\x17\x30\x00\x01\xee\x5a\x80\x62\xe7\xd0\x2f\xb3\x26\x91\x9b\x16\xae\x75\xfb\xcb\xdd\x41\xff\xf2\xfb\xbf\x74\x8e\xb8\xb9\x5e\x84\xe7\x29\xfb\x42\x7e\xef\xc2\x1a\x85\x48\x5f\x1a\x54\x19\xb9\xcd\x15\xfd\xa2\x7f\x29\x59\x0b\xc9\xba\x56\x16\xd2\xeb\x94\xc0\x6e\x01\x52\x40\x5c\x2d\xcb\x16\xa8\x92\xa4\xe4\x1e\x6b\x08\xed\xc6\x61\x2d\x5c\x41\xcb\x9e\x0a\x75\x4f\x7d\xc7\x4e\xbf\x30\x32\xcd\x50\x37\xe0\x1a\xd2\x6a\x1f\xb6\x0f\xc0\x04\x5a\x0f\xb9\xbf\x83\xa2\xac\x90\x7d\xb4\x58\x5f\xd3\x1c\x42\x42\xa6\x17\x81\x56\xef\x96\xed\x11\xd4\xc0\x39\xee\x76\xcb\xb5\xe8\xd6\xbb\x82\xe3\xc9\xb4\xd3\xc8\xc9\x75\xbb\xfd\x3a\xdb\x4d\x3f\x46\xd3\xe8\xd1\x73\xe9\xe9\xb6\xbb\x3f\x21\xcc\x46\x7d\x84\x59\x41\x0b\xcf\x57\xa3\x26\x65\xb5\xfa\xf8\x7b\xec\xf8\x0a\x05\x46\xb2\xfb\xae\x3e\x16\xd8\xf0\xc7\x58\xd7\x46\xc6\x76\x1c\x26\xae\x55\x9f\x14\x45\x33\xcd\xb7\x0f\xce\xca\x7a\x41\x21\xb2\x9c\x6c\x17\xc6\x15\xb8\xa0\x79\xaa\xff\x2d\xb9\x54\xfa\xf3\x51\x2b\xd8\xe9\xc4\x6d\xae\xda\xa7\x8b\xb3\xc7\x61\xf0\x8a\x8f\x38\xab\xab\x2a\x4f\x33\xf6\x56\x88\xdb\xd6\xba\xb8\xc6\x54\x7e\xf0\xbf\xeb\x22\x8b\x68\x30\xf2\x7c\x51\x94\xe2\xa6\xd4\xb7\xb9\x67\x66\x93\xa2\x6a\x4d\x91\xa6\x00\x21\x5b\xd0\xe4\x96\xde\x30\x33\x08\xb8\xa2\x0c\x2a\x16\x9a\xf2\x60\xe2\x74\x29\x6e\x53\x32\xef\xfc\x99\xa0\xdb\xc2\x8c\xd9\x0e\x79\x67\x80\x5d\x41\x2a\x3b\x62\xd0\xd0\xcd\x2c\x42\xa3\x9f\x18\x0d\x6f\x68\xf0\x1f\x58\xdb\x1d\xb8\xa8\xf1\x78\xdb\xf2\xa0\x17\xd0\x65\xa5\xf5\x0f\x16\x92\xb4\xe5\x8f\xa1\x28\xe8\xee\xb8\xe2\xb2\xb2\x76\x5e\xb2\x7b\x61\x95\x34\xb3\x96\x8d\xaf\x75\xd0\x45\xad\xc7\xec\x01\x34\xf9\xb9\xa7\x12\x24\x55\x76\x67\xb2\x8b\x1e\x18\xed\x25\x64\x14\xb4\xcc\x7f\xb0\x69\xe0\x0f\x38\x10\x7b\x0c\x98\x09\x2d\xa3\x19\x64\x2c\xf4\x10\xb5\x3e\xd4\xc1\x26\x43\x2f\x4d\x63\x4e\x3c\xa4\xe1\x80\xcf\x38\xf3\xa1\x97\xa4\x69\x8c\xfd\x30\x46\x04\x3e\xe3\x4c\x89\x5e\x92\xce\xcc\x18\x6a\x50\xf4\x52\x6d\x33\x36\xe2\xcc\x8a\x5e\xb2\xad\x26\x47\x84\x71\x11\xe2\xe3\x56\xc3\xa3\xd7\xc4\xe8\xa5\xd8\x6f\x7e\x74\x1a\x1a\xbd\x34\x7b\x8d\x10\x7c\xa2\x24\x46\x28\xf1\xe4\x6b\x30\x4b\x06\x4c\xb7\x2f\x33\x61\x7f\xba\xcf\xc2\x50\x19\x38\xbb\x1e\xa3\xa5\x6b\x8a\xcf\xc2\x74\x19\x30\xcd\x28\x33\xa6\x6d\xb2\x33\x19\x33\xf8\x7c\x35\x26\xcd\x80\x95\x0d\x64\x40\x3d\x3b\x23\x27\x72\x6a\x7d\x25\x42\x2d\x33\xf3\x6a\x74\x76\xe2\x03\x7a\xb8\xd8\x15\xd9\xf9\xe8\x7d\xb3\xa2\x5f\xd9\x9c\x0c\xf8\x39\x43\x5e\x65\x30\x31\xb2\x03\x01\x15\x9f\xb8\xac\xc8\xf8\xfa\x20\x7c\x7a\x6a\x06\xea\xac\xf0\xbd\xb2\x81\x5e\x92\xa4\x59\x54\x10\x2a\x17\xc2\x27\x1a\x28\x2d\xae\x10\xa7\x5e\x8c\x70\x01\xd1\x80\x85\xd0\x16\x4e\x51\x8a\x55\x1c\x10\xc5\xcc\xb3\x89\xca\x2e\x1d\x5b\xa6\x10\xd8\xd1\x3a\x1e\x57\xf3\xc2\x2c\x4b\xd0\x5f\xc8\xd3\x32\x27\x04\xd7\x6a\x64\x17\xba\xfd\x39\x96\xb0\xe5\x73\x8f\x71\x64\x2a\xae\x67\x00\xe0\xf0\x4e\x6c\x73\xe5\x8f\x65\xc5\x4e\xc8\x8f\x34\x93\x2c\x04\x97\xf1\x29\xbf\xcd\xc5\xfd\x3c\xf3\xe8\xab\xb4\x6e\x99\xc5\x47\x53\x53\x1d\xac\x1a\x8b\x1c\x44\xed\x23\x89\xba\x08\x2e\xdc\xd7\xad\xe7\xcb\x78\x3c\x16\x55\xce\x7f\xad\x9a\x46\x56\x10\x98\xf3\xc5\xae\x59\xf6\xe6\xea\x33\x30\x10\x3a\x30\x64\x03\xd5\x54\xff\x51\x76\x25\xda\x87\x6b\xe4\x7a\x5c\x00\xcd\xa6\xf3\x54\xad\x77\x0c\xc7\xcc\xe0\xa9\xed\x3a\xb8\x8a\xaa\x2d\xa0\x6a\x9f\x0b\x75\x2c\xf5\xb8\x78\x42\xb3\x6c\xab\x6d\x25\xbe\xd1\xc7\xdc\xe9\x52\xe3\x61\xd4\x3a\x9b\xee\xb4\xcc\xe7\x83\xf9\x72\x5b\xcb\xf4\x7a\x2a\x86\x24\x98\x9d\xbd\xae\x25\x7d\x58\xae\x01\x12\x9e\x2a\x58\xab\x11\xb3\x68\x86\xdf\x1f\x3e\x53\xa3\x4f\xd9\x99\xee\x45\xf5\x52\x28\xea\xf2\xca\x1e\x2d\xa9\x43\xd9\xb0\xed\xdd\xbf\xb0\xa4\x72\xcc\x16\xc8\xa7\x79\xc4\xc2\xe5\x47\xae\x1f\x7e\xac\xe2\xdf\x39\x6b\x5a\xdd\xee\x4f\x2b\xf7\xd8\xad\xb9\x1f\x2d\x26\xfa\x6f\xc8\x30\xdc\x48\x2c\x04\x48\xdb\x01\x80\x6b\x0a\xbf\xb5\x62\x75\xf1\x15\xeb\x03\x54\x6f\x72\x3b\x81\x46\xfa\x09\x2b\x41\xf6\x63\x6a\x23\x40\x01\xdc\xaf\x45\x36\x46\x76\xc6\xd4\x5e\x7a\xbf\x7f\xa9\xbf\xee\x2e\x39\x53\x93\xe9\x17\xe1\xec\x26\xa3\xef\x4c\xa6\x67\xa8\x7d\x83\xcc\x68\x67\x3a\xd9\x14\x21\x75\xa5\x58\xb1\x2b\x94\xbc\xc9\xe4\xa0\x7c\xde\xf1\x14\xd3\xad\x58\x41\x3a\x52\x40\x26\x4b\xa4\xfe\xb0\x0e\x06\x2a\xda\x39\x72\xe1\x7c\x14\xad\x7f\xec\x14\xad\x21\x19\xe8\x7e\x73\x82\x8c\xe8\xca\xe9\xc3\x67\x6f\x27\x6c\xe9\x46\xcf\x8e\xf4\x4d\xd6\x0c\x4b\x90\x15\xc8\x89\xe4\x16\xe1\x72\xc2\x7b\x43\xe2\x0c\xe7\x70\x73\xb2\xbe\x62\xc4\xde\x52\xc4\xce\xc2\x53\xfc\x63\x9d\xe8\x18\xf1\x15\x70\x9e\x75\x7e\xaf\xbf\x9e\x31\xc6\x6e\x0f\xd6\x32\xce\xe2\x4e\x8e\x04\x91\xc6\x00\xce\x64\x42\x21\x6f\x6f\x14\x91\x7a\x0b\x66\x24\x15\xf4\xd2\x46\xd1\x8b\x28\x34\x9c\xb7\xdc\x8e\x15\xcd\x12\xe3\xb6\x9b\xa2\xa0\xa5\xe2\x49\x95\xd1\x6e\x4b\xc8\x15\x03\x80\x28\x0e\xdc\x2d\xad\xb3\x38\x14\xb8\xcd\x5d\xe0\x66\xcd\x57\x03\x4f\xfc\x38\x25\x6e\xb6\x19\xd7\x9f\x9c\x84\xad\x8b\xdc\x1a\x7f\xdb\x2b\x73\x6b\x0e\x17\x37\x7c\xaf\xd0\x4d\x18\x66\x71\x85\x6e\x8d\xb7\xa2\x4a\xdd\x6c\xd9\x15\x12\x1a\x51\x70\xd5\x98\x86\xab\x29\xc8\x39\x82\xc9\x57\x99\xe2\x8a\xe5\x34\x37\x35\x05\x3f\xbf\x7d\xa7\xc5\x1f\xbd\xf1\xb2\x99\x1b\x80\x80\x17\xe0\x21\x90\xaa\x84\xce\x27\x6d\x95\x5b\x75\x8f\x09\x9e\x13\xae\x64\x1d\x15\x32\x8d\x29\x5a\x22\xb6\x26\xa1\x47\xd1\xf2\x86\xa9\xfa\x85\x59\x6a\xbe\x0e\x45\x5e\x87\x22\xaf\x43\x91\x57\xcf\x16\xcc\x59\xe4\xd5\x90\x36\x50\xe6\x65\x53\xf6\xf4\xbf\x4d\xd5\x52\x53\x24\xb5\x23\x84\x8e\x00\x38\x8c\xec\x2e\x6d\xdb\x97\x99\xef\xe3\xf0\x1a\x43\x3a\x96\x7d\x92\x28\x38\xc2\xfe\x51\x92\x43\xbf\xe9\x43\xbf\xe9\x43\xbf\xe9\xae\x2f\x1d\xfa\x4d\x1f\xfa\x4d\x1f\xfa\x4d\x93\x30\x47\x1c\xfa\x4d\xff\xbd\xf7\x9b\x96\x8d\x52\xd6\x76\x07\xd1\x8e\xe6\xb3\xfb\x82\x15\xfc\x34\xdd\xf0\xdc\x2b\xce\x0b\x17\xc1\x62\xba\x1a\x20\x2b\xaf\x58\x5d\x0a\x0b\xcd\x78\xdd\xde\xbc\x90\x2f\x5d\x36\xad\x3b\xe4\x60\xfb\x0e\x72\xd3\x4b\x6d\x4e\x25\x97\xd8\x1b\x3a\x3d\xbd\xbc\x08\x15\x8d\x5c\xc1\x0b\x44\xb1\x2c\x93\x60\xd2\x6a\x7d\x5c\x09\xa3\x8f\xb7\x2a\x7c\x85\x47\xbd\x65\xba\xb5\xfb\xa3\x63\xe0\xed\x15\xf3\xa8\x46\x3a\xf3\x3e\x88\x91\xb8\xf3\x75\x23\xba\xd9\x97\x22\xe3\x09\x57\xf6\x86\xaa\xb5\xd2\xf6\x4b\x0d\x7f\x15\x44\x3b\x07\x8d\x4a\x32\x75\x52\xeb\xbd\x5c\x12\x7e\x93\x8b\xd6\x56\x32\x73\x07\x83\x09\xf9\xb2\xa8\xf3\xef\x16\x5a\x5f\x5d\x98\xaf\xb3\x86\x59\x11\xaa\x9d\x6f\x1a\x16\x9d\x38\x83\x3b\xc6\xc5\x87\x61\xb6\x45\x57\x05\x7b\x1d\x45\x4d\x23\x6d\x91\x6c\x10\xce\xba\xf9\xa6\xe9\x99\x66\x1d\x64\x36\x48\x9d\x35\x32\xb1\x76\x18\xb7\x65\x3b\xcc\x7a\xdc\x53\x49\x0c\xe1\x99\xa1\x6b\xf3\x58\x7e\x6e\x72\xb2\x57\xb9\xb5\x67\x5e\xb9\x44\xa6\xc6\xf4\x9e\x0f\x7f\x92\x3d\x79\x1b\x06\x1d\x18\x0a\x35\xd0\x7d\x65\x38\xc1\x7c\x00\x14\x38\x00\x0a\x1c\x00\x05\x0e\x80\x02\x07\x40\x81\x03\xa0\xc0\x88\xb9\x1c\x00\x05\x0e\x80\x02\x3b\xcf\x57\x0c\x28\x30\x3d\x06\xef\x07\x58\x01\xd7\x12\xdb\x73\x1d\xc2\xac\x87\x30\x6b\x93\xe6\x21\xcc\x7a\x08\xb3\x1e\xc2\xac\x66\x68\x87\x30\xeb\x21\xcc\x7a\x08\xb3\x92\x43\x98\xf5\x10\x66\x3d\x84\x59\x0f\x61\xd6\x43\x98\xf5\x10\x66\x3d\x84\x59\x0f\x61\xd6\xa7\x0a\xb3\x1e\x42\xa7\x87\xd0\xe9\x53\x84\x4e\x0f\xe1\xd0\x43\x38\xb4\x6d\x16\x87\x70\xe8\x21\x1c\x7a\x08\x87\xee\x3d\x87\x70\xe8\x21\x1c\x7a\x08\x87\x1e\xc2\xa1\x4f\x10\x0e\xbd\xa6\x99\x3c\xd4\x24\x8f\xa8\x49\x96\xd5\xca\xed\xfa\x63\x95\x24\x5f\x79\xbf\x09\x1f\xd7\x15\xc9\xfe\x9f\xf6\x0a\x92\x1b\x63\xc5\xcd\xde\xab\x47\x96\xd5\xaa\xfe\x97\xf9\x92\xab\x4d\x96\xcd\x1f\x7e\x80\x2e\x9c\x16\xd9\xde\xfc\xd2\x0a\x9c\x19\x86\x0b\x77\x9b\x54\x7a\xc0\x15\xb8\x17\x97\xf8\xf2\x37\x1d\xdc\xdf\xf2\x73\x06\xf8\xca\xa0\x1e\xd4\x8d\x78\x9d\x8a\x54\x34\x48\xee\x8e\xa0\x01\x08\x82\x63\x68\x80\xc1\x47\x0d\x61\x4d\xf3\x9c\x65\x5a\x56\xa0\x53\x04\x34\x41\x37\xff\xee\xe9\x9b\x17\x1b\xbf\xfe\xa6\xf1\xd9\xde\xcf\xcf\xd4\xa0\xd3\x67\x32\x72\xcb\x58\x21\x3d\xe7\x7c\x55\x80\xfb\x89\x2a\x46\x56\x5b\x44\x43\xd1\xca\x1b\xea\x4f\x3b\x6e\x12\x03\xa0\x7f\xe8\xdb\x79\xc8\x35\x38\xe4\x1a\x7c\xc5\xb9\x06\xbe\x40\x68\x36\xee\xcc\x1b\x2d\x3b\x11\x3d\x92\xe6\x33\x36\xe8\xdc\x43\x2f\xb2\x80\x44\xad\x1f\xb6\xa3\x14\x75\x3b\x7d\x8c\x8c\xed\x02\x00\xeb\x02\x37\xbc\xe6\x2d\xd8\x55\x9d\x2b\xf6\x06\x5e\xa8\x23\x21\x48\xa0\xc2\x56\x96\xde\x5d\x74\xdd\x1a\x62\xa1\x8d\x5b\x79\x56\x77\x17\xcb\xef\x22\x34\xdd\xf3\xfc\xae\x99\x02\xc1\xf2\x3b\x5e\x8a\x1c\x92\x08\xee\x68\xc9\xe9\x2a\x33\x97\x1a\x53\x5d\x30\x66\xa4\xe9\xef\x68\x3b\x4e\x3d\x2a\xee\x1c\xb9\x10\xe7\xf9\xdd\x67\xda\x8c\x5d\xe7\xad\x53\x21\xe6\x0b\x1d\x44\xb5\x74\x26\x94\xbc\x71\x53\xe9\x9a\xef\x1c\xc9\x0b\x3d\xd8\x5d\x31\xc9\x09\x83\x5a\x0d\xf8\x26\x7b\xdb\xba\x2c\xc9\x3b\x13\xec\xa5\x3d\x24\x09\x79\xf3\xef\x17\x67\xe7\xef\x3f\x5e\xfc\x78\x71\xfe\x61\x9e\x38\x7c\xf4\x14\x8e\x3f\xdb\x3d\xf4\xfc\xca\xbf\x7d\xf1\xf9\xf4\xc3\xbf\xbf\x3f\x7d\x77\xfe\x12\xe2\x89\xec\x4b\x41\xf3\x34\xd0\x2d\xa4\x92\xf6\x0a\x2a\x4a\x76\xc7\x45\x25\x89\xf5\x5c\xb5\xb3\x7f\x44\xbf\x8c\xda\xc5\x86\x79\x33\x5b\xe7\xee\x6e\x25\x09\x51\xa5\xfe\xa5\x76\x2c\x9b\xb8\xd3\x64\x3b\x0f\x9d\xf8\x96\x69\xe2\x1c\x5b\x3c\x2f\xaa\xfe\xee\x2b\xe6\x42\x76\xf1\xc6\x1c\x35\xbb\x14\x63\xb6\xfe\x62\x1a\x47\x20\xca\xfb\x5e\x9a\x4c\x26\xb4\x60\x29\xba\x16\x29\x49\x45\xa5\x07\xfd\xdb\xdf\x9e\x10\xce\x5e\x93\xdf\x7a\x44\x97\xe4\xdc\x7c\xb7\xde\xc1\x5e\xd2\x30\xce\x9c\xdd\xb1\x12\xd2\x10\xcc\xde\x9e\x90\x92\xdd\xd0\x32\xcd\x98\x04\x48\xb0\xfb\x35\x53\x6b\x56\x9a\xf0\x34\x2e\x5a\xff\x88\x5d\x72\x44\x2e\xd4\x92\x9c\xb1\x6b\x5a\x65\xd8\x5a\xec\xe8\x68\x7a\xcb\x13\x60\xeb\x1f\x4b\xb1\x89\x66\xed\xab\xa6\x05\xd3\xc6\x31\xc7\x26\x3f\xab\x3f\x13\xc4\x13\xbc\x92\xa5\x84\x9b\x34\x1c\xeb\x40\x0d\xe6\x92\x44\xf5\x01\x88\xc5\xe9\xb7\xb7\xe9\x3b\x5a\xfc\xc4\xb6\x3d\xed\xbb\xda\xd7\xc4\xa4\x15\x42\x12\x12\x22\xbf\xbd\xb1\xe4\xfa\x17\x21\x7a\x1a\x24\xaa\xa9\x01\x3e\x7d\xb9\x66\xf6\x89\x5d\x16\x12\x4e\x2d\xb3\xcf\x9e\xc5\x09\x59\x65\xc2\xe4\x93\x85\xd6\x81\x0c\xc1\xe9\x27\x11\x77\x4a\xeb\xb0\x1e\xdb\x1f\x1c\x31\x3e\x62\x82\x08\xa7\x69\x4a\xa0\x33\x83\x3e\x0f\xd7\x55\x86\x31\x03\xb9\xf4\x6c\xc9\x13\xb0\x67\x42\x18\xf5\xf8\x54\x3c\xfd\xe7\x3e\xf1\x60\x9f\x41\x6b\x2e\x0a\x74\xb2\x0c\x5e\x77\x74\xed\x6e\x1b\xf2\xcf\x1d\x11\x08\x22\x05\x12\xeb\xec\xa3\x79\xca\xe6\x7a\x99\x8b\x30\x7a\x92\xed\x09\x1b\xcd\x07\x16\x7d\xe8\xf9\x3f\xae\x05\x00\x06\x7a\x0c\x83\x15\x22\x7d\x4d\x64\x55\x14\xa2\x54\xd2\x19\x42\xe0\x4f\x0a\x6f\x62\xe3\xeb\x60\x4b\x9c\xd4\x9f\x41\xda\xa6\xf4\x3e\xf0\xfc\x8f\x61\xd2\xe8\xd5\x12\x29\x98\x29\x27\xf8\xbf\xfb\xa9\x45\x27\xc6\x1d\xbb\x5c\x0b\xa9\x2e\x2e\x23\xc8\xe2\xd7\x0b\x91\x5e\x5c\x9e\x34\xfe\x4f\xf6\xde\x54\xe4\xa1\xc4\xa0\x8b\x64\xcf\x28\x0c\xe3\xba\x1c\xda\xa7\xc1\x26\x9f\x9b\x41\x7a\xe3\xdc\xd1\xff\xfc\x31\x72\xa0\xf8\x70\x49\xee\x4b\xae\x14\x03\xc4\x50\xc5\xca\x8d\xd6\x2d\x4e\xf4\x79\xa8\x95\x83\xbb\xef\x8e\x66\x17\xb9\x51\x2d\x15\x5b\xa7\x0e\xbd\x15\xcc\xbc\xf1\x88\xb8\x8b\x21\x46\x63\xb5\x4f\x6d\xa3\x7a\x49\x0f\xb3\x4e\xd3\xfa\x78\x7e\x9c\x28\x07\x9c\xaf\x68\x37\xc2\xfe\x1a\x02\xd2\xc1\x21\x3b\x37\x17\xc9\x38\xf8\x80\xb4\xaa\xee\xfc\x40\x2f\xf0\xc3\x65\x52\x54\x27\xe6\x0b\xcb\x0d\xdb\x88\x72\x1b\x3e\xa5\xe6\xeb\xac\x58\xb3\x0d\x2b\x69\xb6\x30\xb1\x99\x13\x47\x1e\xc9\xba\xff\x43\xc2\xe1\x83\xe1\x0d\x70\x9f\x3a\x9a\x3c\x06\x23\x37\xdb\x5a\xa9\xc8\xd2\xa7\x91\x0c\x41\x8c\x6d\x7c\x86\x08\x06\xb7\xc3\x21\x78\x64\xfb\x34\x59\xe7\x4d\x23\x7f\xe2\xb5\x9b\x0b\x68\xda\x77\x22\xab\x36\x2c\x42\xb2\x13\xef\x92\x86\x37\x59\x7e\xa7\xf5\xf2\xde\x9e\x61\xf6\x19\x24\x0b\x52\x7e\xc7\x65\x7f\xd2\x7e\xeb\x44\x4d\x90\xd7\xb8\xba\x45\xa5\x8a\x4a\x99\x54\x35\x73\x56\xa2\x26\xc9\xbe\x14\x02\x5b\x2b\x98\x73\xb2\x23\xfe\xbe\xeb\xef\x16\x8a\x4f\x41\x95\x62\x65\xfe\x9a\xfc\x7f\x2f\xfe\xed\x7f\xfc\xd7\xe2\xe5\x3f\xbf\x78\xf1\xcb\xb7\x8b\xff\xe7\x2f\xff\xe3\xc5\xbf\x2d\xe1\x1f\xbf\x7b\xf9\xcf\x2f\xff\xcb\xfe\xcf\xff\x78\xf9\xf2\xc5\x8b\x5f\x7e\x7a\xf7\xa7\x8f\x97\xe7\x7f\xe1\x2f\xff\xeb\x97\xbc\xda\xdc\xe2\xff\xfd\xd7\x8b\x5f\xd8\xf9\x5f\x22\x89\xbc\x7c\xf9\xcf\xbf\x8d\x18\x1c\xcd\xb7\x3f\x07\xc5\x0f\x71\x8d\xca\x5e\x83\xb3\xfe\x26\xd0\x88\xb5\xf9\x46\xe4\x56\xef\x00\x93\xf0\x5c\x2d\x44\xb9\xc0\x97\xbd\x18\x6f\xdf\x13\x02\xca\xf7\x9f\xe6\xb9\xf8\x60\xcf\xb4\xe7\x7e\xb7\x57\xc7\xac\x4c\x2d\x59\x52\x32\x35\x8f\xf5\x87\xb4\xac\xaf\xa3\x10\x69\x6b\x86\x67\xf3\xc9\x03\xc0\xf6\xcd\x09\xfd\xcd\x1a\x8c\x56\x39\xc2\x15\xac\xb5\x04\x68\x60\x4d\xc0\xf5\x17\x25\x20\x56\xcc\x25\x0a\x1a\x5a\xb7\x2c\x50\x9b\x82\xcf\xc1\x08\xfd\x7b\x32\x42\xaf\x90\x37\xd0\x02\x8d\x38\x06\xf8\xcc\x6f\x81\xb2\xfc\xae\xdb\x0d\xb7\x1b\x3f\xd0\xdf\x6c\x86\x42\xac\xb2\xa8\x04\x29\x44\x51\x65\x54\x35\x5c\x73\x1d\x03\xdc\xf5\x1a\xfb\x71\x11\x73\x1e\x6b\x77\xb3\xeb\xe1\xdd\xab\x39\xd9\x95\xa1\x4d\xf7\x3b\x39\xcd\x32\xc2\x73\x3c\x8f\x40\xd6\xfa\x75\x4b\x86\x7a\x20\xa1\x9d\xb5\x37\x39\x26\x9b\xea\x7d\xdb\x19\x26\xa4\x99\x2a\x5a\x2a\x9e\xdf\x2c\xc9\x9f\xf5\xdf\x51\x0a\x1b\xb7\x69\x67\x10\x08\x50\x10\x8a\x8c\x11\xa7\x3d\xb8\x82\x21\x42\xa5\x14\x09\x87\x4c\x7e\xf0\x13\xbb\xe4\xfd\xde\x89\xc3\x7c\x20\x67\xb7\x28\x59\xc2\x52\xe8\xf3\x46\x3e\x63\x09\x92\x5d\x43\xec\xd5\x72\x9e\xdf\x39\x0f\x74\x85\x41\xcb\x2e\xaa\x7a\x2e\xed\x94\x2f\x36\x9b\x4a\x41\x38\xe4\xe1\xe3\x55\x9a\xdf\xae\xda\xfb\xd6\x38\x23\xc7\x16\x53\x76\x9e\x05\xe7\xee\xe9\xda\xe7\x88\x8b\x2d\xe6\x12\x72\x8e\xdc\xc0\x3d\xbe\x77\xfb\xd4\xfe\xa8\xe6\xad\xf3\x78\x3e\xe8\x98\xdb\xe4\x79\xdf\x24\x43\x6f\x91\xa8\x1b\x22\xfa\x76\x88\xbd\x19\x06\xb8\x26\x87\x49\xfa\x38\x3f\x63\x51\xb2\x6b\xfe\x25\x9a\x37\x4f\xf3\xda\xa4\xab\x9b\x76\x82\xa8\x2f\x59\xc1\x72\xf0\xa5\x30\x9a\xac\x83\xd7\x97\x91\xf2\x75\x6c\xa2\x8e\xa4\xce\x1b\x2d\x45\x8d\x6b\xe8\x01\xbc\x6a\xd3\xf9\x0e\xa7\xef\xef\xee\xf4\x19\x3e\x98\xf7\xe8\xe5\x22\x65\x57\x9d\x70\x21\x7b\xe3\x3a\x7e\xef\x7d\x7f\x07\xa2\x02\x73\xd1\xed\xf0\xb4\xfd\xdb\x91\x32\x43\x4c\xba\x49\x21\xe0\x8c\x5e\x73\x85\x05\x3d\x7a\x2c\xcb\xba\x3a\xd3\xa3\x07\x25\xd1\xe6\x1b\xc7\x9d\x46\x23\x7a\xff\x5d\x0c\xd6\x90\x5f\xa1\x4b\x39\xad\x32\x96\x12\x9b\x04\x85\x3f\x55\xb3\x64\x07\xc5\x18\x46\x6d\xa4\x0b\xbd\xa2\x52\xf2\x9b\x7c\x51\x88\x74\xa1\x7f\xa3\xb7\x48\xe0\xe1\x0b\xa3\x89\xef\x32\x8d\xd9\xde\x0f\xce\xbf\xea\x69\x34\x89\xd8\x14\x95\x62\x9e\xf3\xd5\x5a\xd0\x1d\x23\x5a\x6d\x31\xa7\xcf\xd3\x9b\x6b\xbd\x6c\xa8\x20\x68\xae\x2f\x42\x72\x2d\xcc\x90\x16\x6e\x48\x0b\xf7\x5b\x63\x97\x3c\x2c\x0f\xd1\x45\xdc\x7d\x8e\x9b\x4b\xf9\x16\x1d\xd4\xcd\x9e\x9f\x1b\xfa\x85\x6f\xaa\x0d\xa1\x1b\xac\x9f\xbc\xb6\x8b\xdb\x73\x8c\xeb\x65\xa7\x59\x26\xee\x59\xfa\x54\x4b\x18\xb5\x8c\x64\x20\xf7\x92\xe7\xea\x70\x0c\x3a\x1a\xe3\x1d\x8c\xd1\x8e\xc5\x91\x0e\x45\x1b\x5f\x88\x65\xcd\x0f\x36\x60\xb2\xc3\x9c\x3c\x9f\xc0\x9c\x56\x26\x40\x5e\x94\xfb\x05\x2e\x89\xd8\x70\xa5\x8c\xc7\xde\x2b\xfc\xec\x73\x95\x70\xd5\x70\x5b\x9b\xa3\x04\x35\xa5\x14\xea\xf8\x2d\x10\x40\xb6\xad\x83\x5f\x27\x78\xbd\xdf\x73\xd9\x37\x60\x04\xe1\xe0\x9b\x02\x61\x38\xe0\x48\xb8\xaa\x47\xcc\xcf\x39\x1c\xaf\xc3\xf1\xb2\x4f\x37\x94\x1a\xe9\x84\x53\x6b\x60\x48\x39\xf5\x48\xb3\x7f\x21\x52\x69\x74\x12\xcb\x34\x5d\x99\xb5\x04\x01\x80\x78\x7e\x03\x1d\xeb\x79\x42\xaf\x98\x92\x06\x0a\x06\xe8\xd0\xd2\x82\x52\xa1\x0b\x05\x8b\xa4\xd1\x7f\xd4\xa3\x75\x09\x48\x0c\xbf\xbe\x6e\xbe\x87\x78\x25\x1b\xd0\xd4\x2f\x94\xaf\x75\x19\x55\xaa\x8b\x22\xdb\x14\x19\x55\xec\x58\x1a\xf5\x6b\x24\x12\x4c\xf8\xf6\x8d\x83\x8a\x23\x53\xe0\xe2\x7a\xe5\x9c\x07\x24\x37\x18\x32\x8e\x44\xc2\x21\x05\xc1\x90\x46\xc2\xc7\xf5\x1a\x09\x58\x15\x30\x02\x42\x2e\x40\x15\x03\x17\x61\x18\x39\x12\x6f\xb3\xc6\x44\x6e\x42\x51\x9b\x20\xac\x1c\x19\x60\x1c\x47\x84\x74\x46\x40\xcc\x05\x2d\x5a\x03\x41\x17\x80\x99\x23\xc3\xcc\xd4\x30\xdc\xdc\xde\x74\x62\x21\xe7\x82\x13\x42\x3c\xdc\x21\xb0\x73\x41\x92\x06\x3f\x6d\x08\xf4\x1c\x19\xb2\x60\x61\x08\x3a\x32\x12\x86\x2e\xbc\x5a\x3b\x50\x71\x61\x28\xba\x20\xc9\x06\x54\xdd\x00\x38\xba\xa8\xb1\xb6\x22\xe3\xf5\x42\xd2\x05\xc9\xee\x43\xd6\xc5\xc2\xd2\x91\x68\x68\x3a\x12\x07\x4f\x47\xe2\xb8\x26\x08\x53\x47\xa6\x40\xd5\xf5\x8c\x10\x41\xec\x06\xc3\xd5\x05\x75\x68\x03\x64\x37\x10\xb2\xae\x8f\xec\x0e\xcb\xc5\xc2\xd6\xf5\x90\xec\x04\xb4\x8b\xbf\xb1\x67\x56\xc6\x03\x9c\xa2\x44\xc6\x4a\xbf\x60\x7e\xf7\x69\xba\x87\xeb\x6f\xc3\x84\x5c\x5a\x85\x4f\xe7\xa1\x23\x61\x1f\xad\xaf\x4d\x9f\xe4\x7a\x44\xc0\xb2\x4a\xd1\x64\x8d\x88\x78\x66\x44\x3d\x6a\x03\xcd\xb7\x44\xef\xaa\xc2\x1b\x11\x98\xca\x98\xa6\xaa\x84\xb0\xe4\x3f\x3a\x1e\x3e\x61\xa0\xc1\xfe\x13\x56\x02\x75\x6f\xa1\xe5\x72\x2d\x2c\x1c\x6f\xfd\xa3\xfd\xd7\x3f\x4d\xa8\x0e\x8b\x51\x11\x70\x90\xd1\x0a\xdd\x39\x7c\x9d\xf0\x3c\x85\xe0\xa7\x99\x3a\xac\x08\x52\xd2\xeb\xb8\x09\x0b\xb8\x73\x2d\x5a\xc9\x86\xd1\x5c\x5a\xd7\x29\xc4\x4a\x6b\x42\xd2\x84\x85\x3d\xe3\xd9\x38\x97\x22\xee\x3c\x60\xb5\xf7\xe2\xca\x78\x55\x4f\xc8\x25\x78\xf9\xeb\x4f\xe0\xcc\xbe\x17\xe7\x5f\x58\x52\xa9\xde\x7a\x97\xa8\xdb\x76\x08\x86\xef\x4f\xb5\x82\x85\xf3\x6d\x28\x58\xf5\xa9\x88\x45\xf1\xed\x5d\xcb\x5b\xb6\x75\xb8\xb1\x56\xb5\x83\x6b\xad\xff\x5a\x74\x7c\x68\xaf\x42\xbc\x5b\xff\x97\x75\x9a\x6e\x56\x3c\xc7\x41\xe2\xcf\xda\x4d\xef\x25\xaa\x47\x65\xb7\x47\xeb\xec\x59\x86\xc3\x9b\xba\xf8\x83\x61\x88\x7f\x9e\x09\x86\xd8\xc9\xfc\x76\x4d\xd0\x53\xef\xce\x7f\xad\x68\x56\x17\x81\x05\xb6\xd4\x7e\xdd\x10\xd8\x83\x68\xbd\xe7\x59\x9a\xd0\xd2\x64\x98\x82\xac\xe9\xa5\x28\x05\xf2\x17\x40\x95\x41\xb5\x9d\x95\x74\x35\xa7\x48\x4c\x05\x28\x68\xa9\x78\x52\x65\xb4\x5f\xc3\x37\xf8\x23\x11\x65\x5e\x81\xbd\xab\xd9\xfd\x8a\x25\x22\x4f\xe3\x4d\xcb\x8f\xbb\x6f\xee\x66\x38\x14\xac\xe4\xa2\x07\xba\xce\x0c\xc0\xe2\x3a\x7a\x07\xef\x45\x33\x4e\x24\xae\xad\x6c\x73\x02\x23\x70\x7a\xac\x93\xaf\x09\x21\x66\x91\x3c\x5f\xd6\x17\x4d\x2d\x05\xfa\xc5\xe5\x0f\x5b\xeb\x6d\x3c\x31\x30\xa1\xb9\x50\x08\x15\x6a\xc6\x6a\x8e\xa1\xd9\x56\x47\xb6\x97\xea\xb5\x28\xa1\xec\xf1\x45\x2a\xb0\x72\xef\x8e\x27\xea\xe5\x92\xfc\xbf\xac\x14\xc0\xb6\x39\xbb\xa1\x8a\xdf\x39\xcd\xe6\x9e\x67\x59\x2f\x45\x88\xaa\x31\x8a\x59\x41\xe4\x5b\xf2\x02\x48\x12\xbe\xd9\xb0\x94\x53\xc5\xb2\xed\x4b\xf4\xe7\x30\x22\xb7\x52\xb1\x4d\x98\x81\xc2\xce\x35\x0b\x97\xc9\x73\xf5\x87\xef\x3b\xbf\x37\xac\x0e\xf8\xb3\xad\x68\xac\xc5\x34\xe6\x18\xed\xb0\x8a\xd1\x00\x82\x32\xba\xd3\x5c\xf1\xf3\x97\x0c\xe4\x87\xb5\x3c\x62\x99\xec\x3f\x34\x9f\x52\x52\x32\xc0\xe0\x31\x27\x6e\xc2\xc9\xc4\x9c\xf5\x77\xa2\xca\xbb\xfc\xf5\x4d\x00\x55\xe3\xa8\xfa\xec\xbd\x56\xd7\xf2\xef\x64\xa7\x3d\xb0\xa2\xe7\x8d\xc1\x8b\x1c\x50\x02\xe1\x02\x50\xb0\xb4\x90\xc3\x6f\xf5\xc3\x3a\x12\x3f\x10\xf0\xa0\x15\xfa\x30\xb6\x9e\x12\xa2\xc9\x35\xfc\xee\x07\xa2\xb9\x1f\x8a\x7e\x4c\xda\x60\x33\x6d\x8f\x2a\x07\xe8\xc6\x0c\xa3\xf4\x5f\x3d\x8e\xa5\x61\x14\x2c\x35\x99\xc0\x20\x6f\x2c\x2e\xe8\xf1\xeb\xe3\xc9\x17\x09\x4e\xb2\x14\x05\xbd\x81\x93\x19\x3d\xd7\xdd\x17\x49\xca\x14\x2b\x37\x00\x4e\xb2\x16\xf7\xf8\x77\xb8\xd0\x7b\x27\x5a\x18\x0a\x2c\xad\x71\x62\xd6\x42\x22\x32\x64\xa3\x6c\x1f\xe4\x00\xa4\x4c\xdc\x07\x6c\x7b\x5a\x8a\x2a\x4f\x8d\x1e\xec\x04\xfe\xbb\x9d\x01\xbf\x17\x39\x48\xaa\x4a\x62\x89\x7d\x27\x56\x25\x3e\xee\x36\x5a\x31\x45\xf5\x01\xfd\x6e\xf9\xdd\xb7\x93\x97\x7f\x10\x4e\x04\x38\x54\x76\xfc\xf7\x36\x23\xc7\x9e\xce\xc9\x23\x2a\x19\x4d\x7f\xce\xb3\x78\xbd\xfc\x1d\x32\x28\xbc\xb8\x00\xec\x51\x7e\x0d\x31\x97\x13\xfc\xe8\xbe\xe4\x8a\x45\x05\xf0\x08\x79\x01\x68\x79\x44\x94\xa4\xca\x9d\x01\xf3\xb2\x89\x02\x00\x5f\x09\x4f\x33\x94\x93\x26\xab\xd5\xa4\xb3\x8d\x87\x18\x99\xb6\x3e\xda\x8e\x65\x03\xf5\x0f\xe6\xed\x96\x63\xde\x04\x3c\x20\x2f\xf0\x9b\x5a\xc3\x16\x42\xbd\x9c\x9e\xa8\x86\xd3\x3e\xff\x52\xc4\xeb\xfd\xe7\x06\xdb\x81\x14\xa1\x35\x08\xaa\xfd\xde\xfa\xf4\xac\xc1\x0f\x6c\x4d\xef\x98\x24\x92\x6f\x78\x46\xcb\x40\xf5\xa0\x12\xe4\x0a\x67\x45\x56\x95\x6a\x47\x96\x69\x47\x25\x09\x48\x91\x1a\xd5\xc2\x43\x25\xf1\x67\xe0\xfd\x54\xbc\x91\xd2\xb2\xa9\x76\xfc\x7a\x57\x40\xd6\xd9\xf9\xe8\x31\x6c\x2a\x55\xd1\x2c\xb0\x06\xec\x4b\x92\x55\x92\xdf\x4d\x39\xff\xa6\xe6\x6e\xb0\xea\xb2\xab\xb5\x14\x22\xbd\x2a\x58\xf2\x38\x3a\x4b\xd3\x16\xd5\xe2\x34\xb5\x8c\x05\xb9\xfb\xe8\xbe\xea\xe9\xb0\xb4\xa1\x5b\xc8\x07\x05\xdc\x6c\x9b\xb1\xbe\xf5\x33\xee\xdd\xac\x9e\x33\xe0\x10\xbd\x97\xe7\x19\x95\x8a\x27\x3f\x64\x22\xb9\xbd\x52\xa2\x1c\x80\xde\x73\xfa\xe7\xab\xbd\xb7\x77\x00\x9b\x4e\xff\x7c\x45\xce\xb8\xbc\xed\x65\x43\x0f\x30\x0e\xb3\x39\x7c\x37\x21\x25\xb7\xd5\x8a\x65\x4c\x1d\x1f\x4b\xbc\xe3\x37\x34\x59\xf3\xbc\xff\x4a\x30\x57\x7f\xee\x0a\x20\x0d\x7c\x9f\xde\x8f\xa1\xe9\x1c\xa6\x34\xf7\x95\xe1\xf4\xdf\xd0\x7b\xc9\x70\xda\x2b\x3d\x6d\x40\x4e\x0d\x23\xcc\xcc\x14\xcb\xc4\x41\x5c\x9c\xcd\x10\xab\xbc\x96\x1f\xf5\xc8\x86\x04\xac\x8e\x7f\xe4\x19\x43\x5b\x12\xa6\x65\xb3\x7a\xcd\xd9\x81\xfd\xdb\x8a\x2a\x18\x1e\xb9\xa7\xe8\x5b\x01\xd9\xbd\x24\x1f\x79\xf1\x9a\x9c\xe7\xb2\x2a\x59\xed\x9b\xbb\x6e\xfe\x54\x90\x26\x97\x75\xb5\xb4\x35\x7b\x81\x5f\xd0\x0c\x04\x84\x7c\xb4\x82\xc9\x39\xa2\xd2\x47\xc4\x71\x8e\xd8\x17\xf5\xfd\xd1\x09\x39\xfa\x72\x2d\xf5\x7f\x72\x75\x2d\x8f\x96\xe4\x62\xe3\xd2\x8d\x00\xb2\xb0\x64\x36\xb5\x14\x5f\x08\x0f\xf6\xda\xd7\x55\x1e\x84\x25\x83\x63\xc0\x34\x68\xad\x75\xa7\x82\xdc\x23\x72\x96\xbe\xfe\x58\x59\x9a\x1e\xa5\x3b\xdb\x10\xc8\x33\xc7\x27\x11\x9b\xa2\x14\x1b\xee\xae\x3e\x73\x5c\x67\xcb\x9f\x06\xa7\x59\xc8\xe8\x20\x7b\x9c\x8b\x68\xb6\xe6\x55\xd2\x54\x45\x2c\xdf\x02\x5f\x86\x63\x7b\x8e\x6f\x2f\xae\x6d\x32\x1b\x3a\x16\x8c\xd7\xc8\x34\x35\xc0\xac\xb9\xd5\x36\xc6\x72\x23\x46\xab\xf7\x78\x13\xfa\x27\x98\x01\xbe\x4a\xd9\xdd\x2b\x99\xd2\xef\x4e\x60\x98\xc8\x38\xe1\x1a\x3c\xd5\x98\x33\x95\xe4\xe8\xbb\xa3\x25\xb9\xb2\xfa\xd1\x89\xbf\x06\xee\x7b\x41\xaa\xd7\xa2\x74\x03\x82\xb0\xdc\xb7\x47\xe4\x85\x28\x61\x64\x09\xcd\x49\xc6\xe8\x9d\x09\x3d\xa1\x24\x0a\x0f\x14\x3c\x30\x2f\x23\x31\x0e\xe2\x0a\xb8\x3d\x3f\xd5\x3f\xfc\x3e\x70\xfd\x84\x6d\x17\xd2\x81\xc2\xbe\x25\x47\xda\x68\x39\x02\x13\x43\xe8\x3b\x4c\xdf\x3c\x5a\xad\x01\x38\x54\x43\x39\x38\x7f\xbb\x50\x9a\x2f\x77\x3d\x3b\xf8\x03\x7b\xcc\x16\xa4\xe9\x31\xe3\x11\x58\x3f\x47\x8f\x7e\xf3\x91\x41\x98\x42\xf6\x6a\x1b\xb6\x0f\x9f\x72\xfe\x6b\xc5\x48\x8d\xee\x5e\xb0\x12\xf1\xe4\x15\x49\xb9\xbc\x8d\xc5\xb0\x80\xb2\x1f\xad\xae\xbc\x38\xdd\xd0\xbf\x8a\x9c\x9c\xff\x70\x65\x86\xf4\xf2\x09\x17\x2e\x20\x10\xe9\x5f\xab\x92\x69\x05\x2b\x3e\x49\xcc\xbe\xb1\xab\xa9\xe9\xcf\xc9\x19\x55\x14\x14\x36\x94\x5e\xfd\x3e\xd1\xbc\xbe\x63\x35\xd7\xaf\x78\x9e\x1a\xa1\xe7\x69\x5b\x8f\xa5\x18\xe9\xbd\x7e\xdf\xad\x0d\xd7\x5f\xfa\xf4\xe1\x62\x06\xe5\x29\x81\x5b\xed\xe6\x9d\x48\x07\x6a\x50\xff\xa2\x97\xeb\x0d\xbe\x4d\x36\xfa\x75\xf2\x5e\xe4\xec\x04\x84\x05\xd1\xd2\x02\xff\x19\x64\xd7\x3f\x97\x5c\x75\xb5\x3c\xa9\x9f\xe8\x6b\xd5\xae\xdf\xa0\xd9\x7c\xf4\x7c\x49\x70\x01\x6a\xf6\x81\x53\x67\x2e\xd8\x55\x26\x56\xb6\xab\xc1\x9c\x23\xfd\xf4\xe1\x62\xf0\x40\x3f\x7d\xb8\x78\xbc\x41\x8e\x50\xae\x77\x75\xeb\x5a\xcf\xa8\xcb\x0f\x6b\x6d\x2c\x7c\xf9\x6b\x1a\xf1\x1a\xf1\xd2\xea\xba\x61\x9d\x78\x98\x2e\x4c\x78\x38\x81\xcd\xd7\x85\xe7\xda\x81\xee\xbe\x3e\xf5\xd3\x3c\x9a\xe7\x5f\x0a\x4c\x82\x36\x01\xb8\xab\x35\x05\x44\x15\x57\x05\xaf\x19\x25\x7c\xef\x72\x79\x2b\xf5\x2d\x64\x59\xca\x75\x47\x23\x67\x0c\x13\x39\xd2\xd7\x36\x09\x2b\x9a\x62\x3b\xc1\x77\x50\x5b\x90\xbe\xc6\x7b\x80\x60\xa9\x41\x4a\x1a\x40\xfc\xbd\x54\x5f\xa0\xeb\x35\x77\xaf\xd2\x3b\xca\x33\xba\xe2\x19\x57\x5b\xad\xc7\xbc\x5c\xba\xca\x8b\x18\xc5\x58\xc2\x92\xcd\x26\x94\x46\xa9\x66\x7b\x6e\x5f\xf2\x42\xd3\x79\x05\x2e\xe5\x97\xcb\x78\xad\x0c\x9a\x82\x41\x02\x3d\xaa\x76\xbe\x4a\xa7\xd7\x06\x4e\xd0\x8e\xc6\x16\xc7\xbe\x21\x75\x08\xb6\x53\xcb\x83\x61\xd7\xba\x7e\xa3\xf5\x5a\x87\x3f\x98\x6e\x7e\xbd\x03\x34\x95\x3e\xcf\xea\x66\xc7\x2a\xe9\xe0\xdd\x0e\xac\x17\xf8\x56\xec\xed\xfe\xf7\xca\x77\xc4\x15\xa5\x0f\x56\x05\xfc\x5e\x79\x16\x95\xa8\x51\x48\x00\x9c\x18\x9c\xfb\x95\x11\x71\x06\x60\x13\xb5\x0b\xcd\x83\x3f\x05\x31\x67\xe2\x21\xac\x2c\xa7\x0c\x2b\xc1\x5e\x43\x9a\x5b\x3f\x83\x45\x8f\x23\x61\xc5\xfa\x3a\x3e\xff\xe6\x0d\x2b\xd6\x3f\x5e\x35\xdd\xd6\xfa\x33\xf2\xe3\xd5\xfe\x99\x0d\xc4\x53\xa8\xc2\x15\x90\xe8\xe8\x3e\x96\x24\xe3\xd7\xac\xa5\xf3\xe9\xfe\xa4\x66\x3a\xd1\x1b\x91\x73\x25\xca\xbe\x1b\x25\xf6\xa4\x5a\x52\xc3\x6e\xfa\x1a\x2d\xed\x9d\x79\x1f\x13\xaa\x13\x91\x65\x2c\x51\x88\x3e\x1a\xe4\x55\xd8\x00\x3b\x80\x36\x13\xd1\x74\xbf\xac\x7b\x65\xa1\x39\xf8\x0a\x37\xff\xd5\x87\xf3\xd3\xb3\x77\xe7\xcb\x4d\xfa\x9b\xb5\xb8\x5f\x28\xb1\xa8\x24\x5b\xf0\x20\x5c\xdb\x53\x24\xab\xe3\x53\x44\x60\x9a\x36\x17\xfa\x67\x0b\x76\x40\x3e\x49\x4c\x53\x02\x97\xa0\x0d\xfe\x0a\xa1\x4e\x48\x49\xd5\x3a\x02\x8f\x4f\xad\xa9\x6d\xf6\x98\x65\xb8\xf6\xaa\x64\xec\xc4\x77\x74\xf4\x54\x52\x0e\x9c\xea\x38\xa7\x50\x3d\xdd\xc0\x65\x10\x9c\xad\x93\xf7\x0f\x71\x19\x90\xc7\x66\xd6\xf8\x7b\x27\xa4\xf4\x90\x9e\x35\xbf\x72\x14\x6c\x2e\x19\x84\x9e\x95\x88\x02\x2c\x83\xfa\x91\x6b\x51\x6a\x4e\x2d\x9b\x5c\xc5\x54\x02\xcb\xf0\xaa\x92\xac\x5c\x9a\xdb\xed\x5d\x8c\x8f\xfd\xf1\x96\x38\x1a\xba\x71\x30\x5a\xef\xee\x02\x7f\x60\xd7\xc4\xef\x2f\x69\x74\xc2\xe0\x5a\xd0\x4a\xad\x59\xae\x6c\xf3\x21\xb3\x8c\xad\x2b\x1e\xec\x6a\x80\xcf\x23\x73\x71\x14\x98\xe4\x10\x00\xc8\x03\x2c\x62\xef\x33\x3b\x2c\xa2\x3e\xbe\x13\xee\x2f\x57\xc9\x5d\xd2\x54\x40\x0a\x18\xa2\x10\x87\x67\xe3\xb1\x36\x4d\x37\x3c\x7f\x6c\xce\x0d\x29\xa3\x3c\x4f\xfb\x57\x66\x07\x84\x19\xbe\xdf\xd4\x46\x91\x86\x8d\x26\xd9\x08\x7e\xef\xe8\xa8\xb5\x2a\x11\x88\xc7\xc4\xf9\x9b\x51\xfe\x56\xc6\xde\x5d\xaa\xcd\x56\xfe\x9a\x2d\x70\x04\x8b\x22\xad\xd7\xea\xef\x35\x2c\xff\xb8\xae\xc3\xaf\x20\x98\x3e\x0b\xc7\x90\x83\x02\xe9\x9e\x87\x5f\xe3\x78\x9d\x71\x82\x46\x03\x9d\x25\xa5\x2d\x37\x47\x8c\x5b\x6c\x51\x69\xfc\x16\x31\x48\xbb\x05\x2d\xe9\x86\x29\x56\x62\x5a\xb0\x49\x42\xce\x4d\x7d\xde\xcf\x05\xcb\xaf\x14\x4d\x6e\xe7\x84\xf0\x3f\x68\x19\xcf\x57\xcb\x18\x17\xc7\xb6\xe9\x87\xa9\xe3\x21\x03\x62\xb9\x8d\xcd\xfe\x27\x18\xc3\xc6\x03\xf7\x0c\xa4\xa0\x43\x98\x8d\xf7\x72\x39\x3c\xd1\xa6\x6a\x51\x23\xce\xa2\xf3\x4a\x54\x59\xbf\x66\xe1\xc0\x9d\xa1\x24\x2c\xb8\x76\x33\x23\x64\x1a\x6d\x6f\x78\x6c\xb8\x96\x4b\x1b\x91\x32\xb2\xe2\x28\x9a\x2a\xc9\xb4\x7e\x94\x60\xad\x57\x90\x07\xe0\xa2\xd7\x97\xb6\x19\x87\xaf\x04\x60\xe9\xd3\x8a\xa9\x7b\xc6\x72\xf2\x2d\xa8\x60\xdf\xfe\xcf\xff\xf9\x3f\xc3\x02\xdf\xbf\x8f\xbe\xfd\xc3\xf7\xdf\x2f\xc9\x19\x2f\x01\x9d\x84\x43\xad\x9a\x4b\xef\x2e\x4c\x0a\x72\x58\x2e\x09\xb5\x8f\x3b\x64\x2e\x24\x83\x03\xb1\xe1\x37\x6b\x85\xdd\x69\x81\x0b\x32\x1e\x94\x8c\x04\x31\xa3\x51\x40\x20\xd6\xa6\x34\x05\x99\xa6\x64\xda\x24\xb5\xc1\x1a\x9f\x90\x8c\xdf\x86\x87\x7a\x2d\xff\x54\x8a\xaa\xa8\xc1\x07\x4a\x26\xb5\x3e\x6f\x7a\xe7\xe2\x8f\xd5\x7b\x26\x99\x7a\xa2\x5c\xa6\x28\x8f\x5f\x83\xe9\x2e\x1a\xca\xd3\x89\x43\xc8\x5d\x20\xab\x14\x94\x97\xdd\xf8\xe0\xde\x74\xd6\x26\x79\xa4\xd1\xd9\xcb\xf9\x08\x52\xef\x6c\xf7\x43\x52\xd5\x4f\x51\x8a\xff\x40\xe6\xe0\xb9\x09\x3b\x59\xeb\x42\x1a\x7d\xd6\xc0\x4a\x40\xdc\x21\x50\x89\x43\x76\x30\x88\xf4\xfd\x6e\x70\x91\xbc\xca\xe2\x8b\x6b\xbf\x04\x3e\xc6\xab\x91\x71\xa9\x87\xd8\x00\x6b\x6f\x19\xb9\xdf\xc2\x5e\xad\x23\x5a\xd4\xe8\x31\x56\xf9\x1e\x75\xd3\x0b\xd2\x48\x47\xec\x39\x6a\x4a\xcd\x83\x24\xeb\x31\x60\xe9\x89\x29\x6c\x35\xb4\xf6\x60\x8f\xe3\xe6\x6f\xeb\x31\x98\xaa\xcc\xd6\x42\xfe\xa8\x1e\x3b\x93\xd2\xd4\xcf\x6e\x68\x79\xab\x8d\x3c\x23\xdf\xc2\xd2\xe6\x52\x2f\x92\xab\x09\xc6\x32\xf1\x3b\xe6\x1a\xab\xfb\xf5\x6c\x7a\xcc\xc7\xcb\xe0\x79\x43\xef\x35\x11\x25\x22\xe1\xa3\x94\xd0\xef\x3d\x3a\x36\x4c\xb3\x0e\x8a\x16\x5e\x5b\x75\xd3\x0a\x92\x36\x6a\x66\xc2\xa1\x7c\xbb\x0b\xe1\x75\x1d\xa0\x62\xc6\xf7\x45\x89\xeb\x8c\xa2\xbf\x55\xc4\xf4\x6e\x1b\xa2\xdb\x46\x37\x51\xe9\xee\xbb\x69\x0e\x6b\x4c\xcf\x93\x81\x1d\x38\x08\xe6\x77\x0d\x1f\x5d\x40\x11\x68\xe9\xab\xdf\xf5\x68\x21\x79\xe2\x75\x9b\xe8\xbc\xff\x63\x60\xa6\xf0\x81\xd2\xc8\x86\x8c\xb4\x32\xc0\xd3\x7b\xa2\x85\x3c\x3e\x75\x35\x65\xeb\x95\xdf\x72\xa5\x47\x12\x0e\x5c\xfc\x8d\x8b\x3d\x9a\xe4\x1c\xd7\xbf\xa1\x35\xb0\x23\xd5\x10\x55\x00\x9f\x98\x90\x1d\x3e\x7b\xe7\xc3\x49\xdd\xa2\xd1\x95\x30\x63\x21\xa4\x8e\xfa\xd9\x80\xce\x6e\x8f\xda\x92\xbc\x33\xb2\x5b\xf3\x62\x4e\xe8\x4a\x8a\xac\x52\xf8\x03\x71\xe7\x8f\x38\x12\xbe\xf8\x87\x01\x5a\xf8\x29\x90\xe9\xf6\x6b\x91\x44\xbd\x2b\x01\x2e\x6b\x94\xc6\x31\xb7\x03\x3e\xd1\x62\xe1\x00\x9e\x3f\x6d\xfd\x1e\xa0\x75\x45\xdd\xd3\x28\x3c\xf9\x87\x68\x73\x91\x48\x1e\x6f\x20\x5f\x5d\x90\x17\x75\x0b\x44\x9b\x2c\x73\x91\x2b\x56\x5e\xd3\x84\xbd\xf4\x0c\xe7\x7e\xc7\x99\x79\xd3\x56\xdc\xad\x69\x9e\x66\xae\xf3\x0e\xfb\xa2\x58\x99\xd3\x0c\x7e\x2f\x2d\x39\xc0\x96\x9c\x66\xc5\xba\x5f\x15\xb9\x66\x54\x55\x65\xbf\x73\x72\xde\x9c\x6f\x18\xda\x1c\x16\x3b\x10\x1a\x96\xed\x85\xcb\x62\xcc\x87\xdc\x3b\xa5\xde\xa2\xf5\xd6\x90\xda\x07\xd7\x5e\xfa\xbe\x8a\xa5\xe6\x4f\xb8\x62\x40\x26\x6d\x45\x55\x9a\xc0\x91\x69\x66\x10\x24\x9a\x88\x52\x5b\xe7\x38\x30\x2a\x49\xc9\x6e\xb4\x29\x51\x82\x4d\x82\x25\xc9\x59\xa5\x3f\x98\x2d\xdf\x76\xd6\x8c\x67\x2f\x1f\xd9\x84\x0b\xc2\xd1\x05\x1b\x4e\xb8\x36\x56\x8d\xb8\xe3\xa9\xd5\x50\x20\xa0\x5c\x77\xce\x2f\xa8\x94\x11\x9e\x14\x63\xbb\x79\x9d\xae\xbc\xbd\x45\x1b\x0a\xf4\x1c\x07\x62\x11\x65\x81\xda\x60\xa0\x5f\xe0\x28\x00\x7f\x2c\x18\xf2\x8e\xbf\x67\x44\xca\x2e\xab\x55\xc6\xe5\xfa\x6a\x94\x8f\xfc\x7d\x0b\x01\xcc\x91\xf2\xe3\xfe\x51\xf3\xed\xf2\xab\x13\xc9\x72\xc9\x41\xc3\xd0\x37\x99\xd6\x6b\x62\xca\xcf\xb4\xca\x4e\xa5\xb4\x9b\xe3\x9f\x36\x01\xd5\x87\x19\x33\x98\x4c\xfa\x4f\xde\x3c\x3e\xc7\xb9\x50\x11\xab\x2e\x65\x9f\xf2\xc2\x7f\x8f\x24\x34\xcb\xa4\x51\x52\x1d\xac\x87\xbd\x8f\xe2\xec\x79\x5b\x36\x8e\xdc\xc8\x35\xa3\xba\x1e\x98\x3b\x80\xf9\x31\x67\xbc\x75\x61\x25\xd9\x08\x2c\xa3\xcd\x89\xc8\xed\xea\x03\x9c\x9f\xf9\x77\x84\xdd\xe7\x60\x0f\x68\xc9\xcc\x61\x89\x63\xcd\x43\xf0\xa2\xf3\xf9\x3a\x82\x17\xa3\xc2\x96\x75\xb3\x62\xea\x01\xba\x34\xda\x20\xf4\xb4\xfe\xf1\x46\xe9\x6c\xc9\x16\xf0\x96\x41\xf1\xcf\xa1\x55\x87\xa7\x4a\x95\x7c\x55\xa9\x81\x00\xce\x9f\x77\x5e\x06\xbd\x8a\x49\x23\x90\x16\xc6\x4c\x4e\x06\xb8\x3c\x8c\xc5\xea\x8e\xdd\xbe\x98\x73\xba\x41\x90\x2a\xa8\x0d\xf8\xd2\xb1\x24\xa9\x48\x2a\xd7\xe1\x02\xf4\x88\x3a\xc2\x1f\x06\x64\x27\xc3\x8e\xf8\x50\x14\x5c\xff\x07\x02\x5c\x9a\x8a\xfb\xfc\x9e\x96\xe9\xe9\x65\x6f\x09\x58\x53\x59\xab\xdf\xf1\x43\x4b\x96\x14\xb4\xc9\xa7\x2b\x51\xa9\xa0\xdc\xb5\xc8\x20\x16\x80\xe6\x10\x69\x3a\x44\x9a\x0e\x91\xa6\xae\xa7\x19\x69\xd2\x6f\x34\xdb\x6d\x34\x0e\x60\x64\x88\x5b\xaf\xe8\x93\xba\xec\x3d\x61\x82\xf2\x7f\xb7\xec\x6a\x88\x36\x0b\xfa\x2c\x9e\xb7\x9a\x5f\x3c\x1d\xd9\x36\xae\x03\x35\xe1\xe9\xdc\xfb\x0f\xe0\xb8\x87\x19\x45\x98\x25\xf8\x74\xd5\x6f\xd4\x5d\xe5\xfd\xc0\x63\xa4\xdb\xaf\x10\xe9\x6b\x40\x8c\x27\x34\xcf\x05\xde\x8c\xf2\xc4\x34\xae\x39\x31\xb6\x73\x9e\x46\xf7\x9c\xb7\x0f\x74\xe2\xb1\x97\xeb\x20\x57\x70\xe4\xd6\x91\x41\xdb\x47\x60\x0b\x61\x7d\x7a\x90\x2f\x9b\xcf\xb0\xbd\x24\xd0\x83\xc4\x2a\xb0\xb1\x6f\xec\x2a\x53\xf8\xb6\x6b\x6d\x9f\xac\xd9\x86\xc2\x3f\x7f\x1c\x34\x74\x7c\xb8\x24\x5a\x55\x54\x0c\xc1\x5e\x58\xb9\x91\x44\x5c\x9f\x34\xfa\x88\x1d\xdd\x7d\x77\x14\xeb\x77\x1e\x1c\xfb\x21\x96\xc7\x43\x80\x81\xcd\x67\x1f\x3e\xd0\x79\xde\x35\x7f\xd7\x5d\x5f\x23\x82\xf2\xde\xd8\x1b\x21\x68\x90\xb6\xb8\xda\x0f\x36\xfd\x43\xe8\x2b\x8e\xe6\x21\xf4\xf5\xcc\x42\x5f\xde\xe5\x02\xc7\x8f\x4b\x3b\x71\x0c\x87\xc5\xde\x2d\xfa\x5d\xdf\x2d\x6c\x22\x67\xd0\xeb\x0d\xf5\xeb\xa5\x03\xe7\x8d\xa4\xa9\xf9\xd8\xc6\xcc\x44\xd9\xcc\x80\x38\x5e\x2e\x8f\x8f\x31\x92\x06\x64\xe3\x49\x56\xea\x7a\xf1\x47\xc2\xf2\x44\xa4\xc8\x8a\x7a\xac\xa5\x54\xa0\x1c\xd5\x5e\x94\xe1\xb3\xdf\x58\xe8\x61\x3f\xe3\x02\xc6\x39\x84\x45\xa2\x25\x8e\x05\xfa\xf9\x71\x82\x62\x51\xab\x13\x0e\x94\xd0\x2c\x80\x83\x76\x8c\x15\xe5\xa0\x57\xd4\xed\x30\xb1\x59\x2c\x48\x1d\xdb\x9e\x93\xbc\xc0\x0f\x97\x49\x51\xc5\xb9\x7b\x6c\xcf\xd9\xe5\x86\x6d\x44\xb9\x3d\x71\xa4\x34\x89\x06\x6d\xf3\x8d\x7e\xb0\xd2\xfa\xd1\x1a\x4b\x52\x95\x25\xcb\xa1\x85\xe6\x73\xd3\x5d\xa2\x31\x9c\xc8\x28\xd5\xc5\xed\x6d\x4c\x51\x78\xfd\xec\x14\xc5\xb8\xb0\x1c\xf8\x2c\xdd\x1c\xa3\x3c\x5f\xf5\x63\xca\x7e\x4e\xea\x66\xf6\xd7\xa2\x24\x2c\xbf\x23\x77\xb4\x94\x71\xfb\x41\xc6\x69\x2b\x29\xbf\xe3\x32\xdc\xf1\xcd\x7b\xa1\xdd\x09\x08\x98\xdb\x95\x2a\x2a\x65\x64\x76\x4c\x31\xb5\x37\xf2\x35\x73\xb0\x9d\xee\xfc\xec\x28\x6e\xdf\x85\xab\x42\xec\xf3\x2c\xbb\x9d\x36\x9f\x60\xef\xd3\xe6\x13\xdf\x09\xb5\xfd\xbd\x41\x4c\x31\xba\x09\xf1\xee\x63\xb7\x72\xec\xf9\xaa\xaf\xe5\x1a\x2f\xd6\x2a\xc3\x33\x1f\x0b\x88\xcf\x9c\xf1\x01\x15\x71\xe7\xe6\x8d\x66\xe2\xba\x62\x9b\x42\x94\xb4\xdc\x92\xd4\x78\xb0\x02\x98\xd4\x7b\xd8\x0c\x1e\x38\xc3\x64\x10\x3a\x98\x55\xca\xcb\x19\x8a\xe2\xa2\xd1\x19\x58\xca\xab\xcd\x30\xd7\xe4\x9f\x01\x00\xd6\x80\xcb\xda\x3c\x05\x24\xe4\x50\xbf\x69\xd2\x8f\x28\x8c\x8b\xc9\x65\xbd\xee\xa8\xd7\xf8\x98\x88\x47\x3b\xcd\x5c\xb4\x26\x1e\x15\xa1\xc8\x45\xca\xf4\xc6\x58\x62\x38\x36\xcf\xf7\x99\x9b\x00\x5f\xe4\x39\x7b\x61\x08\xbd\xd4\x3a\xdd\x3b\xb8\xb6\x1f\x65\xaf\xc9\xa0\xda\x71\xfe\x57\x06\x6d\xb7\x07\xa2\xae\x0a\x45\x33\xaf\x81\x78\x26\x12\x9a\xb9\x5d\xb5\x57\x64\xd8\xe7\x07\x59\x0f\x5c\x12\x77\xce\x6c\x98\x48\xef\xaa\x1e\x1b\x2a\x46\xe0\x5d\xcc\x24\x46\xd3\x79\x42\x57\x41\x57\x21\xd2\x46\x65\xc9\xed\xe4\x47\xaf\x33\x7f\x25\xf5\x48\xa1\xf7\x96\xf7\x9d\x20\x55\x37\xd0\x7b\x8b\x53\xaf\xbc\x8e\xea\x4d\x5b\x54\xff\xe5\xca\xae\x6f\x38\xea\xeb\xcc\x78\xa8\xec\xb3\x7e\x62\x59\x81\xae\x6e\x46\x69\xb4\x4d\x71\x4d\x68\xa0\x89\x10\xf1\xf5\x1f\xe9\xe0\xcf\xf7\xce\x4b\xce\x33\xff\xc0\x44\x9c\x14\x83\xe3\xec\x36\xa6\xca\x4d\xda\xd4\x1e\x77\xb7\x33\x77\x25\x59\xb9\xb8\xa9\x78\x3a\x9c\xad\x9f\xed\x9d\x1f\x75\xd3\x0f\xbb\xdf\x07\xdd\xea\xa3\xef\xf2\xeb\x24\xfa\x32\xfc\xf1\x4d\xf3\x16\xfc\x91\xaf\x4a\x46\xde\xac\x69\x9e\xb3\xac\x09\xf6\xde\x1f\x61\xe8\x02\x82\x6f\x56\x88\xef\x61\xbd\xf7\x5f\xb1\x73\xe2\x97\xfd\xed\x96\x74\x3f\x1b\x34\xc8\x38\x94\xf2\xb8\x48\x65\x8d\x62\xfe\xf0\x28\xe5\x59\x35\x10\x9f\xbc\xf6\x7b\xfe\xf8\x86\x28\x5a\xde\x30\xa5\x89\x90\xbc\xda\xac\x58\xe4\x3d\xfe\x3c\x90\xb1\x9f\x4b\x0d\xfb\x7c\x65\xe6\xb8\x1d\x7f\xfe\xf3\xfb\x81\x30\x63\x6d\x7b\x7a\x2f\xca\x2c\xbd\xe7\x29\xe6\x8c\x4a\xf2\x42\x93\x7d\xf9\x7c\x31\xbf\xee\xef\x79\x7f\x9f\x48\xd2\x3f\x6d\xe3\x20\x87\x69\x13\x98\xb7\xa9\x6b\xe6\xac\x17\x00\x0e\x9f\x17\xf0\xf3\x2f\xc9\x39\xc7\x1e\x5e\xfa\xff\xd0\xf5\x59\x37\x45\x15\xd7\xde\x06\x05\x29\xea\xdb\x42\x9f\x2b\x1b\x18\x80\x2e\x5f\xab\x0a\x1d\x95\x2b\xa1\xd6\x44\xf2\x4d\x95\x29\x9a\x33\x51\xc9\x6c\x1b\xc9\x46\x8f\xbd\x35\xd7\x19\xfb\x82\xdc\x1e\x7f\x2f\xbb\x57\x9a\xf7\xf3\x0d\xcb\x59\xc9\x13\xbb\x53\x51\xbe\x36\x9b\x37\x0e\x59\xb6\x92\x8b\x9c\xa5\xaf\xdc\x65\x8d\x6d\x8f\x20\x8f\x9c\x25\x64\x45\x25\x4b\x49\x91\x55\x37\xbc\x37\xda\xf4\x77\x90\x19\x5e\xe7\xa9\xc6\xd8\x9a\xce\xe8\x89\x2b\xee\x3b\x40\x53\xef\x29\x23\x1f\xdb\xb3\xad\x53\x56\xb0\x5c\xcb\x91\xdc\x3b\x13\x61\xbb\x0b\x96\x63\xb6\x5d\x30\xc1\xbc\xb1\x92\xf5\xfc\x8b\x2a\xa9\x16\x83\x1b\x2d\xd0\x6c\xf6\x11\xbf\xd6\x16\xc6\x9c\x40\x23\x0f\x98\xc8\x47\x0e\x1a\x86\x7b\x9e\x18\x9a\x6f\x58\x8a\x7e\x4c\xe2\xbf\x9f\xa2\x8f\xb2\xdf\x1c\x20\x9b\x42\xbf\x9f\x0a\x3f\x70\x94\x5c\x12\xcf\x4c\x30\x2d\x7f\xdb\x53\xe2\x83\x94\x43\x29\xf3\x72\x3f\x23\x37\xbc\x02\xcd\x59\x1f\xc0\x7f\xfe\xe6\xf3\xe7\xaf\x33\x91\xdc\x0e\xc0\xd1\xfb\x11\xbf\xbf\xe3\x2d\x31\x1f\x0e\x01\xd2\xeb\xf1\x8e\x98\xd3\xe6\x5d\x79\x90\x50\x85\x3f\xd2\x4b\x54\x1f\x9e\x52\xe8\x13\x00\xb0\xf1\x64\xc5\xb4\x40\x28\xab\x3c\x80\x89\x35\x77\x8a\x33\x55\x54\x8e\xc0\x23\xdf\x6d\x4b\x22\x99\xc2\xec\x7c\x40\x21\xde\x30\x45\xa3\xba\x24\x2c\xfe\xc9\x68\x70\x79\x83\x92\xd6\xcd\xec\x4e\xd5\xad\x48\x13\x91\x4b\x9e\xb2\x18\x8f\x36\x85\x3d\x29\x59\x12\x91\x68\x1d\xdf\x19\x05\x47\xf7\xe9\xd3\x40\xf0\x29\xfd\xc2\xce\x5a\x19\xbe\x01\xb7\x2d\x34\x58\xaa\xad\xb6\xe0\xdc\xa0\xb1\xb0\x5d\x1d\x43\x6f\x8e\x29\xde\x24\xec\xd2\x35\x77\x1a\xd4\xf4\xe8\xf8\x4f\x6f\xce\x9b\xaf\x36\x0f\xdd\x9f\xde\x9c\x93\xb3\xe8\x66\x51\x83\xda\x54\x3a\xf7\x64\x2f\xc9\x07\x68\x53\x79\x93\xb0\xba\x15\x56\xca\xe5\xed\xa3\x81\x61\x16\xe9\x4c\x6d\x18\x0e\x1d\x2a\x9f\x35\xa8\xe6\x24\x6e\x0c\x0e\xe0\xd0\x9e\xf2\xd0\x9e\xf2\x79\xb5\xa7\x7c\x54\x89\x4c\x1e\xcc\xab\x8f\xe2\x79\x54\x97\x45\xdf\x99\x75\x79\x56\xc7\xf2\x78\xae\xaf\xd0\xb0\xb9\xfd\xa9\x0d\xda\xd2\xb6\x62\xd3\x14\x9e\x68\x89\x1f\xcc\x53\x11\xe5\x5f\x88\x30\x7c\xdb\xfd\x0f\xfb\xee\x0f\x7f\x01\x83\x64\x1f\x71\x81\x43\x3e\x90\x1b\xae\x3e\xb0\xa2\x77\xcc\x3b\x0a\x1d\xbe\xb0\xe3\xc9\xe6\x4a\x7f\x20\x24\x57\xa2\xdc\x12\xaa\x00\x49\xad\x54\x3c\xa9\x32\xda\x7f\x80\x4a\x86\x7e\xec\x25\x39\x3b\xbf\xfc\x70\xfe\xe6\xf4\xe3\xf9\xd9\x6b\x62\x7f\x85\xfb\xda\xfa\x92\x7c\x14\xb5\xe3\xbb\x97\x2a\xf5\x3a\xc2\x43\xfa\x73\x3d\xc6\x13\x23\x80\x69\x5e\xe7\x8a\x00\x5a\x60\xc0\x53\x74\x91\x73\x55\xa7\x9a\x62\x8b\xa5\x4c\xe4\x26\xed\x52\x53\x36\xfe\xf7\x1b\xae\x4e\x30\x2e\x1e\x6e\xe5\xa9\x5f\x6d\x8e\x02\x4e\x38\x26\xa0\xb9\x29\xf4\xfa\x30\x66\xd5\x20\xeb\x4d\x9c\xc3\x82\xb4\x39\x60\xc3\x3a\x46\x62\xb8\xce\xbd\x6c\xee\x3f\x9b\xb1\x6f\x57\x25\x6c\x0c\xed\x03\x0e\x12\x7d\x33\x1f\x2f\x8f\xad\x42\x98\xed\x54\x93\x04\x69\xd6\x83\xb2\x88\x93\xfa\xe5\x26\xf7\x2f\x09\xf9\x59\xad\x59\x79\xcf\x65\x44\x83\x02\xbe\x8b\x7b\xe9\xe2\x76\xfa\x07\xfc\x42\x83\xe6\xaf\x84\x09\xe7\x26\x3b\x69\xe5\x0f\xda\xe0\x6c\xdd\xf0\x3b\x96\xe3\xc2\xce\x27\xa6\xed\xd0\x06\xed\xf6\x87\x5a\x6a\x7c\xfa\xf0\x76\xbe\xc1\xa0\x8c\x18\x34\x94\x37\x62\xb3\xe1\x8a\xac\xa9\x5c\x5b\xb4\x1f\x2f\xe7\xcb\xc9\xa9\x59\x0c\x6a\x84\x00\x1a\xd0\x87\xec\xf8\x4f\xf6\x95\x1d\x03\xda\x7d\x6c\xbb\x91\x05\xe5\x0d\x58\x3e\xc3\x33\x5e\xbb\xda\x64\xb8\xb9\x3c\x41\xf7\x07\x96\xa7\x08\x24\xdf\x6f\x16\xf7\x17\x30\xc6\x8a\x33\xf7\x63\x03\x9b\x9b\xda\xd7\xde\x23\x58\x2e\xa6\xd9\x9b\x0f\x51\xb1\x8b\x42\xab\x4a\x99\xa2\x3c\x93\xde\x8e\x2b\x51\x88\x4c\xdc\xb4\x27\xad\x0e\xd8\xae\xdf\x60\x59\xd4\x82\x2e\x34\x1f\xcc\x67\x8f\x0d\xed\x59\x66\xab\xbe\xf4\x02\xd5\xb3\x74\x76\x08\x14\x58\xcd\xd7\xfb\xe9\xd1\x16\xe2\x01\x14\x58\xb7\x3a\xc1\xb5\xb0\x96\x2c\x78\x20\x6c\xcf\x17\xb8\x07\x6a\xbc\x98\x82\x95\x1b\x2e\xb5\x70\xf3\x34\xdb\x18\x73\x77\x4f\xf3\x7d\xa4\x45\x0f\x29\xb5\x5a\xc2\x85\x8a\x7f\xf7\x9b\x83\x03\xfb\x35\x84\x6b\x51\xb2\x05\xfb\xc2\x25\xd8\x00\x50\x46\x18\xa8\x28\xaa\xaf\x5a\xbf\x93\xab\x75\x48\x5a\xf7\x25\x7e\x2b\xdb\x0e\xc9\x9b\xac\x75\x41\xe7\x1f\x86\xf4\x11\x9a\x65\x5b\x6c\x5c\x00\xc0\x32\xe8\x90\xa1\x37\x41\x1c\x42\x51\x9a\x68\x4e\x51\xf2\x3b\x9e\xb1\x1b\x6d\x1f\xae\x79\x7e\xe3\x01\xe1\xd0\x2c\x13\xf7\xcc\x94\x3e\xb3\x60\xec\x6d\xb7\x7b\x90\x54\x7e\x7e\x33\x70\xf0\xfb\x9f\x3f\x92\x9c\xe1\x4f\xc9\x88\xd3\x3c\xde\x1e\xd5\x83\x09\x62\x27\x2c\x16\x0b\xf0\x76\xbd\xf8\x0f\xad\xc7\xa7\xd9\x4b\xf2\x67\x66\xc6\xa7\x0d\x1c\x7d\xb6\x13\x45\xee\xd7\x02\xfc\x17\x95\x8c\xe8\xf2\x59\x73\x00\x1c\x36\xac\x3b\x34\x14\x5e\x69\x2a\x5a\x85\xc5\xab\x1a\xd6\x2b\xad\x11\x56\xfa\x0d\x1a\x49\xea\xf8\xfa\xe3\xd9\x03\x33\x5d\x9d\x23\xef\x02\x1b\x19\x69\x3b\x55\x51\xd5\xe3\x0e\xac\x06\xc0\x4f\xe4\x76\x93\xf1\xfc\xf6\x84\x70\x65\x05\xaa\xe6\x70\x93\x2c\x9f\xdf\xc6\xe2\xea\x95\x8c\x66\xde\x7d\x34\x03\x97\xce\x76\xd7\xa8\xc1\x6e\xfb\x8f\xdb\x82\x81\xec\x70\x22\xd0\xa4\xaa\xf9\x2e\x8e\xa3\xb0\xdb\xfa\x39\xad\x04\x97\x43\xb0\x5d\x8f\x2f\xae\xde\x5c\x5d\xec\xb4\xef\xc6\xcf\x1a\xa1\xa9\x09\x89\xf3\x73\x65\xce\x0f\xb9\x6a\x61\x11\x9e\x40\x27\xe7\xbf\xf6\x99\x20\x0b\x92\x55\xfd\x7f\xc7\x94\xd2\x4b\x51\x2a\xda\x57\x40\x13\x2b\x7a\x92\x35\x2d\x4e\x2b\xb5\x3e\xe3\x32\x11\x77\x6c\xa0\x79\x6a\x91\x8b\x4d\xf8\x88\x70\xcb\x16\x48\x8b\xbc\xf9\x97\xd3\xcb\x9d\xfe\x9a\xb3\x68\x30\xfe\xc8\xaf\x98\x1c\x6c\xcb\xb6\x8f\xdb\x50\x7a\xd0\x51\x1f\x42\x87\x7f\x33\xa1\x43\x90\x20\x7f\xab\xe1\x42\x9e\x73\xc5\xa9\x12\x51\xd0\x03\x4d\x3f\x51\x25\x95\xd8\x98\x23\x75\x61\xc9\x40\xde\x0b\x84\xfe\x1a\x94\xa3\x18\xac\x6e\x0f\xc3\x41\x57\x49\x24\x77\xc8\xe2\x3b\x59\xf1\x27\x24\x67\xf7\x61\xa2\x30\x36\xee\x68\xfc\xa3\xa9\x81\x28\x40\xaa\xfe\xd3\xeb\x7f\x34\x47\x2b\xa7\x1b\xf6\x4f\xa0\x0b\x05\x49\xd6\xe8\x29\xce\x39\x66\x7a\xed\xcd\xe5\x14\x83\x81\xff\x3a\x4c\xce\x19\x67\x31\xce\xf7\x5f\x2b\x9a\xe1\x3a\xbe\x9f\xd3\xb3\xd9\xdc\x8f\x41\xc3\xb3\x3c\x62\xf7\xe1\xbd\xf5\xf6\x68\x63\x02\xf4\x0c\xf8\x46\x58\xeb\x2c\x69\x2e\xf5\xe6\x35\x23\x4f\xc7\x26\xb0\x7c\x4c\x5e\xa8\xa4\x88\xc4\x66\x7d\x80\x1a\x2a\x9c\xa6\xd9\x8b\xb7\xae\x76\x2a\x6e\x3c\xb3\x47\x59\x81\xc7\x87\x39\xe9\x1a\x13\x40\xd5\x83\xbc\xe5\x52\x61\x26\x3b\x52\x8c\x69\xf4\xc4\xb0\x5a\x46\xeb\x8f\x97\xd0\xdf\xa0\xf8\x77\x9a\xa6\xe5\x6b\xbc\x83\xaf\x8d\x1e\x57\x82\x17\x40\xc4\x37\xdf\xb7\xf9\x03\x2f\xd4\xb6\xe0\x09\x98\xfc\x1f\xdf\x5c\x02\x25\x49\xfe\xf8\x07\x84\xd4\xfa\x87\xdf\xff\xe1\xdb\x48\x16\x78\x8a\x72\xa6\x51\x5e\xb0\x41\x59\xe2\x31\x21\x91\x50\x14\x77\x36\x35\x68\x5c\x5e\x39\x28\x66\x57\x75\x7f\x76\xe4\x4b\x23\xbc\xf5\x26\xbb\xbb\x25\x38\xd9\x11\xea\xdd\x21\x07\xba\xf3\x79\xfe\x39\xd0\xc4\x95\x4b\xa2\xfc\x9a\x2a\xff\x50\xf4\x5d\x5a\xd1\x67\x44\x5b\x98\xed\xa2\x45\x5f\x43\xb4\x05\xe9\xce\x25\xfa\x02\xab\x18\xe2\xd8\x26\xa7\xa2\x34\xd1\xd6\xbd\x17\xa3\x86\x9a\xac\xb3\xf7\x57\xff\xfe\xf6\xf4\x87\xf3\xb7\xa6\x9d\x20\xff\x35\x00\xd7\xe3\xa3\x2b\x8f\xc8\x41\x8d\x67\xf7\xb0\x1f\x20\xb4\x44\x43\xa2\x96\xef\x7f\xbc\xda\x71\xac\xe8\x4f\x6c\xa8\xb2\x19\x8e\xec\x97\xa7\x1d\xa1\xca\xa9\x36\x4e\x7e\x1d\xb1\x22\x8f\xe3\x4c\x5d\x40\xc6\xff\x2c\xc5\x93\x23\xfd\xad\x36\x40\xc1\xbe\x34\x0d\x5e\xbd\x67\x38\xb6\x51\xfd\xc9\x67\xdc\x0f\xf2\xc4\x81\x37\xbd\x12\xb8\x3a\x31\xf1\xb1\x47\x0d\xb9\x3d\xc8\x2a\xc7\xa9\x3a\xe5\xd0\x4a\xdd\xe3\x2b\x78\xc7\x06\x7b\xb5\x08\xc0\x0c\xc7\x52\xdf\x1e\xfa\xde\x60\x52\xc6\x80\xd7\xed\x70\xe7\x73\xe1\xbe\x3a\x53\x0f\xaf\x88\x37\x19\xe5\xbd\x68\x5c\x3b\x87\xb1\xed\x75\xfc\xe7\x15\xba\xa2\x23\xbb\x8d\x35\x9b\x06\x11\x4a\x5a\x29\xbb\x5c\x21\x6a\x5c\x02\x00\xb9\xdd\x7f\xd4\x47\x2e\x74\xbd\x30\x0b\xbb\xe6\xf5\x47\xf8\x49\xa2\x87\xf4\x78\x42\x19\x7e\x6e\xa6\xb2\x09\x47\x6b\xd8\x61\x78\x63\x5f\xdb\x2d\x5d\xef\xd8\xaf\x18\x43\x67\x7f\x3f\x09\x95\x0e\xd4\xbe\x32\x6e\xb5\xe8\x1a\xf7\xa7\xdd\x70\xf2\xe0\x52\xff\xcf\x03\x0b\x90\x83\xcb\x75\x66\xab\xdf\xe7\x33\x2b\x8b\xb5\x50\x22\x1f\x59\x88\x75\xd9\xf2\x72\x33\xd9\x01\xbf\xf1\x06\x8b\x0f\xb3\x80\xaa\x5f\xef\x21\x66\x91\xbb\xb0\x17\x34\x8a\x36\x77\x9e\xc8\x6d\x00\x4c\x86\x03\xe7\xc6\xbf\xfb\x68\xba\x58\x7a\x71\x36\xc3\x89\xff\xfb\x81\x74\x98\x1b\x5f\x6a\xae\xe3\xae\x37\x72\x58\x37\x94\x33\xa3\xe7\xda\xba\x4a\x69\x58\x9f\xd4\xbc\xef\xf1\x77\x70\x52\x11\x35\x55\x71\x3a\x83\x28\xd5\xbd\x28\x87\x82\xcb\x5c\x36\x5e\xdb\xc9\x5f\x32\x7f\x8b\x49\x6f\x8e\x3a\xc1\x8f\x7d\x4a\x71\xdc\x4f\x76\x52\xaf\x20\x39\xc2\x5b\xd2\x96\x08\x62\x4c\xd2\x08\xda\xbb\x6d\xc7\xbb\xe7\xf8\x06\xa9\xf6\x1e\x6f\x3c\xbe\xad\xc7\x36\xd2\x72\x71\xc7\xfa\x41\x8e\xed\xa8\x5b\x3a\x00\x3a\x12\x5f\xd7\x33\x0a\x74\x64\x36\x83\xc9\x72\xf5\x88\x8e\x77\x17\x67\xc6\x99\xa4\xf7\xb3\x16\x60\xd4\x89\x81\xe0\xd4\xa3\x2a\x1d\xe2\x04\x16\xf6\xef\xef\x3f\xc3\x2d\x8d\xa8\xae\x45\x09\x08\x1f\x1c\x41\x3f\x6a\xa4\x7e\x03\xf9\x71\x62\x1a\x18\x6e\x68\x21\xfb\xaf\x29\x2d\xaa\xfc\x4e\x56\x8f\x25\x96\xcc\x80\x67\x90\x4a\x63\xfb\xc8\xbd\xeb\x6e\x1e\xb7\xdf\x1c\x2e\xac\xdb\x47\xf4\x6a\xd9\x6f\x05\x17\x65\x9c\xdb\x56\x71\xd1\xad\xe0\x82\x54\x83\x6d\x5a\x76\x1b\xb0\x04\x29\xf6\x35\x68\xe9\x6a\xbd\x12\x21\xf3\xfd\xd6\x2c\x4f\x12\x09\x35\x6c\x3a\x88\xb1\x6c\x83\x38\x9b\x75\x8f\x67\x3c\xa2\xfb\xcd\xc3\xb6\x7e\xbb\x74\xe3\xc0\xdd\x35\x20\x46\x4e\x04\x11\x9a\x89\x28\x64\x7d\x8f\x5d\xbc\x2e\x9c\x26\xd1\x68\x5b\x44\x84\x83\x06\xf5\xdc\x18\xd6\x12\x23\xb1\xbd\xf1\x47\x74\x50\xf1\x61\xa2\x5c\x47\xcd\x9a\x22\x89\x02\x5d\x31\x33\x14\x76\x61\xa3\x5e\x18\xdc\x84\x64\x78\x9f\x90\x48\x96\xb1\x4f\xf3\xd2\x69\x28\x30\x27\x84\xd1\x64\x4d\x6e\xd9\x76\x01\xb2\x2e\x9a\x26\x21\x05\x85\x1a\x4d\x58\xd7\x33\xaa\x9a\x8d\xef\x6a\x47\x5b\x6c\x4f\x27\xfd\xbc\x71\xdb\x63\xeb\x09\x6b\x8e\x76\xd5\xa0\x91\xb5\x89\xf5\x43\xa5\xd1\x31\xc9\xfd\x5a\x48\xe3\x4e\x32\xae\xa5\x5b\xb6\x05\xb1\x96\x88\x3c\xca\xba\xa9\x1f\x43\x00\x56\x0d\xf2\x9c\x76\xea\x16\xb5\xe4\x60\xa9\xfe\x81\xd8\x46\x59\x04\xce\x63\xe7\xbc\xeb\xb4\x28\x7d\x89\x04\x54\x81\x9d\x15\x80\xa0\x9b\x37\x22\xfc\x1d\x40\x1a\x85\x0c\x35\xc9\xf2\xb8\x0c\x72\x8f\x26\xac\x5d\x33\x5d\x0b\x60\xd9\xb9\x34\x7d\xef\x81\xea\x90\x15\x45\x5e\x72\x4c\xd0\xa8\xff\x94\x4c\x55\x45\x5c\x6a\x56\xfd\x40\xce\x9d\x9e\x39\x93\x92\x20\xf8\xfb\x86\x96\xb7\x2c\x75\x4d\x6d\x96\xd0\x5b\x6b\xc8\x0e\x59\xbc\x56\xdb\x88\x0a\x0d\x44\xba\xf5\x8b\x71\x07\xb4\x7e\xd4\xcf\xf1\x72\x89\x1d\xb3\xda\x8a\x74\xa3\xe9\xc4\xdf\x38\xf5\x33\x50\x90\xec\x6a\x5d\xb4\x80\x3a\x02\xd0\x8b\x81\x1d\xc0\xa9\x1e\xd5\xa3\xd3\x7f\x4c\xb0\x97\x46\x3b\x5f\xeb\x67\xb0\xb0\xc5\x67\x58\xdf\x27\x7c\x16\x7a\x86\x83\xbe\x3f\x70\x21\x86\xdf\x03\xf8\xdc\xb2\xa0\xd9\xb8\xfb\x34\x93\x06\x8d\x1c\xac\xef\xb9\x21\x3b\x40\xc6\xf5\x78\xc2\x27\xbe\x39\x63\xc7\xd8\x3b\xda\x34\x0e\x24\x49\xfc\xb6\x8e\xed\x0d\x1b\x07\x53\x6c\x6f\xf0\xb8\xd3\xba\x71\x30\xd5\xfe\x56\x8f\xd8\xc4\x71\x30\xd1\x98\xa6\x8f\x83\x89\x86\x1b\x51\x0f\x26\x19\x61\x8d\x0c\x1f\xe6\xe8\xc6\x91\xf5\x33\xae\x0b\x16\x3e\x43\x9b\x49\xd6\x4f\x7c\x5b\xc9\xfa\xd9\x3b\xf7\xee\x16\x2b\xea\x02\xb3\xc1\x6b\x68\x3b\x4a\x6e\x68\xe1\x94\x2a\x25\x96\xe4\x9d\xb9\x15\x47\x6c\x0b\xcd\xeb\x0e\x93\xa6\xb4\xac\x79\xc5\x8e\x3a\x39\x30\x49\x96\xb1\x0d\xcb\x95\x81\xc0\xb0\x64\xe1\xda\x1d\x4c\xd4\x21\x48\x98\x3b\x70\xd8\x8d\x6d\x06\x36\x5c\x78\xc6\x26\x12\xe2\x33\x2c\x9d\x70\xc0\xe8\x9f\x20\xf1\x10\x9f\xf8\xf4\xc3\x01\x44\x21\x51\x31\x3a\x09\x11\x9f\x11\x7b\x67\x35\xcf\x49\xdd\x0d\xb7\xae\xa2\xa9\xa1\x31\x0f\x98\xad\x28\x89\x16\x77\x60\x0c\xd8\xab\xce\xb4\x45\x1a\x38\xfb\x18\x17\xaf\x99\x48\xdd\xb0\x7e\x36\x8b\xde\xa3\x19\x39\x6e\x6d\xf9\xff\xad\xd9\xf4\xe0\x48\x86\xa2\x5e\xeb\xb0\x3a\xab\xd7\x25\x12\x57\xbe\x7e\xb4\x3c\x7f\xc6\x66\xc7\xde\xd4\x7e\xd4\xf7\x4f\x64\x0a\xd0\xde\x50\x1a\x70\xe2\xc6\x69\x5c\x2b\x2a\x35\x04\xf9\x20\xaa\x36\xb1\x04\x24\xd2\x73\x35\x67\x1e\xc9\x3c\xb9\x1e\xd4\x06\xb9\x7e\xba\xba\x6e\xd6\xad\x91\x87\xae\x2e\x3e\xc2\x26\x5f\xa7\xaf\xb1\x37\x32\xcd\x73\xa1\x80\x03\xe4\x09\xc9\xe8\x8a\x65\x83\x9c\x2b\xf8\x80\x53\x49\xab\xa4\x5e\x82\x51\xc9\x06\x77\x30\xae\x9f\x91\xac\x40\x46\xb2\x03\x01\x96\x80\x15\xbd\x1c\x6a\xbf\x8f\xe7\x0d\xfd\xd4\xb7\xf5\xf0\x77\x77\x83\x82\x48\xc7\x6e\xb1\x4c\xd6\x6c\x13\xeb\xe5\x6d\x3e\x00\x4e\x6e\x17\x43\x4b\xd6\xfb\x92\x2b\xc5\x10\x11\x95\x95\x9b\x61\x42\xc6\x3e\xe2\x7a\xa7\x7d\xf0\xdd\x77\x47\xc3\xcd\xb5\x09\xf6\x36\xb1\xe7\x31\x04\x07\xd3\xf5\x34\xa3\x10\x1e\x28\x05\x3a\x7f\x47\x58\xde\x04\x52\x66\x33\xe8\xa4\x90\xef\x38\x3a\x4f\x2f\x2f\xc8\x1d\xee\xe9\xa3\x2e\xd3\xc1\x2d\x31\xf0\x39\xb8\x25\x0e\x6e\x09\xf3\x4c\x76\x4b\x78\x57\xbd\x15\xbe\xa3\xbc\x12\x4d\xd7\x86\x8f\x18\x6c\xfc\x15\x23\xce\x8e\x4d\x2a\xf0\xf0\x37\xf5\x59\xb4\x9e\x8a\x41\x0d\xf6\xf1\xf1\x21\x2d\x8f\x8f\x97\xcb\xe3\x63\xeb\xef\x30\x07\xbd\x52\xd7\x8b\x3f\x0e\x26\xcb\xf2\x44\xa4\xcc\x74\xcf\xbd\xe6\xa5\x54\xa0\x74\xd7\x86\x3f\xae\xcd\x60\xba\xb0\x96\x1b\x3b\x77\x3f\x56\x01\x63\x1f\xc7\xa2\x23\x24\xb4\xcd\x92\xf9\x71\x16\xe5\xb2\x56\x29\x1d\xb8\x4d\x44\xb1\xc5\xee\xd3\xc0\x25\x33\xba\x65\x9d\xcd\x83\x9d\x90\x47\x38\xc2\x52\xd0\xe7\x98\x54\x92\xbc\x40\x22\xcb\xa4\xa8\x4e\x0c\xc1\x25\x36\x5a\x1e\x2e\xb5\x2c\x51\x4d\xac\xf1\x2b\x86\xe2\xcb\xe1\x43\x2d\x19\x49\xaa\xb2\x64\xb9\xca\xb6\x5f\x9b\xe6\x1b\xd5\x70\x63\xff\x99\xa2\xf8\x3a\x5e\x89\x29\x91\x68\x7b\x76\xca\x26\x1c\x18\x33\xb8\x07\xe3\x9b\x9a\xb7\x3d\xd7\x0e\x54\x5f\x9e\x38\x97\x15\x7c\xca\xf2\xbb\x51\x14\xef\x68\x19\x2c\x6a\x68\x7b\x26\xe9\xba\x29\xbf\xe3\x52\x04\x8b\xb1\x5a\x5f\xdd\xf7\xba\x71\x03\x6e\x2d\x2a\x55\x54\xc3\x9d\xc5\xc4\xdd\xab\x56\x0c\xdb\x6e\x2b\x4e\x4a\x0c\x3f\xc6\xa4\xce\x9a\x43\x93\xe2\xbb\x30\x2e\xce\xfe\xf3\x6c\xfb\x94\xb7\x3d\x51\xbd\xcb\xdb\x9e\x61\xfd\xcc\xfb\x28\x8c\x64\xc7\x09\x7d\xcf\xbb\x1e\xcb\x3a\xd3\xe5\x47\xad\x76\x8d\x94\x85\xf8\x00\x3a\xa6\xbe\x4e\x1f\xe1\xb0\x63\x86\xec\x6c\xbe\x64\xd3\xb4\xef\x90\x1a\xf6\x0c\x53\xc3\x0c\x0a\xc8\x21\x2f\xec\xef\x36\x2f\xec\xca\x74\xc3\x6c\x4d\x0a\xc3\x54\xaf\x01\x44\x23\x92\xc2\xc0\xce\x19\x40\x32\x22\x29\x0c\x02\xc4\x83\x0e\xd2\x21\x29\xec\x90\x14\x76\x48\x0a\x1b\x36\xf6\x83\xf7\xf5\xe0\x7d\x3d\x78\x5f\xa3\x9f\x43\x52\xd8\x21\x29\xec\x90\x14\xd6\xfe\x7c\xbd\x49\x61\xc6\x60\x1a\xa4\x14\x9b\x8c\xb0\x47\x4b\x08\x33\x2d\xbd\x4f\x93\x44\x54\xb9\xfa\x28\x6e\x59\x64\x0e\x40\x94\x31\xbf\x47\x3b\x72\x1e\x8f\x92\x20\x36\x4c\xd9\x1c\xa0\x36\x0e\x57\x18\x69\x95\x72\x6d\x8e\x8f\x64\xbe\x53\xf3\xba\xb5\x7c\xf5\x95\x97\xa7\x2c\x75\x74\x07\x30\xa0\x11\x41\x4a\xef\xd6\x92\x9c\x92\x92\x25\xbc\xe0\x5a\x30\x03\xfc\x0f\x7c\x3e\xd4\x2c\x73\x3d\x3e\xb9\x92\x2c\xbb\x36\xfd\x0f\x73\xaf\x91\x78\xad\x7b\x0d\xb7\x4a\xed\x24\x1b\x43\x47\x3d\x44\xd8\xb6\x77\x03\xa8\x9a\x1e\xee\x25\xfb\x0f\xab\x1a\x99\xb5\xf8\xe8\xff\x56\x1a\x8b\x90\x56\x3f\xc6\x59\xe0\x4d\xda\x0c\x98\x16\x3c\x16\xcb\xce\xd1\x1a\x2e\xe0\xd8\x97\x82\x97\x70\x44\xaf\x58\x22\xf2\x74\xac\x8b\xea\x7c\x97\x8e\xe5\x3a\x13\xbd\x1a\xb4\x85\x69\x85\xa4\xa0\xc0\x97\x66\x3c\xe5\x6a\xeb\x72\x87\x50\x7c\x10\x8a\xf2\x63\xd0\x4a\x23\xf3\xca\x7a\xfb\x08\x2d\x8a\x52\xd0\x64\xcd\xa4\xb7\x12\x43\xee\x21\xd0\xa0\x10\x7a\xc4\xd5\x22\x67\xd5\x0d\xcf\x51\xcb\x07\xea\x5a\x65\x8b\x00\x7b\xa8\x9f\x52\x28\x9b\xec\xb8\x33\x5d\x9f\xeb\xcc\xcf\x0e\x75\x56\xa1\xcb\x42\x95\x5b\x80\xd6\x12\xfe\x8f\xe1\x9a\x44\x00\xe4\x34\xe7\x6f\x5e\x93\x44\x64\xa9\xc5\x4b\xfd\xe3\xb7\xa4\x60\x65\x62\x24\xc4\xb0\x00\x2b\xe0\x65\x2a\x41\x32\xad\xea\x8a\xd2\xa2\xb2\xb6\xfc\xcc\x00\xa2\xbf\xff\x9e\xac\x45\x55\xca\xa5\x0f\xce\xf1\x1d\x7c\x86\x4e\x21\xbc\x5a\x87\x38\xd4\x14\xc9\x18\x95\x8a\x7c\xf7\x2d\xd9\xf0\xbc\xd2\x1a\xd5\xc0\xa3\x3a\xd4\x0a\xf1\xec\x8f\x3f\x7c\x1f\xf9\xd6\x30\xcb\x63\x3f\x8f\xcc\x9c\xe3\x02\xbb\x8e\x19\x03\x64\x90\xd1\x0e\x6d\x11\x80\x7b\xb1\x97\x60\x33\xdb\xc3\x5e\xe7\x03\x8d\x19\xc3\x0d\xb9\x12\x33\xcb\xc7\x5f\x2b\xb1\xda\xaa\x78\x60\xa3\x7f\xc5\xef\x37\x11\x8d\xec\x87\x7b\x08\xb2\xbd\x63\xdd\x6f\x76\x59\x03\xc8\xf6\xbc\x38\x73\x67\xdd\x1b\x2e\x55\x6f\xe3\xd6\x45\xd8\xa5\x1f\xab\xec\xdc\x94\xa2\x0a\xa2\x08\x34\x96\x1b\xfc\x09\xd6\x7e\x35\x12\x97\x26\x09\x93\x70\xa0\xcf\x5c\x07\xfb\x20\x53\xe4\x02\x7f\x3d\xf0\xc5\x27\x04\x8e\xb7\x4c\x14\x19\x40\x79\x48\x20\xd7\xa8\x45\x8a\xb1\x2f\x2c\x7b\x0d\x5c\x25\x7c\xa9\x79\xc6\x24\xcf\x6f\xa0\xd5\x21\xd9\x54\x99\xe2\x45\x44\x6d\x84\x5d\x51\x47\xd0\x5c\xaf\x7e\x50\x84\x7a\x5e\x72\x1a\x5e\x22\x7d\xa8\x11\x3c\x1c\x82\x6b\x2f\xec\x58\x08\xcb\x15\x80\xd0\x40\xb6\x39\x2b\x68\x49\xed\xb6\x04\x69\x26\x62\xb3\xa1\xf2\xa5\x89\xcf\x50\xc8\x80\x42\x29\xac\x2f\xd4\x92\x66\x6e\x19\xfd\x7c\x90\xb9\x18\x59\xb1\x9c\xe6\xc1\xe0\x6d\xd3\x39\x05\xaf\x10\x71\x9f\xdb\x36\x38\xd8\xb9\x79\x20\x07\x1b\xd5\xfd\x07\x9a\xdc\xb2\x3c\x25\x9f\xa4\xe5\xe3\x74\x9b\xd3\x8d\x81\x55\x77\x8d\xd5\x59\x6a\xe9\x07\x09\xbb\x8c\x19\xc4\x0d\x42\x44\x1f\x0b\x62\x86\xfa\xda\x5c\xab\x57\xc9\x81\x18\xc3\x9f\xa4\x56\x66\xfa\xe5\x59\x94\x97\x5c\xb2\x92\xdf\x25\xcc\x6a\x8a\x7a\x20\x73\x4d\xea\x2e\x88\xf5\xb7\x37\x2d\x83\xf3\xc7\xbd\xd3\x04\xd7\x9b\x0b\x32\x03\xca\x3a\xcd\xb4\x88\x0a\xeb\xc6\x16\x33\xaa\xc9\x50\x7a\x07\x67\x6b\x0e\x5e\xae\xe2\x01\xc2\x8e\x3f\xfc\x70\xd6\x14\x46\x1f\x68\x2a\x24\xf9\x21\x13\xc9\x2d\x39\x63\xa0\xb2\x87\xbb\xea\xef\x22\xcb\x47\x35\xba\xee\xa5\x18\x6a\xb6\x57\xae\xd2\xa7\x68\xb5\xb7\xa1\x37\x7d\x87\x74\x41\x36\x22\xe7\x4a\x94\x73\x40\x95\x1d\x1a\xbb\xfd\xcd\x34\x76\x2b\x57\x61\xaf\xc1\xd7\xda\xd6\x4d\x1f\x89\x81\x1d\x50\xd7\x8c\x94\x20\x66\xe0\x65\xdb\xcb\x23\xbe\xd3\x66\xe3\xf0\xff\x66\x2d\xee\x17\x4a\x2c\x2a\xc9\x16\x3c\x98\x13\x16\x3d\xaf\x5b\xb6\x85\xa4\xb9\x41\x33\xfb\x09\x5f\x6a\x98\x9a\x4a\x80\xc7\x1b\x3e\xd7\x4a\xce\x87\x1f\xce\xf4\x4d\x19\x8f\x68\xcd\x25\x79\xc5\x54\xf2\x2a\x61\xc5\xfa\x95\x19\xd6\xb3\x5b\x2e\x2b\xf7\x86\xad\xd7\x29\x49\x44\x96\x19\x9c\x39\x71\x4d\xde\xb0\x62\xed\x48\x0d\x0a\x0f\x3d\xf8\x1a\x3c\x45\x0b\xaf\x42\x88\x61\x6d\x85\xbc\xa3\xa5\xdf\x35\x27\xcb\x63\xa4\x72\x95\xce\xda\xd3\xff\x31\x58\xeb\x01\xba\x8a\x44\xe3\xd6\x76\x41\xd3\xb6\x74\x32\x7b\x56\xdc\xfa\x70\x1d\xd3\x8e\xaf\xec\x6b\x90\x6f\xe7\x85\x75\x07\x35\x40\xb3\x3f\xdf\x10\x89\xe4\xe2\x1a\xad\xa2\x94\xa5\x44\xdc\xb1\xb2\xe4\x29\x93\x56\x14\x0f\x92\x98\x39\xcf\x1e\x57\x46\x1e\x7a\xb9\x75\x3e\x5f\x47\x2f\xb7\xc1\xf6\xae\x27\x6c\xf5\xbb\xfb\xc2\x96\xa6\x1b\x1e\x51\x56\xfc\x8c\x6e\x72\x99\xd0\x8c\x5d\xfc\x1c\x6d\x3e\x5e\xe1\xf7\x9b\x16\xa4\xfd\xd0\x6b\x59\x31\x01\x0e\xff\x27\xc7\xa7\x24\x17\x69\x7f\x64\x62\x56\x5b\xef\x86\x2a\x76\xdf\x7b\xe5\x2f\x6a\x11\xda\xff\xad\x50\x63\x89\x43\xf3\x8b\x5d\x03\xce\x3b\x45\x88\xab\x3f\x97\x32\x61\x76\x75\x98\x53\xd0\x4e\xb1\xee\x93\x85\x09\x30\x86\xd1\x4f\x2f\x2f\xc8\x9f\x90\xee\x7c\x5d\x36\x4a\xa1\x50\x2f\x3e\x13\x1b\xca\x07\x36\x69\xf6\x5a\x1a\xf9\x03\xbd\x74\x44\x09\x52\x0d\x6e\x8b\xd7\x79\xfa\x9a\xdf\x54\xda\x8e\x36\xb6\xed\xa1\x31\x41\x60\xea\x0f\xa7\x82\xd5\x1a\x98\xe7\x83\xb4\xb5\x1a\x4e\xab\x0a\x4e\xdd\x72\x05\x5c\x5e\x2e\x9d\x84\x48\x96\x4b\x0e\xb1\x51\x2f\xed\x09\x54\x33\xb5\x8e\x88\x46\xb9\x22\x0c\x54\xe3\x4e\xc8\x5b\x71\xc3\x73\x2b\x1d\x84\x49\x27\xb8\xa6\x3c\x8b\x5b\xc6\x83\x5e\xd5\xf9\x7c\x1d\x7a\x95\x94\xd9\x79\x4e\x57\x59\x38\x13\xad\x79\x71\x65\x14\xb2\x3a\x18\xbc\xfb\x2a\xe5\x52\xff\x97\x5c\x5d\xbd\x85\xa8\x52\x95\xc7\xda\x19\x10\x77\x31\xe2\xd9\x81\xe3\xa0\xd0\x98\xef\x1c\xa3\x4c\x1c\xdc\x55\xe2\x22\x4f\xf5\x34\x98\x6c\x24\x56\x1a\x6a\xd8\xb7\x23\x36\xe4\x64\xf2\xba\x56\x8c\x7c\x5c\xf3\xe4\xf6\xd2\x0b\x2e\x89\x52\x7f\x96\x7b\x1f\xb9\x0b\x36\xe6\x38\xef\xbe\x3b\x97\xe0\x37\xd3\xbc\x1c\xea\xe4\xf8\xe8\xdd\x68\x57\x66\xa9\x34\x11\x42\xa5\x14\x09\x8f\x8f\x4e\x82\x8b\xae\xbe\x12\x53\xb8\x12\xe7\x9b\x1e\x68\x41\x93\xee\x6d\xcb\x08\x46\x81\xa3\xd2\xbb\x87\x63\x62\x90\x66\x95\x66\x9b\x12\xb2\xe2\xe0\x7e\x8b\x1f\x1b\x1d\x16\x6d\x68\x10\x03\x66\x2e\x20\x16\xd9\xde\xc4\x6e\xbc\xd5\x69\x4d\x03\xdd\x9d\xad\xf7\x3b\x2d\x86\x4f\x0e\x94\x22\xcf\xb2\x48\xe1\x72\xe1\x36\x5f\xca\x4e\x36\x00\x7e\x66\xc2\x68\x70\xa8\x0b\x51\x54\x19\x0d\x84\x87\xfd\xe6\x92\x53\xe3\x15\x38\x86\x19\xc2\x6a\x0f\xdd\x96\xa7\xa3\x10\x6b\xa7\x43\x4f\x58\xcd\xdd\xed\xe0\x13\xd3\xa1\x27\xd6\x1d\x05\x03\xfa\xf6\x0f\xdf\x7f\xdf\xd6\xd3\xa7\xd1\xb3\x27\xac\xbb\x44\xf6\xf4\xd9\x29\xa8\x8a\xbb\x23\x7b\x7b\xfa\xec\xf6\xec\x09\x2f\x69\x44\x4f\x9f\x81\x05\x50\x0f\xd3\xb4\x27\xca\x69\x3f\xa0\x8a\xdd\xd6\xa6\x47\x89\xb3\xbe\xda\xf5\xce\x8a\xf4\x08\xd1\xdf\xa8\x58\x8f\xa9\x43\x8f\x08\x24\x42\x9d\xfa\xac\xd5\xe7\x03\x6a\xce\x1b\x95\xe4\x41\xc2\x7d\x95\xe6\x9d\xf5\xe3\xf1\xa6\x0d\xd0\x8a\xaa\x1a\x0f\xd2\x8c\x6e\x20\x12\x9d\xd7\x1b\x55\x21\xde\xac\xfb\x8e\x93\x0f\x31\x55\x66\x0f\xdb\x94\xaa\xa7\xf2\xdb\x55\x73\x47\x98\x2e\xb1\xf5\xde\x83\x4a\x6e\xe2\xcb\x6d\xe2\x2a\xba\x23\x0b\x72\x86\x15\xe3\x44\xd7\x6c\xcf\x52\xa9\x3d\xb0\x8a\x23\xbe\x2a\x7b\x88\x0a\x10\xe5\xb4\xc0\xa7\xb5\x02\xbb\xa3\xa2\x3a\x92\x64\xb3\xee\x3a\x50\x47\x1d\x49\x13\xaa\xad\xa3\xaa\xa7\xed\x65\x1e\x49\x38\x70\xe5\x37\xae\xf4\x68\x92\x73\x5c\xfc\x86\xd6\xe0\x4a\x83\xa1\x55\xce\xf1\x15\x06\x51\x15\xcd\x03\x61\x20\xbb\xeb\x98\xf7\xeb\x92\x23\x49\xbe\x6b\x11\xff\xdd\xd5\xc8\x91\x44\x3d\xa8\x90\x51\x35\xc8\xd1\x62\x21\xb6\x66\x35\xbe\x52\xd5\x75\x24\x08\x0e\x74\x58\x81\xea\x50\x8f\xef\x60\x13\xba\xe1\x7f\x34\x16\xa2\xdd\x4f\xcc\xb0\x74\xa8\xe0\xe1\x6b\x0d\x64\xe3\x23\xd8\x88\x24\xda\x6c\x46\xd2\xa2\xf7\x0e\x6b\xee\x32\xbe\xf1\xf3\xd5\x4e\xe8\xd1\x7d\x6c\x35\x5f\x13\x55\xec\x0f\x3d\x3e\x78\xc4\xf1\x10\xe0\xfb\x5a\xba\xdb\x1f\xa2\x51\xe3\xa3\x51\xb2\x81\x61\x69\xfd\x58\xa8\x89\xc5\x04\xa4\xc4\xca\x74\xc2\x40\xa1\xed\xce\xf2\xe9\xe5\x05\x49\x4a\x06\x85\xc5\x34\x93\x4b\x32\x02\xd1\xc6\xfa\xfd\x41\xa7\x93\xce\xf2\xa4\x4a\xb1\x4d\xa1\x62\x19\xe8\x10\x8c\xea\x7c\xbe\x8e\x60\xd4\x48\x0f\xf6\x67\xf7\x9a\xf5\x7f\xac\xab\x0d\xcd\x17\xfa\x94\x43\x58\xca\xb8\xb7\xe3\x5c\xd8\x3b\x97\xd4\x92\xd8\x1a\x13\x58\x6d\xa8\xb3\x82\x52\x37\x6c\x3c\x1f\x65\x9c\x03\x8e\x99\x53\x01\x1e\xc0\xe1\x0f\x74\x47\xae\x19\x36\x2b\xd9\x91\x0e\x89\x28\xa2\x57\xcc\x5c\xe6\x66\xa2\x6e\xfd\xac\x20\xf0\x3a\xa2\xf8\x5e\x9d\x18\xd2\xa8\x42\x5d\x42\x81\x6a\x4d\xa5\x81\x6b\x65\x80\xaa\x68\x96\x89\xfb\x88\x42\xc3\x35\x6b\x28\x10\x9a\x2f\xf4\x5c\x4d\x8d\xfa\x8a\x91\x0d\x2f\x4b\x51\x9a\x40\x45\x84\x9b\xb0\x66\x17\x48\xc6\xd0\x16\x1f\x2b\xd1\x0c\x2a\x4d\x6c\xfe\x8a\x29\x6f\xb9\x63\x14\x40\x9a\x63\xc1\x91\xfe\xb7\x4d\xb4\xc4\x6e\x57\x46\x4e\xae\xd8\x9a\xde\x71\x51\x95\x40\x3d\x86\xe4\x91\x79\x55\x5f\xdd\x64\x2b\x2a\xd7\x84\xbe\x82\xda\x03\xb7\xba\xd1\xdd\xec\xbd\x7d\x7e\x5f\xbf\x0c\x46\x6a\x2a\xac\x27\x6e\xc1\xbe\x70\xa9\x86\xaf\xa5\xdd\x62\x0b\xb7\x3f\xc7\x89\xb9\x93\x85\xbe\xc0\x3f\x07\x6b\xcc\x9a\xe7\xc4\x7f\xab\xa9\xce\xde\x5d\xc1\x9f\xa6\x28\xb3\x06\x5b\x41\xa2\x0a\x67\x8a\x3f\xa6\x2b\xb4\x71\x29\x74\x38\xee\x40\xb7\x9f\x83\x6e\xfc\xb5\xe8\xc6\x2e\x60\x9f\xf1\x64\x7b\x71\x36\x4c\x4b\x74\x81\x7a\xfd\x32\xf9\x81\x4a\x96\x92\x77\x34\xa7\x37\xe8\x88\x78\x71\x75\xf9\xc3\xbb\x70\x47\x80\xa2\x14\xe0\x54\xb9\x38\x6b\x09\xf9\xba\xab\x15\x7f\xe4\xfd\x5c\x05\x95\x7b\x73\x1f\xac\x3f\xcc\x3c\xfb\xd9\x4a\x45\x89\xbb\xe3\x63\xda\x35\xed\x43\x6a\x60\xf8\xdd\x22\xfe\xc8\x5d\x81\x75\xb7\x49\x6f\xc7\x0f\x93\xe7\x52\xd1\x2c\xbb\xcc\x68\x7e\x5a\x14\xa5\xb8\x6b\xf3\x04\x35\x81\xa2\xcc\xd7\xac\x92\x86\x99\x6d\xf6\xc3\x02\x17\x1f\xb2\x6a\x72\x72\x51\x53\xdf\x5f\xca\x9e\x51\xb5\x6b\xec\x3d\x2f\x74\xa1\xa7\x07\x5f\xe9\x51\xbb\xfa\xde\x55\xb4\xd4\x82\xe8\xcd\xd5\xe7\xe8\xf7\xa4\xa2\xaa\xda\x11\xbf\x9d\x17\x41\xbb\xe8\x5f\x90\x8c\x4a\xf5\xa9\x48\xf7\xe2\xed\xdd\xf2\x3d\xa1\x8a\x66\xe2\xe6\x5f\x18\xcd\xda\x98\xaf\xb1\xb5\x6f\xfc\xef\x5a\x7f\x26\xee\xf2\x55\xb5\x72\x5f\x3c\x96\x44\xdb\x34\xdd\x50\x3d\x25\xcb\xd8\x1d\xcd\x95\x25\x78\x85\x6d\x11\x8e\xcd\x1a\x2c\xc9\x05\xc4\xe0\xb4\xe6\xa7\x65\x6e\xca\x14\x2b\x37\x3c\x6f\xfe\xca\x15\x7c\xf7\x8d\xc8\x53\xde\xe5\x5f\x07\x7f\x30\xd2\x68\xfe\x52\x17\xb3\xb5\xc7\xcc\x3a\xa3\x64\x4d\xf1\xe2\x8d\xad\xb9\x50\xf8\xb5\x95\x51\xba\xd7\xf8\xa1\xb8\xee\x08\x93\x35\x46\xba\xb7\xb6\xe4\x36\x17\xf7\x12\x01\xf0\xda\xa4\x4f\x40\x75\xe8\x53\x19\x16\x96\x17\xf0\xa7\xdb\x13\xea\x17\x66\xfc\x6d\x6e\x94\x6e\xf6\xc3\x27\xa4\x64\xec\xfe\x7c\x97\x28\x6c\xe3\x49\xf7\x12\x62\x04\xb8\x00\x3e\x06\x27\x1b\x5f\xea\x12\xda\x11\x5a\x57\x8c\x9a\x14\xd7\xe8\xb0\x29\x32\xeb\x06\x78\x7b\x1e\x85\xa0\x9a\x18\xb8\x5d\xa2\xfa\x00\x36\x3d\x1b\x17\x26\xa7\xb9\x34\xf6\x12\x25\x05\x67\x88\x7d\x47\x73\xb3\x40\x70\x31\x30\xda\xaf\x06\xe3\x0b\xfa\x62\xd2\xd6\x34\xbc\x77\x62\xd2\x65\x30\x5e\x61\x52\xab\x6c\x64\x84\x22\x3e\x5b\x2f\xcd\xff\x7d\xf5\xf3\xfb\x57\x7f\x12\x26\x5f\xc3\x60\x5b\x68\xb9\x01\x97\xf8\x09\x91\x55\xb2\x26\x54\xea\x29\x69\x46\xd7\x52\x82\x2d\x37\x34\xe7\xd7\x4c\xaa\xa5\x6b\xc6\x23\x7f\xf9\xfd\x5f\xfa\x6f\xef\x1f\x45\x49\x4c\x09\xd0\x89\x05\x0d\x33\x73\xaf\xb9\x8b\x4b\x5c\x20\x47\xb7\x97\xa4\x73\x12\x14\x22\x35\x0b\x71\x0f\x0b\xa0\xe8\x2d\xc4\x49\x6d\xb8\x33\xe3\xb7\xec\x35\x39\xd2\xda\xa3\x37\xe4\xff\xd4\xd7\xde\x7f\xf7\xd7\xcd\xbf\xb8\x87\xbb\xff\x48\x7f\xf5\x08\x07\xea\xd2\xd2\xfd\xac\x46\x47\x15\xd4\x87\x5e\x92\xaa\xe4\x37\x37\x0c\xf4\xdf\x35\x23\x50\x0f\xff\xd2\x00\xa9\xe5\xc2\x23\x64\x13\x5a\xe2\x6c\xff\xdd\xc9\xfd\xf2\xfb\xbf\x1c\x91\x17\x35\x35\x50\x27\x79\x9e\xb2\x2f\xe4\xf7\x18\x65\xe1\x52\xaf\xdb\xcb\xfe\x5d\x03\x37\x81\xdc\xe6\x8a\x7e\xd1\x63\x49\xd6\x42\xb2\x1c\x3d\x39\x4a\x90\x35\xbd\x63\x44\x8a\x0d\x23\xf7\x2c\xcb\x16\x26\xae\x44\xfa\x2b\x8c\x80\x8f\xed\x96\x03\x8e\x0f\x29\x68\xa9\x1a\xc7\x61\x69\x5c\x6f\x30\x4a\xcd\x7a\x37\xfd\x76\xb0\xc9\x62\xb9\xe6\x39\xcd\x4c\x72\x16\xa0\x8f\x6b\x9e\x06\x8c\x06\x64\x34\x25\x48\xb2\xa6\xf9\x0d\x33\x71\xa6\x7e\xdb\xac\x52\x55\xc9\x7a\xe3\xb8\x51\x12\xe3\x96\xe7\x03\xb0\x4b\x7e\xe2\xf9\x6e\xda\x54\xbb\x1b\xf4\x86\x2b\x5b\x49\x67\x72\xc7\xd5\xf6\x95\xde\xef\x92\xaf\x2a\x25\x4a\xf9\x2a\x65\x77\x2c\x7b\x25\xf9\xcd\x82\x96\xc9\x9a\x2b\x96\xe8\x09\xbd\xa2\x05\x5f\x24\x22\xd7\x7c\x07\x80\x53\x9b\xf4\x37\x7a\x1e\x72\xa1\x07\xda\xdb\x6c\x2a\x6a\xba\x21\xef\xef\x93\x7a\x7d\x67\x99\x5d\xd0\x6d\xb8\x3f\x45\x74\xc1\x3d\xc2\x3c\xc1\x9f\xf4\x6a\xf2\x34\x6d\x2f\xa3\xa1\x37\xef\xb1\x69\xf9\x95\xec\x52\xd0\x47\x0f\x01\xb3\xe0\x64\x3a\x89\x1f\x3a\xd5\x1b\x9a\xe2\x75\x41\xf3\xed\x83\x1f\x03\xbd\xd0\xd0\x89\x2f\xd9\x2e\x80\x84\xc8\x16\x34\x4f\xf5\xbf\xb1\xe8\x33\xd9\x4e\x5e\xd9\x8a\x0f\x10\x06\x9f\x2e\xce\x1e\xe7\x70\x54\x7c\xe2\xc9\x37\x5a\x6c\x94\x8a\x89\x6a\x3c\x64\x2b\xaa\xb2\x62\x56\x19\x68\x2a\xea\x5c\x5a\x9a\xff\xab\x5b\x17\x83\xb0\xa4\x03\x0c\xee\x57\x44\xfb\x82\x85\x9e\x9e\x1d\x35\x83\xb7\xf5\xf7\x7d\xe7\x26\xa4\x8a\x52\xa9\x0c\x46\xaa\x05\x15\x6a\x4c\x0c\x27\xdf\x39\x25\xbc\x9e\xba\xae\xfa\x08\x0e\xb3\xe9\x41\x7a\x70\x8b\x16\x68\xca\xc4\x19\x78\x21\xe3\xd4\x7d\x11\x4d\x80\x8c\x4b\x07\x0e\xaa\xcd\x40\xa9\x08\xbd\xa3\x3c\x83\x50\x91\x58\x49\x56\xde\xd1\x2e\xc3\x11\xf1\xc5\xe9\xae\x55\x6b\xda\x5e\xa2\xba\xf9\xe0\x36\xa4\x9d\xcf\xfe\x8e\x35\x27\xd3\xba\xb0\xfe\x04\xb1\xe4\x63\x67\x2e\x1d\x73\x98\x68\x41\xa2\x01\xdf\xfa\xa7\x0e\x7c\xaa\x90\x49\xa5\xf9\xf3\x5f\x18\x2d\xd5\x8a\x51\xf5\x91\x77\xdf\xd5\x7b\x0c\xdf\x78\xcb\x7a\xa3\x6a\x76\xbf\x67\xe4\x46\x28\xad\xc2\x55\x70\x32\x3a\x59\x1c\xf4\x72\x44\x20\x74\xcc\xf8\x70\xfc\x5e\xcf\xfa\x63\x49\xa1\x08\x54\xe4\x83\xa6\xdd\x7c\x6d\x7f\xde\x46\xfb\xef\x9d\x87\x56\xfa\x81\x0a\xe0\x5b\x11\x91\x33\xb3\xb3\x18\xb6\xea\xeb\x0a\x33\xdb\x12\x6c\x98\x94\x3d\xa8\x56\xcd\x9c\x64\xfc\x2e\x1e\xfc\x9d\xa8\xf0\xc6\xfe\x0d\xcb\xfc\xfa\xee\xba\x94\x29\xca\x33\xe3\x5d\x31\x4b\xe6\x56\xb3\x5f\x5a\xf7\x4c\xb8\x64\x54\x76\xab\x24\xbb\x00\xae\x52\xe4\x38\x0d\x91\xb3\xc5\xbd\x28\x53\xf2\x86\x6e\x58\xf6\x86\x4a\x66\x28\xf9\xf5\xe0\xb8\x8b\xc7\xdd\x21\xd1\xb9\x26\xd1\xe6\x9d\xec\x98\x04\x3a\xe6\x2c\xe3\x19\xbe\xa9\xcd\x4e\x1c\xf2\x09\x30\x95\xb8\x26\x1f\xcb\xaa\xa7\x1d\xd0\x8f\xfa\xc6\x3c\x21\x9f\xf2\xdb\x5c\xdc\x8f\x1f\xbd\xea\x09\x5a\x35\xb3\x48\xb7\x85\x3b\x32\x16\xbb\xaf\xe1\x7e\x73\x13\x18\x31\x16\x73\x7d\xb4\x3a\x85\x9b\x57\x99\xfb\xa2\x1d\x8b\xfe\xe7\x9e\x2b\x50\x1b\xc4\xa5\xb8\x29\x99\x94\xed\x13\x6f\x43\xb3\x8e\xf3\xf5\xff\x89\xe5\xa6\x54\x3c\x30\xd4\x8b\xb6\x77\xec\xa8\xed\x7d\x79\x53\xff\xa5\xb3\xcd\x90\xf9\xf1\x22\x6b\x51\x79\xfa\x92\x8e\xbd\x41\xb7\xba\x0c\xbb\x46\xdb\xee\x2a\xf4\xee\x57\xef\xbb\x6d\x4b\xab\x95\xa5\x3e\x0f\xb8\x9d\xfb\x9b\xab\xcf\x5d\x9b\xd0\x71\xc7\xf6\xdf\x88\x21\xf7\xe2\x34\xc7\x62\xe0\x24\x05\x9c\x89\xe3\xdd\x88\xdd\x49\x28\x63\x1c\x88\xd6\x49\xd8\x75\xff\x3c\x9c\xeb\x70\x9c\xd3\xb0\x3f\x73\xe2\x61\xdc\x85\xe3\x1c\x85\xb5\x33\xb0\x4b\xfc\x0d\x73\x11\xb6\xba\x01\xbb\x46\x1c\xe3\x1c\x6c\x77\x00\x76\x50\x0c\xbb\x05\x3b\x5d\x7f\xdd\xdc\xda\xe9\x10\x0c\x38\xfd\x3a\x28\x76\xb9\x02\xfb\xdd\x7d\x81\x73\xdc\xed\xe2\xfb\x1a\x9c\x7b\x81\xc9\x75\x3b\xf4\x9e\xa1\x2b\x2f\x62\x2e\x3d\xee\xbb\x67\xea\xb8\x0b\x4c\x2a\xca\x59\xf7\x20\x6e\xba\xaf\xc6\x41\x17\x58\xc1\x4e\xa7\xdc\xb3\x73\xc7\x85\xd5\x4d\x96\x86\x15\xe2\x0b\xef\xab\xbe\x4a\x6c\x94\x2c\xc8\xd1\x32\xdf\xb0\x19\x61\xbe\x3a\x36\x46\x0b\xd6\x8a\x68\x60\x54\xc7\x66\x58\xd1\x7a\xa4\x55\x84\x5b\x6f\x4f\x6b\xd5\x35\x06\x4e\xce\xce\x2f\x3f\x9c\xbf\x39\xfd\x78\x7e\xb6\xab\xbd\xee\xaf\x77\xaf\x56\xd9\xed\xb7\x59\x78\x3a\x65\xcb\x1f\xb5\x20\x6e\xf9\x38\x6f\x4b\x72\x5d\x90\xaa\x6a\x89\xdf\x4e\xd3\x68\x47\xdf\x65\xa3\xef\x89\xd0\xe9\x8b\x3b\x7e\xfa\xf4\x01\x67\x60\xda\xa3\xd6\x9e\xd6\x22\x4b\xa5\x49\x29\x27\x17\x67\xa6\x10\xe2\x84\xf0\x3c\xc9\xaa\xb4\xdb\x35\xf1\xe9\xd3\xc5\x99\x5c\x12\xf2\x03\x4b\x68\x25\xc1\x77\x95\x8a\xfc\x58\x91\x9f\xdf\xbf\xfd\x3f\x50\xda\x01\xdf\x30\x4a\x22\x37\xcd\x10\x38\xed\xe9\xf4\x80\xb3\x03\x9a\xa8\xd8\xc0\x28\x13\x5a\x68\x59\x26\xb1\xbd\x9f\x02\x2d\x65\xcd\xb2\x42\xcb\xcd\x5b\x46\x1c\xf8\x7c\xd7\x38\x2f\xce\x24\xbc\x83\x49\xf4\x26\x43\xf8\x86\x29\x2c\x8c\xed\x4e\xf2\xed\x59\xf1\x5e\x5f\xf7\x04\x2f\xb7\x7f\xce\x5a\xc6\x64\xfc\x16\xf7\x54\x1a\xff\x60\xcb\xc8\x7b\xf9\x24\xe4\xe5\xea\x72\x0b\x75\x38\x84\x50\x88\xc3\xff\xed\x39\x02\xf4\x20\x6b\x1f\x4f\xab\x74\x51\x02\xca\x2e\xa3\x3c\xd8\x5d\x29\x6d\x6d\x6d\xac\xf6\x3c\x3f\x6c\x77\xe9\x1b\x3f\xe9\xc0\x10\xfb\x16\x7f\x6f\x14\xd0\xb9\x30\x7d\x0d\xd1\x17\xfc\x00\x53\x39\xfd\x4f\xaa\x95\x55\x0d\x9c\x90\x31\x3e\x2b\xf2\x9f\xff\xfd\x4d\xed\xbe\xd2\x66\x5f\xa1\x58\x0a\xca\x12\x7e\x13\x24\x08\x39\x42\xbb\xa3\xc8\xaa\x92\x66\xe6\x7f\xbd\xe0\x03\xf9\xe5\x2f\xdf\xe0\x0f\xb3\xd4\x88\x2b\xfc\xf0\x9b\xff\x3f\x00\x00\xff\xff\x61\xa3\xc0\x75\x4b\x6e\x0c\x00") + +func olmManifests0151CrdsYamlBytes() ([]byte, error) { + return bindataRead( + _olmManifests0151CrdsYaml, + "olm-manifests/0.15.1-crds.yaml", + ) +} + +func olmManifests0151CrdsYaml() (*asset, error) { + bytes, err := olmManifests0151CrdsYamlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "olm-manifests/0.15.1-crds.yaml", size: 814667, mode: os.FileMode(420), modTime: time.Unix(1591299779, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _olmManifests0151OlmYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5a\x4b\x6f\x23\xb9\x11\xbe\xeb\x57\x14\x84\x00\x4e\x82\x69\xbd\x2c\x7b\xed\x06\x16\x58\xc7\x3b\xbb\xb3\xc8\xd8\x16\x6c\x4f\x2e\x41\x10\xb0\xbb\x4b\x2d\xc6\x7c\xf4\x92\x6c\x69\xb4\x41\xfe\x7b\xc0\x7e\xb3\x45\xc9\x1a\xaf\x9d\xc9\x61\x78\x91\x45\x56\xb1\x8a\xc5\x62\x3d\x3e\x39\x08\x82\x01\xc9\xe8\xdf\x50\x69\x2a\x45\x08\xeb\xe9\xe0\x89\x8a\x24\x84\x5b\xc2\x51\x67\x24\xc6\x01\x47\x43\x12\x62\x48\x38\x00\x10\x84\x63\x08\x92\xf1\xc1\xcb\x18\x33\x54\xc4\x48\xa5\x0b\xf6\x92\xfe\x01\xd5\x9a\xc6\x78\x15\xc7\x32\x17\xa6\xbf\xa7\x57\x78\x50\xef\x13\xe8\x92\x99\x54\xcc\x25\x4d\x21\xdd\xaf\xa5\x8a\x48\x3c\x22\xb9\x59\x49\x45\x7f\x23\x86\x4a\x31\x7a\xba\xd0\x23\x2a\xc7\x8d\xfe\xd7\x2c\xd7\x06\xd5\xbd\x64\xbe\x13\xe8\xad\x36\xc8\xc3\x58\x0a\xa3\x24\x63\xa8\xc2\x46\x17\x46\x97\x18\x6f\x63\x86\x01\x27\x82\xa4\xa8\x06\x2a\x67\xa8\xc3\x41\x00\x24\xa3\x3f\x2b\x99\x67\x3a\x84\xbf\x0f\xff\x3c\xfc\xc7\x00\x40\xa1\x96\xb9\x8a\xb1\x33\xb5\x46\x15\x35\x5f\x03\x10\x52\xdc\x57\x44\x9f\xee\x3f\xee\xa5\xfb\x5d\x27\xfc\x0b\x15\x09\x15\xe9\x73\x66\x8e\x4a\xb2\xc0\x9a\x54\x49\x86\xf7\xb8\xb4\x94\xf5\xb1\x0e\x48\x1d\x00\xec\x9a\xf5\x45\xc6\xd4\x79\xf4\x2f\x8c\x4d\x61\x4f\xaf\xe7\xbc\x8a\x83\x90\x2c\xd3\xad\xa5\x7e\xc4\x8c\xc9\x2d\x47\x61\x9e\xb1\xd0\xee\xc6\x00\x8c\x44\xc8\xb4\xa5\xb7\x96\xca\x7a\x0c\x3a\xc3\xd8\xae\x69\xa3\x88\xc1\x74\x5b\xd2\x99\x6d\x86\x21\xdc\x4b\xc6\xa8\x48\x3f\x65\x09\x31\x58\xf8\x4a\xc6\x68\x4c\x74\x08\x53\xcb\x81\x0c\x63\x23\x55\xc9\xc1\x89\x89\x57\x1f\x3b\xa2\x7c\xc2\x00\x0c\xf2\x8c\x11\x83\x15\x53\xe7\x30\x76\x30\x87\xdf\xbf\x03\x40\xad\x72\xf1\xb7\x63\xfb\xdb\x23\x0c\x6f\x87\xbd\x69\x42\x05\xaa\x8e\xac\xc0\x6f\xce\x7a\xc4\x92\x73\x22\x92\xb0\x33\x15\xc0\x38\xa2\x62\x5c\x5a\xb9\x51\x59\xa5\xda\x25\x0a\x82\xe6\x4a\x9c\xf9\x3f\xfc\xf1\x6e\xf1\xfe\xfe\xea\xf1\xee\xfe\x9f\xb7\x57\x37\xef\x1f\x16\x57\xd7\xef\xff\xd4\xe3\xdc\x28\x6a\xf0\xc1\x10\x93\x6b\x7b\x36\x67\x75\x38\xec\x7c\xa5\x9c\xa4\x18\xc2\xaf\x39\xd9\xda\x37\xd6\x1c\x7f\xa9\x08\xc7\x8d\x54\x4f\x56\xcd\x1f\xf4\x8a\xcc\xce\xce\xc3\x59\x7c\x7a\x71\x99\xcc\xf0\xf4\x62\x12\x5f\xcc\x67\x71\xb4\x3c\x9b\xcf\x2e\x66\x13\x92\xcc\xe7\x97\xa7\xb3\xf9\xe5\xf4\x7c\x7e\x3a\x99\x25\xc9\x72\x82\xe7\x97\x97\xd1\x84\x9c\x7e\x37\x9d\x9c\x25\xb3\xd3\x39\x9e\x7f\x87\xd8\x97\xbb\xc8\x19\x5b\x48\x46\xe3\x6d\x08\xbf\x2c\x6f\xa5\x59\x28\xd4\xd8\x58\xdb\x8e\x4c\x2a\xe3\xd8\xc5\x9e\xa0\xb9\x86\x85\x54\x26\x84\x8b\xc9\xc5\xe4\x59\x8a\xa9\x43\x51\xbf\x01\x8e\x46\xd1\x58\xf7\xd6\x32\x25\x8d\x8c\x25\x0b\xe1\xf1\x7a\xd1\x59\x63\x74\x8d\x02\xb5\x5e\x28\x19\xa1\xab\xd4\xca\x98\xec\x67\x34\x61\x7f\x27\x62\x56\x21\x8c\x57\x48\x98\x59\xfd\xd6\x5f\xf4\x69\xaf\x90\x24\xf4\xad\x85\x18\x54\x9c\x8a\x22\xce\xdd\xa0\xd6\xf6\x2a\xaa\x6b\xf8\x89\x30\x16\x91\xf8\xe9\x51\x7e\x94\xa9\xbe\x13\xef\x95\x72\xdc\x19\xc5\xba\x15\xef\xb8\x55\x69\xd0\x5d\xd7\x74\xf4\x59\x13\x96\xe3\x4f\x4a\xf2\xfe\x19\x96\x14\x59\x52\x85\x65\xcf\xca\xa2\x38\x62\xfd\xec\x47\xfe\x87\xe1\xd1\x60\x57\xf8\xde\x87\xda\x26\x34\x87\x49\xe1\xaf\x39\xea\xbe\x0f\x02\xc4\x59\x1e\xc2\x74\xc2\x7b\xd3\x1c\xb9\x54\xdb\x10\xa6\xe7\x93\x1b\xda\x59\x1b\x38\x1f\x42\x26\xf8\xe0\x84\x41\x3b\x22\x34\x64\xf4\x94\x47\xa8\x04\x1a\x2c\x72\x9e\xd4\x21\x30\x2a\xf2\xcf\xbf\x27\xd0\xc7\xc4\x10\x26\xd3\x2f\x0b\xf6\x3b\x4c\x6f\x1d\xf0\x3d\x5a\xbe\x20\xe8\x7b\x76\x79\xeb\xc0\xef\x15\x59\xb3\xed\x0b\xfe\x15\xd3\xc1\x04\x70\xd2\x26\x80\x13\x67\xc1\xcd\x1c\x01\x04\xb1\x14\x4b\x9a\x72\x92\xd9\x92\x02\xd5\x2f\x36\xb8\x7e\x7f\x20\xa6\x37\xf4\xed\xb1\x15\xa6\x54\x1b\xb5\x0d\xad\xc1\xb5\x71\xf7\xcf\x0d\x65\x41\x11\xb2\x9d\xf9\xaf\x94\x36\xbe\xa5\x2b\x77\xed\x5b\xba\x3a\x2e\x5d\x39\x09\xeb\x75\xc3\xfd\xc5\x1b\x44\xfb\xdd\xbe\xe3\xe8\x3e\x69\x37\x07\x90\x34\x55\x98\x12\x83\xb6\x07\x0a\x30\xa1\xa6\x17\xf4\xf7\xef\xd7\xb2\x1a\x19\x90\x84\x53\x11\xc2\xd0\xa8\x1c\x87\x5f\xc2\x68\x45\x36\x7c\xfe\xc6\xb2\xe9\xae\x47\xb1\x54\x28\xed\x07\xdf\xed\x35\x75\x1e\xe9\x58\xd1\xcc\x4a\xd2\x6e\x3f\x19\x2b\x24\x06\x87\xef\x60\x98\x17\x99\xc8\xfe\x95\xd9\x74\x63\xff\x48\x90\xa1\xc1\xa2\x33\x7d\x81\xd4\xb8\xbc\x86\x2a\x39\xac\xcb\x5b\xd0\x76\xdf\x2a\x92\x57\xb4\x76\x86\x0a\x6d\x08\x63\x19\x23\x25\xc5\x01\x8d\x5b\xa5\xde\xf6\xc2\xd7\x14\x37\x5f\xf3\xc2\xbf\x80\xcf\xaa\xfa\x2a\x8e\xf2\x7a\x57\xf6\x0e\x1a\x91\x69\xa1\x84\x7b\x89\x29\x1a\x4b\xc2\xa8\x2e\x3e\x37\x85\xc7\xed\xf8\x59\x46\xe2\x27\x92\xa2\x1e\x1d\xa7\x7d\x45\xce\x89\xa0\x4b\x1b\x90\x4a\x5f\x76\xe7\xc6\x34\x96\xe2\x38\x5d\x7a\xd5\xa3\x4f\x87\xb6\x9a\xbc\xab\x56\x0b\xe5\x3d\xbe\x95\x32\x19\x11\x16\xb4\x68\x98\x5b\x50\x3a\x20\xd9\xeb\x49\xed\x56\x69\x7d\x91\x8c\x37\xf5\xa9\x21\x2a\x45\xd3\xa0\x78\x95\xb7\x07\x5e\xb4\x64\x8f\x42\x84\x65\x2b\xd2\x43\x9b\x2a\xb0\xa6\x62\xf5\xa8\x57\xdf\x6f\x51\x81\x3d\x57\x62\x4b\xc6\x47\xeb\x5a\x8b\xc9\x68\x7a\x36\x9a\x36\x07\x48\xa8\xce\x18\xd9\x96\xa5\xe9\xa2\xdc\x15\x1e\xea\x6d\x13\x6c\x1c\x33\x84\x7b\xcc\xca\x12\x44\x03\x11\x8d\x01\x6b\x55\xc0\xac\x88\x01\xaa\x81\xac\x09\x65\x24\x62\x08\x4b\x25\x39\x10\x48\x6d\x65\x00\xd7\xe5\x33\x78\x28\x9c\x0e\x36\x2b\x1a\xaf\x60\x43\x19\x2b\x1c\x91\xad\x11\x8c\x04\xe2\x3f\xff\x68\x00\xc0\xa9\xf8\x6b\x1e\x61\x63\xcc\xe9\x68\x3a\x1d\xd9\xb4\xfd\x84\xdb\x8d\x54\x89\xf5\xc7\x93\xbe\xcb\x9e\xbc\x83\x13\xc9\xb8\xfd\xa8\x0d\x76\x62\x1d\x98\x13\xda\xad\xb0\xeb\xda\xfa\x1e\x13\xf8\x40\xca\x0a\x0b\x39\xa1\xac\xb8\x33\xa1\x57\x74\x69\x5a\x67\xf8\x41\x61\xb2\x22\xc6\xde\xde\xa0\x28\x87\xd6\x34\xc1\x2a\xd5\xf6\xf7\x61\x54\x3c\x39\x22\x76\x2c\x0c\x90\x2b\x16\x16\xd5\x8b\x0e\xc7\xe3\x94\x9a\x55\x1e\x15\x9e\xe1\x2b\x37\xf7\x02\x7e\x63\xa3\x10\xc7\x9c\x58\xe3\x8d\xb3\xa7\x74\x5c\x9d\x37\x68\x3c\xa4\x0a\x3a\x37\x32\xc1\x4a\xa3\xb2\x9b\xba\xdb\x88\x5b\xa7\xc1\xd5\x79\x66\xeb\x22\x4c\x42\xb0\x61\xb1\x43\xfa\x40\x45\xca\xf0\x58\xea\x9b\x9c\x19\x7a\x2c\xf1\x15\x63\xed\x23\xda\x43\x5b\x9d\xa0\xb4\x74\xd3\x18\x42\xd2\x76\xa3\xd0\x6b\xbf\xaa\xa0\xbc\xb0\x15\x9d\x2e\x02\x72\xbd\x12\xbc\xb0\x35\x03\xa8\x92\x44\xfd\xb5\x1b\x77\x7b\x75\xf6\x1e\x84\xf7\x99\x9a\x30\x80\x0a\xbb\x25\x71\x8c\x5a\x2b\xb4\x29\xaa\x5b\x84\x97\xd1\xb7\x5f\xd3\x17\xc5\x48\x6f\x32\x45\xf3\x9c\x9e\x3d\x80\xce\xab\x53\xd1\x31\x94\x1d\xdc\x41\x3d\x5c\x81\xf6\xbb\x4d\x0c\xce\x44\x91\x21\x8e\xd0\xc9\x9b\xb5\x8e\xd0\xd3\x49\xb5\xff\x23\x5d\x0f\xa7\xda\xe7\x95\xee\x07\xad\x17\xab\xdd\x3e\x84\x8e\x9b\xfb\xd3\x45\x39\xba\x4f\x05\xa0\x0f\xb6\xd4\xc3\x0f\xba\xb4\x87\xaa\xc1\x97\x59\x77\xa7\x9d\x06\x04\xfc\x60\x4c\x3d\x0a\x38\xc5\xaf\x65\x1f\x99\x69\x76\xeb\x21\x34\xf5\xe8\x23\x35\x47\x89\xd8\x35\x06\xbc\x18\xbe\xa9\x87\xbf\x13\xab\xc7\xc1\x8e\xcc\x25\xf5\xe1\x41\xe5\x38\x7c\xbf\x2d\xff\x0e\x30\x54\xb3\x17\xf0\xd0\x4e\xae\xe8\x53\x05\xeb\xef\xe7\xbe\xe9\x40\x63\x9c\x2b\x0c\x6c\xa0\xf6\xac\x0f\xcf\xe6\xf3\xd3\xa1\x97\xb1\x2a\xea\x7c\xd0\x6a\x4d\xe4\xe2\x4e\xe5\xf8\x5a\x88\x4c\x47\x7a\x17\x97\xb9\x62\x1b\xb2\xed\x03\x24\x5e\x5c\x06\x7c\xc8\x8b\x35\xcf\x0e\xd5\x01\x1c\xa5\x1c\x7b\x80\x8e\x72\xe8\x78\x85\xd6\x21\x3e\x3c\x3e\x2e\x1e\xbc\x14\x07\x01\x91\x56\xff\x3d\xda\x1d\x42\x60\xfe\x0f\xd4\x7b\x39\x76\x53\x1f\xcf\x9b\x93\xeb\x45\x3f\x5a\x53\x8e\x3d\x98\x4d\x39\x6a\xe4\xe6\xcc\x45\x6e\x2a\xa3\xd8\x47\x44\xcd\xf6\x5a\x0a\x83\x9f\xbd\x96\x53\xb9\xb8\xd2\x9f\x34\x2a\x2b\x62\x32\xd9\xa1\x58\x4b\x96\x73\xbc\xb1\x41\xc8\xeb\x78\x65\x94\x30\x3c\x5b\xee\x7a\x2b\x00\xb7\x7c\xe5\x8f\x1e\x63\xc3\xb3\x81\x6f\xef\xbd\xa1\xc7\xbf\x29\xf2\xcc\x6c\x7f\xa4\x2a\x84\x7f\xff\xa7\x28\xb8\x4d\x71\xc4\x10\x8a\x6e\xa7\xec\x21\x9d\x7e\xa4\xf8\x7d\xbc\x0a\xa7\x09\x2e\xa9\xa0\xa6\xad\xd7\xe4\x46\x60\x52\xb7\x56\x69\xf9\x23\xfa\xc1\xb4\x5b\xe9\xb3\xee\xfc\x6f\x44\x39\x53\x76\x59\x55\x15\x7e\x53\xa5\xdc\x1a\x39\xeb\x86\xd2\x7e\x3a\xf6\xf5\x49\x3d\x7e\xa7\x59\xba\xea\x13\x15\xad\x51\xe3\x60\x90\xa2\xb0\x6a\x63\x52\x76\x49\xf8\x99\x6a\x43\x45\xea\xb6\x49\xb6\xd1\x4a\xc0\xac\x90\x2a\xb8\x2e\x6a\xb0\x9b\xb6\x06\x6b\xd3\xfd\xed\xde\x1c\xe0\x0b\x38\x2f\x6a\x4b\xbb\x5a\x1d\xf8\x57\x95\x55\x1e\x51\x19\xb4\x3f\x37\xec\xe9\x9a\x4b\x1b\x3c\x16\x85\x45\xaa\xb2\x78\x70\x4c\x64\xcf\x33\x6d\x14\x12\x1e\xd8\x74\x96\x0b\x6a\xb6\x6d\x4f\xd6\xfe\x8e\xe0\xdc\xd3\x75\x4d\xd9\x74\xab\xd6\x78\x59\x1e\x31\xaa\x57\xf6\x31\xd5\xd3\x1f\xf2\xc8\x16\xe7\xff\x0d\x00\x00\xff\xff\xcd\x4f\x3b\xa4\xe0\x23\x00\x00") + +func olmManifests0151OlmYamlBytes() ([]byte, error) { + return bindataRead( + _olmManifests0151OlmYaml, + "olm-manifests/0.15.1-olm.yaml", + ) +} + +func olmManifests0151OlmYaml() (*asset, error) { + bytes, err := olmManifests0151OlmYamlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "olm-manifests/0.15.1-olm.yaml", size: 9184, mode: os.FileMode(420), modTime: time.Unix(1591299779, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _olmManifests0161CrdsYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\xfd\x7d\x73\x23\xb9\x91\x27\x8e\xff\xef\x57\x91\xd1\xf6\x86\xa4\xb5\x48\x75\xdb\x6b\xff\x76\xfb\x7c\x37\xa1\xed\xee\x19\xeb\xe7\x7e\x50\xb4\x34\xe3\x73\x8c\x67\xe7\xc0\x2a\x90\xc4\xaa\x08\x94\x01\x14\xd5\xf4\xcd\xbd\xf7\x6f\x20\x81\x7a\x22\x8b\x22\x0b\x80\xdc\xea\x31\xd2\x11\x9e\x96\x44\x66\xa1\xf0\x90\x99\xc8\xfc\x64\xe6\x64\x32\xf9\x05\x29\xd9\x77\x54\x2a\x26\xf8\x4b\x20\x25\xa3\x9f\x34\xe5\xe6\x27\x35\xbd\xfb\x77\x35\x65\xe2\x62\xfd\xe2\x17\x77\x8c\xe7\x2f\xe1\x55\xa5\xb4\x58\x7d\xa4\x4a\x54\x32\xa3\xaf\xe9\x9c\x71\xa6\x99\xe0\xbf\x58\x51\x4d\x72\xa2\xc9\xcb\x5f\x00\x10\xce\x85\x26\xe6\xd7\xca\xfc\x08\x90\x09\xae\xa5\x28\x0a\x2a\x27\x0b\xca\xa7\x77\xd5\x8c\xce\x2a\x56\xe4\x54\x22\xf3\xfa\xd1\xeb\xe7\xd3\xdf\x4e\x9f\xff\x02\x20\x93\x14\xbf\x7e\xcb\x56\x54\x69\xb2\x2a\x5f\x02\xaf\x8a\xe2\x17\x00\x9c\xac\xe8\x4b\xc8\x88\x26\x85\x58\xd8\x41\xa8\xa9\x28\xa9\x24\x5a\x48\x35\xcd\x84\xa4\xc2\xfc\x67\xf5\x0b\x55\xd2\xcc\x3c\x7d\x21\x45\x55\xbe\x84\xc1\xcf\x58\x7e\xf5\x20\x89\xa6\x0b\x21\x59\xfd\xf3\x04\x44\xb1\xc2\x7f\xb9\x57\xb7\x0f\xbd\xc1\x87\xe2\xef\x0b\xa6\xf4\x9f\x76\xff\xf6\x96\x29\x8d\x7f\x2f\x8b\x4a\x92\x62\x7b\xb8\xf8\x27\xb5\x14\x52\xbf\x6f\x1f\x3e\x31\x1f\x52\x32\xb3\x7f\x64\x7c\x51\x15\x44\x6e\x7d\xf3\x17\x00\x2a\x13\x25\x7d\x09\xf8\xc5\x92\x64\x34\xff\x05\x80\x9b\x3e\x64\x34\x01\x92\xe7\xb8\x20\xa4\xb8\x96\x8c\x6b\x2a\x5f\x89\xa2\x5a\xf1\xe6\x31\x39\x55\x99\x64\xa5\xc6\x09\xbf\x5d\x52\x28\x25\xd5\x7a\x83\x13\x01\x62\x0e\x7a\x49\xeb\xa7\xe2\x37\x00\xfe\x5b\x09\x7e\x4d\xf4\xf2\x25\x4c\xcd\x9c\x4e\x73\xa6\xca\x82\x6c\xcc\x18\xdc\x27\xec\xa2\xbc\xb6\xbf\x77\xbf\xd3\x1b\x33\x50\xa5\x25\xe3\x8b\x7d\x8f\x36\x9f\x39\xee\x99\x76\x02\x6e\x37\x65\xff\x91\x9d\x5f\x1c\xf3\xbc\xb2\x9a\x15\x4c\x2d\xa9\x3c\xee\xa1\xcd\xc7\x7b\xcf\xbc\xde\xfa\xed\xc0\x83\x3b\x8c\xea\x63\x31\xdd\xd9\xd2\x3d\xa6\x97\x8b\xfe\x7b\xe4\x44\xdb\x5f\xd8\x3f\xaf\x5f\x90\xa2\x5c\x92\x17\x76\x77\x64\x4b\xba\x22\x2f\xdd\xe7\x45\x49\xf9\xe5\xf5\xd5\x77\xbf\xbd\xe9\xfd\x1a\xfa\x6f\xdf\xdb\x9f\xc0\x14\x10\x90\xb4\x14\x8a\x69\x21\x37\x66\x36\x5e\xdd\x7c\xa7\xce\xe1\xd5\xc7\xd7\xea\x1c\x08\xcf\x9b\xe3\x02\x25\xc9\xee\xc8\x82\xaa\x69\xc3\xd8\x8e\x50\xcc\xfe\x9b\x66\xba\xf9\xa5\xa4\x7f\xab\x98\xa4\x79\xfb\xfc\x09\xd4\xef\xde\xf9\x95\x99\xd7\xe6\xc7\x52\x9a\xa7\xe8\xe6\xc0\x59\xea\xc8\xa2\xce\x6f\xb7\xde\xe7\xc4\xbc\xb2\xfd\x14\xe4\x46\x08\x51\x85\x0b\xea\xce\x02\xcd\xdd\x2c\xd9\x85\x66\xca\xbc\xad\xa4\x8a\x72\x2b\x96\x7a\x8c\xc1\x7c\x88\x70\xf7\x46\x53\xb8\xa1\xd2\xb0\x31\x47\xb4\x2a\x72\x23\xbb\xd6\x54\x6a\x90\x34\x13\x0b\xce\xfe\xde\xf0\x56\xa0\x05\x3e\xb4\x20\x9a\x2a\xbd\xc5\x13\xcf\x1e\x27\x05\xac\x49\x51\x51\x3b\xa9\x2b\xb2\x01\x49\xcd\x53\xa0\xe2\x1d\x7e\xf8\x11\x35\x85\x77\x42\x52\x60\x7c\x2e\x5e\xc2\x52\xeb\x52\xbd\xbc\xb8\x58\x30\x5d\xcb\xe0\x4c\xac\x56\x15\x67\x7a\x73\x81\xe2\x94\xcd\x2a\x23\xce\x2e\x72\xba\xa6\xc5\x85\x62\x8b\x09\x91\xd9\x92\x69\x9a\xe9\x4a\xd2\x0b\x52\xb2\x09\x0e\x9d\xa3\x1c\x9e\xae\xf2\x5f\x4a\x27\xb5\xd5\x49\x6f\xac\x3b\x1b\xd8\x12\x0a\xbd\x07\x56\xc0\x08\x3e\xbb\x93\xec\x57\xed\x5b\xb4\x13\x6d\x7e\x65\x66\xe7\xe3\x9b\x9b\x5b\xa8\x1f\x8d\x8b\xb1\x3d\xfb\x38\xef\xed\x17\x55\xbb\x04\x66\xc2\x18\x9f\x53\x69\x17\x71\x2e\xc5\x0a\x79\x52\x9e\x97\x82\x71\x6d\x0f\x71\xc1\x28\xdf\x9e\x7e\x55\xcd\x56\x4c\x2b\xdc\x97\x54\x69\xb3\x56\x53\x78\x85\x8a\x09\x66\x14\xaa\xd2\x9c\xb0\x7c\x0a\x57\x1c\x5e\x91\x15\x2d\x5e\x11\x45\x1f\x7d\x01\xcc\x4c\xab\x89\x99\xd8\xe3\x96\xa0\xab\x53\xb7\x3f\xbc\x75\xfe\x00\x6a\x7d\x77\xf0\x83\x43\x87\x15\xec\xe9\xdc\x96\xb2\x96\x86\xcf\xa9\x21\x92\xe7\x92\xaa\x9d\x5f\xef\x1c\x56\xfb\x31\xbb\x5b\x96\x42\x99\x75\x23\x1a\x3e\xbc\x7d\x07\x19\xe1\x50\x29\x6a\x8e\x52\x26\x38\x37\x1b\x41\x0b\x20\x46\x2b\x4d\xe8\x27\xa6\x74\x7f\x46\xda\x37\x58\x30\xa5\xe5\x66\x0a\x5f\x0b\xb9\x22\xfa\x25\xfc\xa1\xfe\xd5\x04\x1f\x20\x24\xb0\xf2\x7f\xbd\xfc\x43\x29\xa4\xfe\x5f\xf0\x81\x17\x1b\xf3\x98\x1c\xee\x97\x94\xc3\xcd\xf0\x7b\x5a\xfa\x9f\x9d\x3f\x7f\x23\xcb\x6c\x0a\x57\x0b\x2e\x64\xfd\x5d\xb3\xe3\xae\x56\x64\x41\x61\xce\x68\x81\x27\x40\x51\x3d\x3d\xd9\xe1\xb4\x67\x4d\xc1\x9a\x43\x73\xb6\x78\x47\xca\x03\x13\xf7\xaa\xfe\x9c\x79\x8a\x79\x70\x57\x49\xb7\x7f\xd4\x02\xb7\xb4\x79\x3d\x2d\x06\xde\x68\x46\xb2\x3b\x20\xee\xa9\x2b\x52\x4e\x14\x1e\xaf\xce\x24\xee\x9d\x9f\xde\x6c\xbc\xaa\x19\x0c\x3c\x43\xc8\xce\x07\xaf\x9c\xec\x9b\x8e\x99\x94\xee\x9b\x8f\xfa\x5e\x6b\x8e\x1c\x98\xce\x77\xdb\xfa\xe8\x08\xee\x2c\xdb\x3f\x9c\x81\x93\x05\x7b\x4f\x17\xe0\x09\x9b\x11\x45\x7f\xff\x6f\x83\x83\x30\xfa\x32\x67\x44\x0f\xed\xca\xfd\x27\x10\x70\x7d\x6b\xa6\x43\x7f\x7d\xf0\xf5\x00\xa5\x8c\x7b\xec\xe8\x6f\x33\x73\x0e\x0e\x4c\xba\x3d\x2b\xe6\xe4\xf3\xc6\xa8\x98\xd4\x3b\x0f\x2f\x06\x84\x71\x2a\x2d\x2f\xb3\x95\x19\x57\x9a\x70\xcd\x6a\x0b\xa8\x4f\xa4\xd9\xb5\xf5\x2e\xbe\x67\x7a\x79\xec\x0e\xc6\xf3\x3c\xc0\xf5\x6a\x0e\x4e\xf9\x9c\xe3\xd9\x72\x72\xad\x3d\xe2\xcc\x8a\x80\x51\x1b\xba\x94\x4c\x48\xa6\x37\x87\xa4\xe3\xb5\xfb\x9c\x7b\x1a\x51\x8a\x2d\xb8\x91\x94\xf7\x94\x2d\x96\xba\xb6\x32\x9c\xad\x0a\xaa\xbd\x7f\x6c\x0d\x45\xd4\x8f\x64\x7f\x37\x8a\x96\xae\x40\x09\x2b\x69\x99\x46\x41\x3b\xa3\x66\xc2\x55\xb5\xa2\x39\xcc\x36\xc8\x35\xa7\x25\xe5\x39\xe5\xd9\x66\x50\xca\x2a\x51\xac\xa9\x9c\xc2\xb7\xca\xac\x34\xfc\x91\x2d\x8c\xf5\xec\x06\xc6\x78\xce\xcc\xa5\x49\xd9\x87\xa0\x8a\x3e\x38\x4a\xa6\xcc\x54\xcf\xa9\x34\x12\x55\x98\x05\x2c\xc4\x7d\xc3\x93\xe6\x5b\x1c\x14\xe4\x15\x5a\x17\x87\x07\x5a\x99\xf9\x9c\xa2\xa1\x2f\x09\x5f\x34\x82\xb2\x5e\x07\x67\xa0\x98\x89\x58\x08\x6b\x4b\xa0\x05\xcc\xd6\x7b\x66\x93\xd3\x05\x31\x7f\x05\x66\xc5\x7e\xc3\x95\x71\xfd\xdb\xdf\xd8\x27\xe5\x74\x4e\xaa\x42\x3b\xde\xa8\xba\xfa\x97\x8a\x2e\x39\x1b\xc8\xec\x58\xa8\xb8\x5d\x68\x9a\xb7\x03\xbc\x47\x83\x73\x46\xe1\xb9\x65\xde\x9f\x0a\xfc\xde\xd0\x48\x97\x14\x94\x51\x0c\xfd\x17\x55\x70\xcf\x8a\xc2\x70\x93\x84\xdf\xd1\x1c\x0a\xfa\x89\x65\x62\x21\x49\xb9\x64\x19\x29\x8a\x0d\x0a\x8e\x7c\x48\x98\x73\x30\xb6\x93\xd1\x36\x7b\x15\x9b\xb1\x6f\x17\xcd\x25\xa8\xa6\xe6\xca\x34\x4a\x84\x2b\x9a\x49\xaa\x0f\x99\x11\x37\xf6\x53\xad\xa1\x68\x14\xaf\x59\x0e\xf7\x75\xbb\x0b\xdd\x3e\xdf\xaf\x0d\x49\x96\x99\xa3\x8d\x47\x4a\x70\x6d\x0c\xce\xad\xeb\xe0\x14\xae\xb4\xd9\xa7\x33\xaa\xf0\xf4\xdd\x51\x5a\xda\xdd\x5d\xb0\x1d\x3b\x1f\xc7\xbf\x22\x45\x71\x6e\xae\xed\x19\x05\x4a\xb2\xa5\x9d\x7a\x4e\x71\x0c\x66\x38\x5a\x32\x9a\xc3\x5c\x48\xa0\x6b\x6a\xe4\x9e\x5b\x59\xca\x8d\xfe\xdd\x33\x57\x44\x4a\xb2\xbb\xdb\x99\xa6\xab\x41\x35\xf0\xd0\x04\x37\x12\xf0\xd0\x1c\xb7\x72\xd3\x99\x1c\xf5\x1d\x7d\xcf\x81\x7e\xe0\xa1\xd6\xc6\xbe\xd1\x92\x68\xba\x38\x24\x05\xbf\xed\x7d\xb8\xb9\xd3\x2d\xc5\x7d\x6d\xab\x6f\x9f\x06\x54\x18\xdb\x77\x09\x40\x3f\x0e\xee\x80\x9c\xa9\xcc\xc8\x17\x9a\x1b\x53\x49\x31\x65\xd7\x99\x70\x7b\x35\x5b\x93\xc2\x6e\x98\xfa\x51\xa5\x28\x0a\x14\x34\x95\x1c\xba\x23\x1a\x32\x77\x38\xc2\x81\xae\x66\x34\xcf\xcd\x3d\xb0\x1e\xee\xa0\xd2\x7e\xd0\x48\x78\x58\xa3\xd7\x3a\xee\x5a\x14\xc5\x43\x5a\x79\x0f\xf3\xc3\x0f\x80\xfa\x86\xba\x26\x7b\x1e\x00\x3b\x8a\xbc\x9e\x35\xa6\xea\xd3\x05\x39\xd5\x54\xae\x18\xa7\x76\xab\xb0\x15\x6d\xb8\xee\x65\x0a\x30\xa3\xfa\x9e\x52\x0e\xd9\x92\x66\x77\xcd\xe1\xb3\xb7\xe8\xed\x55\x76\x17\x7a\x94\x87\x0f\xb0\xac\xbf\xd5\xba\x2d\x44\x51\xe0\x05\x5d\x51\x0a\x6c\x0e\x04\x38\xbd\xaf\xb9\x0d\xbb\x7f\x86\x48\xb5\x0e\x93\x35\x61\x05\x99\x15\x74\x6a\xac\x85\xe6\xa7\xf3\xee\xd8\x59\x6d\xeb\x94\x55\x51\x0c\x4a\xd6\x9a\xcc\x4e\x5a\x7c\xbc\x7e\x05\x5a\x92\xf9\x9c\x65\xe6\x4b\x39\x93\x34\xd3\x76\x62\xf7\x4e\xc8\x90\xf5\x62\x69\xcf\x49\x54\x9a\xe8\x4a\x1d\x79\x31\xdc\xbf\x69\x9a\x2b\xcb\x47\xa3\xbb\x29\xcf\x06\x24\x89\xb7\x55\xcc\x5b\x57\xe2\xf6\xaf\xd1\xcb\x39\xf2\xf4\x14\x44\x69\x2b\x4f\x6e\xd9\xd0\xa5\x00\x0e\xdb\xc4\x60\x64\x35\xde\x2b\x0d\x9b\x89\xd9\xd9\x03\x9f\xe2\x83\x77\x8e\x23\xd8\x37\x6f\xe6\xf5\xed\xda\x99\x32\xe8\x26\x3b\x92\x47\xc5\x06\x56\x02\x76\xa4\xf2\xd5\x6b\x7b\x69\x47\x2d\x80\xe2\x72\x29\x8a\x5c\x41\xc5\xd9\xdf\x2a\x0a\x57\xaf\x9d\xad\x71\x0e\x8c\x67\x45\x95\xef\x9b\x4d\x80\x6f\xbf\xbd\x7a\xad\xa6\x00\xff\x49\x33\x62\x2e\xfc\xf7\x14\x72\xc1\x4f\x34\x7c\x78\xff\xf6\x2f\xe8\x02\xc0\x4f\x9c\x5b\x45\x6b\xef\x0b\xa4\x60\xe8\x65\xdb\xc3\xd2\xbe\x1c\xf2\x34\x82\xdb\x8d\x32\x23\xa5\xae\x24\x55\x28\x89\xb8\xc6\xa3\xb6\xa4\x45\xa9\x60\x45\xee\x28\xa8\x4a\xda\x37\xd9\x37\xce\xab\xd7\x0a\xbf\x83\x6b\x04\xb9\x00\x2e\x34\x2c\xa8\xc6\x23\x50\xa0\xd7\x68\xec\x84\x3b\xcf\x06\x13\xfc\x46\x13\x1d\xf3\xe4\x98\xad\xfe\x61\x86\x37\xa1\x1c\x79\x8f\x3c\x2a\x7b\x1d\x38\x07\xde\x08\xdc\x31\x7b\x65\xdf\xec\x11\xcf\xd8\xce\x1b\x8e\x7e\x96\x95\xa3\x78\x0f\xfd\xf8\xa0\x5e\xdd\x89\x17\x98\x67\x5b\xad\x86\x0e\x97\xbe\x0f\x1d\x65\x7d\x73\x91\x5d\x12\x63\x2f\xd2\x21\xab\xc1\xa8\x22\x2b\xd5\x29\x77\xbb\x8f\xb6\xaa\xa2\x2a\x27\x5a\x4c\xf2\xa1\xa5\x7b\x70\xfe\x0e\xcd\xdd\x8a\x2a\x75\xf8\x76\x7e\x09\xcb\x6a\x45\x38\x48\x4a\x72\xa3\xce\xea\xaf\xd5\x77\x3b\x7b\xf3\xd2\x84\x15\x0a\xc8\x4c\x54\x1a\xee\x97\x43\x17\xb0\x81\xf9\x51\xf6\xda\x64\xee\x84\x82\xdb\x98\xd4\xa8\xeb\xb3\xa4\x44\x0d\x09\xb7\xde\xf8\x3f\xe2\x87\x6a\x5b\xd5\x7e\x65\x60\x30\xf7\x46\x8c\x48\xc2\x15\x0e\x63\x50\x33\x6b\x81\x77\x9e\xac\x92\x12\xaf\x16\x66\xab\x8d\x1c\xaf\xdd\x0a\x37\x54\xae\xd9\x68\xf5\xf8\xf0\x31\xc5\xe0\x11\xcd\x2f\x1f\xf3\xa0\x95\x42\xfa\xb1\x2f\xa5\xd0\x22\x13\x0f\x1a\xaa\x7b\xbf\xac\xec\x6c\x0d\x7b\xef\xc6\x7d\x7f\x8c\x42\xb5\xf2\xe4\x25\x68\x59\xd9\xb9\x50\x5a\x48\x74\x71\xb4\xbf\xa9\x66\x4d\xc0\xa4\xe6\xea\x8c\x29\xf8\xbf\xff\xef\x17\xbf\xf8\x22\xe3\xe6\x45\xa5\x34\x95\x6e\xd2\xea\xc0\xf1\x3f\x2a\x7e\x6e\x1f\xee\xce\x87\x9b\x37\xfc\x7b\x27\x8e\x3e\xf4\x99\xdd\x78\xfa\xe0\x6b\xd8\x55\xdb\x8d\xab\xab\x75\xfb\x2f\xf7\xa1\x36\xbe\x3e\xc4\xe9\x71\xe2\xec\x3d\xdf\xfd\xcd\x77\x6e\x47\x3d\x5e\x70\x7d\xeb\xae\xb3\xff\x91\xeb\xce\x4a\xd4\x8f\xfb\xae\xf7\xbb\x63\x1e\x57\xbf\x1e\x31\x4f\xea\x38\x04\x05\xc7\x98\x60\x41\xb2\xe6\xb2\xbe\x3d\x80\xad\x3f\xdb\x11\x7c\xec\xff\xf2\xe1\x28\xbb\x3d\x97\xd3\x72\x49\x54\x7f\xda\xae\x3b\xbf\xd9\x61\x11\x2b\xb6\x3e\xb4\x67\xad\xd9\x6c\x4f\x3d\xd4\xc7\x1e\xd7\xc2\xd8\xa8\xff\x67\xf0\x3b\x37\x25\xcd\xfe\x4f\x8a\xb3\xa7\x38\x7b\x8a\xb3\x7f\x51\x71\xf6\xc3\xd2\xc0\x9c\x6c\xc8\x69\x56\x10\xeb\x5b\x54\xa0\x69\x51\x60\x00\x7c\x29\xee\x9b\xa8\x57\xb1\xed\x35\xeb\xc4\xcc\x5a\xef\xf6\x8a\x70\x63\xa1\x93\xb2\x54\xe8\x51\x26\xb0\x60\x6b\xca\x1b\x57\xd9\x71\xae\x9e\x7d\x18\x80\x5d\x05\x54\xff\x65\x68\x88\x0f\x40\x03\xb6\x6d\x99\xbd\x33\x76\xd9\x7e\xd2\xdd\xfb\x2b\xae\xb4\xac\x70\x79\x73\xb8\xa3\x75\xe4\x66\x45\x4a\xb4\xd3\x68\xbe\x2f\x14\x42\xba\x07\x80\x68\xdc\xd7\x33\x8a\x71\x82\xd9\x06\x8c\x79\x86\xa2\x42\x0b\xe1\x9c\x83\x86\x1b\x8a\x0c\x49\xb5\x64\x74\x30\x12\x44\xe4\x8c\x69\x49\xe4\xa6\xd9\x27\xfb\xee\x05\x7b\x6c\xfb\xae\xa9\xf0\x90\x95\xff\x80\xa9\x4b\x4a\xe6\x6c\x94\xbc\x31\x1d\x0f\xce\xeb\xf5\x95\xdb\x85\xad\xb9\xa9\xdc\x2e\xa4\x0a\x48\x51\xd4\xb6\x41\x63\xb7\xe2\x73\x06\x46\x66\xb7\x5c\x0e\x42\x36\xfb\xc6\x4c\x68\x77\x7b\xce\xd0\x07\x23\x09\x37\x7f\x18\x3c\x04\x23\x67\xed\xe1\x1b\x91\xb8\xe7\x43\x1e\x11\x38\x10\x3c\x81\x87\x02\x28\x0f\xce\x60\xf3\x6b\x33\xb0\x35\xcb\xa9\x6a\x2e\xc6\x5a\xe0\x49\xc6\xfb\xf1\x1e\xb6\x76\x05\xeb\xaf\xe6\xb0\x66\x04\xc8\x62\x21\x31\xc2\x38\x18\x6b\x38\x38\x3f\x96\xf6\x3b\x87\x2c\x4d\xac\xfd\xbe\xf7\xaf\x46\x48\xee\xfd\xe3\xa0\x5f\xb6\xfe\x63\xdf\x6c\xdc\xa6\xc3\xe1\x07\x00\x82\x2e\xb1\x7a\x6a\x85\x7c\xe0\xa3\x87\x57\xd5\xd2\x83\x6b\x6b\xa9\xbf\xc2\x5b\x43\x70\x7f\x9d\x99\xf3\xd1\x0a\xec\x41\xb1\xb0\xfb\x26\xbd\x00\x64\x49\xa5\xb9\x75\x9b\x43\xc3\x81\x40\x66\x2d\xc1\x46\x3c\x59\x94\xc3\x60\x84\x7c\xfb\x9d\x1f\x5c\x7f\x4b\x87\x76\x81\xa5\x09\x94\x64\x50\x6c\xb6\x74\xcc\xb2\x59\x7a\x10\xae\xb3\x4d\x07\x1d\x14\x1d\xbe\x0f\xc1\x79\x02\xf8\x9a\x57\x8f\xca\x10\x75\xd2\x61\x8e\x7d\x77\x15\xb9\x7f\x57\x3b\xd8\x10\x83\x4b\xee\x81\xf2\x4c\x18\x91\xf0\xff\xbf\xf9\xf0\xde\x32\xdd\x1f\xe3\x69\xe9\x4a\x03\x5b\x95\x05\x5d\x61\xfc\xfa\x1d\x91\x6a\x49\x0a\x2a\x51\x97\x7d\xcb\x57\xbd\x9f\x33\xb2\xef\x94\x76\xa9\x0d\x9a\x43\x4e\x0b\xb2\xb1\x03\xca\x69\x26\x72\x23\xd9\x85\x84\xd2\x98\xd2\xab\xb2\xd2\x14\x08\xfe\xf5\x08\xae\xf8\x76\x8c\x2f\x0e\xbf\xd3\x88\xa9\x6f\x1d\x5a\xb3\xcd\x20\x4a\xa8\x4b\x9f\x26\xf9\x71\x12\xa6\x3b\x8c\x43\x72\xc6\xd2\x11\xd2\xa6\xcb\xf4\xc0\xbb\x35\x58\xa8\xeb\xbd\x9e\xb8\x2e\xb7\x61\x00\x46\x97\xea\x49\x42\xb8\xca\xde\xcf\xe5\xb4\x2c\xc4\xc6\xec\xa3\x43\x67\xee\xa8\xb7\x38\x52\x2e\x1c\xc7\xeb\x38\x59\x70\x14\x2f\xeb\xc6\x0a\xe5\xb2\x7b\x59\xf3\x60\xb2\x3f\x6c\x38\x82\xc9\x8e\x6f\x72\x3f\xa7\xe8\x4a\xf3\xfa\xaa\xf6\x68\x34\xd1\x60\x2b\xcf\xfe\x54\xcd\xa8\xe4\x54\x53\xd5\x8c\xef\xc0\xe9\x40\x77\x08\xca\x1d\x63\x4f\x6e\xab\xc9\x7f\xac\x76\x7c\xc0\x16\xaa\x3f\xf2\x80\x45\x54\x7f\xe4\x61\xbb\xc8\xd2\xf1\x6a\xf6\xd0\x86\xb3\x34\x42\x76\x1e\xda\x7c\xa3\x19\xae\x1f\x8a\x42\x8f\xe6\x69\x6e\xd7\x9f\xd5\x22\xbc\xe9\x0d\xa0\x67\x0f\x3a\x34\xa8\x31\xe7\x7a\xfe\xb5\x61\x9a\x15\x22\xbb\x73\x1e\xd1\x8f\xaf\x1b\x28\x66\x0d\x7a\x77\x40\x4c\x60\x0f\xef\xdd\x64\x02\xc6\xe3\x9b\x4c\xc0\x03\x94\x4c\xc0\xce\x30\x3e\x87\x09\x68\xe3\x18\x9f\x57\xfe\x6d\x0d\x61\xaf\x04\xc4\xcf\x25\x19\x98\x64\x60\x92\x81\x87\xb9\x26\x19\x08\xc7\xbe\xdb\x11\xf6\xe4\x41\x7c\xe4\x43\x62\x20\xb9\x87\x3b\x94\xdc\xc3\xdb\x94\xdc\xc3\x0f\x50\xd2\x8b\x49\x2f\x26\xbd\x98\xdc\xc3\xfe\x6f\x91\xdc\xc3\xc9\x3d\x9c\xdc\xc3\xc9\x3d\xec\xc9\x33\xb9\x87\x87\x5e\x32\x99\x80\x31\xf8\x26\x13\xf0\x00\x25\x13\xb0\x33\x8c\xe4\x1e\x4e\xee\xe1\x24\x03\x93\x0c\x4c\x32\xf0\xd0\x67\x9f\x92\x7b\xd8\x5e\x20\xea\xfb\xc3\xf1\x58\xea\x67\xfb\xf2\xf7\x86\x01\xd5\xaf\x3e\xbe\x56\x35\x68\x7a\x60\xa0\x61\x30\x6a\xf8\xeb\xd0\x46\xbd\x6a\x9e\xec\x4a\x2c\x61\x85\x1c\x57\xb9\xe8\xc3\x3d\xa7\x39\xa6\xd9\x9d\x03\xc3\xda\x36\xe6\x58\xb0\x8c\xe9\x62\xd3\x0c\x65\xfa\x6c\x87\xed\x53\x07\x68\xbf\xfa\xf8\xfa\x68\xd7\xbb\x99\x88\xbd\x9b\xc6\x2c\xd8\x9e\x3f\x46\xf1\xb2\x27\x3f\x7a\xf2\xa3\x77\x28\x19\x10\xc9\x80\x48\x06\xc4\xe7\x31\x20\x9e\xaa\x07\x3a\xf9\x8e\x93\xef\x38\xf9\x8e\x7b\x94\x7c\xc7\xc3\x94\xfc\x26\x3d\x4a\x66\x4f\x32\x7b\x0e\x7d\xf2\x9f\xde\xec\x49\xbe\xe3\xfd\x2f\x9a\x64\x60\x0c\xbe\x49\x06\x1e\xa0\x24\x03\x3b\xc3\xf8\xf2\x7c\xc7\xf0\x0f\x84\x16\x27\xc7\x66\x72\x6c\x26\xc7\x66\x43\x49\xbb\x25\xed\x76\xe8\x93\xff\xf4\xda\x2d\x39\x36\x93\x63\x33\x39\x36\x93\x63\x33\x39\x36\x93\xd9\x13\x8d\x6f\x32\x7b\x0e\x50\x32\x7b\x3a\xc3\x48\x8e\xcd\xe4\xd8\x4c\x32\x30\xc9\xc0\x24\x03\x0f\x7d\xf6\x29\x39\x36\x1f\xa5\xf3\xee\x03\xdf\x7b\xa8\xa7\xae\x57\xcf\xc3\xbd\x62\xee\x21\xe1\xf6\x60\x33\xde\x87\xdb\xf1\x1e\x16\x76\x87\x5a\xf2\x1e\xb1\xae\x07\xda\xf2\x3e\x3c\xc3\xb6\x54\xf7\x01\x50\xb3\x59\xb8\xfc\xca\x7e\xb4\xe9\xbc\xd8\x96\x87\x47\xe4\x70\xab\x8d\xf8\x03\x0d\x3c\xfa\xd4\x38\x29\xef\x97\xb4\x6e\x77\x64\x9f\xd2\x76\x4c\x64\x0a\xef\x03\x6c\xce\xf6\x77\xd5\xf5\xe8\x87\x55\xf3\xdf\xf9\xd3\xc3\x0b\xb6\x5b\xd3\x7d\x70\xc2\xea\x49\x7a\x6d\xbd\xf0\xaf\x9b\xd4\xe8\xed\x59\x2b\x89\x34\xf2\xd0\x79\xeb\xf7\xac\x1f\xaa\xf8\x0e\x8f\xad\x95\x78\xa8\xcb\xd8\x03\x7a\xfd\x61\x7d\x3e\xe9\xe4\x73\x0f\x8f\xeb\xb0\x1a\x77\x3d\x53\xae\xa9\x5c\x31\xa5\x86\xc1\xf3\xfd\xe1\x3e\x2c\x12\x0f\x8a\xc2\x3d\x6b\x50\xbf\x47\x67\x20\x8d\xe1\xf5\x60\x4c\xc4\x90\x9c\x91\x0c\x64\x55\x50\xdb\xec\xcd\x15\x57\x07\x92\x65\xa2\xe2\x1a\x5b\xb7\xb6\x4d\x92\xb7\x77\xef\x41\x31\x7b\xd0\xee\x3a\xc6\xea\x9a\xd8\xf1\x3d\xf8\x09\x37\xee\x4b\x3b\xec\x9d\xa2\xfd\x7d\x3a\xd6\x42\xc3\xc7\x1e\xd2\x4d\xc7\x2b\xbb\x23\x55\x5d\x6f\x95\xaf\x45\xc1\xb2\xcd\xc7\xaa\xa0\xae\xe1\x20\xe3\x56\x6f\x37\x61\x92\xc6\xc4\x3e\x42\x87\x12\x28\x91\x1f\xbe\xd9\x39\xcc\x2a\x0d\xb9\xa0\x0a\x3b\xfb\xb9\xb2\x0a\xdd\x07\x1c\xc3\xd1\xf5\x42\xb3\x8d\x49\x0c\x5b\x20\x65\x59\x30\x8a\xa1\x39\x21\xe1\x7e\xc9\xb2\xe5\x03\x1d\x2c\x77\x69\x80\xd1\xb1\x96\xcf\x11\x66\x3e\x1c\x6d\xea\x43\xed\x91\x9b\x1d\x9e\xda\xe3\x6d\x7e\xb0\x35\x8e\xbe\x91\xa2\x2a\x8f\xfa\xf0\xae\xff\xd4\x7e\xb7\xee\xf5\xd6\x6d\xa7\x54\xff\xf1\x28\xb6\xe0\xc2\x6c\x76\xdd\xeb\xc6\x71\xce\x31\x3c\xc5\x44\x9a\x55\x55\x68\x56\x16\xc8\xf8\x48\x9e\x0b\x3b\x38\x22\x69\xab\xd7\xce\x81\xf0\x4d\x1d\xdb\x73\x0d\x52\x68\x0e\x64\x61\x9e\x7b\x78\xb9\x2c\x09\xde\xbc\x26\xe5\xd5\x8a\x4a\xec\x85\xdc\x0c\x18\x2f\x96\x7c\x63\x46\xfa\x60\x29\xa7\x6d\xaa\x7b\x83\x93\xa2\x10\xf7\xfb\x5a\x5a\x6e\xd3\x18\x03\x17\xc6\x18\xb9\x30\xd6\x88\x07\xe0\x82\xd7\x0e\xf5\x6f\x3f\xbe\xf5\xd9\x52\xef\xfb\x1c\x5c\x8f\x1d\xdb\x52\xbc\x24\x52\xb3\x07\x9b\x18\x77\xa9\x92\x85\xeb\x3e\x4e\xcc\x45\x48\xd6\x2d\x8d\x96\x64\x4d\x9b\x7e\xe3\x62\x0a\xf0\xaf\xc7\x48\x2b\xc0\x9e\x23\xcd\xd2\x58\x79\x25\x78\xb1\x01\x62\x77\xeb\xbc\x2a\x8a\x73\x98\x33\x4e\x8c\x4a\xa2\xc7\x2e\xb9\xcb\x05\x33\xb7\x59\xb8\xc1\x56\xe5\x5c\xf0\x49\x63\xac\xe1\x1c\x98\xe7\x72\x71\xec\xde\x6c\xc4\x5b\xee\xda\xb6\x3a\x5f\x87\x72\xc3\x35\x82\x2c\xc3\xb6\x92\x73\xf1\x50\x25\x9a\x2e\x39\x23\xf3\xa3\x28\x30\x20\xe2\x42\x25\xb9\xed\x49\x44\xba\x7f\xfe\x4f\xc6\x8f\xbb\x1e\x5a\xfa\x88\xca\x3e\x23\x1c\x28\xd3\x4b\x73\xbf\x2d\xcb\x62\x63\xc4\xb5\x39\x3b\xed\x81\x3a\x55\x55\xf6\xb0\xa7\xa3\x25\xa2\xe0\x59\x29\x72\xf5\xcc\x88\xfc\x67\xae\x0f\xfd\xb3\x33\xf3\xd3\xf6\xdc\x1e\xc9\xd1\xac\x8e\x1b\x03\x72\xbf\x20\x25\x7b\x76\x76\x0e\xb8\x09\xb0\xa9\x92\xd0\xcb\x2f\xef\xb4\xd6\x33\xd1\xe9\xcc\x77\x88\xb6\xfa\x7c\x76\xbe\xef\xba\x04\x89\xd2\x36\xd5\x31\xba\xf6\xe0\x55\xbe\xa6\x82\x29\x3c\xe0\xb6\xbb\xaf\x6b\x53\xb7\xab\x78\x01\x2e\x8f\x31\x03\x0c\xd1\x55\xa9\x37\x28\x37\x56\x94\x70\xc7\x13\xbb\xfc\xeb\x25\xe3\x0b\x1c\xec\x97\x2a\x64\x8f\x0a\x98\xb6\x34\xb8\x64\x4e\xb0\xd6\x13\xdf\xb0\x3c\x5a\x59\x33\x35\xb0\x3c\x35\xf7\xcb\xa2\xe8\x5c\xbe\x8e\x3d\xb6\xf8\xa5\x5a\xe5\x7f\x71\xab\x82\xb6\x99\xc7\x8a\x7c\x67\xbe\xd7\x5f\x0d\xfb\x2b\xab\xba\x8c\x38\x3c\x76\xc0\x02\x2e\xdf\xbe\xb5\x6d\xe7\xdc\x3c\xfe\x89\xf1\xdc\xde\xa5\x2e\xb5\xed\xd9\x46\x3f\x52\xf3\x4a\x68\xfe\x1c\xbb\x32\x75\x91\xb3\xbc\x69\x1e\x6c\x96\x7e\x0a\x38\x50\xef\xb5\xc6\x4e\x70\x5f\xd2\x3a\xef\x5e\xeb\x8e\xbb\x8e\x3d\xc8\xba\x73\xf3\xff\xbc\x17\x76\xec\x86\xd7\xb3\xbf\x8d\x34\x3e\x3f\x1c\x20\x36\xbb\xab\x20\x33\x5a\xd8\xc6\x77\xe6\x9b\xed\x4b\xc1\xe5\xdb\x77\x4d\x2f\x49\xec\x97\xfc\x8f\xba\xa6\x1f\x00\x38\x4c\x0e\xbd\xd8\xb1\xb7\x28\x7c\xf5\x31\xc1\x15\xb8\xa1\xda\x9e\xf7\x15\x29\xcd\x71\xb7\x1c\x6c\xa4\xa0\x1f\x07\x38\xb8\x83\xdf\xe2\xbc\x1f\x3a\x44\x23\xee\xa3\xc7\x76\xc5\x1b\x7a\xc0\x11\x47\xe8\x18\xcc\xc6\xf1\xe7\x71\xaf\x7f\xb0\xa5\xde\xc4\x6f\x6d\x76\x77\x67\x75\x37\xc3\xcc\xba\x31\xc4\xfc\xf0\xdb\xe2\x0e\x57\xb6\x50\x04\x5d\x92\x35\x13\xb2\xbe\x0d\xb6\x8f\x88\xb8\x28\xc7\xba\x08\x26\xa0\x68\x41\x33\x7d\xd0\xac\x9f\x80\xa6\xab\xb2\x78\xf8\x34\xc2\x48\x57\xc2\x8a\xf1\x8f\x94\xe4\x9b\x1b\x9a\x09\x9e\x1f\x25\x7e\x7b\xab\xf3\x8e\x71\xb6\xaa\x56\xc0\xab\xd5\x8c\xe2\x84\x2a\xcb\x09\xc5\x0a\xba\x6e\x8e\x92\xe8\x04\x38\xbd\x2f\x36\x75\x7b\x76\x28\x45\x5e\x4b\xa0\x19\x76\xa3\xcf\x37\xd8\xa9\x52\x54\xda\x5c\xd2\x8f\xe2\x29\xe6\xb6\x0f\x7d\x5d\xed\x13\x32\x49\x94\x31\x24\xcf\x71\x70\x4c\x1b\xe5\x3b\xa3\x18\x07\x66\x39\x95\x83\x05\x46\x06\x86\xba\x26\xac\x30\x57\xb1\x29\xbc\xa6\x73\x52\x15\xd8\xaa\x15\x9e\xc3\xa9\x19\x74\xed\x0d\xf0\x65\x6a\xae\x2a\x4a\x08\x6e\xfe\x6b\xeb\x8b\xe0\xcb\x9f\x1d\xe3\xf6\xc2\xcd\x79\xb8\x5a\x69\x4d\xc7\x55\x2d\xad\xa9\x24\x95\x3a\xc6\xe1\xb5\xb5\x41\xae\x78\x6e\x4e\x69\xf7\x86\xd0\x51\x34\x4c\x39\xbe\xc7\x98\x14\xf6\xfd\x66\x42\x14\xf4\x88\x58\x6a\x29\xc5\x42\x52\xa5\x5e\x53\x92\x17\x8c\x53\xdf\x1d\x7e\xbb\xa4\xb0\x22\x9f\x70\x97\x6b\xb6\xa2\xc6\x9c\xea\xee\x71\xd2\x79\x9f\xe3\xec\x22\x01\x2b\x72\x47\x9b\x01\xc2\x8c\xce\xb1\x89\x2f\x4e\x47\xbb\x6f\xec\xee\x3c\x8a\xe5\x9c\xb0\x82\xe6\x53\x1c\x6b\x67\x76\xdb\x9e\xf7\x76\x5b\x9a\x9f\x19\xaf\x8e\xe3\xa9\x85\x19\x21\x3a\x5c\x2c\xfb\xae\xd5\x83\xf6\x03\x31\x0c\xad\xe6\x39\x8a\xa3\x39\xbf\x40\xe0\x7a\x6b\x61\xde\x7c\xca\x6c\x88\x40\x52\xa2\x04\xaf\x4f\xd0\x51\x2c\x55\x25\xe7\x24\xab\x6d\xdc\xde\xcb\xbb\x46\xe6\xf0\x5e\x68\xd7\xc2\xb6\x9e\xf0\x23\x07\x5b\x14\xe0\x5a\x2f\x53\xa5\xd9\x0a\xc5\x52\x5e\xc9\xba\x49\x34\xee\x85\xd1\x8b\xdf\x6e\xf8\x9e\xf0\xf8\xfd\xf3\xe7\x47\x59\xd5\x8f\x7b\xc4\x25\x45\x2f\xd3\xf8\x33\xf2\xbe\x91\xfe\xb5\x8a\x2d\x45\xae\xcc\x7e\x64\xee\x96\x84\xbd\xaf\x8f\x1a\x32\xee\xbc\x9c\x29\xcd\xf8\xa2\x62\x6a\x09\x33\xaa\xef\x29\xe5\x40\x3f\xd9\x3a\x4b\xf0\x77\x2a\x05\x6e\x40\xb3\x3c\x0f\x84\x3e\x87\xa8\x3b\xe9\x2f\x9e\xc2\x8c\xaf\x99\x62\x82\xff\x91\x29\x2d\xe4\xe6\x2d\x5b\xb1\x07\x0b\x52\xd7\xb4\x23\xa1\x5a\xfd\x2b\x8a\x1c\x3b\xfe\xb3\x8c\xdc\x50\xfb\xa2\x92\x1a\x05\x78\xec\xdc\xa3\x8b\x05\x8c\xdc\x98\x91\xec\x6e\x60\x11\xb7\x16\xe8\x28\xbe\xc7\x2e\x62\xb3\x40\xc7\x8e\xf6\xc5\xf3\xcf\xbf\x8a\xb5\x01\x37\x7a\xe5\xf0\x26\xd0\x7c\x1d\xd5\x89\x3d\x38\x6f\x3e\xd9\xf9\xed\xae\xe4\x71\x62\x6b\x29\x14\x45\x26\x36\x80\x82\xac\xeb\xf0\x2b\x53\x8d\x79\x62\x24\x98\xe0\x47\xba\x8e\xc8\x7c\xde\xe7\xd2\x0a\x3d\xbc\xfb\xac\x2a\xa5\x61\x45\x74\xb6\x3c\x18\x2c\xae\xc9\x98\x4a\xb5\x39\x7b\xa2\xdc\x55\xf4\xf8\x95\x3c\x32\x4c\x37\x36\xac\x06\xf6\x2d\xde\x7c\x2a\x8d\x9e\x78\x38\x1e\xdf\xa7\xde\xb2\x6e\x33\xe9\x3b\x8a\xf0\x5d\x8f\x64\xdb\xee\xad\xfa\x3e\x81\xea\xd7\x6a\xfa\xee\x6f\xcc\x6a\x1f\xcd\xf3\xf2\xfd\xeb\x63\xe5\xe5\x78\x37\xce\x48\x47\xce\x76\x70\xd2\x4e\xcf\xe0\x6b\x1f\xcd\x11\xea\x00\x94\xe3\xd1\x8f\x52\xe2\x9d\x5d\x9d\x03\x81\x3b\xba\x39\x1f\xc1\x14\x6d\x9e\x4e\x81\x41\x64\x2b\x69\xe1\xac\x5b\x8a\xfd\xf5\xc9\x81\x24\x8e\x3e\xd9\xb1\x1c\xbb\x14\xa3\x77\xbf\xa5\xe3\x83\xd5\x35\x4d\xcc\xab\x8c\xf8\x74\x3d\x25\x47\x7f\x65\xec\xb1\xb4\x74\x47\x37\x63\x3e\xbe\xb5\xb5\xcc\xea\x38\xef\x81\xdd\x63\xe6\x17\x66\x0d\x47\xb1\xb4\x9e\x84\x66\x6b\x8d\x41\x18\xf4\x98\x8c\xf3\x53\xd7\x54\x4f\x74\xc0\x34\x34\xdb\xb7\x03\xb4\xc2\xa3\x70\x72\xac\x1f\xb8\x26\xdc\xfa\x46\xbe\x2d\x59\x89\x86\x43\x1d\xf2\x75\xbb\x1a\xbe\x23\x05\x1b\x73\x1a\xba\x6f\x68\xf5\xd7\x15\x3f\x37\x06\xbc\xf9\x0f\xaa\x44\x35\xf2\x7c\x19\x7a\x2d\xa8\x7a\x2f\x34\x7e\xff\x1f\xb2\x48\xf6\xf5\x03\x96\xc8\x32\x70\xb1\x39\x94\xbc\xe8\x58\x19\x3b\x8e\x76\x2c\xd3\xba\xa6\x69\xb3\xf8\x4c\xc1\x15\x07\x21\xdd\xec\x7a\x1c\x01\x37\x48\x3b\x3c\xb4\x00\x66\x36\x0c\x8e\x51\xbc\x71\x13\x0d\x43\xe3\x73\x0b\x2e\x64\x6f\x05\xa3\x0d\xd5\x0e\x13\xad\xdb\x91\x2c\x2d\x1f\xf4\xcc\x94\x05\xde\x3e\xdd\xb5\x90\xd4\xb0\x36\x76\x28\x3b\x6b\x9b\x56\x54\x2e\x10\x4f\x90\x1d\x19\x91\x6e\x5e\x6f\xb4\x76\xb6\x34\x52\x47\x77\x1f\x36\x62\x1f\xa2\x21\x64\xdd\xdd\xfe\x86\x94\xfd\x7e\xcf\xf9\xfe\x7f\x8d\xe6\xc6\x55\xfd\x7f\xc7\xab\x1c\xc2\xa4\x9a\xc2\x25\x28\xc6\x17\x05\xed\xf2\xa8\xbd\x07\x9d\xc7\x1d\xcd\xd6\x8c\x88\x29\x30\x2a\x76\x4d\x0a\xca\xd1\xa9\x48\x38\x50\x1b\x0d\x30\xa3\xdd\x36\x07\x8f\xdf\xc2\xd6\x9a\x37\x7a\xaa\x81\x83\x3c\xbb\xa3\x9b\x67\xe7\xdb\x87\xe5\x68\x8e\xcf\xae\xf8\xb3\x73\xb4\x64\x76\x0e\x46\x63\x20\x21\xe2\xe4\x19\xfe\xed\xd9\xf1\xbb\x71\xc8\x22\xf5\xb1\x34\x47\x19\x37\x7e\x91\x8f\xfe\x03\x8f\xdc\xcf\x35\x62\xd5\xeb\x7a\xde\xf3\x4b\x39\xdc\xb6\x16\x50\x29\x6a\xef\xe7\x28\x47\x8e\x1a\x37\xad\x6f\x86\x78\xc7\x43\x97\x1a\xa7\xf7\x78\x97\x7b\x02\xd7\x27\x29\x8a\x82\xf1\xc5\xb7\x65\x4e\xf4\x11\x69\x39\x96\x7a\xb3\x75\xf2\xd1\xb2\x80\x0a\x79\x98\x5d\x39\x67\x0b\x28\x89\x24\xab\x11\x86\xf2\xb5\xab\xda\x8d\x7b\x99\xcd\xbb\x51\x24\x37\xff\xb7\x9b\x92\xc2\xff\x84\x8f\xdd\x11\x1f\xcf\x7f\x32\x99\xc0\xed\x87\xd7\x1f\x5e\x82\xfd\xa6\xbd\x17\x6b\x01\x73\x81\xee\x13\x51\x49\x33\xf4\x35\xe5\x47\xbb\x47\xc1\xfa\x1d\xcc\x52\x7e\x98\x9f\xc3\xfd\x92\x68\xba\xa6\x12\xee\xcd\xf6\xc9\x58\x4e\x9b\x88\xc5\xf4\xe4\xf1\x4e\x94\x8f\x65\xbe\x22\x9f\x6e\x2a\xb9\x38\x7a\xc1\x61\x67\xd1\xbb\x4e\xf6\xd6\x95\x65\xb6\xf8\x38\x6d\xd8\xa9\xfa\xa2\xb2\x25\xcd\xab\x82\xe6\x40\x66\x62\x4d\xbb\x01\xc0\x51\x3c\xfb\xc3\x41\xa3\xb6\xa2\xf5\x43\x8c\x7d\x36\x53\xa2\xa8\x8e\x46\x4d\xf5\x98\x9e\xd2\x4f\x2f\xe1\x77\x08\x72\x23\x50\x52\x99\x51\xae\xc9\x82\x76\x1c\xa9\xa3\xb8\xa2\x48\x40\x9e\x2f\x9e\xff\xcb\x99\xf3\xdc\x99\x91\x3a\x3f\xf6\x73\x73\x12\xde\x91\x4f\xdf\xf2\x26\xdc\x34\xce\x68\x50\xf0\x7c\x0a\x97\xee\x85\xeb\x97\xc0\x67\x14\x59\x55\xa0\x87\x7c\x2e\xc5\x6a\xdc\xa0\xdb\xd7\x9e\x6d\x40\x8a\x0a\xa1\x88\x50\x95\x3d\x0f\xf9\x28\x96\xbf\xf9\xdd\xbf\x4c\xe1\xcd\x27\xb2\x2a\x0b\xfa\x12\xee\x97\xd4\x01\x60\x98\xc2\x1b\x8a\x16\xf0\xdb\xe7\xff\x32\xce\x90\x44\x68\x05\xbd\xef\xf8\xe3\xda\x7d\x46\xcc\x26\xab\x4a\x60\x2b\x9b\x68\x44\x8f\x06\xff\x58\x72\x03\xa4\xb5\xf4\xac\x45\x9f\xd2\x44\x6a\x75\x0e\x88\x60\x1c\x7d\x51\xc5\x18\x85\xd0\xa4\xd8\xf2\x0d\xa3\xcf\x95\xde\xdb\xcd\x92\x8f\x9b\x58\xb3\x8f\x28\x86\x6b\xe0\xc5\x6f\x9f\xff\xcb\xae\xc3\xff\xc3\xa1\x3a\x4a\xdb\x64\x46\x84\x23\x41\x80\xef\x8c\x52\x0e\x77\xac\x28\x68\x7e\xbe\x35\xdd\xa3\xb8\xee\x2c\xcd\xbc\x92\x7a\x49\xe5\x39\x50\xae\xea\x10\xce\xd8\xf9\xdc\x9a\x4b\x1c\xb5\xac\x38\x47\xcb\x1f\xa3\xd2\x18\x13\x1a\x77\xed\x6b\xe3\x49\x6e\xd1\x8d\x99\xab\x61\x25\x94\xde\x9e\xe2\xd1\xa2\xe0\x68\x35\x01\xe8\xdc\xda\x7c\x98\x8f\x11\xe0\x93\xd1\x4e\xf5\xed\x6f\x8e\xbe\xd0\x7e\x9a\xdc\x35\x15\x5e\x26\x8c\xeb\x89\x90\x13\xcb\xe4\x25\x68\x79\x64\x5c\x13\xac\xc2\xea\xc8\xc0\x27\xa5\xb6\xaa\x76\x5c\xbb\xbb\x63\xdc\xdd\x70\x9f\xa6\xda\xd2\x3e\xe3\xce\xeb\x5e\x4d\xb5\xad\x7d\x46\xb1\x3d\xac\x53\x3a\x0f\x1d\xc5\xb9\xab\x53\x72\x71\xcf\x87\xb5\xe2\x28\x96\xef\x9c\xb9\xe3\xf4\x61\x37\xa4\xd8\xd3\x3c\x3e\x4a\x60\x47\x4b\xd9\x9b\x5e\x2f\xa6\x17\x20\x0a\xcd\x0c\x18\xce\xff\xbf\x5d\xe1\x3d\xce\x12\x68\x55\xdd\x01\xf5\x35\x6e\x1f\x7c\xc0\x5c\x8a\x5a\x3b\x99\x1b\x24\xa2\x5f\xce\x23\xcf\x40\xa3\x0e\xac\xb5\x8e\x91\xad\x51\x3c\x0d\x33\xfb\xaa\x03\x96\x41\xab\x65\xc6\x4b\x81\x21\xad\x6d\xe7\xc2\xcb\x62\x33\x7a\xa9\x28\x50\x2f\xa9\xbd\xca\xa6\xa0\xe4\xe8\x1c\x2a\x4b\x03\xdb\x27\x29\x9b\x21\x7a\x28\xe9\x7c\x9b\xfa\x4e\x03\x73\x3b\xc5\x29\x6e\x23\xad\xaf\xec\x46\x7e\xf6\x91\x5a\x94\xdc\x6e\x93\xa9\x7d\x24\x24\x3c\xeb\x5d\x74\x9f\x35\x62\xcb\xec\x01\xaf\x3b\xf0\xa8\x69\xad\x43\xbd\xe3\x9d\x27\xee\x8b\x9d\x3a\x30\x98\x79\x65\x8e\x04\x1e\x98\x7b\x56\x1c\x17\x4c\x9d\xd1\x1a\x5c\xf8\x04\xfc\x24\x2b\xaa\xc9\x43\x25\x0d\xb6\xa9\x6f\x76\xdc\x68\xc2\x73\x22\x73\x37\xbe\x93\x13\xd5\x30\x9c\xc2\x3b\x31\x22\x12\xcc\xf8\x5c\xbc\x84\xa5\xd6\xa5\x7a\x79\x71\xb1\x60\x7a\x7a\xf7\xef\x6a\xca\xc4\x45\x26\x56\xab\x8a\x33\xbd\xb9\x40\x10\x19\x9b\x55\x5a\x48\x75\x91\xd3\x35\x2d\x2e\x14\x5b\x4c\x88\xcc\x96\x4c\xd3\x4c\x57\x92\x5e\x90\x92\x4d\x5a\x6f\x87\x9a\xae\xf2\x5f\xd6\x03\x7a\x44\x57\x45\xef\x84\x62\x2c\x4b\xae\xe9\xa4\xe2\x77\x5c\xdc\xf3\x09\x7a\x4c\xd5\x88\xb3\x7a\x0c\x32\xb9\xa6\xad\xf5\xd8\x02\x23\x0f\x82\x8d\x8f\x3f\xac\xf3\x7a\x8b\xdb\xc5\x7c\xc4\x45\x32\xaf\x3c\x21\x3c\x9f\x58\xb0\xdc\x23\xae\xd5\xd8\x18\xf4\xa4\x85\xed\x1e\x6b\x99\xf8\x78\xae\x48\xa6\xd9\x9a\x7a\x40\x44\x6b\xea\x6d\x84\x0f\x75\x1a\x5d\x5e\x49\xbb\x17\x5a\xac\xe8\xe8\xbb\x7b\x29\x72\x58\x91\x0d\xda\xee\x38\x4a\x10\xd6\xcc\xe2\x22\xa7\x2e\xf6\x7a\xb0\x1a\xf2\x16\x5b\x01\x37\xc6\x28\xbb\x65\x2b\x5a\xa3\x4e\x31\x9a\xbd\x51\x9a\xae\x2c\x36\xc8\x3e\x6b\xa4\x07\x43\xcb\x8d\x85\xb5\xca\x3b\x60\xba\xc6\x8b\x12\x9e\xe3\x65\x1e\x88\x52\x22\x33\xd6\xe2\xb8\x3b\x6c\xbb\x03\x6a\xaf\x5b\x1d\xbb\x23\x50\x0a\xc5\x70\x52\x9c\x45\x30\xc6\xcc\xf4\x35\x25\x3a\xa0\xb0\xdf\xff\xdb\xf1\x5b\x6c\x8e\x0d\x2e\x47\x21\x17\xfa\x08\xea\x79\x37\x0f\xde\x6d\x8d\x13\x55\x3b\x38\xc7\x9a\x99\x99\xe0\x4a\x4b\xc2\x8e\xcf\xfb\x02\x5f\xe0\x89\x2f\xce\x03\x70\x8f\x5f\x7a\x4c\x1c\xec\x66\x8f\xd4\x66\x03\x1e\x9b\x7a\x31\x46\xb2\x84\xce\x64\xbb\x52\x27\x75\xd6\x94\x11\xd3\x5e\x61\xd4\xd1\x73\x09\x01\xf3\x69\xbf\x4b\xe7\x54\x4a\x9a\xbf\xc6\x7b\xc0\x4d\xf3\x46\x57\x0b\x2e\x9a\x5f\xbf\xf9\x44\xb3\xea\xb8\x7a\x72\xbb\xb4\x13\xf7\xaa\x9d\xf0\xf2\x78\x3b\x6d\x78\xd8\x46\xbc\xd4\xcc\x9c\xf5\x27\x70\x49\xc7\x06\xef\x2d\xa1\xe9\xa8\x88\x66\x6a\x6e\xeb\xd2\xd4\x1b\x03\x68\x1b\xa7\xf5\xe2\xdc\x1c\xd5\x06\x2c\x89\x86\x88\x2d\x3d\x70\xa0\xd2\xe0\x3e\x32\x6a\x20\x5b\x0a\xa1\x8c\xe4\xc3\x7d\x8c\xe3\x5f\x33\x81\xd8\x33\x2f\x9e\x58\x0c\x43\xc2\xca\xe8\x80\xba\x28\x46\xfb\xea\x63\xb7\xb4\xa5\xdb\x5a\x3b\xe1\xf0\x98\xb2\x6e\xcc\x66\xdf\x79\xf1\x74\x88\x2d\x33\x5c\x0c\x76\x9a\x1f\x16\x68\xc7\x2b\x0d\xaa\x1a\x17\x6b\xa8\x49\xcc\xe1\x9e\xb2\xc5\x52\xab\x73\x60\x53\x3a\xc5\xd3\x4c\x49\xb6\xc4\xe1\xfb\xef\xa8\x15\xa5\xba\xd7\xbd\xd8\x53\x46\xd7\xd4\x8b\xa7\x9f\x36\x35\x10\x5c\x01\x94\xb1\x50\x98\x1e\xcf\x1d\x29\xe0\x2f\x1b\x01\xc3\xd2\x2d\xbc\x01\xa8\xce\xa6\x67\xe7\xd0\x94\x29\xf4\x3b\x48\xd5\xca\x1c\x21\xa6\xa9\xb1\xa5\xd0\x6f\x21\x45\xb5\xb0\x3b\x80\x1e\x9b\x6b\x39\x44\xb8\x36\x4d\x89\x0d\x44\x75\xe6\xe8\x1f\x7c\x66\x37\xc5\xf1\xf7\xea\x2e\x69\x5b\xc0\xc8\x0c\x9b\xcd\x5b\x43\x0d\xc1\x1f\xde\x52\x8a\x42\x26\xa4\xa4\xaa\x14\xd6\x83\xb9\x0d\x25\xf9\x1f\xde\x7c\xcd\xe0\x4e\xd5\x59\x7b\xa8\x96\x6c\xb1\x0c\x39\x53\xc4\x19\x93\xfd\x33\xef\x23\x48\x7c\x31\x4d\x96\xbc\x90\x4d\x96\xfa\x48\x64\xee\xea\x51\x84\xc9\xaf\x9e\xe9\xa0\xa9\x5c\xd5\x3b\xc2\x88\x09\x4f\x8e\xd6\x74\x70\xe8\x8f\xba\xfd\xb8\x93\x68\x9e\x2c\x9f\xc3\x29\x0a\x42\xa6\x4f\x14\x2a\x99\x89\x28\xcf\xa6\x70\x09\xbc\xf2\x1e\x66\x33\x71\xfb\xa6\xc0\x93\x2f\x17\xcd\x0c\xb8\x41\x9b\xc9\x54\xa2\x1d\xb7\xdf\xa9\xf0\x37\xcb\x2c\x8d\xc7\x59\x77\x69\xe2\xe6\x8b\x8e\x0d\xa1\xb6\x0c\x02\x76\x40\x88\x61\x59\x73\xa8\x47\xef\xcb\x61\x27\x15\x00\x05\xe8\x91\xd9\xd1\x0f\x91\xd9\x73\xe7\x9d\x5b\x68\x23\xf4\x02\x78\xf6\xe5\xb2\x9d\x79\xbf\x7d\x07\x31\xf6\x1e\x44\x59\x43\x08\xc8\x80\x19\xa6\xed\xe4\x0e\x9b\x03\x13\xc4\x12\xfa\xfb\xa2\x67\x24\x05\x32\x9e\x6d\x90\xf7\xa8\x84\xa4\xfd\x14\xa6\xc7\x5a\x0a\xd0\x68\x2d\x0d\x1c\xad\x40\x8e\xc3\xb9\x49\xc1\x4c\x77\x53\x77\x82\x59\xee\xa6\xfe\x04\xb3\xbc\xa3\x9b\xf3\xed\x84\xa0\x60\xa6\x43\x09\x45\xc1\x4c\xcd\x20\xc7\xa6\x19\xed\x19\x5e\x0c\x21\x65\x29\x4c\x55\xb6\x34\x2e\x51\x69\x1f\x8f\x48\x0b\x18\x47\xfe\x5a\x1a\x9d\xea\x34\x4c\xdb\x0e\x99\x08\x2c\x21\x2c\x7b\x6a\x98\x86\x72\xaa\xe2\x30\x1e\x99\x97\xb5\x87\x8b\x5f\x08\x79\x98\xfc\x72\xb8\x86\x69\xab\x4c\xdc\xc8\x82\x5e\x0f\x93\x4b\x0a\xeb\xa5\x79\x45\x5a\x93\x9d\x54\xb1\x28\x7c\x31\xdd\xac\x4d\x20\x8b\x33\x09\xbd\x24\xb4\x28\x2c\x6d\x5e\xd3\x79\x40\x5e\xda\x3e\xfa\x46\x5b\x9d\xf4\x36\x0a\xbf\xa8\x9b\xde\x27\x27\x6e\x98\xb6\x2e\xe9\x91\x56\x39\x24\xc7\x6e\x98\xfa\x99\x77\x51\x58\xf6\xb3\xf7\xe2\xb0\xac\x33\x00\xa3\x0d\x72\x27\xd9\x2e\x0a\xd7\x90\xdc\xc2\x61\xda\xca\x38\x8c\xc2\x33\x5a\xd6\xe2\x30\x6d\xa7\x6c\x45\x61\xda\xcf\x87\x7c\xca\x53\xfb\x8d\x36\xd3\xfa\x56\x3f\xf5\xbd\x6a\x6b\x55\xbb\x3c\xc3\x28\x1c\x9d\xbb\xfb\x7c\x44\x41\xb5\x43\x54\x17\x02\xc1\x8a\x2e\xa5\xa4\x63\x83\xf3\xfb\x88\x60\xd2\xb2\x47\x54\x7e\x3f\x21\x60\xb7\x4e\xba\x8d\xc2\x71\x2b\x71\x37\x92\xb9\xd4\x24\xff\xda\x74\xde\x28\x5c\x3d\x52\x82\x87\x29\x96\x33\xc2\x52\x14\x97\x44\x77\x60\xc1\x8a\x17\xdd\x56\x5f\x5b\xcc\xd7\x3f\xa5\xc7\xca\xe2\xdd\x92\xc7\xea\x41\x4a\x1e\xab\xe4\xb1\xf2\xa3\xe4\xb1\x3a\x40\xc9\x63\x95\x3c\x56\x47\x50\xf2\x58\x75\x28\x79\xac\x92\xc7\xca\x8f\x92\xc7\xea\xa9\x7b\x01\x92\xc7\x2a\x79\xac\x92\xc7\x2a\x79\xac\x92\xc7\xca\x93\x7e\xce\x1e\x2b\x8b\x17\x8b\x04\x94\xfb\x33\x32\xf3\xcd\xb2\xda\x1a\x18\xd3\x4b\xeb\x4b\xab\x53\xc5\x7b\x40\xb7\x00\xce\x5c\xe4\xf4\xc6\x5d\x98\x6e\x11\x90\x67\xab\xee\x05\xb0\x94\x84\x2f\x28\xbc\x98\xbc\x78\x7e\x54\x11\xf0\x61\xf2\xcd\x06\xeb\xd3\xb8\x82\xe1\xdb\xb4\x0f\x93\xff\x48\x99\x39\x4e\xdb\x35\x39\x2f\xc1\xfe\xc8\x3d\x49\x2f\x23\x7b\x60\xf6\x69\x45\x35\x10\xdd\x83\x0e\xb3\x15\x6d\x12\xe0\xbc\x78\x76\x9b\x3a\xb4\xf5\xc1\x04\xb7\xd8\x7d\x2f\x96\x66\x5b\x4f\xff\x71\x33\x9a\x51\xa2\x3c\x13\x54\xb0\xd7\x4d\x3d\xab\x62\x45\x6d\x39\xff\x10\x85\x52\x8a\x1c\x68\xbd\x2b\xe1\x94\x4e\x17\x53\xc8\x2b\x6a\x2b\x60\x7a\x71\xb4\x75\x29\xce\xce\xbb\x69\xa9\x2b\x73\xd1\x91\xe6\x3f\x9e\x0b\xa4\xeb\xfc\x54\xba\xa6\x5c\x57\xa4\x28\x36\x40\xd7\x2c\xd3\xde\x8b\x6e\x5e\x1c\x8b\xd2\x30\x6d\x13\x0b\xfd\xd3\x1c\xbc\x9d\x93\x21\x0e\xc9\xc9\x8e\x34\xf6\xd9\xa5\xa1\xde\xc3\x9d\x31\xf8\xea\xc3\x2d\x9f\x92\x9d\x97\xa9\x0b\xde\x78\x8b\x74\x31\xdf\x0a\xdb\x68\x33\xc6\x69\x90\x53\x12\x59\xa0\x58\xfc\xf0\xd1\x2f\x39\x06\xa2\x58\x46\x81\xd6\xd0\x76\x68\xa6\x2a\x0a\x73\x44\xf1\x42\x16\x68\x22\xf4\xa7\x3b\x30\x53\x04\x7a\xd9\x22\xbb\x5d\x13\x02\xd8\xda\x04\xbf\x55\xa7\xca\x2d\x72\xbf\x15\xa5\x28\xc4\x62\xd3\xdd\xd7\x01\x4f\x31\x2b\xdd\x69\x2d\x68\x4c\xf6\x6a\xa6\x46\x16\x40\x1a\x1a\x38\xbc\xdf\x3a\x7c\x29\x77\x61\x87\xbe\xd4\x48\x70\xca\x5d\x38\x82\x52\x24\x38\x45\x82\xfd\x28\x45\x82\x0f\x50\x8a\x04\xa7\x48\xf0\x11\x94\x22\xc1\x1d\x4a\x91\xe0\x14\x09\xf6\xa3\x14\x09\x7e\xea\xd1\xb5\x14\x09\x4e\x91\xe0\x14\x09\x4e\x91\xe0\x14\x09\xf6\xa4\x9f\x73\x24\x18\x52\xee\x42\xca\x5d\x38\x8a\x92\xc7\x2a\x79\xac\xfc\x28\x79\xac\x0e\x50\xf2\x58\x25\x8f\xd5\x11\x94\x3c\x56\x1d\x4a\x1e\xab\xe4\xb1\xf2\xa3\xe4\xb1\x7a\xea\x5e\x80\xe4\xb1\x4a\x1e\xab\xe4\xb1\x4a\x1e\xab\xe4\xb1\xf2\xa4\x9f\x9f\xc7\xaa\x14\x79\xe4\x86\x1c\xa5\xc8\x23\xf6\xe3\xb0\xe8\xe3\x4c\x4c\x0a\x91\xd5\xfd\xb8\x47\x73\x35\x43\xb2\x59\x09\xa0\xc8\xca\x16\x49\x3f\x87\xbf\x0b\x4e\x6d\x51\x7b\x20\xe3\x79\x22\xd4\x5a\xe8\x25\x95\x86\xfd\xa9\x3a\x1b\x5d\x9e\x3a\xf5\x0b\x19\x3f\xec\xd4\x2f\x24\xf5\x0b\x49\xfd\x42\x52\xbf\x90\x2f\xae\x5f\xc8\x92\xa8\xf1\xed\x78\x6b\x42\x83\xb5\x69\x30\x11\x27\x7b\xaf\xa3\xf8\x6f\xa9\x5c\xfd\x8f\x9d\xee\x21\x9e\xdb\xbf\xd7\x71\xe4\x67\xd7\x3d\xc4\x88\x36\x27\x32\xcc\xfe\x09\xe8\xf5\x61\xf7\x86\x5d\xd3\xdc\xe5\x7a\xd2\xfc\xba\xbf\x2a\x9e\xcc\x6d\xdc\x0d\x27\x9f\xe4\x39\xcd\xa1\xa4\x72\x62\x25\xb2\xf0\x66\xc9\xf3\x81\x95\xac\x77\x8c\xdf\x66\xf9\xec\x9d\x39\x22\xcc\xf6\xe7\x6e\xcf\xd1\x7f\x85\x48\xb9\x3f\xdd\x64\x2b\xdf\xa4\x4c\x4b\x8d\x41\xb5\xdd\xac\x23\x80\x67\x63\x00\x3c\xc1\x66\x1d\xe1\x31\xb9\x09\x68\x97\x6c\xf4\xa7\x80\xa8\x5c\x9c\x30\x1a\x06\xa9\xea\x74\xa2\xb8\x18\x06\x0c\x7f\xfd\xad\xa2\x32\xf4\x26\x2d\xd6\x54\xb6\xa1\x90\xda\x38\x52\xa1\xce\x42\xe6\xda\xf6\x67\x44\xd9\x9b\x46\x0c\x18\x43\x84\xb0\x6f\xbc\xf8\x68\xdc\xac\x2a\xd8\x5e\xe3\x6d\xf6\x31\x1c\x26\x0a\x48\x8d\x7e\xb1\x3b\x28\x02\xd3\x41\x08\x4c\x0c\x67\x51\xc4\xac\xc4\x9a\xda\xac\xc4\x70\x98\x44\x44\x57\x56\x34\x47\xd6\x90\x90\x88\xe2\x1f\x7b\x14\x90\x0d\x6c\x03\x6d\x22\xc5\x27\x88\x6e\xc0\x36\x11\x1d\xf4\xe7\x36\x16\x1d\x27\x88\x12\x1b\xb4\x03\x03\xc0\x9d\x28\x4c\xef\xe8\x26\x22\x78\x07\xe2\x02\x78\x20\x22\x88\x07\x22\x01\x79\x20\x26\x98\x07\x22\x03\x7a\x20\x1e\xa8\x07\xb6\xc5\x4d\x9c\xa9\xb3\xe4\xbc\x55\xf1\xe4\x17\xb8\xad\x8c\x67\x24\xd6\xd9\x80\xae\x60\x8c\x89\x17\x82\x68\x98\x21\x88\x0d\xa1\x80\xc8\xd8\x21\xd8\xde\x46\x51\x45\x22\xd8\x30\x5b\x4c\x40\x12\x3c\x26\x28\x09\xfa\xc0\xa4\x68\x3c\x6b\x18\x08\x82\x93\xa2\x71\x8d\x0b\x72\x82\xc7\x01\x3a\x41\x03\x76\x32\x7a\x2c\x1a\xcb\xf8\xb8\xa9\x47\x38\xa8\xf1\xf0\x4e\xb0\x7d\x4c\x2d\xeb\x98\x02\x9f\xf0\x88\x78\x12\xb0\x2e\xc2\x88\x73\x09\x3d\x34\x55\xbc\xd3\x1e\x1b\xa2\x02\x76\x36\xaf\x78\x8b\xaa\x8a\x3a\xd8\xc8\x0b\x1f\x19\xf5\x02\x8f\x82\xd2\x82\x47\x82\x13\x41\x17\xad\x15\x6f\xdf\x3f\x06\xea\x0b\xbe\xa4\xe5\x8f\xbc\xf4\x2d\xf4\x27\xe6\xaa\xd7\xf0\x9f\x68\x3c\x2d\x8c\xa8\x0b\x01\x8a\xc6\x1a\xa1\x44\xf1\x60\x40\x10\x1d\x0a\x04\x71\xe1\x40\x10\x57\x1b\xa3\x2b\xef\x2d\x96\x1f\x7a\x0c\x27\xa1\xe5\x1c\xcb\x3f\xb8\x22\xa5\x51\x9d\xff\xf7\x8e\x6e\xce\xf1\xb4\xff\xbf\x18\x97\x58\xc2\xa4\x9a\xc2\x65\x3c\x3c\x62\x67\x7c\xe1\x15\x53\x6b\xea\x4c\xa7\x99\x87\x38\x53\x4a\xff\x56\xb1\x35\x29\x28\xd7\xfe\xe1\xc3\x2e\x11\x5e\xc7\xed\xcd\x3a\x6d\xbb\x89\x63\x88\xfb\xfb\xa5\x50\x98\xf7\x65\x23\xa1\x71\xa6\xe1\xd9\x1d\xdd\x3c\x3b\x8f\xad\x44\x0d\xe3\x2b\xfe\xcc\xa6\x1c\xc4\xd9\x04\x3d\x3c\x6e\x44\x47\xa2\xe0\xc5\x06\x9e\x21\xf7\x67\x61\xe5\x12\x5b\xea\x21\x5b\x88\x8c\xc1\x32\xaa\x7f\x3c\x92\x9b\x8f\xe4\x39\x33\x02\x8f\x14\xd7\x51\xbd\x61\x91\x64\x3c\x27\x2b\xaa\x4a\x92\x85\x0e\xaa\x27\xda\x5b\xa6\x81\x2f\x5a\x43\xe9\x94\xc3\xc1\x44\x63\xdc\xb8\xe8\x6e\xe2\x3a\xc1\xb4\x80\xd3\x1a\xac\x43\x16\xe6\xf4\xe9\xb3\xff\x11\xc8\xb3\x57\x8b\xd3\xc6\xc0\x56\x94\x04\x9f\xeb\x67\x18\xe3\x2c\x45\x7e\xa2\xda\x79\xf5\x03\x3e\xd5\xf4\xa4\x12\xb6\x23\x1d\x90\x4e\x44\x3e\xe2\x09\xb9\x75\x73\x1f\x7a\x3e\x96\xa2\x2a\x72\x73\x6f\x68\x60\xd2\xa1\x2c\x4f\x6b\xd8\xc6\x99\xd9\x73\x5c\xe8\x98\xac\xb9\x66\x93\x96\xbf\x37\xd4\xac\x25\x57\x3a\x5c\xf5\x0a\xdc\x07\xf2\xec\xcb\x85\x28\x06\x5a\x0b\x09\x6e\x25\x58\xa8\xb5\x73\xbf\xa4\xb2\xbb\xee\xe1\xb9\x1d\x39\x9d\x33\x4e\x73\x20\x0a\x64\xc5\xb9\x99\x4d\x11\x9a\x25\xe7\xd0\xca\xd6\x2c\x43\x03\x22\xdc\x39\xdc\x08\x6f\x0b\x07\xc2\xe0\x48\x04\xdc\x8c\xa5\x16\x6a\x49\xd0\x48\x25\x3c\x94\x23\x4e\x80\xe0\x4e\x85\x11\xbe\x89\x33\x03\x36\x7c\x43\x73\xbb\xff\x83\x17\xdf\xad\xf8\x14\xde\xa0\x9a\x89\x37\xa1\x4c\xa1\x14\x21\x45\x21\xee\x43\xad\xb3\xa7\xd6\xa7\xe3\xfe\x8b\xe8\xd3\xb1\x05\x14\x4c\x6d\x3a\x5a\x4a\x6d\x3a\x76\x29\xb5\xe9\xf8\xa2\xdb\x74\x78\xaf\x91\x55\xa9\x7b\xfa\x75\x78\x71\xb4\x3d\x3e\x1e\xea\xd7\xe1\x37\xa1\x76\x23\x6e\xf5\xeb\x80\x3f\x2f\x29\xca\x35\x4f\x57\x82\x39\x32\xab\xaa\xd0\xac\x2c\xda\xec\x12\x3b\x0d\x85\x77\x90\xc3\x75\x9c\x50\x5b\x78\x65\x33\x13\xc4\x33\x11\x79\x4b\x9a\xe3\xb8\x31\x09\x59\xa1\x39\xe0\x67\x56\x62\x0a\x14\x29\x0a\xd7\xce\xa2\xce\x69\xb7\xf9\x71\xec\x4b\x4e\xdb\x78\x8d\x46\xad\x0a\x05\x26\xa0\x91\x75\x6a\xac\xf7\xc2\x88\x05\x63\xcd\xd6\xba\xda\x93\xe3\xae\x0b\xc2\x62\x32\xd6\x01\xa9\x1a\x98\x1a\xc7\xd6\x94\xb7\xf7\x8c\x53\x75\x76\x16\x52\x67\xa8\xf6\x12\xc4\xbc\x6b\x3e\xc2\x1d\x73\xe8\x6e\x79\x6e\xef\x48\x9e\x1c\x7b\x37\xab\x81\xbb\x91\x27\x5b\xc1\x87\xef\x44\x01\x16\xd9\xd6\x5d\xe8\x0f\x1d\xdb\xfd\x7f\x79\xb2\x1c\xb8\x05\xd5\xf7\x18\x5f\xbb\xdb\xde\x7e\x70\x2b\xd5\xa9\x91\x16\xb7\xef\x9d\x1b\x67\x63\x91\x01\xab\xf1\xd9\xb3\x90\x42\x6f\x59\xe1\x00\xcb\x48\x69\x1e\x8f\x92\xe2\xf1\x08\xe9\x1d\x11\x53\x3b\xfe\x39\x9a\xe4\x44\x4e\xe5\xd8\x4d\xe3\x88\x85\xa0\xef\xa5\x70\xc4\x4e\xc0\x88\x94\x7c\xf1\xa4\xfc\xe3\x8f\x92\x70\x91\x2a\x9a\xa6\x8a\xa6\x7e\x94\x2a\x9a\x1e\xa0\xc7\xa8\x68\x1a\x2b\xf1\xa1\x9b\xf4\x10\x8d\x69\x9d\xf0\x10\x37\xc7\xca\xc5\x79\xff\xa9\x0a\x9b\x46\x45\x7e\xb6\x49\x09\x75\x32\x41\x24\xb6\x6d\x42\x42\x1c\xb0\x11\xa4\x2a\xa9\x98\x38\x10\x1d\xf0\xff\x25\x14\x36\x8d\x08\xf6\xed\x00\xfc\x63\x25\xb6\xd8\xb9\x8b\xba\x2d\x1f\xa9\x66\x64\x74\x30\xfe\xa3\xd6\xe0\x4c\x25\x4e\xbf\x94\x12\xa7\xa9\x26\x65\x34\x41\xfc\x73\xaa\x49\xd9\xa7\x68\xe0\xf3\x47\x02\x9e\x3f\x0e\xe8\x7c\x0b\x70\x1e\x91\xb3\x2b\x84\x19\x17\x2a\xbe\x0d\x13\x07\x12\x8a\x19\x7a\x44\x88\xf8\x16\x3c\xbc\x05\x77\x47\x00\xe4\x74\xab\x8b\x23\xb0\x3b\xd4\xe9\xe4\xca\x6e\x45\x14\xe7\x8d\xdb\xa3\x07\xe8\x0e\x64\xba\xed\x6b\x8b\x00\xe6\x8e\xe6\x6b\x8b\xe0\x9a\x78\x0c\x00\x77\x04\xf9\x18\x03\xb8\xbd\x07\xb4\xdd\xc2\xae\x43\xe0\x4c\x5b\x80\xed\xdd\x78\x67\x00\xf3\xf6\x12\x1f\x17\x6e\xfd\x08\x50\xeb\xc8\x30\xeb\x18\x2a\x3f\x58\xd1\x47\xd8\xbe\x51\x60\xd5\x83\x90\x6a\x17\xa8\x0e\x78\xbd\x5e\x88\xbb\x13\xac\x0e\x09\x65\x6d\x87\xb9\xb7\x03\xd6\xa1\xc0\xc1\xd8\x40\xe8\x21\x10\x74\x8b\x8d\x0a\x39\x62\x2d\x00\x7a\x07\xc2\x1c\x12\xd8\x1b\x0a\xd1\x87\xc1\x97\x63\x87\xe9\x61\x37\x54\x1f\x07\x65\xbb\x2f\x58\x1f\xb2\x5f\xfb\x70\xe5\x1e\xe0\x38\x80\xad\x83\x2a\x3f\x0e\xd8\x38\x16\xd0\x38\xa8\xa0\x3e\xd7\xec\x31\x8a\xea\x77\x65\xc5\xe8\x17\xdb\x53\x59\x9f\xac\x05\xcb\xa1\xac\xb4\xf6\x11\xe3\x0d\x2e\xe8\xa1\xea\xfa\xa3\xb9\x12\x95\xaa\xeb\x3f\x40\x5f\x70\x75\xfd\xa0\x1d\x0c\xfd\xfa\xe2\xbb\x20\x5d\x2f\x8e\xbd\xb2\xfc\xbb\x25\xf6\xfd\x5f\xbc\x2e\xcb\x3f\x50\x62\x3f\xf4\xd5\xa7\x3b\x25\xf6\xbd\x38\x6e\x95\x72\xde\x2a\xb1\xef\xf9\xe6\xfd\xb2\xfc\x3b\x25\xf6\xfd\xd6\xa8\x5b\x96\x7f\xb7\xc4\xbe\xf7\x48\xbb\x32\x71\xb0\xc4\xbe\x37\x1e\x8c\x2a\x7d\xbe\x37\xaf\xc0\x8b\x6b\xef\xec\x0c\xd5\xd9\xf7\xe2\xda\xd4\xe6\xdf\x5b\x67\xdf\x7b\x72\x6b\xf4\xf4\x6e\x9d\x7d\xbf\xf7\xef\xd7\xe6\xef\xd7\xd9\xf7\x1e\x64\xaf\x36\x7f\xbf\xce\xbe\x37\xcf\x3e\xca\x7b\xbb\xce\x7e\xd0\x50\xeb\xda\xfc\xdb\x75\xf6\xfd\x66\x34\xd5\xe6\x1f\xa6\x54\x9b\xff\x09\xa0\x62\x53\x6d\xfe\x96\x52\x6d\xfe\x54\x9b\x7f\x87\x52\x6d\xfe\x54\x9b\x7f\x04\xa5\xda\xfc\x5d\x4a\xb5\xf9\x47\x53\xaa\xcd\x9f\x6a\xf3\xa7\xda\xfc\xde\x94\x6a\xf3\x8f\xa3\x54\x9b\x3f\xd5\xe6\x8f\x40\xa9\x36\x7f\x97\x52\x6d\xfe\x54\x9b\x3f\xd5\xe6\x8f\x40\xa9\x36\x7f\xaa\xcd\x9f\x6a\xf3\xa7\xda\xfc\xc1\x94\x6a\xf3\xa7\xda\xfc\x41\x94\x6a\xf3\xa7\xda\xfc\xa9\x36\x7f\xaa\xcd\x9f\x6a\xf3\x7b\x52\xaa\xcd\x1f\x40\xa9\x36\x7f\xaa\xcd\x1f\x36\x98\x54\x9b\x7f\x24\xa5\xda\xfc\xa9\x36\x7f\xaa\xcd\x9f\x6a\xf3\xa7\xda\xfc\xc3\x94\x6a\xf3\xa7\xda\xfc\x63\x68\xb0\x36\x7f\x70\xa2\x4a\xef\xf2\x14\x31\x53\xa5\x2e\xea\xbf\x5b\xa0\xdf\x8b\x67\xaf\xa8\xff\x70\x81\x7e\x2f\xbe\x75\x51\xff\xad\x02\xfd\x4f\x77\x5a\xb1\xb2\xff\x6e\x95\x7e\x2f\x8e\xdd\xca\xfe\x43\x55\xfa\xbd\x98\x76\x2b\xfb\x0f\x54\xe9\xf7\xe2\xd9\x56\xf6\x7f\xb0\x4a\xbf\x17\x6f\xac\xec\xff\x50\x95\x7e\xbf\xfd\x8a\x36\xd5\xfe\x2a\xfd\x5e\x4c\x0b\x5b\x89\x69\x5f\x95\x7e\xbf\xd7\x27\xd9\x32\x55\xe9\x3f\x48\xa9\x4a\x7f\xaa\xd2\x9f\xaa\xf4\xa7\x2a\xfd\x07\xe9\xb3\xe7\x23\xa5\x2a\xfd\x0f\x51\xaa\xd2\x7f\x24\xa5\x2a\xfd\xa9\x4a\xff\x68\x4a\x55\xfa\x53\x95\xfe\x54\xa5\x7f\x0f\x8f\x54\xa5\x7f\x14\xa5\x2a\xfd\xa9\x4a\x7f\x30\xdb\x54\xa5\x3f\x55\xe9\x0f\xa1\x54\xa5\x3f\x55\xe9\x4f\x55\xfa\x53\x95\xfe\x54\xa5\xdf\x8f\x52\x95\xfe\xb1\x94\xaa\xf4\xa7\x2a\xfd\x96\x52\x95\xfe\x54\xa5\x7f\xf4\xe0\x52\x95\x7e\x5f\x4a\x55\xfa\x53\x95\xfe\x54\xa5\xdf\x51\xaa\xd2\x9f\xaa\xf4\xa7\x2a\xfd\x9f\xb9\x4a\x3f\xa9\xb4\x58\x89\x8a\xeb\x1b\x2a\xd7\x2c\xa3\x97\x59\x66\x7e\xba\x15\x77\x74\x14\x80\xb4\x1f\x95\x7b\x80\xe9\xa8\xd7\x63\x3c\x67\x19\xc6\x90\xee\x97\x14\x0b\xe0\x13\x50\x96\x27\x10\xcb\x14\xf4\x68\xae\x2d\x22\x08\xdf\x9e\x68\x96\x91\xa2\xd8\x00\x0e\x79\xdc\x0a\xd8\x39\x9f\x09\x51\xd0\x11\xd7\x07\x67\xce\x52\x39\x4a\x9b\xf5\xa6\xf8\xad\x8b\x45\xb7\xac\x60\x46\x0b\xc1\x17\x63\x55\x9b\x83\xa6\x96\x22\x9f\xc2\xab\x96\x59\x46\x38\x0a\xfe\x4a\x4a\xca\xf5\x48\xd8\xe3\xac\x2e\xe7\x8b\x01\xd5\x95\x58\xd3\x1c\x43\xdb\x88\x54\xb4\x2e\x99\x91\xb1\xd0\x82\x12\xf3\xbe\x9c\xb6\x2f\x6c\x84\x3b\x81\x6b\x1c\xb7\x1d\xec\x6c\x9c\xe4\xb0\x88\x51\x8f\xe5\x1e\x6b\xc5\x78\xd8\x2d\x5b\x41\x6e\x77\xa3\x46\xf3\x31\xc3\x70\x43\x3b\x0f\x23\xe5\x05\x0a\xdb\x8d\xa8\xe0\x9e\xd8\x6b\xaf\xac\x38\x0a\x76\x9c\x4e\xb3\x0d\xc6\x6d\x1f\xdf\xeb\x8a\x5f\xdc\x74\x82\x7a\x78\xd4\x57\xfc\x63\x99\x44\x2e\x3c\xcc\xcd\xde\xd2\x9d\x5c\xca\x45\x65\x6f\x97\xee\xa0\x51\xae\xe5\x06\x41\xd1\x3e\x92\xde\xdc\x59\x73\x91\xdd\x99\xed\xbf\x22\x0b\x7a\x72\xa2\xe0\xd5\xbb\xd7\x46\x87\x54\xca\x4b\xc5\x31\x57\x90\xde\x69\xa1\x52\x8a\x35\xcb\xcd\x79\xfd\x8e\x48\x46\x66\x5e\x25\x04\xb0\xe8\x36\xe5\xe6\xf6\xf4\xab\xd3\xef\x2e\x3f\xfe\xf8\xfe\xf2\xdd\x9b\x33\x8c\x16\xd1\x4f\x25\xe1\xb9\xd7\x48\x2b\xd5\xa6\x9a\xb8\xbd\x6f\x5e\x9f\xf2\x35\x93\x82\x9b\x49\xf6\x99\xd1\xab\x39\x10\x58\xbb\x77\xad\xc5\xde\x8c\x22\x6c\xab\x58\xfb\xe1\x92\x35\x7a\x16\xdc\x1c\xd4\x46\x28\xe3\x65\xa5\xfd\x2f\x1f\x98\x8e\x30\xa3\x50\xf1\x6c\x49\xf8\xc2\x49\xd4\xee\xfc\x7a\x30\x55\x1b\xae\xc9\x27\xf3\xd6\xe8\x26\x57\x19\x29\x69\x6e\xcd\x3c\x02\xb9\xa8\xfc\x96\xff\x57\xbf\x3a\x07\x46\x5f\xc2\xaf\x3a\x83\x9b\xc2\x1b\xc7\xbd\xdd\x1c\xbe\xb3\xc0\xe9\x9a\x4a\x1c\xb0\xdb\x4c\xe7\x20\xe9\x82\xc8\xbc\xa0\xca\x87\xa9\x98\x37\xe6\x85\xf5\x5b\xb9\xcd\x40\xeb\x78\x87\x07\x4f\x2e\x74\x47\x2f\x35\xba\x06\xde\x09\x84\xbd\xcf\x85\xcf\xed\x71\xa9\x75\xa9\x5e\x5e\x5c\xdc\x55\x33\x2a\x39\xd5\x54\x4d\x99\xb8\xc8\x45\xa6\x2e\x34\x51\x77\xea\x82\x71\x23\x87\x27\x39\xd1\x64\xd2\x51\x16\x17\xf6\x8a\x31\xc9\xc4\x6a\x45\x78\x3e\x21\x4e\x28\x4d\x9a\x83\x74\xf1\x4b\x67\xda\x4e\x48\xf3\x29\xc6\x27\x64\xa2\x96\xb4\x28\x4e\x46\x8f\x35\xe4\xba\xef\x7d\xcd\x0f\xb8\xde\xbb\x77\x0e\x95\xf6\x6f\x1a\xe1\x6e\xdf\x7d\x0a\xef\x85\x8f\x17\xcf\xe6\xc8\xb8\xa3\x88\x8a\x19\xd7\x61\xda\x91\xff\x3e\xa2\xbe\xd6\x18\x6f\xde\xdf\x7e\xfc\xcb\xf5\x87\xab\xf7\xb7\xb5\xe2\xa8\xd5\x80\x0f\xd7\x7d\x8a\x23\xec\xa4\xef\x53\x1c\xad\x1a\xf0\x60\xba\x57\x71\xf4\xd5\x80\x0f\xe7\x5d\xc5\xd1\x57\x03\x3e\x33\xbb\xab\x38\x06\xd4\x80\xa7\x15\xd1\x9d\xdf\x41\x35\xe0\x25\x9d\x3b\x8a\x63\x58\x0d\x78\x70\xdd\x55\x1c\x7d\x35\xe0\x75\xbe\x76\x15\x47\x47\x0d\x78\xaa\xfc\x5d\xc5\xd1\x55\x03\x1e\x4c\x87\x15\x47\x52\x03\xc7\x3c\xd4\x4b\x0d\x50\xbe\x0e\x54\x01\xf5\xbd\xbc\x23\x5c\x9a\x7d\xe1\x23\x06\xb5\x40\x2c\x98\x13\x05\xcd\x42\xc5\xd9\x54\x5f\xc6\x7a\xf6\xe6\xf7\x0d\x5f\x7f\x47\x64\x0f\xcc\xe7\xe7\x2b\x1d\x5a\x20\x70\x4c\x81\xf9\xf1\x24\xad\x07\xc5\x3f\xf1\xd0\x3b\xf4\x17\x82\x44\xf6\xb8\x57\x5b\x0a\x45\x0a\x9b\xc7\xfa\x06\x52\x7a\x1b\xe3\x3d\x59\xd5\x7e\xee\xee\xda\x7a\x7b\x53\xeb\x3d\x31\x85\x77\xb5\xcb\x0a\x5e\xfd\x78\xf5\xfa\xcd\xfb\xdb\xab\xaf\xaf\xde\x7c\xf4\xf5\xd3\x06\xc7\xa0\xd0\xa3\x1f\x65\xca\x4e\xe2\x58\x6a\x96\x1e\xb6\xd7\xfc\x9d\xda\x4b\x3c\x95\x6b\x26\xaa\x36\x52\x12\x73\x7d\xd5\x8e\x6c\xf5\x66\x69\x93\x28\x36\x8d\x87\x3a\xea\x30\xa7\x83\x9e\x0a\x6f\xbe\x51\x0d\x55\x4b\x0f\x98\xab\xde\x3c\xa3\x7a\x3b\x2c\xed\xf7\x79\xf8\x2f\x7c\x6c\x93\xd7\xd2\x83\x86\x6f\xc8\xca\xef\x31\x7f\xbd\x59\x3e\xe0\x3d\xf1\xe6\x59\x1b\xcf\xaf\xe9\x9c\x54\x85\xf5\x9f\x3e\x7b\x36\x1d\x6f\x83\x5a\x8a\x23\x76\xbf\x96\xc2\xbb\x73\x5d\x4f\xf4\xde\x60\x4a\x28\xf6\x72\x0d\x09\xcc\x0e\x19\x31\x27\x2e\x39\xcc\x7f\xdf\x75\xdc\x56\xce\x35\x60\xa3\xc8\x01\x80\x57\xc3\x2f\x08\x85\x1b\x01\x16\x15\x23\xa9\x29\x13\x7c\xce\x16\xef\x48\xf9\x27\xba\xf9\x48\xe7\x21\x60\x94\xfe\x7e\xc0\x18\xb5\xcb\x4c\x09\x02\x69\x89\xb9\x35\x43\xed\x30\x43\xb0\x68\x91\x90\x68\x31\x12\xe4\x42\x93\xe3\x62\xe5\xb3\x45\xc8\x65\xdb\xe9\xd2\x1a\x23\xed\x0c\x6f\x89\x66\x07\xc5\x49\x8c\x8c\x90\x22\x13\x62\xd7\xd7\xd4\x37\x56\x9d\x81\x1f\x3e\x57\xad\xb1\xa3\xad\x5b\x25\x98\xe5\x41\xb7\x4c\x26\x78\x46\x4b\xad\x2e\xc4\xda\xd8\x86\xf4\xfe\xe2\x5e\xc8\x3b\xc6\x17\x13\x63\x77\x4c\xec\x19\x53\x17\x88\x31\xba\xf8\x25\xfe\x27\x78\x50\xb7\x1f\x5e\x7f\x78\x09\x97\x79\x0e\x02\x95\x73\xa5\xe8\xbc\x0a\xcf\x94\xb6\x2d\x7b\xa7\x40\x4a\xf6\x1d\x95\x8a\x89\x08\xf9\x35\x77\x8c\xe7\xe7\x50\xb1\xfc\x2b\x5f\xf5\x5e\x53\xb4\xfd\x2b\x4a\x8b\x9d\x8d\xba\x87\x6f\x10\x87\x16\x7e\xdc\xbb\xf6\x56\x23\xea\x83\xb9\x0a\x89\x45\xa9\xee\xe8\xa6\x46\x69\x04\xb3\x74\x17\xb6\x28\x8b\x3a\x16\x64\xb3\x4d\xb8\x71\x63\xea\xec\x93\x46\x69\x07\xbd\x9f\x05\xf4\x3b\xcf\x45\x29\xf2\x97\xa0\xaa\xb2\x14\x32\xb0\xf8\xc3\x8a\x6a\x92\x13\x4d\xa6\x46\x9a\x9c\xf7\x7f\x44\x1c\x63\xd8\xb1\x6d\xf8\x21\x32\x50\x75\x1e\x80\xc6\xa3\x4d\x89\x0d\x7b\x84\x2a\x69\x36\xe5\x22\xa7\xef\xf1\x0d\xf0\x47\xd5\x03\x94\xe1\x1f\xc2\x9e\xa1\x89\xae\xd4\x74\x29\x94\xbe\xba\x3e\xaf\x7f\x2c\x45\x7e\x75\x1d\x85\x31\x72\x52\xde\xb7\x16\x78\x6a\x66\x18\x6e\xd6\x6b\x12\x54\x09\x39\x96\x31\xd6\x6a\xa0\xa8\x42\xda\xf1\x0c\x17\xa7\x0e\x7d\x9a\x2d\xe9\x8a\x44\xe9\x98\xf0\x75\x3d\xf9\xc0\x14\xdc\x4b\xa6\xb5\x67\xe1\xc0\x2e\x31\xee\x6a\xe7\x89\xf9\xb9\x91\xd7\x78\xd9\x8e\x61\x90\x3e\x5b\xbf\x08\x4e\xd1\x89\xa6\xce\x9b\x7d\x1b\x75\xab\xe0\x5a\x44\x32\x49\xad\x1a\x68\x0c\xf9\x28\xeb\xda\x85\xbe\xc3\xe5\xf5\x55\x30\xd3\xb5\x3d\x1b\x4f\x62\x59\xeb\xba\x5a\x5f\x3f\x51\xbd\x5e\x8f\xaf\x16\x04\x8d\x7f\x39\x6c\x0b\x62\x06\x5c\x53\x53\x0c\x0a\xb6\x62\x81\xe7\x95\xf0\x1c\xb5\x03\x55\x5a\xc1\xa9\x65\x38\xcd\xca\x2a\x4c\x01\x3a\x3e\x2b\xba\x12\x72\x73\x5e\xff\x48\xcb\x25\x5d\x51\x49\x8a\x89\xd2\x42\x92\x45\xa0\xfa\xae\x87\x8d\xc3\x6d\x7f\xb2\x0f\x8d\x36\x29\xbb\xa3\x0e\x49\x7b\xb1\x55\x33\x1a\x60\x75\x6d\xed\xd1\xfc\xe7\x63\x25\xd4\xdb\xf3\x09\x18\x09\xcd\xa9\x7b\x1f\xdd\x21\xf1\x2a\x38\x60\x54\x13\x3a\x4b\x9a\xb9\x87\x79\x84\x92\x0d\x6b\x51\x54\x2b\xaa\xce\x9b\x8b\x6c\xf8\xc5\x5f\x48\xa0\x7c\x0d\x6b\x22\xd5\x93\xb9\xa6\xe7\x6c\xcd\x54\x78\xe5\xa1\x81\x5b\x7a\x8c\x16\xd3\x98\x5d\x5d\xe9\xb2\xd2\xae\xf0\x7b\x2c\xa3\x92\x7e\x2a\x85\xc2\xc8\x50\x84\xda\x92\x96\xf2\x6e\x9c\xe5\x45\x58\x67\x1d\x2c\x15\xa1\xa9\xe4\x2f\xe1\xbf\x4e\xff\xfa\xeb\x9f\x26\x67\x5f\x9d\x9e\x7e\xff\x7c\xf2\x1f\x3f\xfc\xfa\xf4\xaf\x53\xfc\xc7\xbf\x9e\x7d\x75\xf6\x53\xfd\xc3\xaf\xcf\xce\x4e\x4f\xbf\xff\xd3\xbb\x6f\x6e\xaf\xdf\xfc\xc0\xce\x7e\xfa\x9e\x57\xab\x3b\xfb\xd3\x4f\xa7\xdf\xd3\x37\x3f\x1c\xc9\xe4\xec\xec\xab\x5f\x05\x0e\x9c\xf0\xcd\x87\x20\x53\x02\x6c\x81\xd4\x28\xdd\x02\xfa\xdc\xa2\x14\x2e\xfa\x34\x69\xdd\x93\x13\xc6\xf5\x44\xc8\x89\x65\xfc\x12\xb4\xac\xc2\x2e\x29\xf5\x76\x8c\x2b\x67\x3f\x46\xaa\xb0\xd7\x31\xc9\x1a\x33\xfb\x49\x08\x32\x45\x33\x49\xf5\xd3\x8e\x28\xd9\x31\xd6\xb7\x0a\x4c\x0b\x0f\x8e\x0f\xa0\x1b\xea\xe7\x62\xf3\xa4\x00\xd5\x43\xd4\xa4\xe2\xe2\x2e\x8a\x77\xcb\x9d\x4b\xb1\x9a\x42\x07\xa2\xb5\x8e\xd2\x78\xdf\x8d\xf3\x8e\x06\x57\x8d\x4a\x01\x35\x1f\x4a\x01\xb5\x30\x4a\x01\xb5\x71\xd4\x0d\xa8\xdd\xe0\xd9\x4f\xd1\xb4\x21\xa2\x7c\xed\x07\x81\x1a\xc4\xc8\xd7\x3e\x2c\x2d\xa0\x14\x65\x55\x10\xed\x95\xcb\x31\x84\xb4\xdf\x05\xcc\x7b\x70\x76\xca\xaf\xc5\x9d\xb6\xd9\x58\xbe\xee\x8d\xd5\x30\x96\x18\x2e\x8b\x02\x18\xf7\x55\x5e\x38\xc8\x3a\x33\x48\x52\xeb\x4e\x02\x82\xf5\x3f\xb1\x73\x91\x07\xcf\xfb\x25\xdd\x9a\x42\x60\x0a\x94\x26\x52\x33\xee\xd5\xb6\xe9\xcf\x86\x23\x9a\xa3\x75\x82\x0c\xe3\x6d\xe7\xa2\x80\x8b\x6c\x53\x6c\xac\xd3\xda\xae\xad\x2e\x53\x10\xe5\xf3\xfe\xee\xa6\x80\xb3\xaa\xc9\x1d\xa2\x90\x33\x9a\x53\x9e\xd1\x29\x7c\xe7\x5b\xa5\xb5\xde\x49\xb3\x8d\x59\x9b\x37\x7c\xdd\xe4\x4c\x55\x36\x4d\xc7\x67\x53\x99\x19\x1d\x1e\xe7\x3f\x6f\x92\x88\x11\x53\x0e\x64\xd9\xe6\x8a\x78\x49\x4e\xb4\x5b\x1b\x4f\x7e\x53\x9a\xb9\xc1\x5d\x78\x65\xf5\x84\xdd\x5c\x42\x6f\x0b\x0d\x8a\x31\xe0\xc2\xb9\x73\x4d\x68\x26\x24\xa4\x0a\xb6\xbd\x16\xa0\x59\xef\xc9\xe3\x89\x00\x45\x43\xcd\xf5\x41\x53\x3d\x38\x8a\xdc\x37\xd3\x9f\x9e\x99\xfd\x08\x26\xf6\x80\x79\x6d\xcd\xe3\x20\xae\xa1\xa6\x75\x14\xb3\x3a\x86\x49\x3d\x64\x4e\x07\xa4\xc1\xb6\xd4\xc3\xa6\x45\x31\x81\xc3\xcd\xdf\x70\x20\x59\x29\xe9\x9c\x7d\x8a\x22\x33\x2f\x79\xb3\x80\xc0\x72\xca\x35\x9b\xb3\x80\x39\x37\x46\xb4\xa4\x25\xe5\x08\x22\xc0\x8e\x8b\xc6\x2e\xf0\xcc\x64\x84\xed\x15\x7c\x72\x69\x70\xd6\x45\x13\x53\x81\xdd\xc4\x72\x4e\x25\xed\x95\xb4\x57\xd2\x5e\x87\xe8\xc9\x6b\x2f\x27\x0f\xea\x2b\xfb\xe7\x55\x3f\x58\xbb\x25\xb4\x3c\xcd\xeb\x4e\xe5\x30\x3c\xe3\xde\xee\xda\xe3\xcf\x5e\x5b\xa0\xf0\x02\x9f\xeb\x73\xc4\xb0\x44\x6e\x53\xf8\xbc\xd1\x9a\x5a\xd8\xa2\x99\x1e\x1c\x97\x6c\x61\x4e\x68\x41\xd7\xb4\x70\xd7\x21\x58\x11\x4e\x16\xb6\x82\xbb\xd7\x0d\xc6\x45\xd0\x41\x48\xec\x00\x29\x59\xde\x73\x9e\xf8\xbe\x3c\xe3\x60\xc4\x56\x21\x48\x8e\xec\xa4\x28\x0a\x2a\x15\x14\xec\x8e\xc2\x6b\x5a\x16\x62\xe3\xdb\x2a\x90\xf0\x1c\x6e\x34\xd1\x46\x4c\xdd\x50\xed\x83\x53\x0e\x10\x05\x38\x23\xd7\x55\x51\x5c\x8b\x82\x65\x1e\x71\xab\xfe\xe6\xbe\xc2\x5d\x5d\x56\x45\x01\x25\x32\x9c\xc2\x07\xee\xb3\xb7\xc5\x1c\x2e\x8b\x7b\xb2\x51\xe7\xf0\x9e\xae\xa9\x3c\x87\xab\xf9\x7b\xa1\xaf\xad\x13\xc1\xc7\xe0\xe9\xe6\xb0\x5a\xd6\xc0\xe6\xf0\x12\xbb\xe3\x69\xd0\xc4\x47\x88\xb2\x4e\xcb\xf7\x73\xb3\xe7\xba\x83\xb4\x0a\xe8\x9e\x29\xaf\x2c\xd0\x07\xcb\x96\xf9\x1d\xfa\x5f\x22\x27\xa3\x7a\xed\xcf\xff\xd0\x8d\x56\xb0\x39\xcd\x36\x59\x11\x2a\x3f\x2f\x33\xcc\x6a\x68\x1b\xbc\xb5\x12\xc3\xc7\xc1\x68\xfb\xcd\xbb\x62\xb4\xe8\xba\x63\x1c\x6c\xb3\x75\xe5\xd9\x4b\xbb\x15\x37\xcd\x3b\x5b\x07\xb0\xfa\xac\xbe\x40\x4f\x7b\x36\xcc\x92\x2d\x85\xd2\x37\x9a\x48\x1d\xa1\x19\xfb\xc9\x75\xcd\x0c\xb0\x09\x6f\x51\x78\x1b\x02\x6c\xb5\xa2\x39\x23\x9a\x16\x1b\x20\x73\x8d\x25\x8d\x43\x4b\x4f\x98\x31\x49\x6a\x4f\xaa\xeb\xfd\xb4\x24\x3c\x2f\xa8\x84\x39\x61\x85\x37\x3a\x6c\xc7\xfd\xaf\xa9\x5c\x31\x1e\x50\xf2\xdc\xc2\x6a\x31\x8a\x40\x73\x2c\xe1\x2c\x73\x2c\xe7\x26\xc0\x1f\xc6\xec\x18\xb6\x62\x1f\xad\xef\xa0\xc3\x09\x2d\x66\xa1\x9d\x80\x59\x21\xb2\x3b\x05\x15\xd7\xcc\xd7\xaa\xc7\xa5\x11\xe2\x0e\x32\xb1\x2a\x0b\x14\x9e\x61\x25\x21\xe1\xe1\xb2\x90\x43\x12\xb9\xf9\xe7\xa4\x11\x12\x13\x33\x26\x75\xf1\xcb\xf6\x4f\xf8\x0b\xbf\x3b\x42\xf0\x1d\x36\xfc\x06\x4b\x3f\xd1\x2c\x52\x7b\x86\x0f\x9c\xe2\xae\x15\x7c\x64\x11\xec\x3e\x09\xde\x24\x02\xcc\x85\x31\x5a\xcd\xae\x8f\xd1\xf1\xa1\x31\x02\xa6\xf0\xe6\x13\xcd\xa2\xf4\x40\x31\xa3\x24\xa8\xec\xb0\x6a\x31\xb9\x0b\x28\x26\xf1\x84\xda\x8d\x7b\x17\xf9\xec\x52\x6f\x73\xbc\xb2\x1c\xc3\x5b\xc1\x59\x41\x63\x99\x15\x8c\x7b\xaa\xff\x2e\xb9\x12\xa2\xc0\xb8\x32\x17\x91\x9e\x24\x8b\xd1\x35\xca\xb9\x52\x20\x67\x12\x7b\x6d\x84\x82\x30\x5c\x29\x94\x66\x16\xc2\xe7\x54\x0a\xa1\xe1\xf4\xe4\xe2\xe4\x6c\x07\x0d\x10\xdc\xfb\x75\xce\x0a\x6a\x0d\x38\x5b\x98\xc8\x8d\x3a\x90\xab\xb1\xe9\xd9\xaa\x2c\x36\xb8\x7a\x27\xf9\x39\xb0\x50\x20\x8a\xab\xce\x2a\x2b\x5e\xef\x84\xd0\x8e\xe1\x58\x0a\xf2\x1c\x94\x00\x2d\x49\xdd\x62\x2a\x06\x4f\x33\x40\x2d\x2b\x67\x64\x9f\x9e\xfc\x74\x12\xba\x4f\xa9\xce\xce\xe0\x5e\xf0\x13\x8d\xdb\x75\x0a\xb7\xa1\xa7\xaa\x52\xb4\x2e\xc6\x7b\x8e\x55\xf4\x39\x0d\x07\xe4\x08\xa0\x9f\xca\x82\x65\x4c\x17\x1b\x34\x2e\x41\x54\xa1\xeb\x8e\xd5\xe6\x89\xae\xeb\x06\xbf\xf9\x14\xbc\x93\x6c\x46\xb3\x51\x62\xcf\xd1\x14\xb4\x06\x67\x20\x53\xa2\xa0\x60\x6b\x7a\xb1\xa4\xa4\xd0\xcb\x0d\x84\x9f\x21\x2e\xf8\xe4\xef\x54\x0a\xac\x6c\xcc\x1d\xdf\x18\x2d\xd9\xc2\xfb\xd8\x45\x69\x54\x19\xc1\xf7\x6a\xec\xc5\x6f\xa8\xe7\xbd\x08\xb6\x75\xe0\x1f\x6f\x6f\xaf\xbf\xa1\x3a\x9a\xe1\x61\x46\x57\xa7\xde\x61\x54\x8b\xca\xb9\x90\xab\xcf\x6c\x81\x84\x83\xc4\x27\x50\x0a\xf9\xb9\x4d\xa0\xa5\x50\x01\xeb\x0e\x3b\x6b\x2f\x94\xf6\xad\x1c\xda\x25\x2d\x8c\x6e\xe6\x34\x33\x2b\x1e\x2d\x0d\xbd\x6d\x6d\x03\x57\xd7\x53\xf8\x8b\xa8\xcc\x2c\xce\xc8\x2c\xc8\x92\x37\x54\xf7\x4e\x51\x54\xc3\x33\x33\x09\xcf\x42\x02\xad\x96\xcc\xbe\xff\x23\x25\x39\x95\x0a\x35\x21\x25\x51\x3a\x49\x06\x43\x77\x3b\xe3\x8a\x69\x39\x57\x4a\x8b\x15\x2c\x2d\xe3\xf0\x85\xee\x14\x49\x76\xb2\x23\x14\xb9\x6f\xe4\x9a\x8d\x2f\x28\x90\xb4\x8c\xa1\xed\xdc\xdb\xfe\x8c\xb4\xd1\x8e\x26\xb0\x3b\x25\x90\x6b\xcd\x77\x46\x15\x10\xc8\x70\xab\x04\xb3\xb4\x93\x6f\xf6\x8a\x2b\x6c\x18\xcc\x91\x71\xbb\x49\x8c\x50\x09\xce\x2f\x88\xd6\xf7\x35\x4e\x42\x13\x84\x14\x85\xee\x33\x41\x68\x6e\x20\x97\x58\xf9\x51\x10\x29\x93\x06\x06\x00\x24\x11\x58\x36\xbb\xd4\x06\x3b\x23\x4c\x3f\xc4\xcc\xe1\x80\xd0\xf2\xd3\x5d\x7a\xfc\xe9\x8b\xb1\xf1\x20\xde\xfc\x95\xc1\xe5\x67\x76\x8b\xcf\x68\x01\x24\xcb\xfc\xda\x1e\x75\x49\x58\xd5\x89\xe2\x4c\x51\xb9\xf6\x4b\x98\x68\x29\xd6\x94\x09\xdf\xf0\x4d\x4d\x03\x35\xe2\x25\xf0\x6a\x35\x0b\x56\x52\x4d\xc5\x36\xa9\x63\x2f\x43\xa7\xcd\xc3\xfb\x18\x43\xad\x21\x2c\xb5\x81\x44\xf8\x22\xf4\x5c\xbc\x30\xef\xfc\xfb\xdf\xfd\xee\xb7\xbf\x9b\xda\x69\x35\xcf\x08\xe4\x39\xa3\x40\x38\x5c\x5d\xbe\xbf\xfc\xf1\xe6\xbb\x57\x58\x3d\x3b\x6c\x17\x46\x48\xe6\x8f\x99\xca\x1f\x31\x91\xff\x11\xd3\xf8\xb1\x60\x59\xa0\x84\xef\xe3\xb2\x90\x61\xb8\x47\xbb\x52\xb6\x60\xb6\xbb\x29\xda\xb0\x61\x04\x4f\xb6\xb9\x13\xf7\xea\x8c\x47\xb8\x38\x7c\x76\xe9\xa9\xb3\xf2\x46\x64\x77\xd1\xbc\x3c\x27\xb7\xaf\xae\x2d\xc3\x28\x8e\x1e\xc2\xeb\x00\x13\xe3\x6b\x51\xac\xcd\x62\x12\xb8\x7d\x75\x1d\xa8\x2c\xa6\x86\x07\x46\x58\xad\xdf\x7b\x13\x94\xc9\xd9\x94\x66\x72\xd0\x4e\xb6\x2a\x8b\x90\x88\x32\x60\xaf\x00\x49\x49\xc1\x94\x66\x19\x8e\xb5\x89\xc1\x06\x79\x75\xc4\x9d\x3f\x9e\x33\xf9\xc7\x5a\x8a\xec\x1f\x3b\xf9\x10\x29\xeb\xb9\x71\xb4\x75\x5c\x65\xc1\x4e\x93\xf3\x5e\xd1\x9f\xf0\x0a\x95\xce\xd1\x16\x96\x72\xfe\x44\x2d\x47\x34\xc3\xfc\x5a\x81\x76\x89\x77\xba\x14\x39\xcb\x31\x34\x82\x82\x76\xe7\xae\xe5\x18\xc8\xd6\xbd\x70\xdf\x72\x0c\xf5\x4b\x18\xbb\x73\xc7\x72\x8c\x64\xdb\x26\xcb\xf1\x38\x7a\x04\xcb\xb1\x94\xf4\x46\x8b\x32\x0a\xce\xce\xb2\x8a\x8a\xb2\x9b\xd1\xb9\x90\x34\x0e\xcc\xae\x05\xc0\x41\x5e\xa1\x30\x26\x3c\xa0\xb2\x6a\x1d\xe6\x12\x5d\xb8\x9a\x77\xca\x3e\xa0\xc9\x92\x2d\xeb\xa8\x2a\xa7\x4a\x5d\x20\x34\xae\x2a\xad\x93\xd2\x93\xe9\x9c\xb0\xa2\x92\xf4\xdc\xac\x34\x5d\xe1\x5a\x9d\x87\x16\x79\x34\x8b\x41\xb9\x65\x45\x75\x66\x61\x14\x0e\xb5\xe8\xbf\x3e\xc6\xe6\xb3\x1b\xc7\x76\xb4\x0d\x6f\xeb\x95\x49\xa2\x96\x14\x9b\x79\xd2\x4f\x4c\x2b\x3b\x50\x49\x89\xf2\xae\x11\x8d\x50\x17\xb7\x91\xd0\x04\x56\x50\x12\xa5\x68\xee\xaf\x0d\x3a\x90\x4f\x3b\xc0\x6b\x91\x9f\x9c\xa8\xee\x63\x3c\x39\x2f\x24\xc9\x28\x94\x54\x32\x91\x03\x56\x5d\xcf\xc5\x3d\x87\x19\x5d\x30\xee\x7b\x03\x70\x27\xd2\x0c\xba\x3e\xf0\xc6\x84\xa5\x01\x40\xaa\xba\x63\xf2\x14\x3e\xf6\x3a\xba\xfa\x6b\x2d\x51\xe9\x4c\xb4\xda\xda\xcd\xee\x79\x00\xc7\x16\x49\x8a\xd5\x1a\xf0\x98\x57\xa4\x28\x36\xad\x58\xf1\xe4\xec\x0a\x93\xe8\xc7\x5a\xf8\x2f\x0c\x53\x6b\x0e\x6b\x28\xc7\xee\x01\xed\x4e\x85\xbf\x6c\x92\x94\x64\xcb\xb0\x64\x8a\x04\xdd\x3d\x40\x09\xba\x9b\xa0\xbb\x7b\x29\x41\x77\x13\x74\x37\x41\x77\x13\x74\x37\x41\x77\x13\x74\x77\x24\x25\xe8\xee\x21\x4a\xd0\xdd\xbd\xf4\x24\x43\x13\x09\xba\x9b\xa0\xbb\x47\x53\x82\xee\x26\xe8\xee\x38\xbe\x09\xba\xeb\x45\x09\xba\xfb\x20\x25\xe8\x6e\x08\x25\xe8\xae\x2f\x25\xe8\xee\x68\x4a\xd0\xdd\x04\xdd\x0d\xa0\x04\xc0\xf0\xa0\x04\xdd\x8d\x70\x71\xf8\xec\xd2\x33\x41\x77\x13\x74\xf7\x48\x4a\xfe\xb1\x96\x12\x74\x37\x80\x12\x74\xf7\x20\x25\xe8\x6e\x82\xee\x06\xf0\x7a\x7a\x96\x63\x0d\x11\xbd\x96\x62\x16\x5c\x5a\xfa\x1a\xc1\x51\x2c\xb3\x1e\x35\x73\x4e\x42\x80\x97\xf5\xd0\xa6\xf0\xaa\x8f\x99\xc3\xfe\x56\xae\x7c\xa4\x07\x5f\x87\x09\xb5\x63\xc4\xd2\x98\xd3\x81\x6a\xb7\x1e\x8c\x47\x42\xba\xea\x82\xce\xea\xa2\x14\xf6\xff\x5a\x40\x57\x07\xc9\x65\xbd\x93\xbe\xb5\x72\x3f\x4b\xd5\x55\x7f\xf8\xd6\x5e\xe8\x16\x08\xaf\x32\xce\xd0\x5e\xf4\xb7\x61\x5b\x7d\xf0\x95\x27\xef\x3e\x64\xab\x0f\xbc\xf2\xb5\xfc\xbd\xe1\x5a\x4f\x00\xb8\x17\x0c\xd1\xda\x03\xcf\x0a\xd4\x5e\x5b\xd0\xac\x1a\x5c\x15\xc0\x71\x10\x96\x15\x38\xca\x1d\x48\x56\x0d\xaa\x8a\xf0\xe6\x88\x3d\xed\x02\xaa\x02\xa3\xfc\x1d\x28\x56\x17\x4c\x15\xc0\xb5\x03\xc3\xda\x05\x52\x85\xac\x94\x1e\x02\x51\x39\x0c\x50\xc8\xe5\xb2\x07\xa0\x1a\x80\x40\x05\xf0\x46\xf0\x54\x64\xf8\xd3\x20\xf4\x29\xcc\x7e\x1d\x80\x3d\xd5\xc0\xa5\x90\x89\x6d\x21\x4f\x5d\xd0\x52\xc8\x16\x68\xe0\x4e\xdb\x80\xa5\x20\x17\x48\x1e\x1b\xac\x14\x23\x34\x1c\x1c\x16\x0e\xb4\x54\x5d\x9a\xd0\xed\x52\x52\xb5\x14\x85\xa7\x2a\xe8\xa9\x81\x77\x8c\xb3\x55\xb5\x32\x32\x47\x19\xb9\xcd\xd6\x81\x39\x4c\xaa\x41\xab\x5a\x23\x10\x63\xca\xde\x1a\x0f\x25\x8a\xa4\x39\x72\x37\x5b\x0c\x0b\xba\x2f\xc9\xda\xdf\xd4\x57\x55\x96\x51\x9a\xd3\xbc\xe7\xd7\x84\xdf\x4e\xeb\xb9\xf0\xe4\x6b\x1b\xa4\x32\x05\x2f\x42\x2c\x8c\x90\x1b\xd1\x5c\xc8\x15\xd1\xc8\xe3\xb7\xbf\xf1\xe0\x10\x84\x7d\x7b\x14\xdc\x5b\x74\xcc\x5b\xb0\x19\x17\xe6\xcb\x0b\xf0\xe3\x85\xdb\x8f\x61\xfe\xbb\x61\x6c\x5b\x98\x8e\x1b\xc2\xb5\x85\x71\x7c\x04\x4c\xdb\x20\x9e\xad\x8b\xfc\x0a\xb3\x74\xc3\xb0\x6c\x91\x10\xaf\xc1\x18\xb6\xc7\xc1\xaf\x0d\x63\xd7\x50\xba\x84\x18\x17\x7d\xdc\x5a\x38\xf2\xec\x49\x98\x16\x8f\x81\x36\xdb\x45\x9a\xb9\xc9\x0a\xf3\x62\x37\x28\xb3\x78\x28\xb1\x48\x08\xb1\x18\xe8\xb0\x60\x64\x58\x38\x2a\x2c\x16\x22\x2c\x06\x1a\x6c\xa7\x0b\x68\x84\x1d\x04\x75\xe3\xc6\x28\xf8\xea\x58\xde\xe3\x28\xe8\xaf\xc7\x9d\xae\x18\xa8\xaf\x08\xf3\x15\x86\xf6\x7a\x1c\xa4\x57\x4c\x94\x57\x8c\x29\x0a\x8a\xd1\x3d\x0e\xb2\x6b\x10\xd5\x05\xde\xf9\xef\xb0\xed\xee\x9a\x76\x23\x6b\x01\x4c\xb7\xd0\x5c\xdd\xa8\x5a\x00\xd7\x06\xc9\x15\x37\xa2\x16\x18\x4d\x8b\x15\x49\x8b\x14\x45\x7b\x24\xec\x55\x28\xee\x6a\x18\x73\x65\x6c\x90\x80\x0d\xb1\x83\xb7\x6a\x11\x53\x01\x5c\xbb\x3e\x89\x30\xb4\x54\xe0\x82\x32\xce\x34\x23\xc5\x6b\x5a\x90\xcd\x0d\xcd\x04\xcf\x3d\xad\x89\xad\x5e\xd5\x0e\x2d\x30\x07\x65\x99\x7a\xbe\x9f\xf5\x04\xf5\x6b\x5d\x2c\x89\x02\xff\xd8\x25\xb4\x85\x53\xea\xf0\xa8\x33\x4c\x81\x60\xf0\xd1\xcc\x87\x67\xf8\x12\x9e\x5c\x08\x13\x9e\x84\xcb\xc9\x96\xfc\x88\xb7\xbd\xfe\x28\xee\x41\xcc\x35\xe5\x70\xca\x78\xbd\xc3\xce\x7c\xbd\x4f\x8d\xb3\xa9\xf5\x67\x36\x4e\x43\x7f\x9e\x2f\x9e\xd7\x03\x6b\x5c\x8e\x41\x86\xd9\x97\xec\x72\x44\x67\xac\x52\x4f\xd3\xa3\xed\x06\xf7\x58\x2e\x6d\xc7\x7e\x5e\x15\x56\x98\xf9\xfa\x6f\xd0\x19\xee\x1c\xe4\x7d\x9f\xb6\xe7\xb6\x00\x78\xe7\xcc\x9c\x17\xf8\xe6\x8d\x34\x24\x3c\x07\x57\xee\xcc\x9b\x73\x77\xc3\x7f\xd1\x5b\x37\x10\x45\xfc\x58\x08\xe2\xbd\xe8\x61\x8b\x01\xf6\xe4\xba\x83\x1c\x6e\xf1\xbf\xbe\x1c\xfb\xa8\xe1\x2e\xf6\x37\x60\x8c\x6d\x57\x66\x7f\xdc\x6f\x8a\x11\xf8\x7d\x77\x2f\xbe\x17\xc3\x05\x01\x26\xf1\x16\xb6\x37\x56\x1a\x7c\x3f\x05\x3e\x14\x23\xfe\x64\x6e\xfb\x35\x1a\x37\xd4\x37\x96\x6e\xfb\xe9\xb6\x7f\x80\x1e\xe1\xb6\xaf\xd9\x8a\x8a\x4a\x3f\xd9\x0b\xe7\xfd\x92\x65\xcb\xae\x2d\xc8\x56\xde\xaa\x5a\x54\x7a\xcb\x5e\x73\x43\x8c\x08\x45\x48\xb7\xce\x2d\xf2\x8b\x69\x0c\x38\x54\xc3\xab\xdf\x36\x08\x59\x20\x0a\x08\xbc\x7e\x7f\xf3\xe3\xdb\xcb\xff\x7c\xf3\x76\x0a\x6f\x48\xb6\x0c\x62\xcd\x38\x10\xd4\x6c\x28\xc2\x96\x64\x4d\x81\x40\xc5\xd9\xdf\x2a\xea\xab\x17\x4e\x9b\xf1\x9d\x45\xc1\x74\x07\x48\x20\xa3\x93\x3c\x64\x43\x6f\x11\xdf\x32\xa5\xcd\x22\x22\x2f\x57\x67\x4c\x78\xf9\x03\xe7\x52\xac\xb6\x55\xdb\x1b\xc3\xcc\x9a\xde\x9e\xd6\xdc\x92\x4a\x0a\x0b\xb6\x76\xc8\x67\x8b\x01\x05\x92\x07\x54\x95\x33\x52\xc0\x1c\x1c\x73\x39\x20\x33\x04\x14\x2e\x29\x70\xaa\xcd\xa1\x6f\x5c\x99\x7e\xe8\xca\x4e\xf1\x6f\xa8\x14\x55\xe7\x30\xab\x10\x1c\x5a\x4a\xb6\x22\x92\x79\x41\x30\x3a\x03\x26\xc5\x14\xde\x8b\xfa\x7a\xb4\xc1\xa9\xf5\xf1\x37\x19\x6b\x06\xa7\xf6\xf5\x87\x37\x37\xf0\xfe\xc3\x2d\x94\x12\xeb\x04\xfb\x22\x2b\x91\x23\x6e\x81\x19\x35\xa3\xb2\xdb\x28\x9f\xc2\x25\xdf\xf8\xae\xbd\x55\x32\x4c\x81\xb9\x0f\x51\x6e\xd8\xba\xf0\x54\xee\xed\x7c\x7a\xf6\x7c\x8a\xff\x7b\x66\xf6\x90\x34\xa6\x5c\x03\xd7\x0d\x11\x34\x75\xd2\x88\x35\x0f\xd9\xac\xa0\xed\x79\x70\x3b\xcb\xc7\x5a\x8a\x26\x5f\xfc\x50\x19\xde\x68\x8c\x2d\x88\xbd\x9b\xd7\x6b\xb3\x47\x24\x2d\x25\x55\x94\x7b\xde\x59\x48\x73\x50\x71\xc7\xa1\x80\x37\x12\xa6\x08\x4c\x6c\x0b\xbc\xed\x86\xdc\x75\x27\xed\xc8\xaf\xfd\x0e\x4a\xe8\x85\xb7\xf7\x7c\x5f\xb3\x7c\xf0\xfa\x35\x0f\xcb\xd8\x6d\xf4\x51\x7d\xf0\x4b\x91\x9f\x28\xb8\xf2\xc7\x3d\xb9\x53\x3f\x85\xdb\x25\x53\xed\xcd\xc6\xd8\x8a\xcc\xbf\xdc\x13\xee\x45\x1b\x58\x3e\x87\xe7\xf0\x07\xf8\x04\x7f\xc0\xcb\xd7\xef\x7d\xef\x48\x31\x2e\x38\xa1\xae\x3d\xeb\x07\xb9\xba\x8e\xb2\x23\xfe\xbc\x24\x1a\xf9\xc1\xd5\x75\x08\xb8\x71\xc6\x78\x8e\x5b\x81\x7e\xd2\x54\x72\x52\xd4\x57\xf3\xb0\x99\x0e\xb8\x02\x9a\x97\x7a\xf2\x07\xc7\x56\xb0\xb8\x9a\x7b\x73\x6c\xac\xf4\x73\xd0\xbd\xa3\xe3\xcd\x11\x8f\xdc\xe0\xd1\xf1\x66\x69\x8f\x1c\x5c\xcd\xd1\xd7\xf6\xde\x69\x0a\xa6\x3a\xa3\xf7\x9f\xd2\xe6\xad\x57\x44\x67\xcb\xbe\x5a\xf3\x77\x85\xbc\x33\x47\xa2\x2d\xbd\x0f\xb9\x40\xdf\x72\x50\xd1\x60\x33\xd4\x2f\x5b\xf0\x84\x40\xee\x7a\xe7\xe9\x6a\xbe\xbd\x73\xbd\x67\x75\x9f\x1b\x2c\xa8\x22\xb1\xbb\x8c\x76\x1a\x6b\x94\x22\xb7\x37\x5f\x6f\x9e\x66\xf2\xf2\x8e\x7d\xd4\xbb\x00\xfb\x6b\xce\xee\xc5\xd9\x55\x74\x0a\x4d\x1e\xb4\xa2\xdb\x68\x86\x8c\x70\x9b\x74\x3d\xa7\x52\x86\x6c\x7d\x01\xb3\x0d\x22\xd7\x58\x46\x03\x0f\x41\x80\x4e\x28\xa5\xd0\x22\x13\xde\x45\x3d\xfa\xe0\x3e\xc7\x0c\xa7\x3b\x24\x7c\xd5\x46\x34\xbf\x7d\x7d\x7d\x0e\xb7\xaf\xae\xcf\x41\x48\xb8\x79\x15\x82\xaf\xe9\x7a\xee\x9e\xdd\xbe\xba\x7e\xf6\xd9\x26\x1d\xea\x7b\xe1\x4b\xaf\x32\x41\x3d\x37\xae\xb9\x72\x4e\x56\xa4\x9c\xdc\xd1\x8d\x87\x55\x1d\x6a\xd3\x4f\x9a\x1d\x14\xe1\x35\xec\xc4\xae\x48\x39\x92\x97\xa4\x24\x67\x4f\xb4\x72\x83\x3b\xe1\xed\x18\xb7\x4b\x38\x78\xf0\x44\xf9\xb3\x12\x6b\x9a\xdb\xcb\x7b\xfd\x0c\xca\xf3\x52\x30\xbf\x1b\x6b\xaa\x04\x71\x98\x52\x25\x88\xe3\x28\x55\x82\xe8\x53\xaa\x04\x11\xc0\x33\x55\x82\x48\x95\x20\x2c\xa5\x4a\x10\xa9\x12\x84\x27\xa5\x4a\x10\x87\x07\x97\x2a\x41\x7c\xb1\xd8\xd6\x54\x09\xe2\x30\x25\x94\x67\xaa\x04\x91\x2a\x41\xec\x50\xaa\x04\xf1\xb9\x4d\x8b\x54\x09\x22\x55\x82\xa8\x29\x55\x82\x18\x41\xa9\x12\xc4\x38\x4a\x95\x20\x0e\xd2\x13\xcb\x0d\x49\x95\x20\x52\x6e\xc8\xb1\x7c\x9e\x5e\x6e\x08\xa4\x4a\x10\x7e\x94\x2a\x41\x8c\xa7\x54\x09\x62\x1c\xa5\x4a\x10\xe3\x79\xa6\x4a\x10\x2d\xa5\x4a\x10\xa9\x12\xc4\x17\xba\x75\x53\x25\x88\x54\x09\x62\x98\x52\x8c\x20\x55\x82\x18\x47\xa9\x12\x84\x3f\xd3\x74\xdb\xf7\xe7\xf3\xf4\x6e\xfb\xa9\x12\x44\xaa\x04\x71\x90\x42\x4c\x37\x49\x95\xa8\x64\xe6\xa3\x22\xfb\xfb\xea\x95\x58\x95\x95\xa6\xf0\xb1\x66\xd8\xe8\x7d\x8f\x77\x9a\x6d\x6c\xc2\x55\x47\x3a\x7e\x0e\xd8\x74\x26\xf8\x9c\x2d\x2a\x89\xc9\xf7\x17\x2b\xc2\xc9\x82\x4e\x32\xfb\xa2\x93\x66\xe6\x26\xcd\x28\x2f\xbe\x28\xe8\x74\xc1\x56\xcc\xa7\x82\x04\xec\xac\xfd\x5b\xe4\xd4\xc6\x47\x03\xe0\x2d\x2b\xf2\x09\x2f\x44\x64\x25\x2a\xae\x6d\x9e\x00\xce\xb7\x27\xcf\x66\x95\x6c\x9c\xdb\x5c\x09\xdb\x4d\x10\x00\x11\x78\x02\x5b\x07\x62\x18\xe7\x6d\x2d\x8d\xeb\x60\x6b\xb9\x24\x5a\x53\xc9\x5f\xc2\x7f\x9d\xfe\xf5\xd7\x3f\x4d\xce\xbe\x3a\x3d\xfd\xfe\xf9\xe4\x3f\x7e\xf8\xf5\xe9\x5f\xa7\xf8\x8f\x7f\x3d\xfb\xea\xec\xa7\xfa\x87\x5f\x9f\x9d\x9d\x9e\x7e\xff\xa7\x77\xdf\xdc\x5e\xbf\xf9\x81\x9d\xfd\xf4\x3d\xaf\x56\x77\xf6\xa7\x9f\x4e\xbf\xa7\x6f\x7e\x38\x92\xc9\xd9\xd9\x57\xbf\xf2\xbe\x1c\x06\x98\x1f\x71\x8c\x8f\x28\xa6\xc7\x23\x18\x1e\x0e\x5d\x12\x45\x3c\x7c\x74\xbc\xe2\x08\x08\xe7\x31\x89\x2f\x20\x6a\x7d\x85\x19\xc4\xf5\x98\xfd\x9d\x90\x62\xc5\xb4\xa6\x39\xba\x8c\x3a\xe5\x45\x7c\x71\xe0\x4c\xf7\x9a\x71\x3b\x91\x8b\x09\x46\xde\x10\x68\xa6\xba\xb8\xea\x4e\xa6\xac\xd0\x4b\x2a\xef\x99\x77\x3c\xc8\x5c\x90\x78\xeb\xcd\x40\x21\x38\xc9\xe9\x9c\x71\x6f\x07\x09\x1a\x71\xa3\xed\xb7\x24\x86\x93\x18\x1e\xc3\xe5\x29\x89\x61\x45\xb3\x4a\x32\xbd\x79\x25\xb8\xa6\x9f\x3c\x1c\x22\x7d\x29\x7c\xe3\xd8\x81\xc0\xdf\xf8\xe6\x39\x95\x22\xaf\xb3\xda\x64\xc5\x31\x75\x3d\xd0\xa4\x3a\xe6\x1c\x97\xa2\x60\xd9\xe6\xa2\x9e\x12\x3c\xb0\xf4\x93\xbe\x78\xb4\x3b\x80\x26\xea\xae\x15\x1f\x74\x62\x6e\x7e\xad\x94\xd8\x19\xc7\x17\x65\xf8\xa3\x25\x7c\x2d\xd9\x9a\x15\x74\x41\xdf\xa8\x8c\x14\x28\x1f\x63\xe8\xfa\xcb\x3d\xbc\xfd\xe3\x43\x5a\x8a\x42\xc1\xfd\x92\x1a\x9d\x04\xc4\xbc\x3b\xba\xde\x32\xe2\xcb\x74\x41\x18\x87\x95\xd9\x06\x65\x3d\x50\x73\x1a\x8c\xc6\xf2\x56\xf8\x25\x91\x94\xeb\x7a\x70\xae\xc0\xd0\x4c\x88\xc2\xa5\xd8\x79\x63\xae\x9b\x19\x70\xb9\xc4\x5c\xfc\xc8\xe9\xfd\x8f\x66\xe4\xbe\x63\x9d\x17\x64\xd1\xd4\x2c\x53\x54\xd7\x60\xaf\x90\x8c\x6c\xb0\xbb\xd2\xbe\x7c\xe4\x4d\x80\x39\x55\x15\x05\x52\xdc\x93\x0d\x6e\x85\x38\xe3\x65\xea\x25\xbc\x38\x43\x31\x46\x14\x34\xe3\xcd\xe1\x37\xbe\x21\xf2\x25\x51\xf0\xea\xf2\xfa\xc7\x9b\xbf\xdc\xfc\x78\xf9\xfa\xdd\xd5\xfb\x10\x73\xc2\xec\x1e\xea\xb5\xc9\x33\x52\x92\x19\x2b\x98\xbf\x15\xb1\x83\xbb\xec\xb2\x0c\x30\x0a\xf3\xfc\x22\x97\xa2\xb4\x6b\x28\x2b\x8e\x65\xfd\xda\xfa\x37\xbe\x9e\xe4\xae\xd7\xb0\x53\x21\xd0\x6c\x6e\x5f\x67\xe4\xbc\xf7\xca\xb0\x90\x84\x1b\x6b\x1e\x3d\x53\x01\xd1\x6e\x07\xcd\x91\x15\xd7\x6c\xf5\xe5\x26\x5f\x93\x3c\x56\xe2\xf5\x65\x9e\xd3\x3c\xc6\xf6\x7a\x8a\x89\x07\xaf\xea\xd7\x0a\xc9\xb8\x81\xb6\x6a\x22\x5c\x7f\xb8\xb9\xfa\xdf\x71\x66\x0b\xdc\x8c\x85\x04\xb0\x22\xd4\x6c\x91\xa2\x8c\xb4\x93\x3e\xba\xea\x1d\x69\x2f\x3d\x44\x3f\xd3\xbd\xd4\x58\x72\x31\x30\x53\x1f\x2b\xde\x91\xd5\xde\x05\x0c\xda\x31\xc1\x4a\xe4\x74\x0a\xd7\xd6\x40\xa2\x2a\x0a\xcf\x4e\xd9\x38\x22\x29\x18\xc6\x5c\x33\x52\x78\x9b\x9a\xf4\x6f\x15\x5b\x93\x82\xda\x04\x3f\x2c\xe1\xd0\xad\x1f\x18\x41\x37\xcf\x49\xa1\x82\x94\x9e\xbf\x4d\x64\x8c\xd3\x77\xa2\xe2\x31\xf0\x49\x0d\x2f\xc8\x29\x17\x3a\xc8\x9f\x69\xde\x0b\x0b\x3e\x4a\x91\x81\xf5\x69\x06\x41\xb1\x6b\x6c\x5e\xc7\xa8\x42\x03\xce\xbf\x68\x32\x58\x13\xdc\xad\xe3\x75\xf3\xee\x36\xf6\x5b\xa9\xa0\xd7\xdf\x31\x89\x42\xa1\x2c\xe6\xfd\x25\x25\x39\x56\xf2\x29\x89\x5e\x5a\x9c\xde\x8a\xa8\x3b\x6f\xdf\x23\xb2\x71\x77\x3a\xe7\x25\xb6\x05\x78\x9a\xc9\xb8\xf5\x17\x7e\x73\x4a\x74\x25\xa9\xbd\x95\xd9\x64\x40\xca\xc9\xac\xf0\x45\x56\x07\x0a\x52\x33\x77\x1f\x78\xb1\xf9\x28\x84\xfe\xba\xa9\xb6\x12\xe1\xd0\xfc\xd9\xdd\xe0\xfb\x81\xdd\x80\x8b\x16\x42\xe4\xf2\x09\x2e\x34\x0a\xab\xf0\xe2\x30\x6e\x8f\x9b\xed\xfe\x19\x45\x95\xac\xf8\xa5\xfa\x46\x8a\xca\xd3\x32\xda\xb9\xbc\x7d\x73\xf5\x1a\x25\x7a\xc5\x03\x2e\x2f\x94\x6b\xb9\xc1\x4a\x68\x31\xda\x3e\x40\xd7\x5f\xf0\xad\x51\x89\x5b\xe7\xdf\x57\x50\xcd\xa1\xe2\x8a\xea\x29\xbc\x23\x1b\x20\x85\x12\xb5\x93\xc3\x5b\xe5\x5e\x23\x22\xbf\xeb\x8a\x9d\x02\x56\x16\xf5\xbe\x5c\x32\x0e\x33\xa1\x97\xb0\xc5\x36\xa0\x94\xe8\xee\x18\xb1\x42\x54\x10\x90\xbe\xed\xcc\xc1\xf8\xf6\x50\x7d\x25\x3e\xb9\xa3\x0a\x4a\x49\x33\x9a\x53\x9e\x05\x9d\xaf\x48\x88\x99\xdf\xff\x9b\xef\x09\x7d\x2f\xb8\x11\x92\x11\xce\xe8\x15\xcf\x59\x46\xb4\xf5\x42\xea\x28\x0e\x06\xc4\xea\x39\xcf\x16\xc1\xe2\x41\x46\x44\x7a\xb2\xad\x14\x95\x18\x15\xd5\xb2\xa2\x76\x63\xfd\xa9\x9a\xd1\x82\x6a\xdf\x62\x8b\x50\x57\x80\x26\xda\x56\x36\x63\x2b\xb2\xa0\x40\x74\x2d\x06\xfc\x7d\x4c\x94\x2b\xa3\x4e\x71\x26\x99\x86\x5c\xd0\xa6\x24\x97\xaf\xb3\x43\xc1\xb7\x57\xaf\xe1\x39\x9c\x9a\x39\x3c\x43\x7b\x62\x4e\x58\xe1\x5f\x9b\x03\xb3\x06\xb6\xec\x1f\x36\xaf\x87\xeb\xab\xbd\xae\x9c\xec\x03\x21\xad\xfa\x3a\x07\x2e\x40\x55\xd9\xb2\x9e\x6b\x7f\x1f\x6c\xed\x2e\x76\x19\x40\x88\xa3\x71\x02\xd6\x93\x63\x23\x96\xf7\x09\x58\xdf\xb9\xb5\x4c\x87\x04\xac\x77\x7c\x32\xdf\x27\x60\x83\x10\x89\x4f\x5c\xc0\x06\x1a\x30\xdf\x2a\x2a\x23\xd9\x2f\xdf\x3e\x71\xfb\xa5\x7b\xc5\x35\xb2\xb2\x5d\x59\x7f\x03\xc1\x0a\xc4\x15\xd5\x24\x27\x9a\x38\xbb\x26\xb4\x86\xe8\xae\x4d\x94\x0e\xdf\xd3\x3c\x7c\x9f\xd3\xba\x51\xf4\x2d\xe3\xd5\x27\x9b\xb0\x12\x2b\x80\x74\xf3\x06\x99\x42\x16\x36\xc5\xb8\x75\x49\x59\x16\x0c\x2b\x4a\x6e\xe5\x50\x04\x29\xce\x6e\xa3\x80\x70\xe1\x50\x5f\x67\x50\x71\x92\xa2\x10\xc6\xc0\x33\x77\x56\xc2\x73\xe1\x8b\x64\xdf\x9a\x44\x74\x76\xd0\x5e\x9b\xbc\x29\x1e\x72\xdf\xb3\x96\x44\xc3\x17\x20\x1a\x3e\x6b\xe0\xaf\xa0\x6b\xea\xdd\xd7\x60\xbb\xfb\xa0\xe1\x05\x4c\xd5\xdb\x3a\x20\x7a\x80\xc3\x82\x82\xcc\x68\x61\x2d\x7f\x2b\x22\x22\xe4\xc3\x05\x0b\x97\x28\x61\x32\x29\x8a\x58\xf5\x3e\x3e\x8a\x02\x93\x61\x48\x84\x69\x37\xc3\xfa\x19\xcf\x3a\xb2\x88\x33\xeb\xb7\x9b\x32\xda\xac\x63\xc8\xe0\xe7\x3b\xeb\x95\xf7\xc5\x01\xb6\x67\xdd\xdc\x41\x62\xcd\x3a\x1a\xf6\x3f\xcf\x59\xbf\x67\x3c\x17\xf7\x2a\xae\xc1\xf7\x67\xcb\xb4\xd6\xa6\xbe\x69\xec\x8a\x6a\xcd\xf8\x42\x75\x8d\x3e\x52\x14\x11\x40\x43\x43\x56\x9f\xc3\xc6\xfa\x86\x72\xea\xa6\x9f\xbb\x56\x49\xa0\xdb\xa5\x52\x2e\x2f\xa1\x63\x45\xf9\xda\x90\xbb\x4e\xe7\x21\x2b\x2a\x20\xa6\x97\xac\xa8\x43\xb4\x58\x29\xf2\x4a\x9a\x97\xd0\x8c\x14\x37\xa5\x6f\x0f\x13\xd8\x3e\x78\xdf\xbc\xbb\xb9\xec\x33\x0e\x90\x4f\x0c\xb1\x96\xd2\x3a\x68\x0d\x67\x20\xf9\x8a\x29\xe5\xef\x45\x34\x74\x4f\x67\x4b\x21\xee\xe0\xb4\x46\x5f\x2f\x98\x5e\x56\xb3\x69\x26\x56\x1d\x20\xf6\x44\xb1\x85\xba\x70\x82\x69\x62\xe6\xcb\x17\x93\x89\x6f\xc2\x0b\xc6\x5d\xcc\x16\xef\x4e\x5c\x2b\x10\xfe\xed\x10\xa1\x9d\x92\xac\x99\x6d\xdc\xf1\x01\x2c\x6d\xe3\x36\x0b\x30\x1c\x58\xc8\xf7\x61\xf5\x0b\xb0\xe2\xe5\x67\xd5\xeb\xbb\x9b\xfe\x7d\x50\x41\xd5\x03\x1b\x3f\x70\xbe\x6c\x23\x18\x5b\x6c\xc3\xf9\x0b\xcd\x33\x02\x38\x6e\xed\x14\xe7\x2c\xfc\xbc\xd7\x8a\xda\x51\x1b\x71\x25\xd0\x61\xeb\x58\x06\x1d\xd9\xc6\x82\x68\x5d\xbf\x1d\x27\x6e\x00\xeb\x6d\xf7\x6f\xe3\xc8\x0d\xe0\xb9\x8d\x40\x8e\xe2\x06\x86\x47\x74\x05\xc3\xd1\xee\xe0\x80\x07\xf4\x0d\x96\x48\x56\x00\xec\x77\xfd\x04\x0a\xf4\x47\x33\x5c\x20\x9a\xf1\x02\x61\x07\xdf\x95\x2b\x8b\xd2\xd2\xef\xa6\xc3\x0b\x58\x1d\xc2\xf6\x78\xab\x3a\xe8\x6d\x56\xd4\x16\xad\x6c\x4a\xc1\x15\x9b\xba\xf0\x26\xfb\xbb\xdf\x5e\xef\xb7\x80\xe5\xc2\xe6\xb6\x76\x2a\x59\x7a\xf0\x74\x3d\xbd\x72\xa8\xb8\x66\x45\x8d\x68\x5a\x95\x85\xb1\x5c\x7a\xa3\xf7\x1c\x31\x72\xec\x74\x0d\x3c\x6f\xa6\x27\xa4\xb9\xa1\xab\x05\x7a\x0e\xff\x5d\x29\x0d\xa4\x49\x29\xaa\x0b\xda\xe1\x4a\x7a\x30\xaf\x6b\xed\x21\x3e\xce\xb5\x72\xc5\x7a\xf6\x5a\x98\x97\x58\xb3\xdc\x87\x6b\xce\xe6\x73\x5a\x27\x55\xcd\x28\x94\x44\x92\x15\xd5\x08\x77\xf5\xc5\x48\xcc\xe8\x82\xd9\x9c\x13\x31\x07\x62\x26\xf4\xe4\x44\xb5\x55\xd2\x7c\xe4\x07\x66\xb2\x30\x0d\x2b\xb6\x58\x6a\x3c\xe4\x40\xa0\x10\x7c\x81\xb5\x70\xfc\x20\x02\x85\x20\x39\xa0\xac\x17\x12\xee\x89\x5c\x01\x81\x8c\x64\x4b\xc4\x5e\x78\x45\x64\xf3\x4a\x62\x3b\x42\x4d\x49\xbe\x99\x28\x4d\xb4\xb9\xeb\x52\x9b\x17\x6d\x57\xce\x83\x6b\xb6\x53\x93\xc5\xee\x01\xf4\xb8\xcc\xa8\xf6\xe9\x0e\x5e\xc3\x21\x1d\x06\xb2\xb6\x87\xbb\xc2\x26\x80\xeb\xbc\x20\x8b\xa7\x56\x04\x28\x75\xcf\x74\x94\xba\x67\x1e\x4b\xa9\x7b\xe6\xd1\x94\xba\x67\xa6\xee\x99\xa9\x7b\x66\xea\x9e\x99\xba\x67\x6e\x51\xea\x9e\x99\xba\x67\x3e\x40\xa9\x7b\xe6\x61\x86\xa9\x32\xb6\x27\xa5\xee\x99\xa9\x7b\xe6\x7e\x4a\xdd\x33\x3f\xb7\x69\x91\xba\x67\xa6\xee\x99\x35\xa5\xee\x99\x23\x28\x75\xcf\x1c\x47\xa9\x7b\xe6\x41\x7a\x62\xfd\x34\x52\xf7\xcc\xd4\x4f\xe3\x58\x3e\x4f\xaf\x9f\x06\xa4\xee\x99\x7e\x94\xba\x67\x8e\xa7\xd4\x3d\x73\x1c\xa5\xee\x99\xe3\x79\xa6\xee\x99\x2d\xa5\xee\x99\xa9\x7b\xe6\x17\xba\x75\x53\xf7\xcc\xd4\x3d\x73\x98\x52\x8c\x20\x75\xcf\x1c\x47\xa9\x7b\xa6\x3f\xd3\x74\xdb\xf7\xe7\xf3\xf4\x6e\xfb\xa9\x7b\x66\xea\x9e\x79\x90\x42\x4c\x37\xa5\x73\xe6\xd1\x36\xe5\x71\xea\xa2\x3a\xb4\x6c\xa7\xd6\xcc\xac\x9a\xcf\xa9\x44\xb3\x1b\x47\xea\xe5\xb8\x19\x2e\xd3\x3b\xad\xd3\x14\x7c\x78\x5a\xc3\x4f\x51\x7d\x8e\x25\x5c\x95\x4d\x9c\xc6\x21\xfa\x01\x1e\xfb\x43\x74\x25\x77\xb0\x59\x88\xa4\xca\xef\x7e\xcd\x38\xbc\xf9\xf0\xf5\x34\x42\x49\xd8\x90\x6a\x6a\x38\x27\x1f\x78\x16\x9a\xac\xd3\x6e\xb2\xb0\xca\x46\x75\x55\x23\xb7\xd7\xb2\x42\x28\x8b\xad\xb5\x8b\x97\x2d\x09\xe7\xd4\x27\x41\xc5\x0a\x44\xa6\xd1\xed\x36\xa3\x94\x83\x28\x29\xb7\xf8\x7f\x02\x8a\xf1\x45\xe1\xa3\x01\x88\xd6\x24\x5b\x4e\xcd\xfb\xf3\x7a\x83\xb9\x6e\x32\xcd\xa8\x7d\x8e\x9a\x96\x94\xac\xec\x46\x93\x74\x45\x98\x1d\x2e\x90\x4c\x0a\xa5\x60\x55\x15\x9a\x95\x01\x03\x06\x45\x31\xcd\x5a\xd9\x9c\xff\x7a\x13\x80\xd7\x71\x53\xd4\x82\x3d\xb1\x76\x67\x33\x07\x6e\x7a\xbd\x4c\xb0\xf6\xa8\xe1\x05\xfe\x1c\x1b\x09\xae\x4a\xbd\xb1\x09\x51\x9e\x07\x78\xce\xa4\xd2\x90\x15\x0c\x6f\x70\x38\x0f\x14\x35\x19\x8e\xd9\x07\x01\x4c\x78\x6e\x38\x73\xb7\x46\xca\x2d\x12\xcf\xd1\x00\x2d\xbd\x0c\x7e\x4c\xcb\xa9\xf3\xbe\x68\x3d\xdc\x9c\x29\x77\xa1\x50\x5e\x03\xad\xab\xa9\xdb\xc3\x55\xaf\x11\x1e\xaf\xdc\xb3\x2c\x70\xfd\xce\x8e\x49\x67\xc8\x01\xe7\x1f\x0b\xa0\x3b\xaf\x78\xa3\x02\x6c\xe9\xf2\x5a\x40\x7a\xbd\xff\x6e\x32\x6e\x5d\x0c\x17\x15\x84\x07\xcb\x8e\x4a\xc1\x63\xca\xe9\xda\x68\x2f\x9a\x51\xb6\x36\x46\xb8\x07\xcb\x41\x7d\xf0\x0f\x55\x07\x9a\xca\x15\xe3\x98\xb4\xf5\x8e\x2a\x45\x16\xf4\xda\x2b\xfa\xbd\xef\x6e\x8d\x01\xf0\x7a\x33\x7a\x1f\xe3\x02\x2f\xd8\xad\x71\xdb\xa6\x20\x9c\x78\xa5\x87\xb6\x2f\x0d\x2b\xfb\xd6\x4d\x5d\x94\x7b\xc9\xb4\xa6\x5e\x86\x8d\xb2\xdd\x16\x10\x38\xb4\x5d\x89\xc7\x6f\xa0\x9d\xf4\x0a\x78\x57\x0f\xd4\x0e\xd0\x3c\xce\x18\xa9\x3c\xf7\xf2\x71\x59\x94\xd3\x4c\x32\x3a\x87\x39\xc3\x2c\x06\xc4\xdb\x9f\xdb\xea\xbe\xc4\x67\xb4\x84\x03\x51\x8a\x4a\x9c\x57\x87\xb7\xae\xe7\x77\x0a\x7f\xf6\xce\x33\xd5\xb2\xe2\x19\x69\x7b\x65\x01\x17\x39\x05\x36\x87\x05\x22\xfb\x7d\xa4\x0e\xf6\xe6\xfb\xb7\xe7\xff\xf1\x7b\x98\x6d\xcc\x45\x03\xb1\x2c\x5a\x68\x52\xd4\x03\xf6\x60\x5a\x50\xbe\x30\xbb\xdd\xaa\xec\x7e\x49\xa1\x80\x34\x5b\xec\xaa\x6e\x73\x5f\x5f\xfc\xe6\x6e\xd6\xbb\x93\x79\x70\xbc\xc8\xe9\xfa\xa2\x73\x02\x26\x85\x58\x74\x9a\xe1\x7b\x70\xac\x53\x35\x7d\x13\x15\xbd\xae\xf9\x03\x82\x0b\x3b\x7a\x06\x8a\xae\xba\x70\x3a\x2c\xc5\xbd\xed\xa6\xd2\x3e\xc7\x63\x6a\x6a\xe9\xd2\xe6\x1d\x96\xa2\xac\x0a\x9b\xd9\xfa\x35\xf3\x32\xe8\x50\x52\x55\x8a\x6e\xd7\x9e\xd9\x23\xcb\xfd\x84\x43\x3d\xcc\xad\x8b\x90\x15\x12\x01\x13\x21\x5c\xe1\x06\x17\x5d\x6a\x2a\x9f\x57\xd2\x2b\xf3\xf1\x6b\x52\x14\x33\x92\xdd\xdd\x8a\xb7\x62\xa1\x3e\xf0\x37\x52\x0a\xd9\x9b\x21\x9f\x73\x4c\x8c\xd5\xb8\xac\xf8\x9d\x6d\x06\x5e\xbf\x7c\x21\x16\x20\x2a\x5d\x56\x5e\xb7\xbf\xf9\xf6\x76\x6a\xe6\x64\xee\xb7\x0f\x1a\x13\xd9\x19\xa5\x9d\x91\xd2\x4f\xcc\x2f\xf4\x71\xcf\x8c\x00\xe3\x40\xcd\x3c\x5a\xa9\xd8\xbe\xb5\xdf\x65\xa1\x23\xbe\x7e\xf3\xfc\xdf\xfe\xdd\x0a\x5c\x10\x12\xfe\xfd\x39\x26\x65\x7a\x99\xb7\x68\x0a\xa0\xfd\xc5\x14\xa8\x15\x29\x0a\x2a\x43\x05\xa3\x39\x8e\x1d\x41\xd8\x88\xb5\x7f\xa8\x54\xd3\xa1\x02\xec\x11\x9d\x3f\xb7\xb7\x7f\x41\xcf\x0f\xd3\x8a\x16\x73\x2f\xab\xbc\x50\xa2\xed\x77\x74\x82\xc6\xf4\x89\xb3\x45\xcc\x6d\xd2\x47\x04\x7c\x5e\x77\xca\x5a\x14\xd5\x8a\xbe\xa6\x6b\x96\xf9\x84\xb5\x7a\x4b\xd7\xe3\xe5\x9f\xf9\x5c\x30\x85\x05\xe9\x67\x85\xc8\xee\x20\x77\xec\x5a\x58\xbb\x8f\x15\xb2\x09\xad\x2b\x19\x92\x84\xe0\x9d\x7c\xb0\x77\x76\xdb\xd4\x01\x2f\x07\x2f\x81\x15\x29\xcb\xa6\xe8\x87\x24\xf7\xbd\xc9\xf6\xe2\x69\x24\x2f\xe3\xdd\x7b\xab\xcf\x61\x08\x0c\x0e\x87\x84\x86\x27\xee\xed\x3d\x6d\x0e\xef\xbc\x84\xd0\xa8\x72\x3b\x6a\xdf\xc0\x57\x6f\x9b\xb5\xec\x42\x6b\x17\x94\xc8\xc3\x26\xad\x47\xea\x2f\xd1\xa9\x8c\x64\xc7\xd9\x5c\x7b\xcd\x86\x0e\xa8\x2a\xa6\x85\x6f\xd0\x31\x38\xd2\x17\x92\x05\xd2\x5b\x39\xde\xc4\x54\x57\x44\x7b\x39\x2b\x2c\x75\x8b\xfc\x11\x28\xa9\x54\x4c\x19\x1b\xfd\x3b\x14\x40\xaf\x0a\xc2\x7c\x03\x67\x4d\xf0\xa4\x14\xbe\x4b\x15\x30\xdd\x56\x80\x62\x73\xc2\x50\x4d\x77\x2d\x72\xc7\x0e\x15\x13\xba\x4d\xbc\x22\x2a\x3b\x6e\x96\xd0\x92\x14\xd1\xcc\xbf\xcf\xa9\xea\xbe\x6b\x57\x2a\x5c\xd3\x19\x2e\x8d\xaa\xb3\x9c\x9d\xb2\xf2\xe4\xf8\xe5\x2a\x38\x9c\x8b\x2f\x4d\xbf\x35\x83\x8e\x22\x24\x51\xb1\x39\x5b\x25\x44\xb9\xb5\x77\xd5\x36\x52\xb1\xa4\x4e\x28\x78\x73\x6d\xdd\x2c\xce\x13\x3b\x75\x60\x51\xee\xdd\xa9\xae\x19\x2a\x9c\xbc\x3c\xf9\x6c\x4a\xce\x2e\xa2\x14\x25\x59\xa0\xef\x20\xca\x5a\x6e\x33\x0d\x40\x78\x59\xb7\x06\x55\xe8\x36\x43\xbe\xbe\x95\x10\x2d\x95\x6e\x54\x34\x6f\x4b\xa0\x2f\x05\x56\x58\x88\xb1\xe5\x9c\xc3\xc4\x16\x6e\xbc\x0f\xc8\x8b\x26\x52\x54\x3c\x77\xd1\xe0\x06\x82\xf0\x6e\x6b\x62\xdf\xfb\x57\x30\x43\x37\x8f\xad\xd5\x8e\x85\xf0\x6c\xa2\x24\x53\xbe\xc5\xf0\x1c\x4f\x0e\x2f\xa6\x2f\x9e\x7f\xf9\x36\x1b\xce\x49\x24\x9b\xed\x7d\x63\xb3\x59\x2d\xf7\xd9\x66\xa7\x6e\x98\x1c\x65\x86\xde\xb9\x90\x54\xd3\xd9\xd8\x7f\xd3\xd4\xdd\x3a\x91\xd5\xbd\x64\xda\x9d\xa0\x7b\x16\x90\xa8\x76\x8a\x4e\x1b\x10\xb2\x5b\x82\xf8\xac\xf5\xe5\x05\x5c\x49\x42\x3a\x2e\x87\xb7\x2c\x04\x50\xd5\xec\xc9\xe9\x5d\xab\x60\xad\x50\x1d\x8a\xa7\xfa\xcf\xb7\xe3\xbc\xab\x82\xbd\x39\x76\xb1\x87\xcf\x9e\xc1\xa9\x7d\xc2\x89\xad\x66\x77\xf6\xd9\x8e\xa7\x5b\xd6\x37\x9f\x4a\xef\xa6\x32\xbd\xa5\x7d\xf3\xa9\x24\x3c\xa7\xb9\xbd\xf0\x07\x98\xd6\x50\x17\x9d\x1e\x5a\xe3\x70\xb5\x79\xa2\xfa\x6b\xec\xcd\xb1\x6b\x9e\xfd\x27\x5d\x92\x35\xc5\x9a\x7f\xac\x20\x32\x40\x3c\x69\x01\x37\x76\x65\x60\x56\x69\xa0\x7c\xcd\xa4\xe0\x2b\x1a\x50\xd8\x7d\x4d\x24\x23\xb3\x82\x82\xa4\x58\x38\x38\xa3\x0a\x7e\x75\xfa\xdd\xe5\x47\x84\x59\xfb\xb7\x8f\x20\x92\x02\xad\x57\xbd\x52\x98\x9e\x1b\xe9\x14\x76\x5e\x7b\xba\x75\x80\xfc\x45\xf4\xd6\xc1\xab\xe7\xd9\x9c\x00\xff\x39\xe0\x79\xb3\x5e\x66\x3e\x56\x95\xae\x48\x81\x65\x1f\xb3\xa2\x52\x6c\xfd\x39\xf4\xaf\x2b\xc3\xf9\x9a\x79\x9c\xec\xad\xf2\xa5\xed\xa1\xd9\xa9\xed\xe9\x59\xc2\x1b\xcd\xcb\x78\x2d\x25\x1d\xf0\xf2\x44\xd5\xc9\x2a\xbd\xd6\x40\xde\x41\x39\x57\xb6\x7a\x86\x83\x9b\xb3\x45\x25\x6d\x21\x1d\x3f\x11\xd4\x69\x66\xbd\x42\x14\xc9\xe7\x0a\xcf\xe5\x5c\xbd\xc2\xf7\x19\xb3\x31\xfa\x79\xfd\xbd\x52\xc1\xaf\xdf\xdf\x74\xea\x8f\x8f\x7a\x07\xeb\x56\x14\xf9\x14\xae\xdb\x02\xe6\x6d\x8b\x01\xec\xaf\x33\x1a\x6d\x62\x64\x32\x95\x8b\xb6\x05\xea\x82\x72\x2a\xf1\x02\x66\x86\x5a\xaf\xe5\xf8\x7b\xe2\x8c\x28\x04\x85\x1a\x36\x16\xa1\x31\x66\xc5\x3c\xdd\x3d\xbe\x3e\x13\x73\x2f\xb1\xd5\x55\x46\x3b\x5b\x7a\x6b\x7d\xd9\x04\xe1\xcc\xe4\xa1\x33\xd8\xb2\x1d\xbd\x59\xaf\xae\x81\xe4\xb9\x44\xf8\xa2\xbb\x02\xd6\xc7\x94\x94\xa5\x1f\xfa\xcb\xad\xb0\x59\x99\xee\x1b\xb7\x4b\x3e\x9a\x23\x9a\x1a\xed\x02\xc3\xeb\xaa\x2c\x98\x85\x6c\x75\x1e\x30\x9a\x6d\xfd\xa6\x92\xae\xc4\x7a\xfc\x51\xf7\x77\xc4\x7a\xba\x61\xbd\x35\x8f\xf0\xeb\x93\xf7\xc0\x9e\x93\x54\x89\xc2\x67\xc3\xb9\xa1\x6c\xed\x35\x27\x1b\x8c\x71\x3a\x7e\x56\xea\xbd\xe6\x58\x77\x44\xcb\xd6\xbe\x19\xcd\xba\xb3\xcf\x28\xd7\xd2\x08\xd7\xc0\x3d\x03\xf0\xd1\xcc\x5c\x85\x00\x9d\x66\xc0\x6c\x4d\xb9\x51\x62\x1f\x3c\x9b\xf9\xe1\xa0\xc4\x9a\x4a\x69\x2b\x87\xdb\x1c\x07\xdb\xf2\x91\x12\xe9\x93\xa2\xd2\xcc\xaa\xf7\xf4\xfd\xc3\x8f\xc7\x76\x08\xe8\xf5\xfb\x1b\xab\x53\xed\xb4\x1a\x3b\x84\x71\xaf\x40\x45\x77\xc7\x37\xab\xd6\xe8\x49\xcf\x73\xfc\x59\xfa\x27\xf8\x7b\xc6\xfa\x2d\x79\x5d\x9c\x23\xa4\x7a\x81\xf7\x15\x39\xa0\xd2\x9c\xf7\x93\x15\x25\x32\x5b\x8e\x9f\xf3\x07\x44\xa8\x65\x09\xb9\xc0\xac\x87\xf1\x3a\x51\x48\x74\x59\x4f\x50\xfd\x17\x42\xdc\x55\x65\x5f\xaa\x8e\x66\x59\x6b\xfc\x9e\x06\x77\xc3\x2c\x89\x5e\x8e\x1f\xe4\x5e\x51\xdc\x11\xad\xa3\x99\x76\x47\xf4\xcf\xa1\xc3\x73\xae\xc6\xa3\x8f\xfb\xb7\x03\xaa\xed\x9d\x00\xd9\xb4\x15\x5d\xc6\x8a\xaf\xde\x95\xff\x55\x51\x29\x4d\xe5\xd7\x4c\x2a\xfd\x6c\x0a\xdf\x91\x82\xb9\x22\x8b\xe3\x76\x8a\xb9\x9f\x9f\x74\x99\xfd\x99\xe9\xe5\x1f\x85\xd2\xef\xa9\x3e\x39\xef\xff\xe9\x64\xdc\xcd\xf1\xc4\x0d\xf8\x04\x84\x84\x93\xf7\x82\xd3\x93\xe9\xd6\xe5\xc8\xaa\xdf\x51\x5c\x19\x5e\x37\xac\x72\x19\xb2\x61\xdc\xdc\x9a\xa9\x1e\x29\x65\x0a\x9a\xe9\x9a\x49\xe7\xb4\xdc\x0a\x58\x92\xb5\xbd\xd6\xf9\x74\xfc\x55\x54\x03\xc1\x1e\x4f\xc8\x79\x69\xe7\xf6\x5e\xc8\x3b\xdb\xb0\x01\x99\x8f\x8c\x7d\xd9\x2b\xe1\xa6\xbb\xad\x3a\x5d\x1b\xb4\xd8\xbf\xa4\xe3\x6f\x68\x23\xcf\x8b\x6d\xc5\x74\x43\xe5\x9a\x65\xf4\x2d\xe3\x77\xa3\x0e\x6a\x3f\xd7\xe8\xcd\x0e\x2f\xcf\xd6\x71\xf7\x0e\x39\xcb\xb8\x4d\xe0\x36\x26\x09\x99\x89\x4a\xe3\xdd\x0d\x41\x94\x1e\x8e\x4f\xac\xff\xf0\xdf\x76\xd7\x20\x5e\xa5\xb4\x2d\xc2\x3a\x8e\xba\xc6\xcf\x38\x12\x0a\x8d\x21\xaf\xda\x79\xa8\x36\x5c\x93\x4f\xa8\xbb\x44\x76\x47\x25\x14\x66\x2a\xa6\xd0\xa4\x62\x79\x8b\x11\x04\xe6\x8e\xc9\xed\xf0\x8b\x9c\xd0\x72\x49\x57\x54\x92\xa2\xf1\x9d\xf9\x6f\x8a\xb7\x4e\x8d\x37\x3c\x3b\x99\x38\xa3\xe6\xc1\xf6\x8d\x71\xdd\xf3\x44\x3e\x85\x37\xa1\x1c\x57\x64\x83\xea\xd0\x32\x26\x1c\xe8\x27\xa6\x10\x60\x53\x8a\xbc\x53\xd3\x6d\x14\xd3\x4a\x51\x39\x69\x2a\x00\xba\x0a\x4b\xaa\x4e\xe5\x82\x9c\xce\xaa\xc5\x82\xf1\xc5\x38\x5d\x82\xb6\x0a\x5a\x44\x6d\x5b\xb6\xd6\xcf\x84\x6d\xea\x32\x49\x89\x1e\x6b\xab\xa1\x55\x7e\x8e\x1e\x60\xd6\xe5\xbd\x12\xb9\x65\x3d\xdb\x58\xef\xde\x58\xc6\x75\xbd\x1c\x33\xc8\x29\x5c\x71\x10\x32\xa7\x12\xcb\xc3\xe4\x39\xce\x75\xbd\x7a\xa3\xd8\xb6\x4e\x48\xc3\xa9\xbf\x62\xe7\x5e\x79\x26\x46\x06\xa8\x76\x34\x9d\x34\x31\x55\xcd\xcc\x45\xa6\x92\x63\xdb\x79\xf6\xd1\x01\xa4\x28\x97\x64\x52\xd0\x35\x2d\xc0\x75\x55\x1a\x1d\xfb\x5d\x0a\x2e\xa4\x5d\x8d\xda\x43\x84\x77\x56\x2b\xbc\x71\xb2\xdf\xec\x9e\xd9\x51\x8f\x70\x4d\xf4\xc6\xeb\x9b\xb1\x06\xa1\x87\x31\xd8\xbf\x19\xf0\x81\x77\x1d\x9f\x0f\xd3\xcd\x4a\xc6\xb9\x74\xd2\x80\xe4\x68\xd5\xd3\x55\x29\x24\x91\x6c\x74\x14\x6c\x77\x5f\xa2\x05\xd9\x17\x0b\x63\xc7\x9a\x69\xb6\x66\xe6\x1e\x3b\x20\x47\xda\xd9\x18\xc9\xb5\xb3\xd5\xd1\xa6\xe1\x02\xea\xfd\x6e\x2c\x40\x95\x2d\x69\x5e\x15\xe3\xef\x9d\x8b\x8a\x48\xc2\x35\xa5\xea\xbc\x86\xf7\x6c\x5c\x9a\xb6\x15\x2e\x4d\x92\xf9\xd8\x90\x90\x11\x73\xc8\x8d\x7e\x62\x1a\xdb\x67\x9a\xdf\xa0\x0c\xb3\xc9\xeb\x78\xaf\x19\xc9\x55\xc8\xad\xac\xf7\xae\x70\xf2\x0e\xeb\x64\xa4\x52\xd8\x0d\xc1\xa9\x12\xfa\x29\xa3\xc6\xec\xd0\xaa\x99\xe4\xb1\x9b\xc0\x66\xff\x30\xc1\xcf\x1b\xe9\xea\xf6\x2c\x5d\xb3\xcc\x23\xfe\x32\xa4\x40\x91\xa5\x5b\x27\x3c\x0a\x23\x79\xce\x36\x2e\xb8\x56\xb4\x8a\x63\x4b\x19\xdc\x2e\xe9\xd8\x43\xd5\x94\xd7\xc2\xc3\xb9\x66\xa4\x66\x39\x2c\xba\x47\x72\xef\x08\xfa\xed\x1d\xeb\xeb\x14\xec\xbe\x31\x08\x9e\xb9\xa1\x77\x5a\xa8\x8e\xe5\x88\x6a\x64\x5f\x03\xd5\x50\xe1\xbf\xd5\x43\x75\x9c\xa6\xf7\xf5\xd0\xf9\x01\x80\x3d\xc0\xbb\xfe\x6e\x40\x22\x17\xa1\xce\xd5\x93\x4b\xb9\xa8\x56\x98\x17\xec\x5c\x45\x6d\x9b\x7b\x1f\x97\xe0\xed\x92\x42\x6e\xaf\x15\x18\x87\x35\x17\x98\x57\xef\x5e\xd7\xd8\x44\x0f\x8e\xcc\x15\xfa\x70\x95\x9b\x5c\x53\xe7\x7c\x0a\xdf\xb9\xbb\x90\x4f\x44\x7b\x10\xa5\xd1\x43\x5b\x78\x70\x1d\xc2\x67\xf4\xef\x6f\x9e\xf1\x7c\xd2\xe2\x4b\x5a\x1b\xd8\x79\xb1\xbd\xe2\xef\xb6\x0b\x91\x9b\x83\x3a\x55\x84\xf1\xd2\xdc\x60\x7d\x7d\xb9\x0d\x26\x80\x67\x4b\xc2\x17\x56\x9a\xd0\x40\x14\x8c\xbb\xab\xba\xc6\xde\x54\x65\xa4\xac\x7d\x2a\x04\x72\x51\xf9\x2d\xff\xaf\x7e\x75\x0e\x8c\xbe\x84\x5f\x75\x06\x37\x85\x37\x8e\x7b\xbb\x39\x7c\x67\xc1\xd6\x7b\x99\xb5\x9b\xe9\x1c\x24\x5d\x10\x99\x17\x7e\xad\x3d\xc4\xbc\x71\x39\x20\x6a\xab\xde\x0c\x68\xc6\x29\x10\x3e\xa0\x0e\x2e\xf4\x10\x46\xa2\x53\x66\xcf\x83\xe9\x03\x85\xf9\x34\x51\x77\xea\xc2\x3a\x38\x26\x39\xd1\x64\x42\x4a\xeb\x37\x66\x82\x5f\xd8\x80\xce\xc4\xb5\x76\x9d\x10\x27\x94\x26\xcd\x41\xba\xf8\xa5\xac\xb0\x7b\xfa\x84\x34\x9f\x62\x7c\x42\x26\xd8\x08\xd4\xb7\x9e\xc4\x3f\x38\xf5\x26\x20\x5a\xe2\xdd\x33\x79\xdb\x05\x56\x0b\x77\xfb\xee\x53\x78\xef\x95\xef\xe0\x7a\x23\xe7\x6d\x32\xaa\x6b\xc8\xda\xca\x7f\x1f\x51\x5f\x6b\x8c\x37\xef\x6f\x3f\xfe\xe5\xfa\xc3\xd5\xfb\xdb\x5a\x71\xd4\x6a\xc0\x87\xeb\x3e\xc5\x11\x76\xd2\xf7\x29\x8e\x56\x0d\x84\xa0\x98\xb6\x15\x47\x5f\x0d\xf8\x70\xde\x55\x1c\x7d\x35\xe0\x33\xb3\xbb\x8a\x63\x40\x0d\x78\x5a\x11\xdd\xf9\x1d\x54\x03\x5e\xd2\xb9\xa3\x38\x86\xd5\x80\x07\xd7\x5d\xc5\xd1\x57\x03\x5e\xe7\x6b\x57\x71\x74\xd4\x80\xa7\xca\xdf\x55\x1c\x5d\x35\xe0\xc1\x74\x58\x71\x24\x35\x70\xcc\x43\xbd\xd4\x00\xe5\xeb\x40\x15\xd0\x38\xbc\x87\xa2\x0a\x3e\x2f\xd3\x6b\x6d\xd9\x29\x8a\x1d\x63\x53\x7d\x19\xeb\xd9\xc7\xe8\xf3\xf5\x77\x44\x82\xa4\xa5\xa4\x0a\xef\x55\x9e\x39\x21\x43\x0b\x04\x8e\xa9\x6f\x6b\x7e\xd2\xc2\x8d\xbf\xb8\x94\xda\xcf\x94\x14\x1b\x2d\x01\xad\x4e\x1a\xb3\x77\xec\x78\x29\x07\xd3\xa6\xc9\x09\x81\x57\x3f\x5e\xbd\x7e\xf3\xfe\xf6\xea\xeb\xab\x37\x1f\x3f\x5b\xd6\x4b\x50\xfb\xc8\xbe\xb9\x1a\xc7\x52\xb3\xf4\xb0\xbd\xe6\xcd\xd6\x56\x50\xa7\x6b\x26\x2a\xe5\x70\x69\x79\xd4\xf5\x55\x3b\xb2\xd5\x9b\x25\x56\x9f\xe5\x9b\x3a\x4a\x1d\x77\x98\xd3\x41\x4f\x85\x37\xdf\xa8\x86\xaa\xa5\x07\xcc\x55\x6f\x9e\x51\xbd\x1d\x96\xf6\xfb\x3c\xfc\x17\x3e\xb6\xc9\x6b\xe9\x41\xc3\x37\x64\xe5\xf7\x98\xbf\xde\x2c\x1f\xf0\x9e\x78\xf3\xac\x8d\xe7\x7e\xea\x94\x77\xfb\x95\x38\x62\xf7\x6b\x29\x56\x51\x44\xef\x8d\x0d\xb4\x39\x74\x99\xf7\x24\x0d\x19\x31\x27\xca\x8e\xd5\x7f\xdf\x75\xdc\x56\xce\x35\x50\x37\x8a\xf0\x66\x69\xf8\x61\x8d\xc4\x30\xb5\x19\xd4\xb8\x3b\x46\xb7\x6b\x9b\x7e\xf3\x8e\x94\x7f\xa2\x9b\x8f\x34\xa0\x43\xcb\x0e\xea\xb0\xa0\x99\x31\x66\xe1\x6e\x74\x78\xac\x4f\x08\xb6\x7e\x55\x0f\x33\xa4\xb5\xcd\x93\xea\x95\x1e\x36\x2d\xb1\x1a\x9d\xdf\x51\xef\x5a\x00\x35\xed\x34\xee\x0e\x5d\x70\xa8\x6f\x89\x66\x07\x85\xac\x37\xc4\x6c\x72\x1e\xbd\x25\xfc\x89\x33\xf0\xc3\xe7\xaa\x35\x76\xb4\x75\xab\x04\xb3\x3c\xbe\x6d\x8e\x58\x1b\xdb\x90\xde\x5f\xb8\x5c\xd4\x89\xb1\x3b\x26\xf6\x8c\xa9\x0b\x4c\xd1\xba\xf8\x25\xfe\x27\x78\x50\xb6\x71\xde\x65\x9e\xbb\xea\x2a\x95\xa2\xf3\xca\xa7\xf2\x75\x9f\x10\xd9\xa4\xa6\x40\x4a\xf6\x1d\x95\x8a\x09\xaf\xf6\x0d\x7d\xba\x63\x3c\x3f\x87\x8a\xe5\x5f\xf9\x77\x57\xb3\x14\x6d\xff\x0a\x2f\xb4\xe6\x2e\x0d\x64\x9e\x86\x1f\xf7\xae\xbd\xd5\x88\xfa\x60\xae\xb6\xa0\xac\x91\x47\x35\xe2\x22\x98\xa5\xbb\xb0\x45\x59\xd4\x90\x02\x20\x50\x6f\xdc\x98\x3a\xfb\xa4\x51\xda\x41\xef\x67\xa1\x82\x4d\x17\xbd\xfc\x65\xdd\x32\x33\x4c\x04\xac\xa8\x26\x39\xd1\x64\x6a\xa4\xc9\x79\xff\x47\x55\x92\xcc\xab\x99\xc7\x00\xfb\x82\xcc\x68\xa1\x3a\x0f\x40\xe3\x11\xfd\xcd\x5e\x05\xa5\x5b\x42\xbc\x10\x17\x39\x7d\x8f\x6f\x80\x3f\xba\xab\xf5\x65\x96\x89\x8a\x6b\xfc\x43\xd8\x33\xb0\x8c\xfa\x74\x29\x94\xbe\xba\x3e\xaf\x7f\x2c\x45\x7e\x75\x1d\x85\x31\x72\x52\x01\x4d\x23\x9f\x98\x19\x86\x9b\xd5\xb3\xf0\x5e\x4d\xb1\x8c\xb1\x56\x03\x45\x15\xd2\x8e\x67\xb8\x38\xb5\x27\x5a\x65\x4b\xba\x22\x41\xb7\xbc\x9a\xbe\xae\x27\x1f\x98\x0a\x68\x8f\xd2\x27\xc6\xb1\x14\xbe\xb9\xff\x47\xe9\x96\x6a\xc9\x5c\xd6\xd7\x2f\x9e\x3d\x19\x73\xb4\xd9\xb7\x51\xb7\x0a\xae\x45\x24\x93\xd4\xaa\x81\xc6\x90\x8f\xb2\xae\xcb\x6e\x9a\xc0\xe5\xf5\x55\x30\xd3\xb5\x3d\x1b\x4f\x62\x59\x6b\xd0\xe6\xd7\x4f\x54\xaf\xb7\x68\xea\xad\x92\xd1\x61\x5b\x50\xf0\x62\xd3\xf0\x56\xb6\xa9\x43\xd8\x79\x25\x3c\x47\xed\x40\x95\x56\x70\x6a\x19\x4e\xb3\xb2\x0a\x53\x80\x8e\xcf\x8a\xae\x84\xdc\x9c\xd7\x3f\x36\x70\xdd\x89\xd2\x42\x92\x45\xa0\xfa\xae\x87\x8d\xc3\x6d\x7f\xb2\x0f\x8d\x36\x29\xbb\xa3\xf6\xf7\x3e\x83\xcb\xe2\xcc\x2a\x69\x2e\xa0\xc5\xa6\x6d\x90\xfe\xf3\xb1\x12\x3c\x31\xee\x5d\x8a\x65\x24\x34\xa7\xee\x7d\x74\x87\xc4\xab\xe0\x80\x51\x4d\xe8\x2c\x69\xe6\x1e\xe6\x5e\x88\xc3\x3e\xb9\xa2\xde\xe7\xcd\x45\x36\xfc\xe2\x2f\x24\x50\xbe\x86\x35\x91\x9e\x0d\x7d\x5b\x8a\xa6\xd7\x73\xb6\x66\x4a\x04\x8a\xd4\x7d\xf5\xa1\xa2\xe8\x75\xd7\xb1\xc7\x66\xb2\xc6\x32\x2a\xe9\xa7\x12\x3b\x3f\x36\x7a\x20\xdc\x07\x93\x77\xe3\x2c\x2f\xfc\x6b\xd4\x59\x2a\x89\xd6\x54\xf2\x97\xf0\x5f\xa7\x7f\xfd\xf5\x4f\x93\xb3\xaf\x4e\x4f\xbf\x7f\x3e\xf9\x8f\x1f\x7e\x7d\xfa\xd7\x29\xfe\xe3\x5f\xcf\xbe\x3a\xfb\xa9\xfe\xe1\xd7\x67\x67\xa7\xa7\xdf\xff\xe9\xdd\x37\xb7\xd7\x6f\x7e\x60\x67\x3f\x7d\xcf\xab\xd5\x9d\xfd\xe9\xa7\xd3\xef\xe9\x9b\x1f\x8e\x64\x72\x76\xf6\xd5\xaf\x02\x07\x1e\xd8\x78\xdd\x52\xac\xf6\xeb\x7d\x6e\x11\x8e\xcb\xa3\xb4\x62\x6f\xa9\xde\x8e\x71\xe5\xec\xc7\x08\x3a\xa9\x3f\xbe\xd6\xcc\x7e\x12\x82\x4c\xd1\x4c\x52\xfd\xb4\x23\x4a\x76\x8c\x9d\xb6\x17\x01\xa5\x31\xa1\x2e\xf0\x56\x92\x20\x1b\xe1\x49\xd9\x3c\x29\x40\xf5\x10\xd5\xce\x10\xbb\x8b\xe2\xdd\x72\xe7\x52\xac\xea\xd6\x02\x08\xd1\x5a\x93\x82\x85\xfa\x9b\xeb\x13\x69\xde\xfc\x49\x5c\x75\x21\x05\xd4\x52\x40\x6d\x0c\xa5\x80\xda\x38\xea\x06\xd4\x6e\xf0\xec\xa7\x68\xda\x10\x51\xbe\xf6\x83\x40\x0d\x62\xe4\x6b\x1f\x56\xa7\xcb\xad\xc7\xbb\x0d\x22\xed\x77\x01\xf3\x1e\x9c\x9d\xf2\x6b\x71\xa7\x6d\x36\x96\xaf\x7b\x63\x35\x8c\x25\x86\xcb\xa2\x00\xc6\x7d\x95\x17\x0e\xb2\xad\xef\x66\xdd\x49\x40\x14\x16\x33\x58\xfb\xc1\x4f\xeb\x72\x0b\xdd\xca\xcf\x0a\xb0\x52\xc2\xe8\xfa\x35\x96\xfe\x6c\xcb\x35\xdc\xd9\x0a\x0e\x4a\xe3\x22\xad\xaa\x42\xb3\xb2\xa0\x10\x70\x91\xb5\xb0\xc3\xa2\xa2\x40\x94\x12\x99\x2d\xbd\xd3\x54\x17\x2b\x88\xf2\x79\x7f\x77\x53\xc0\x59\xd5\xe4\x0e\x51\xc8\x19\xcd\x29\xcf\x28\x16\x70\x1b\x5b\xba\xcd\x52\xbd\x93\x66\x1b\xb3\x36\x6f\xf8\xba\xc9\x99\xaa\xab\xfc\xf9\x2d\xff\x9e\x71\xfe\xf3\x26\x89\x18\x31\xe5\x40\x96\x6d\xae\x88\x97\xe4\x44\xbb\xb5\xf1\xe4\x13\x4c\xc7\x11\xf3\x16\x77\xe1\x95\xd5\x13\x76\x73\x09\xbd\x2d\x34\x28\xc6\x80\x0b\xe7\xce\x35\xa1\x99\x90\x90\xd6\x50\xf6\x5a\x80\x66\xbd\x27\x8f\x27\x02\x14\x0d\x35\xd7\x07\x4d\xf5\xe0\x28\x72\xdf\x4c\x7f\x7a\x66\xf6\x23\x98\xd8\x03\xe6\xb5\x35\x8f\x83\xb8\x86\x9a\xd6\x51\xcc\xea\x18\x26\xf5\x90\x39\x1d\x90\x06\xdb\x52\x0f\x9b\x16\xc5\x04\x0e\x37\x7f\xc3\x81\x64\xa5\xa4\x73\xf6\x29\x8a\xcc\xbc\xe4\xcd\x02\x02\xcb\x29\xd7\x6c\xce\x42\xfa\x09\x0b\x33\xb8\x92\x72\x5b\x70\x8a\x64\x4b\xb4\x0b\x02\x3b\x18\xb5\x40\xf2\xa7\x96\x06\x67\x5d\x34\x31\x15\xd8\x4d\x2c\xe7\x54\xd2\x5e\x49\x7b\x25\xed\x75\x88\x9e\xbc\xf6\x72\xf2\xa0\xbe\xb2\x7f\x5e\xf5\x83\xb5\x5b\x42\xcb\xd3\xbc\xee\x54\x0e\xc3\x33\xee\xed\xae\x3d\xfe\xec\xb5\x75\xf9\x2e\xf0\xb9\x1e\xd8\x81\x80\xed\x86\x8f\xbc\xae\x8a\x62\x7c\x55\x78\x4b\xfd\x09\xbc\xc2\x99\x2b\xab\xa2\x70\x85\xbc\xa7\xf0\xc1\xab\xa3\xac\x98\xc3\x65\x71\x4f\x36\xea\x1c\xde\xd3\x35\x95\xe7\x70\x35\x7f\x2f\xf4\xb5\xbd\xa8\xfa\x28\xd5\x6e\x9e\xa4\x65\x0d\x6c\x0e\x2f\x0b\xa2\xa9\xd2\xa0\x89\xcf\x41\x65\xaa\xdb\xe7\x4c\xc8\xde\x20\xdb\x96\xa3\x71\xda\xbb\x8f\x15\xea\x3b\x1b\xeb\x97\x75\xc5\xc9\xc9\x67\xd8\x68\x05\x9b\xd3\x6c\x93\x15\xa1\x67\xf4\x6d\xcd\xa7\xae\xab\x44\x8a\x42\xdc\x7b\x89\x1d\x04\xec\x0c\x14\xf9\xfc\xa2\xda\xb0\x94\x42\xe9\x1b\x4d\xa4\x8e\xd0\x8b\xe5\xe4\xba\x66\x66\x26\x37\x23\x45\xe1\x2d\xce\xd9\x6a\x45\x73\x46\x34\x2d\x36\x40\xe6\x9a\xca\x6e\x45\x61\x5f\x9e\xca\x56\xf1\x76\x85\x68\xb1\xd3\x36\xe1\x79\x41\x25\xcc\x09\x2b\xbc\x31\x3e\x3b\x4e\x5c\xdb\x23\xdc\xab\xa3\x88\x25\x0b\x8e\x74\x55\x73\x81\x64\x99\x90\x39\x16\xe5\x12\xe0\x0f\x46\x75\x0c\x5b\xc1\x8a\x36\xd4\x8a\x70\xb2\xa0\x01\x25\x14\xb6\xd1\xb7\x30\x2b\x44\x76\xa7\xa0\xe2\x9a\xf9\xda\x66\xb6\x09\xba\xb8\x83\x4c\xac\xca\x02\xc5\x53\x58\x61\x3f\x78\xb8\xb8\xdf\x90\xcc\x6b\xfe\x39\x69\x44\xcf\xc4\x8c\x49\x5d\xfc\xb2\xfd\x13\xfe\xc2\xcf\xd2\x0b\xbe\x89\x84\xdf\x43\xe8\x27\x9a\xf9\x5b\x87\xbd\xa3\xff\x81\x53\xdc\xb5\x41\x7d\xb7\x01\x04\x6f\xe0\xdc\x73\x61\x04\xb3\xd9\xf5\x81\x4d\x78\xa1\x57\xcd\x7f\x0a\x6f\x3e\xd1\xac\xf9\x39\xe4\x42\x62\x46\x69\x1b\x10\x60\xed\x59\x72\x17\x50\x12\x20\x0a\xd4\x26\x0e\xc8\xc5\xbb\x54\x63\x97\xb6\x7a\xc4\x22\xc7\x90\xfa\x06\x96\xac\xa0\xb1\xcc\x0a\xc6\x47\x37\x8a\xd9\x25\x57\x08\x12\x18\x57\xb6\x61\x5d\x47\x92\x85\xc2\x04\x0c\xb3\x9d\x96\xb8\x81\x3c\xeb\x76\x49\xf5\x2c\x84\xcf\xa9\x14\x42\xc3\xe9\xc9\xc5\xc9\xd9\x4e\x4c\x37\x10\x82\x66\x6e\xd7\x05\x55\x1b\xa5\xe9\xca\x96\x97\x71\xa3\x0e\xe4\xca\xb0\x89\x76\x89\x1d\x94\x69\x76\x92\x9f\x03\x0b\x85\x13\x38\x5b\xd0\xf6\x2a\xc1\x9d\x10\x96\x9b\x02\xb6\x9e\xe8\x39\x28\x01\x5a\x92\x9c\x45\xc1\x88\x23\x4f\x33\x40\x2d\x2b\xd7\xf8\xe4\xf4\xe4\xa7\x91\x7d\xa8\x76\x89\xea\xec\x0c\xee\x05\x3f\xd1\xb8\x5d\xa7\x70\x1b\x7a\xaa\x2a\x45\xeb\x92\xaa\xb6\xab\x13\xa7\xe1\xb0\x0a\xd1\x6d\xea\x64\x8c\x4b\x10\x55\xe8\xba\x63\xcd\x70\xa2\xeb\xea\xaf\x6f\x3e\x05\xef\x24\x9b\x97\x6a\x94\xd8\x73\x34\x05\xad\xc1\x19\xc8\x94\x28\x28\xd8\x9a\x5e\x2c\x29\x29\xf4\x72\x03\xe1\x67\x88\x0b\x3e\xf9\x3b\x95\x02\xeb\xd3\x72\xc7\x37\x0c\x8b\x17\x12\x96\xee\x92\x77\x88\x7a\x77\x30\x41\x1e\x34\x63\x2f\x7e\x43\x3d\xef\x45\xb0\xad\x03\xff\x78\x7b\x7b\xfd\x0d\xd5\xd1\x0c\x0f\x33\xba\x3a\x81\xaa\xd3\x4c\xe9\x33\x5b\x20\xe1\x50\xdf\x09\x94\x42\x7e\x6e\x13\x68\x29\x54\xc0\xba\xc3\xce\xda\x0b\xa5\x7d\xeb\x3f\x76\x49\x0b\xa3\x9b\x39\xcd\xcc\x8a\x47\x4b\x26\x76\x7d\x13\x4a\x91\xc3\xd5\xf5\x14\xfe\x22\x2a\x33\x8b\x33\x32\x0b\xb2\xe4\x0d\xdd\x13\xae\xeb\x02\xab\xcf\xcc\x24\x3c\x0b\x09\x97\x59\x32\xfb\xfe\x8f\x94\xe4\x54\x2a\xd4\x84\x94\x78\xb6\x7e\xad\x29\x12\x00\xb3\x33\xae\x98\x96\x73\xa5\xb4\x58\xc1\xd2\x32\x0e\x5f\xe8\x4e\xa9\x5b\x27\x3b\x42\xf1\xd7\x46\xae\x59\x1f\x9a\x02\x49\xcb\x18\xda\xce\xbd\xed\xcf\x48\x1b\xed\x68\x02\xbb\x53\x02\xb9\xd6\x7c\x67\xd8\x09\x29\xc3\xad\x12\xcc\xd2\x4e\xbe\xd9\x2b\xae\x3c\x5d\x30\x47\xc6\xed\x26\x31\x42\x25\x18\x25\x1e\x29\x25\x05\x22\xa5\xa5\x40\x48\x69\xdf\x3e\x13\x04\x58\x06\x72\x89\x95\xe5\x02\x91\xf2\x21\x60\x00\x06\x10\x81\x65\xb3\x4b\x6d\x4d\x87\x08\xd3\x0f\x31\x91\xf8\x10\x5a\x44\xb8\x4b\x8f\x3f\x7d\x31\x36\x1e\xc4\x9b\xbf\x32\xb8\x88\xc8\x6e\x09\x11\x2d\x80\x64\x99\x5f\xf3\x9a\x2e\x09\xab\x3a\x51\x9c\xd9\x4e\x91\x4f\xc2\xf6\x30\x16\x73\xc4\x29\xb3\x70\x12\x09\xbc\x5a\xcd\x82\x95\x54\x53\x77\x4b\xea\xd8\xcb\xd0\x29\xd6\xff\x3e\xc6\x50\x6b\x20\x42\x6d\x20\x11\xbe\x08\x3d\x17\x2f\xcc\x3b\xff\xfe\x77\xbf\xfb\xed\xef\xa6\x76\x5a\xcd\x33\x02\x79\xce\x28\x10\x0e\x57\x97\xef\x2f\x7f\xbc\xf9\xee\x15\xd6\x40\x0e\xdb\x85\x11\x52\xb2\x63\x26\x64\x47\x4c\xc7\x7e\xc4\x64\x6c\x2c\x3b\x15\x28\xe1\xfb\xe8\x1a\x64\x18\xee\xd1\xae\x94\x2d\x7b\xec\x6e\x8a\x36\x6c\x18\xc1\x93\x6d\xee\xc4\xbd\x6a\xd1\x11\x2e\x0e\x9f\x5d\x7a\xea\xac\xbc\x11\xd9\x5d\x34\x2f\xcf\xc9\xed\xab\x6b\xcb\x30\x8a\xa3\x87\xf0\x3a\xc0\xc4\xf8\x5a\x14\x6b\xb3\x98\x04\x6e\x5f\x5d\x07\x2a\x8b\xa9\xe1\x81\x11\x56\xeb\xf7\xde\x04\xe5\xe3\x35\x05\x76\x1c\x40\x8f\xad\xca\x22\x24\xa2\x0c\x58\xf1\x5d\x52\x52\x30\xa5\x59\x86\x63\x6d\x62\xb0\x41\x5e\x1d\x71\xe7\x8f\xca\x4b\xfe\xb1\x96\x22\xfb\xc7\x4e\xfc\x5a\xf7\xef\x52\xe3\x68\xeb\xb8\xca\x82\x9d\x26\xe7\xbd\xd2\x2d\xe1\x75\x06\x9d\xa3\x2d\x2c\x71\xf8\x89\x5a\x8e\x68\x86\xf9\x35\x74\xec\x12\xef\xf4\x9a\x71\x96\x63\x68\x04\x05\xed\xce\x5d\xcb\x31\x90\xad\x7b\xe1\xbe\xe5\x18\xea\x97\x30\x76\xe7\x8e\xe5\x18\xc9\xb6\x4d\x96\xe3\x71\xf4\x08\x96\x63\x29\xe9\x8d\x16\x65\x14\x9c\x9d\x65\x15\x15\x65\x37\xa3\x73\x21\x69\x1c\x98\x5d\x0b\x80\x83\xbc\xa2\xae\x69\xbf\x7f\x7d\xcc\x3a\xcc\x25\xba\x70\x35\xef\xc4\x6b\x40\x93\xc5\xf6\xf9\x2f\xd8\x9a\x72\xaa\xd4\x05\x42\xe3\xaa\xd2\x3a\x29\x3d\x99\xce\x09\x2b\x2a\x49\xcf\xcd\x4a\xd3\x55\x69\x7b\xc9\x07\x96\xea\x33\x8b\x41\xb9\x65\x45\xb5\x6d\xef\x5e\xa3\x16\xfd\xd7\xc7\xd8\x7c\x76\xe3\xd8\xbe\xa4\xe1\xcd\x99\x32\x49\xd4\x92\x62\x4b\x46\xfa\x89\x69\x65\x07\x2a\x29\x51\xde\x95\x7e\x11\xea\xe2\x36\x12\x9a\xc0\x0a\x4a\xa2\x14\xcd\xfd\xb5\x41\x07\xf2\x69\x07\x78\x2d\xf2\x93\x13\xd5\x7d\x8c\x27\xe7\x85\x24\x19\x85\x92\x4a\x26\x72\xc0\xda\xd9\xb9\xb8\xe7\x30\xa3\x0b\xc6\x7d\x6f\x00\xee\x44\x9a\x41\xd7\x07\xde\x98\xb0\x34\x00\x48\x55\xf7\xbd\x9d\xc2\xc7\x5e\x5f\x4e\x7f\xad\x25\x2a\x9d\x89\x56\x5b\xbb\xd9\x3d\x0f\xe0\xd8\x22\x49\x31\xe7\x1e\x8f\x79\x45\x8a\x62\xd3\x8a\x15\x4f\xce\xae\xbc\x84\x7e\xac\x85\xff\xc2\x30\xb5\xe6\xb0\x86\x72\xec\x1e\xd0\xee\x54\xf8\xcb\x26\x49\x49\xb6\x0c\x4b\x57\x48\xd0\xdd\x03\x94\xa0\xbb\x09\xba\xbb\x97\x12\x74\x37\x41\x77\x13\x74\x37\x41\x77\x13\x74\x37\x41\x77\x47\x52\x82\xee\x1e\xa2\x04\xdd\xdd\x4b\x4f\x32\x34\x91\xa0\xbb\x09\xba\x7b\x34\x25\xe8\x6e\x82\xee\x8e\xe3\x9b\xa0\xbb\x5e\x94\xa0\xbb\x0f\x52\x82\xee\x86\x50\x82\xee\xfa\x52\x82\xee\x8e\xa6\x04\xdd\x4d\xd0\xdd\x00\x4a\x00\x0c\x0f\x4a\xd0\xdd\x08\x17\x87\xcf\x2e\x3d\x13\x74\x37\x41\x77\x8f\xa4\xe4\x1f\x6b\x29\x41\x77\x03\x28\x41\x77\x0f\x52\x82\xee\x26\xe8\x6e\x00\xaf\xa7\x67\x39\xd6\x10\xd1\x6b\x29\x66\xa1\xc5\x47\x91\x87\xc2\xfe\xd4\xa9\xf4\x68\x00\x86\x69\x2f\x7e\x09\x84\x57\xb5\x60\x68\x6f\xbb\xdb\xd8\xa5\x3e\x02\xc9\x93\x77\x1f\xb7\xd4\x47\x1f\xf9\x9a\xbf\xde\x98\xa5\x27\x80\x5e\x0b\xc6\x29\xed\xc1\x28\x05\x8a\xf0\x2d\x7c\x52\x8d\x30\x0a\xe0\x38\x88\x4d\x0a\x1c\xe5\x0e\x2e\xa9\x46\x16\x45\x78\x73\x04\x60\x76\x51\x45\x81\xa1\xee\x0e\x1e\xa9\x8b\x28\x0a\xe0\xda\xc1\x22\xed\xa2\x89\x42\x56\x4a\x0f\x21\x89\x1c\x10\x26\xe4\x86\xd5\x43\x11\x0d\xe0\x80\x02\x78\x23\x82\x28\x32\x06\x68\x10\xff\x13\x66\xc4\x0d\x60\x7f\x6a\xf4\x4e\xc8\xc4\xb6\xb8\x9f\x2e\x72\x27\x64\x0b\x34\x98\x9f\x6d\xd4\x4e\x90\x1f\x20\x8f\x8d\xd8\x89\x11\x1f\x0d\x8e\x8d\x06\x9a\x6b\x2e\x57\xe6\x76\x29\xa9\x5a\x8a\xc2\x53\x15\xf4\xd4\xc0\x3b\xc6\xd9\xaa\x5a\x19\x99\xa3\x8c\xdc\x66\xeb\xc0\x44\x1e\xd5\x40\x36\x31\xfe\x69\x03\xab\xde\x1a\x0f\x25\x8a\xa4\x39\x72\x37\x5b\x0c\xab\x9a\x2f\xc9\xda\xdf\xde\x55\x55\x96\x51\x9a\xd3\xbc\xe7\xdc\x83\xdf\x4e\xeb\xb9\xf0\xe4\x6b\x7b\x3d\x32\x05\x2f\x42\x2c\x8c\x90\x6b\xc1\x5c\xc8\x15\xd1\xc8\xe3\xb7\xbf\xf1\xe0\x10\x04\x00\x7b\x14\xf0\x57\x74\xe0\x57\xb0\x19\x17\xe6\xd0\x0a\x70\x66\x85\xdb\x8f\x61\x4e\xac\x61\x80\x57\x98\x8e\x1b\x02\x77\x85\x71\x7c\x04\x60\xd7\x20\xa8\xab\x0b\x7f\x0a\xb3\x74\xc3\x00\x5d\x91\x60\x9f\xc1\x40\xae\xc7\x01\x71\x0d\x03\xb8\x50\xba\x84\x18\x17\x7d\xf0\x56\x38\xfc\xea\x49\x98\x16\x8f\x01\xb9\xda\x85\x5b\xb9\xc9\x0a\x73\xe5\x36\x50\xab\x78\x50\xa9\x48\x30\xa9\x18\x10\xa9\x60\x78\x54\x38\x34\x2a\x16\x2c\x2a\x06\x24\x6a\xa7\xa1\x61\x84\x1d\x04\x75\x0f\xba\x28\x20\xe3\x58\x2e\xd4\x28\x10\xa8\xc7\x9d\xae\x18\xd0\xa7\x08\xf3\x15\x06\x79\x7a\x1c\xb8\x53\x4c\xa8\x53\x8c\x29\x0a\x0a\x54\x3d\x0e\xbc\x69\x10\xda\x04\xde\x49\xe0\xb0\xed\xee\x9a\x76\xc3\x4b\x01\x4c\xb7\x20\x4d\xdd\xd0\x52\x00\xd7\x06\xce\x14\x37\xac\x14\x18\x52\x8a\x15\x4e\x8a\x14\x4a\x7a\x24\x00\x52\x28\xf8\x68\x18\x78\x64\x6c\x90\x80\x0d\xb1\x03\x3a\x6a\x61\x43\x01\x5c\xbb\x3e\x89\x30\xc8\x50\xe0\x82\x32\xce\x34\x23\xc5\x6b\x5a\x90\xcd\x0d\xcd\x04\xcf\x3d\xad\x89\xad\xb6\xbb\x2e\x64\x3e\x07\x65\x99\x7a\xbe\x9f\xf5\x04\xf5\x0b\x3e\x2c\x89\x02\xd7\xff\xcd\x93\xab\xab\x1e\x52\x87\x2f\x9d\x61\x8a\xb1\x47\x3b\x1f\xda\x3f\x9e\x35\xb2\x34\xc3\xbd\x90\x77\x85\x20\xb9\xba\x28\x85\xfd\xbf\xb6\x30\x43\xa7\x22\x83\x1d\x61\x48\x49\x86\xcf\xe9\x72\xb2\x75\x2f\xe2\x6d\xaf\x3f\x8a\x7b\x10\x73\x4d\x39\x9c\x32\x5e\xef\xb0\x33\x5f\xef\x53\xe3\x6c\x6a\xfd\x99\x8d\xd3\xd0\x9f\xe7\x8b\xe7\xf5\xc0\x1a\x97\x63\x90\x61\xf6\x25\xbb\x1c\xd1\x19\xab\xd4\xd3\xf4\x68\xbb\xc1\x3d\x96\x4b\xdb\xb1\x9f\x57\x85\x15\x66\xbe\xfe\x1b\x74\x86\x3b\x07\x79\xdf\xa7\xed\xb9\x2d\xa0\xe9\xaa\xff\x02\xdf\xbc\x91\x86\x84\xe7\xe0\x6a\x7e\x79\x73\xee\x6e\xf8\x2f\x7a\xeb\x06\x42\x69\x1f\x0b\x46\xbb\x17\x42\x6b\x81\xb0\x9e\x5c\x77\xe0\xb3\x2d\x08\xd6\x97\x63\x1f\x3a\xdb\x05\xc0\x06\x8c\xb1\xd1\x90\x01\xe0\xd7\x14\x23\xf0\xfb\xee\x5e\x90\x2b\x86\x0b\x02\x4c\xe2\x2d\x80\x6b\xac\x5c\xf0\x7e\x1e\x78\x28\x50\xfa\xc9\xdc\xf6\x6b\x48\x6a\xa8\x6f\x2c\xdd\xf6\xd3\x6d\xff\x00\x3d\xc2\x6d\x5f\xb3\x15\x15\x95\x7e\xb2\x17\xce\xfb\x25\xcb\x96\x5d\x5b\x90\xad\xbc\x55\xb5\xa8\xf4\x96\xbd\xe6\x86\x18\x11\x8a\x90\x6e\x9d\x5b\xe4\x17\xd3\x18\x70\xa8\x5a\xf1\xd8\xe0\x89\x3d\x5e\xa4\x75\x5c\x34\x58\x59\x20\x0a\x08\xbc\x7e\x7f\xf3\xe3\xdb\xcb\xff\x7c\xf3\xd6\x47\xd0\xdc\x2e\x99\xb2\x2a\xb3\x16\x5f\x15\x67\x7f\xab\x28\x90\x95\x30\xb6\x60\x11\x34\x54\x75\x8e\x8e\x90\xce\x2f\x3c\x8b\x33\xc5\x04\x62\x7b\x89\x31\xa3\xd8\x3c\x04\x4c\x3f\xfa\x60\x78\x3c\x41\x64\xba\x5f\x2c\xda\x3b\x06\xbd\x05\x2c\x76\xa3\x37\x93\x03\x92\x96\x92\x2a\xca\x3d\x2d\x35\x02\x9c\x6a\x23\x93\xac\x1d\xc2\x38\x10\x50\x8c\x2f\x8a\xc0\x9c\x96\x40\x1b\x3f\xc4\xc2\x9f\xb4\x23\xbf\xf6\x33\xf4\x43\xcd\xfc\xde\xf3\x7d\x8d\x91\x41\xa3\x73\x1e\x96\xac\x67\x4b\xde\x09\x45\xeb\x68\x5c\x29\xf2\x13\x05\x57\xfe\x68\x0f\x92\xe7\x92\x2a\x2c\xac\xcd\x54\x6b\xcf\x19\x0d\xc9\xfc\x2b\xbd\xe0\x5e\xb4\xe1\xb4\x73\x78\x0e\x7f\x80\x4f\xf0\x07\x34\x39\x7f\xef\x6b\x19\xc6\x30\xeb\x42\x1d\x1a\xf6\xf6\x77\x75\x1d\x65\x47\xfc\x79\x49\x34\xf2\x83\xab\xeb\x10\x48\xd7\x8c\xf1\xdc\x2a\xda\x4f\x9a\x4a\x4e\x8a\xfa\x42\x12\x36\xd3\x01\x86\xaf\x79\xa9\x27\x7f\x70\x6c\xf2\xfa\xd5\xdc\x9b\x63\x63\x91\x9c\x83\xee\x1d\x1d\x6f\x8e\x78\xe4\x06\x8f\x8e\x37\x4b\x7b\xe4\xe0\x6a\x8e\x1e\x86\xf7\x4e\x53\x30\xd5\x19\xbd\xff\x94\x36\x6f\xbd\x22\x3a\x5b\xf6\xd5\x9a\xff\x05\xf0\x9d\x39\x12\x1d\xe3\x29\x17\x68\x3a\x04\xd5\x0b\x35\x43\xfd\xb2\x05\x4f\x08\xd0\xa8\x77\x9e\xae\xe6\xdb\x3b\xd7\x7b\x56\xf7\x5d\xfe\x83\x8a\x91\x3a\x53\xbc\x53\x53\xbf\x14\xf9\x14\xde\x90\x6c\xe9\xcd\xd3\x4c\x5e\xde\xb1\x8f\x4a\x91\xdb\xc1\x2f\x89\x77\xe8\xc3\x58\x5e\x6e\xac\x86\xbd\x2b\xe6\x12\x9a\x32\x65\x45\xb7\xd1\x0c\x19\xe1\x66\x6e\x25\x9d\x53\x29\x43\xb6\xbe\x80\xd9\x06\xf1\x3a\x2c\xa3\x81\x87\x20\x40\x27\x94\x52\x68\x91\x09\xef\x7c\xfe\xed\x7c\x57\x64\x86\xd3\x1d\xe2\xb4\x6f\xe3\x38\xdf\xbe\xbe\x3e\x87\xdb\x57\xd7\xe7\x20\x24\xdc\xbc\x0a\x41\x15\x74\xfd\x15\xcf\x6e\x5f\x5d\x3f\xfb\x0c\x93\x2e\x29\xc9\x59\x4a\x2f\x1e\xa6\x94\x5e\x7c\x1c\xa5\xf4\xe2\x3e\xa5\xf4\xe2\x00\x9e\x29\xbd\x38\xa5\x17\x5b\x4a\xe9\xc5\x29\xbd\xd8\x93\x52\x7a\xf1\xe1\xc1\xa5\xf4\xe2\x2f\x16\x30\x95\xd2\x8b\x0f\x53\x82\x0e\xa5\xf4\xe2\x94\x5e\xbc\x43\x29\xbd\xf8\x73\x9b\x16\x29\xbd\x38\xa5\x17\xd7\x94\xd2\x8b\x47\x50\x4a\x2f\x1e\x47\x29\xbd\xf8\x20\x3d\x31\xc0\x71\x4a\x2f\x4e\x80\xe3\x63\xf9\x3c\x3d\xc0\x31\xa4\xf4\x62\x3f\x4a\xe9\xc5\xe3\x29\xa5\x17\x8f\xa3\x94\x5e\x3c\x9e\x67\x4a\x2f\x6e\x29\xa5\x17\xa7\xf4\xe2\x2f\x74\xeb\xa6\xf4\xe2\x94\x5e\x3c\x4c\x29\x46\x90\xd2\x8b\xc7\x51\x4a\x2f\xf6\x67\x9a\x6e\xfb\xfe\x7c\x9e\xde\x6d\x3f\xa5\x17\xa7\xf4\xe2\x83\x14\x62\xba\x49\xaa\x44\x25\x33\x1f\x15\xd9\xdb\x57\x1f\x6b\x3e\x8f\x09\x4c\x86\x37\x31\xb2\x97\x15\xe2\xd3\x54\x69\x06\x2a\xdb\x61\x17\x92\x92\xdc\x27\x62\x69\x5e\x34\xc3\xd0\x69\xab\x42\xbf\x28\x0c\x75\xc1\x56\xcc\x27\xb5\x18\x76\x84\xcb\x5b\xe4\xd4\x06\x4a\x03\x70\x2e\x2b\xf2\x09\x6f\x46\x64\x25\x2a\xae\x8d\xbc\xca\xc4\xaa\xf4\x47\xd2\x76\x57\x1a\x37\x66\x57\x16\x04\x60\x05\x0e\x49\x90\x4c\xf0\x39\x5b\x54\x92\x98\x29\xba\x58\x11\x4e\x16\x74\xe2\x5e\x65\xd2\x0c\x6a\xd2\xec\xce\x8b\xcf\x64\xa5\x93\xbc\xc6\x97\x5e\x07\x9b\xcd\x25\xd1\x9a\x4a\xfe\x12\xfe\xeb\xf4\xaf\xbf\xfe\x69\x72\xf6\xd5\xe9\xe9\xf7\xcf\x27\xff\xf1\xc3\xaf\x4f\xff\x3a\xc5\x7f\xfc\xeb\xd9\x57\x67\x3f\xd5\x3f\xfc\xfa\xec\xec\xf4\xf4\xfb\x3f\xbd\xfb\xe6\xf6\xfa\xcd\x0f\xec\xec\xa7\xef\x79\xb5\xba\xb3\x3f\xfd\x74\xfa\x3d\x7d\xf3\xc3\x91\x4c\xce\xce\xbe\xfa\x95\xf7\x2d\x31\xc0\x0e\x89\x63\x85\x44\xb1\x41\x1e\xc1\x02\x71\x30\x93\x28\xe2\xe1\xa3\xe3\x15\x47\x40\x38\xd7\x49\x7c\x01\x51\x5f\x58\x31\x53\xb3\x1e\xb3\xbf\x37\x52\xac\x98\x36\xda\xc1\xa8\x35\xd2\x81\xf0\xfb\x72\xd4\xbd\x7e\xa7\x4e\xe4\xb2\x79\x08\x16\x9a\xa9\x2e\xc0\xba\x93\x91\x28\xf4\x92\xca\x7b\xe6\x1d\x18\x32\x37\x25\xde\xba\x35\x50\x08\x4e\x72\x3a\x67\xdc\xdb\x53\x82\xd6\xdc\x68\x43\x2e\x89\xe1\x24\x86\xc7\x70\x79\x4a\x62\x58\xd1\xac\x92\x4c\x6f\x5e\x09\xae\xe9\x27\x0f\xcf\x48\x3f\xde\xdb\xe7\xe6\x32\x56\x3c\xed\xde\x7b\x27\xd7\xbe\xf8\x3c\x42\x7c\x99\x6b\xc9\xd6\xac\xa0\x0b\xfa\x46\x65\xa4\x40\x51\x11\x43\xed\x5d\xee\xe1\xed\x1f\x33\xd1\x52\x14\x0a\xee\x97\xd4\x88\x67\x20\xe6\xdd\xd1\x1d\x95\x11\x5f\xa6\x0b\xc2\x38\xac\x8c\x4c\x2d\xeb\x81\x2a\xa3\x51\x38\x30\x6f\xdd\x67\x6e\x58\x5c\xd7\x83\x73\x35\x4d\x66\x42\x14\x2e\xed\xcc\x1b\x87\xdc\xcc\x00\xb3\x4e\x39\x2e\x7e\xe4\xf4\xfe\x47\x33\x72\xdf\xb1\xce\x0b\xb2\x80\x7b\x56\x14\x98\xab\x49\xf5\x4e\x27\x6a\xdf\x39\xa8\x5f\x3e\xf2\x26\xc0\x3c\xa3\x8a\x02\x29\xee\xc9\x06\xb7\x42\x9c\xf1\x32\xf5\x12\x5e\x9c\x61\xfe\x1a\x51\xd0\x8c\x37\x87\xdf\xf8\x86\x8d\x97\x44\xc1\xab\xcb\xeb\x1f\x6f\xfe\x72\xf3\xe3\xe5\xeb\x77\x57\xef\x43\x34\xab\xd9\x3d\xd4\x6b\x93\x67\xa4\x24\x33\x56\x30\x7f\x85\xba\x83\x45\xec\xb2\x0c\xb0\x8f\xf2\xfc\x22\x97\xa2\xb4\x6b\x28\x2b\xce\x19\x5f\x04\x89\x51\x4b\xaf\xfb\x4d\xf1\x6b\xa3\xd1\x6c\x6e\x5f\x07\xdd\xbc\xf7\xca\xb0\x90\x84\x1b\xc3\x76\xb6\x09\xc8\x1c\x6d\xe1\x2a\xb2\xe2\x9a\xad\xbe\xdc\x84\x64\x92\xc7\x4a\x46\xbe\xcc\x73\x9a\xc7\xd8\x5e\x4f\x11\x8c\xff\xaa\x7e\xad\x90\x2c\x14\x68\x0b\xb5\xc1\xf5\x87\x9b\xab\xff\x1d\x67\xb6\xc0\xcd\x58\x48\x50\x27\xdc\x7c\x34\xd2\x20\xd2\x4e\xfa\x48\x57\x62\x9d\xf6\xd2\x01\xfa\x99\xee\xa5\xc6\x92\x8b\x81\x23\xfa\x58\xf1\x8e\xac\xf6\x4e\xea\x6f\xc7\x04\x2b\x91\xd3\x29\x5c\x5b\x03\x89\xaa\x28\x3c\xbb\x65\x3e\x25\x05\xc3\x98\x6b\x46\x0a\x6f\x53\x93\xfe\xad\x62\x6b\x52\x50\x9b\xf4\x86\x65\x0d\xba\x25\xcb\x22\xe8\xe6\x39\x29\x54\x90\xd2\xf3\xb7\x89\x8c\x71\xfa\x4e\x54\x3c\x06\x66\xa7\xe1\x05\x39\xe5\x42\x07\xb9\xf6\xcc\x7b\xfd\x7f\xec\xbd\x0b\x73\x1c\xb7\xb5\x2e\xfa\x57\x50\x4a\x4e\x91\x4c\x38\x43\xc9\xc9\x71\x12\x9d\x54\x5c\x0c\x49\x39\xac\x48\x14\xaf\x48\xd9\x77\x5f\xc7\x3b\x85\xe9\xc6\xcc\x60\xb3\x1b\xe8\x00\xe8\x21\x27\xd7\xf7\xbf\xdf\xc2\x02\xd0\x8f\x99\xa1\xa5\x5e\x00\x45\xd2\x69\x9c\xaa\x63\x4b\xd9\x5e\x83\xc6\x63\xbd\xf0\xad\x6f\x01\xc7\x9c\x92\x19\x71\xe9\xbd\x28\x78\x72\xc0\xab\x75\x9f\x92\xae\x5b\x97\x08\xef\x82\xfb\x7d\xbc\x6c\xbe\xdd\xbd\x87\xd6\x3a\xea\xf3\xb7\x5c\xa2\x58\x78\x87\xfd\x7e\xc5\x68\x0e\xec\x36\x15\x35\x4b\x87\x5d\x2b\xa9\xbe\x41\xa7\xe1\x40\x8c\x8f\xe9\x7c\xc2\xd4\x91\xd2\x34\x8b\x71\x8d\x57\x7e\x73\x46\x4d\xad\x98\x8b\xca\x5c\x81\x1c\x13\x74\x56\x60\xd1\xc6\x91\x8a\xd4\xae\xdd\x7b\x51\xac\x3f\x48\x69\xde\x34\x0c\x24\x09\x2e\xcd\xf7\x3e\x82\x07\xf2\xbe\xd8\xd0\x6d\x09\x5c\xcc\x76\xae\x13\xd8\x68\x50\x56\xf1\x84\x29\xfe\x8c\xdb\xe3\xfe\x88\xaa\x4a\xd5\xe2\x58\x7f\xab\x64\x8d\xf4\x8c\xb6\x82\xb7\x6f\xcf\x4f\x41\xa3\xd7\x22\x22\x78\x61\xc2\xa8\x75\x25\xb9\x7b\x7f\x48\x9a\x2f\xf8\x68\x4d\xe2\xc6\xfd\xc7\x2a\xaa\x39\xa9\x85\x66\x66\x4a\xde\xd1\x35\xa1\x85\x96\x21\xc9\x81\x36\xb9\x97\x80\x52\xef\xe6\x11\xa7\x04\xc8\x0c\xd1\xc1\x25\x17\x64\x26\xcd\x72\x2b\x3d\x89\x67\x2f\xdc\x9e\x23\xb0\x26\x45\x81\xcb\x5b\xe2\x73\x2e\x36\xa7\x8a\xd5\xf8\xf4\x86\x69\x52\x29\x96\xb1\x9c\x89\x2c\xea\x7e\x25\x42\x91\x7c\xfd\x7b\xec\x0d\xbd\x90\xc2\x2a\xc9\x04\x77\xf4\x5c\xe4\x3c\xa3\xc6\x65\x21\x4d\x92\x04\x03\xe0\xd7\x7c\x66\x8b\x02\xa1\x8e\x55\x91\x48\xb1\xb5\x66\x0a\x1e\x08\x8d\xaa\x99\x3b\x58\x7f\xaf\x67\xac\x60\x06\xd2\x88\xf8\xc7\x2d\x9e\x53\xe3\xd8\xbe\x78\x49\x17\x8c\x50\x13\xd4\x00\x3e\xc7\xc4\x84\xb6\xe6\x14\x56\x92\x1b\x92\x4b\xd6\xd0\x54\x61\x93\x1d\x9a\x7c\x3c\x3f\x25\x2f\xc9\xbe\x5d\xc3\x03\xf0\x27\xe6\x94\x17\x78\xbe\x0a\x40\xd2\x6f\xf8\x3f\x7c\x1e\xa6\x8b\xb5\x5e\xe7\x5e\xf7\x11\xa9\x9c\xf9\x3a\x24\x42\x12\x5d\x67\xcb\xb0\xd6\xf8\x1c\x6c\x48\x17\xfb\xaa\x18\x80\x94\x78\x05\x8b\x94\xd8\xa8\xe5\xfb\x14\x2c\x76\x6d\x9d\xd0\x5d\x0a\x16\xfd\x54\x97\xdf\xa7\x60\xa3\x50\x7a\x4f\x5c\xc1\x46\x3a\x30\x1f\x35\x53\x89\xfc\x97\x8f\x4f\xdc\x7f\xe9\x86\xb8\x56\x57\xb6\x3b\x8b\x77\x10\x9c\x42\x2c\x99\xa1\x39\x35\xd4\xfb\x35\xb1\xbc\x9a\xdb\x3e\xd1\x78\xf9\x9e\xe6\xe5\x7b\x4c\xef\x46\xb3\xb7\x5c\xd4\x77\xae\x88\x23\xd5\x03\xd2\xd5\x19\x08\x85\x4b\x17\xb1\xc4\x70\x74\x69\x55\x15\xbc\xc5\xa0\x46\x75\x1b\x21\x8d\xe1\xec\x72\x93\xc7\x2b\x87\x10\xce\x80\xe1\x0c\xb0\x59\x1b\xb3\x52\x91\x4b\x2c\xba\x7b\x63\x11\x1d\x1c\x81\x66\xcb\x6e\x69\x85\xbd\xe4\xd8\xbb\x36\xaa\x86\x67\xa0\x1a\x1e\xf5\xe1\xaf\x60\x2b\x86\xa6\x52\xdf\x50\x0b\x6f\xad\x2c\xc2\x75\x38\xd6\x11\xaf\x07\x30\x2d\x52\xd0\x19\x2b\x9c\xe7\xef\x54\x44\x82\x1a\xb1\x68\xe5\x92\xe4\x99\x4c\xc9\x22\x15\x07\xc6\x07\x59\x40\x81\x08\x4d\xb0\xec\x76\x5a\xbf\xe0\x55\x07\x11\x69\x56\xfd\x7a\x5d\x25\x5b\x75\x78\x32\xf8\xe5\xae\x7a\x8d\x0e\x1c\xc8\xe6\xaa\xdb\x18\x24\xd5\xaa\x83\x63\xff\xcb\x5c\xf5\x5b\x2e\x72\x79\xab\xd3\x3a\x7c\xdf\x3b\xa1\xc1\x9a\x62\x4b\xbb\x35\x33\x86\x8b\x85\xee\x3a\x7d\xb4\x88\xc3\x5e\xba\xb1\xcb\xeb\x93\x55\x0c\xc7\xf8\x5c\x49\xc7\x17\xb2\xed\x95\x44\xa6\x5d\x6a\xed\x21\xfa\x1d\x2f\x0a\xeb\x43\x6e\x27\x9d\x77\x79\x51\x11\x6f\x7a\xa3\x17\xf5\xa9\xb1\x28\x35\x3d\x51\xf6\x23\x0c\xa7\xc5\x55\x85\xed\xeb\x41\x36\x2f\xde\xb7\xef\xae\x8e\xfb\x82\x23\xf4\x13\x07\xac\xa5\x72\x09\x5a\x2b\x99\xd0\xbc\xe4\x5a\xe3\xb3\x88\x76\xdc\xb2\xd9\x52\xca\x1b\xb2\x1f\x4a\x19\x16\xdc\x2c\xeb\xd9\x34\x93\x65\xa7\xaa\x61\xa2\xf9\x42\x1f\x79\xc5\x34\xb1\xeb\x85\xc5\x64\xc2\x97\x88\x82\x0b\xff\x66\x0b\xb1\x93\x30\x9a\x48\x7c\x07\x36\xd2\x2e\x49\xd6\xac\x36\x9c\xf8\x08\x91\xae\x57\x94\x03\x18\xee\xd8\xc8\x8b\xb8\x9a\x7e\x60\x81\x7c\x54\xbb\xbe\x7d\xe8\x2f\xa2\x48\x46\x3f\x71\xf0\x23\xd7\xcb\x35\x47\x71\x04\x14\x3e\x5f\x68\x7f\x23\x42\xe2\xc6\x49\xf1\xc9\xc2\xc7\x0d\x2b\x42\xa2\x36\xe1\x4e\x40\xc2\xd6\x8b\x8c\xba\xb2\x8d\x07\xd1\xa6\x7e\x3b\x49\xdc\x08\xd1\x9b\xe9\xdf\x26\x91\x1b\x21\x73\x13\x81\x9c\x24\x0d\x4c\x1e\x30\x15\x4c\x3e\x3b\x1d\x1c\xf1\x03\x7d\x87\x25\x91\x17\x40\xee\x4f\xfd\x44\x2a\xf4\x07\x73\x5c\x48\x32\xe7\x85\xc4\x5d\x7c\x4f\xe1\x35\xf6\x66\xdb\x1e\x63\x6f\xb6\xcf\x1b\x63\x6f\xb6\xfe\x18\x7b\xb3\xc5\x04\x03\x63\x6f\xb6\xb1\x37\x1b\x8c\xb1\x37\xdb\xd8\x9b\x0d\x39\xc6\xde\x6c\x9f\x9e\xdc\xd8\x9b\xed\xd9\xb2\xcd\x8e\xbd\xd9\x3e\x3d\x46\xde\xd5\xb1\x37\xdb\xd8\x9b\x6d\x6b\x8c\xbd\xd9\x1e\xdb\xb5\x18\x7b\xb3\x8d\xbd\xd9\xc2\x18\x7b\xb3\x0d\x18\x63\x6f\xb6\x61\x63\xec\xcd\xf6\xc9\xf1\xc4\xd8\xda\xc7\xde\x6c\x23\x5b\xfb\xe7\xca\x79\x7a\x6c\xed\x64\xec\xcd\x86\x1b\x63\x6f\xb6\xe1\x63\xec\xcd\x36\x6c\x8c\xbd\xd9\x86\xcb\x1c\x7b\xb3\xb5\x63\xec\xcd\x36\xf6\x66\x7b\xa6\x47\x77\xec\xcd\x36\xf6\x66\xdb\x3d\xc6\x37\x82\xb1\x37\xdb\xb0\x31\xf6\x66\xc3\x0b\x1d\xa3\x7d\xbc\x9c\xa7\x17\xed\x8f\xbd\xd9\xc6\xde\x6c\x9f\x1c\x31\xae\x9b\x36\x39\x47\x34\x20\x78\x18\x86\x41\x8f\x96\xed\xb0\x36\xcc\xea\xf9\x9c\x29\x70\xbb\x61\xa6\xa8\xc4\xcd\x6e\xc2\x4b\x47\xac\xb5\xe4\x98\xe3\xea\x51\x7e\x9a\x99\x43\x20\x43\xd4\xae\x04\x11\xa6\x88\x03\x3c\xf6\xa7\xe8\xc9\x2b\x80\x76\x5f\x31\x8d\x8b\xaf\xb9\x20\x67\xef\xdf\x4c\x13\x90\x2b\xc6\xf0\x12\xc1\x9a\xbc\x17\x59\x2c\xec\xbd\x3d\x64\x71\x1c\x21\x81\x1f\xc4\x9f\xb5\xac\x90\xda\x61\x6b\xdd\xe6\x65\x4b\x2a\x04\xc3\x50\xab\x39\x85\xc8\x0d\xa4\xdd\x66\x8c\x09\x22\x2b\x26\x5c\x65\x19\x25\x9a\x8b\x45\x81\xb1\x00\xd4\x18\x9a\x2d\xa7\xf6\xfb\x45\x38\x60\xbe\x2f\x43\x33\x6b\xcc\x55\x33\x8a\xd1\xd2\x1d\x34\xc5\x4a\xca\xdd\x74\x09\xcd\x94\xd4\x9a\x94\x75\x61\x78\x15\x31\x61\xa2\x19\x14\x2c\x6a\x57\x3d\x1b\x0e\x01\x41\x5d\x37\xcd\x1c\xd8\x13\x58\xf0\x9a\x35\xf0\xcb\x8b\x72\xc1\xda\xab\x06\x01\xfc\x21\x74\xa7\x2a\x2b\xb3\x26\xf6\x78\x60\xb6\x1f\x70\xff\x5c\x69\x43\xb2\x82\x43\x04\x07\xeb\xc0\xc0\x92\xc1\x9c\x31\x08\x60\x2a\x72\x2b\x59\xf8\x3d\xd2\x7e\x93\x44\x0e\x0e\x68\x85\x72\xf8\xa1\x98\x09\x3e\xd3\x5d\x26\x37\xdd\x9c\x6b\x1f\x50\x68\xd4\x44\x03\x2f\xb1\xbb\x5c\x61\x8f\xe0\x7a\xe5\x48\x82\xcd\xf0\xcd\x5e\x48\x67\xca\x11\xf7\x1f\xa8\x84\x7d\x56\xbc\x31\x01\x8e\x04\x38\x28\x48\xd4\xf7\x6f\x97\xb5\x05\x5a\x49\x30\x10\x08\x91\x1d\x93\x02\xd7\x54\xb0\x95\xb5\x5e\x2c\x63\x7c\x65\x9d\x70\x84\xc8\x9d\xf6\xe0\x8b\x9a\x03\x43\xd5\x82\x99\x93\xb0\x56\xb8\xfa\xc7\x3e\x89\xe7\xdc\xd9\xe1\x8d\xaa\xd1\x28\xa5\x00\x4b\x7f\x29\xf3\x2b\xa8\x17\x75\xdc\xa0\x28\xcd\xb5\xa3\xbe\xca\x2f\x81\xa3\x07\x4f\x24\x32\xd0\x15\xe0\xb8\x36\xbd\x87\x64\x17\x4f\x57\x34\x63\x9a\xec\x9f\x5f\x9e\x1c\x92\xcb\xf3\x53\x57\x19\x80\x90\x29\xe7\x1b\xee\x20\xdc\x35\xef\x34\x81\x4a\x43\xea\xd8\x5d\x9f\xcf\xb5\x2f\xb8\x40\xc8\xbc\x5d\x52\x03\x17\xab\xf3\xf9\x54\x59\xff\x80\x2a\xd7\x78\x0c\x39\xd1\x4a\xe6\x53\x72\x21\x0d\x6b\xc8\x65\x93\xf8\x2d\x10\x84\xfb\x6c\xa3\xd7\x5d\x8e\xc8\x1c\xeb\xd6\xa1\x82\x5e\xc3\x54\xc9\x05\x10\x9b\xbe\x63\x5a\xd3\x05\xbb\x44\x81\x58\xee\x4b\x91\x01\x8e\x25\xd8\x14\xb4\x35\x2e\x20\x4f\xd6\xc6\xa8\x6d\x25\xd1\x1e\xe6\x32\x77\x3e\x9a\x94\xee\xab\x9b\x9b\x77\xab\xb8\x31\xa8\x43\xcd\xb5\x6b\x3f\x00\xf8\xbf\x4d\x6a\x1a\xdc\x44\x3b\x55\x52\xe4\x5d\x98\xa8\x9b\xa0\xfd\x39\x1b\x6b\x8a\x1c\x95\xaa\x76\x60\xc5\x99\xe2\x6c\x4e\xe6\x1c\x8a\x91\xa0\x6c\xe6\xd0\xd1\xdd\x52\xcc\x6c\xa9\x20\x54\x6b\xa6\x60\x5d\x7d\xd9\x44\x58\xdf\x29\xf9\x1e\x47\x74\x3c\x63\xd6\x5d\x14\xae\x67\xb6\xe7\x76\x10\x32\x67\x84\xcf\xc9\x02\x0a\x74\x70\xf7\x9a\x0a\xf2\xfb\x97\x7f\xfa\x9a\xcc\xd6\x86\xf9\x0e\x0f\x46\x1a\x5a\x84\x09\x23\x84\x16\x4c\x2c\xec\x69\x77\x9e\x77\x9f\x63\x07\xcb\xf3\x3c\x63\xae\xe3\xb6\xe3\xed\x79\xf5\xd5\xcd\xac\x97\x5a\x41\x48\x3c\xca\xd9\xea\xa8\x73\x03\x26\x85\x5c\x4c\xc9\x09\x15\x56\xa7\xa3\xde\xff\xea\x2a\x07\xfc\xc0\xf0\xb4\x49\x5a\xc5\x25\x0b\x9e\xad\x63\x9d\x10\xcf\x24\x4e\x96\xf2\xd6\xb5\x17\x69\x7f\x07\xb1\x34\x41\xbb\xb4\xe5\xc3\x95\xac\xea\x02\x96\x8b\xbc\xe1\xa8\xb8\x0c\x34\x55\xad\xd9\x26\x19\xcb\x3d\xba\x1c\xa7\x1c\xc2\x34\x37\xf2\x19\x4e\x49\x44\x2c\x84\xf4\x4c\x06\xfe\x91\xb8\xa1\x02\x47\xd9\x3d\x42\xde\xd0\xa2\x98\xd1\xec\xe6\x5a\xbe\x95\x0b\xfd\x5e\x9c\x29\x25\x55\x6f\x85\x30\xf7\x98\xda\xe0\x6f\x59\x8b\x1b\xd7\x28\x3a\x7c\x7c\x21\x17\x44\xd6\xa6\xaa\x51\x49\x9c\xf9\xe6\x71\x6a\xd6\x64\x8e\x3b\x07\x4d\xa4\xeb\x63\xcb\xce\x4c\xd9\x1d\xc7\xbd\x60\xde\x72\xab\xc0\x04\x61\x76\x1d\x9d\x56\x6c\xbf\x1a\x17\xf3\x77\xd4\xd7\x57\x2f\x7f\xff\x47\xa7\x70\x89\x54\xe4\x8f\x2f\xa1\xb6\x1a\x15\xa5\x82\x2b\x00\xde\x1e\xd7\x44\x97\xb4\x28\xac\x63\x1a\xa7\x18\xed\x75\xec\x28\xc2\x46\xad\x7d\x51\xad\x66\x62\x15\xd8\x03\xe6\x70\xaf\xaf\xff\x0b\x12\xb8\xdc\x68\x56\xcc\x51\xc1\x75\xa1\x65\xdb\x00\x68\x0f\x62\xe2\x3d\xef\x8b\x18\x55\xa3\x54\xc0\xe3\x66\x45\x57\xb2\xa8\x4b\x76\xca\x56\x3c\xc3\xbc\x4e\xf7\xb6\xae\x27\x0b\x4f\x60\x50\x70\x0d\x0c\xed\xb3\x42\x66\x37\x24\xf7\xe2\xda\xea\x14\x8c\x17\xb2\x8e\x25\x5a\x8c\xa9\x25\x42\xd7\x10\xdd\xbb\xba\x6d\x05\x10\xea\x9d\x86\x92\x92\x56\x15\x17\x0b\xbb\xcc\x94\x28\x7a\xdb\x5b\x6c\x94\x4c\xab\x79\xb9\xe8\xa6\x9f\x30\x97\x21\x12\xe3\x11\x83\xf0\x98\xf8\xaf\x47\xfa\x1c\xe8\xf2\xa2\x58\x70\x48\x3b\x6b\xec\xfb\x75\xef\x98\xb5\xe2\x62\x29\x48\x2a\x90\xe1\xb8\x27\x12\x35\x5c\x20\x6d\x0a\xc3\xcd\xb3\x09\x7b\xed\x81\x8e\xa0\xd9\x32\x12\x8b\x1d\x88\x7e\xb0\x8f\x29\xe6\xea\xed\x9c\x68\xa0\x11\x25\x35\xa8\x64\x85\x1b\xdd\xfc\x25\x25\x15\x53\x9a\x6b\xeb\xa3\x7f\x07\x0a\xe8\xa4\xa0\x1c\xfb\xfe\xdd\x64\xf8\x2a\x89\xdd\xaa\x88\xe5\x76\x0a\x14\xba\xf5\xc5\x5a\xba\x4b\x99\x7b\x71\x60\x98\x20\x6d\x82\xca\x77\x6e\xa5\x59\x62\x99\x65\x92\xb9\x7f\x8f\x69\xea\xbe\x6b\x77\x2a\xde\xd2\x59\x29\x8d\xa9\x73\x92\xbd\xb1\x42\x4a\x7c\xbe\x06\x0e\xd6\xe2\xb9\xd9\xb7\x66\xd2\x49\x94\x24\x18\x36\xef\xab\xc4\x18\xb7\x36\x56\x6d\x1f\x1c\x97\xcc\x2b\x05\xb4\xd4\x36\xcd\xe2\x33\xb1\x53\x8f\xf9\x16\xe8\xd6\x6d\xcd\x54\xc9\xde\xeb\xbd\x47\x33\x72\x6e\x13\x95\xac\xe8\x02\x72\x07\x49\xf6\x72\x53\x28\x7a\x85\x72\xe6\xd2\x1a\x4c\x43\xda\x0c\xe4\xc2\xe3\x0b\xde\xf7\xf1\xb3\x62\x79\xcb\x09\xbe\x94\x40\x94\x92\xe2\xc8\xf9\x84\x89\x84\x48\xf9\x36\x82\xde\x80\x2a\x59\x8b\xdc\x83\x3a\x1a\x24\xd1\xbb\x8d\x85\xbd\xc0\x13\x11\x42\x9a\xc7\x91\x97\x43\xf7\x5c\x57\xef\xcc\x35\x99\x31\x43\x63\xdc\x88\x57\xd3\x57\x2f\x9f\xbf\xcf\x06\x6b\x92\xc8\x67\xbb\x68\x7c\x36\x67\xe5\x1e\x6d\x75\x42\x07\xe1\x24\x2b\xf4\xce\x3f\x49\x35\xad\x7e\xf1\x87\x26\xb4\xaf\x04\x51\xb7\x8a\x1b\x7f\x83\x6e\x79\x44\xbd\xe9\x3e\x24\x6d\x88\x54\x5d\x4e\xde\x83\x36\x97\x17\x11\x92\xc4\xb4\x20\x8e\xef\xe1\x47\x88\xae\x67\x4f\xce\xee\x3a\x03\xeb\x94\xea\xae\xf7\x54\xfc\x7a\x7b\xc9\xdb\x26\x18\x2d\xb1\x0b\x21\x7e\xf1\x82\xec\xbb\x5f\xd8\x73\xa4\x94\x07\x8f\x76\x3d\xfd\xb6\x9e\xdd\x55\xe8\x2e\x2b\xbd\xad\x3d\xbb\xab\xa8\xc8\x59\xee\x02\xfe\x08\xd7\x9a\x04\x16\xe6\x5d\x7b\x1c\x6f\x36\xf7\x74\x7f\x8f\xd1\x12\xbb\xee\xd9\x5f\xd9\x92\xae\x18\x50\x77\xf2\x82\xaa\x08\xf5\x64\x24\xb9\x72\x3b\x43\x66\xb5\x21\x4c\xac\xb8\x92\xa2\x64\x11\x4c\xe7\x2b\xaa\x38\x9d\x15\x8c\x28\x36\x67\x8a\x89\x8c\x69\xf2\xeb\xfd\xef\x8e\x3f\x40\xb5\x04\xbe\x9f\x02\x55\x8c\xb0\xb0\xeb\xb5\x86\x2a\xfb\x44\xb7\xb0\xf3\xd9\xd3\x8d\x0b\x84\x57\xd1\x1b\x17\x2f\xac\xb3\xbd\x01\xf8\x35\x10\x79\xb3\x5f\x76\x3d\xca\xda\xd4\xb4\x00\xf6\xd6\xac\xa8\x35\x5f\x3d\x86\xfd\xf5\x6c\xba\xa7\x1c\x71\xb3\x37\x58\x88\xdb\x4b\xb3\x45\xd1\x8b\xf9\xb0\x80\xb9\x4a\xd7\x63\xd1\xe3\x90\xf6\x74\xa8\x39\xeb\xf5\xca\x41\x3f\xca\x91\x92\x2f\x96\x90\x40\xc9\xa4\x98\xf3\x45\xad\x1c\x1f\x56\x2c\x92\x0f\x38\xfc\x1f\xef\x79\xce\x06\x1f\xc7\x05\xa7\x7a\x58\x18\xbe\xc5\x2e\xe8\x65\x40\x4f\x2d\xe1\xbb\x25\xd1\x61\xc0\x90\xf0\xbe\x63\xa7\xe4\x1e\xd0\xcf\x2f\x3d\x42\x35\xec\x20\x17\xff\xc3\xb2\xa1\x2f\xc0\x4d\x36\xad\x92\xf9\x9e\xf6\xe2\x01\x7b\xc5\xe7\x58\xd6\x73\xf0\xcf\xb9\x76\x74\xec\xd0\x43\x1b\x5e\x10\x85\x14\x13\x2b\xff\x82\x19\x7b\x3b\x06\x89\xac\x64\x3e\x88\xd3\x0e\x97\x8e\x43\x24\xe2\x76\xef\x35\x59\xca\x22\x77\x2c\xef\xfe\xd1\x68\xe0\x81\x9d\x31\x73\xcb\x98\x20\xe7\x97\xb0\xd7\x76\xd9\x00\xe1\xd8\xdb\xf1\x81\x32\xc3\xf9\x80\xe6\xf6\xc2\x35\x05\xe9\xe4\x96\xc3\xee\x0f\x94\x6a\xcf\xca\xb0\xe3\x81\xce\xe6\xe1\x93\x62\xcd\xfa\x45\x6a\xf8\xbf\x35\xfb\x10\x48\x14\xe8\x4c\xa2\x28\x19\xec\xc6\xe6\xb9\x42\xf5\x4f\x79\x94\x5c\x73\x84\x81\xe5\x55\x2c\x3e\xab\x59\xac\xf0\x26\xb6\xc4\x15\x61\x83\x62\x83\x83\xff\x05\x2d\xc8\xf9\xe5\x09\xda\x7a\xec\x7d\xf4\x90\x2f\x2b\x68\x6f\x4f\x13\x5e\x65\x2d\xd6\x79\xd8\x47\xb4\xf8\xdc\x80\x9e\x68\xa2\xe5\x21\x20\x3e\x5c\x88\xdc\x51\xfc\x51\xa6\x94\x08\x27\xc4\xfa\x56\x9e\x43\x15\x81\xf3\x06\x9c\x0c\x40\xbc\x7b\xeb\xab\x83\x74\xec\x12\x87\x82\x14\x67\xe2\x01\xa6\x14\x8a\x1b\x2a\xa9\x8c\x1e\xce\x78\xdf\x75\xcf\x9a\x12\xee\xd6\x2e\xa3\x08\x7c\x30\x49\x12\xfc\xae\x5f\x9e\x9f\xa6\x3b\xfe\x15\xcf\x9f\xed\xf1\x1f\x9a\xff\xec\xf3\xbc\xf5\x5a\xc7\x04\x71\x98\x6a\x99\x4b\x99\xdf\x13\x58\xb4\x4e\xc0\xe0\x57\xab\x70\x4c\x7d\xad\x1f\x25\xee\x31\x76\x92\xb3\x39\x17\xcc\x73\x75\x0e\x3f\x6f\x03\xb5\x2d\x84\x0b\x97\x75\x51\x5c\xb1\x4c\xb1\x61\x0f\xd6\xfd\x73\x77\xbe\x21\x29\x85\xeb\xde\xc9\x27\x00\x17\xb4\x17\xec\x1c\x30\x3d\x74\xc5\x9b\x5b\xe0\xb9\xff\xc0\x23\xa9\xea\xa2\x00\x8e\x1c\xb1\xc6\x1c\x0d\x58\x3f\xf7\xf2\xe0\xd0\x5f\x5c\x87\x3a\x2a\x57\x08\xda\x9c\x97\x81\xda\x96\x69\xd6\x7c\x70\x38\x2a\x15\xd5\xda\x21\x44\xb9\xc8\xf9\x8a\xe7\xf5\xc0\x75\xb5\x1f\x0b\x31\xa2\x67\xdd\x81\x57\x97\xc6\x33\x2b\x51\x9d\x02\xdf\x48\x45\xd8\x1d\xb5\x22\x0f\x9b\xda\x73\xaa\xe1\xa2\xe5\x32\xbb\x61\xea\x90\x0c\xce\xa7\x9f\xc2\x7f\x78\x02\x91\xb1\x6b\x43\x1d\xd6\x82\x2a\x7b\x97\x85\x54\x43\x43\xac\x81\x44\x08\x6d\x49\xc2\x91\xdb\xe3\x5f\xb9\xad\x5c\x73\xb1\x98\xc0\xdf\xd8\xc5\xf4\xb3\x9a\x48\x31\xa1\x13\xab\x0c\x9e\x7c\xc0\xf5\x56\x66\xb4\x78\x0f\x91\xc4\x87\x70\xbb\x42\xfa\x60\x68\x20\xc3\x84\xac\x17\x4b\x58\x54\x55\x52\xdf\x9a\x8b\x14\xcc\x40\x0f\x1c\x87\x87\x1d\x28\xd2\x11\xbd\xfb\x79\xe5\x3e\xe4\xe9\x76\x84\x1a\x7c\xeb\x09\xd6\xfa\x3d\x42\xd0\x85\x7b\xef\xdb\xe0\x3b\xe9\x34\x12\xf5\x2b\x89\xa2\xfd\x1a\x78\x5f\xe4\x8a\xa9\x15\x67\xb7\x47\xde\xd5\x9c\xdc\x72\xb3\x9c\xb8\xd5\xd3\x47\xb0\x05\x47\xbf\x82\x7f\x20\xe6\xe2\xc8\xc2\x8e\xf3\xdc\x3f\x45\xd7\x9a\xcd\xeb\xc2\x3d\xf2\xea\x29\xa1\x15\xff\x8e\x29\xcd\x25\xaa\xe4\xfc\x86\x8b\xfc\x90\xd4\x3c\xff\xe6\x0b\x15\xe6\x70\xc1\xdb\x82\xe0\x08\x8b\xfb\xd6\x5b\x49\xcf\xd4\xca\xff\xed\xae\x60\xab\xb9\x06\x7d\xce\x8c\x15\x52\x2c\x3a\x4c\xb6\xe0\xec\x9f\x0b\x6e\xb0\x12\x5d\xfa\x1e\xba\xc1\x41\x6a\x53\xaa\x1c\x8a\xc5\xb9\x35\x37\x12\x3f\x4f\xe8\x33\xd8\x29\x68\xb7\xa6\x9b\xf7\xe6\x09\xa5\x32\x03\x0b\x26\x02\x17\x98\x2b\x07\x08\x24\x8d\x46\x92\x25\x5d\xb1\xa6\xff\xd0\xc0\xba\x7e\xae\xc9\x92\x8a\x1c\xfe\xd3\x2c\x93\x2a\xf7\xeb\xcb\x4d\x53\x95\xef\xca\xb1\x86\xa6\x0b\x3d\x74\xd2\x5a\x6e\x2a\x36\xbf\x1e\x32\x87\xaa\x1c\xe8\x1c\xb4\xff\x7d\x08\x9a\x6a\xc1\xff\x55\x33\x42\x4b\x69\x1d\xa4\x88\x5e\xf8\x1b\xa7\x88\x94\x74\x0d\xde\x34\x2c\xed\xdb\xc0\x2f\x34\xec\x70\xb9\x46\x70\x87\xe4\x03\xa3\x39\xef\x90\xf5\x1e\x92\xb7\x7d\xf6\xde\x61\xc7\x40\x2a\x72\xe5\x28\x2e\xfd\x7f\xee\xaa\x7b\x14\xd3\xb2\x56\x19\xfb\xe0\x80\x71\xd6\x79\x1a\x76\x6c\xe5\x7c\xc7\x46\xd9\x1b\x62\xe8\x0d\x13\x2e\xa9\x6c\x8f\xc8\x50\x84\x67\x5e\x2b\xb8\x0f\xd9\x92\xe5\x35\x78\xb2\xb3\x35\x99\x5b\xff\xd0\xbf\x96\x2d\xf9\x62\xc9\x06\xa6\x7e\x7c\x9a\xe0\x08\x6a\x92\x5c\xdf\x54\x9a\x2d\x9b\x45\x00\xb5\x37\x6c\x59\x1b\x5e\x8f\xf6\x19\xaf\xa4\x77\x76\x55\xc0\x54\x51\x83\xa0\xc0\xf5\xf9\x44\x5d\x97\xc1\xde\xb9\x53\xdf\x3d\xa6\xe4\xad\xfd\x84\xe1\x7a\x8b\x56\x55\xc1\x83\xaf\xdd\x3f\xbc\x50\x7d\xe0\xdf\x61\x07\xc9\x9d\x53\xbd\xe4\x52\x6c\x29\x55\x92\xb9\xc7\x9a\xac\x56\xd6\x58\x0f\x74\x95\x67\x8c\xd0\x3c\xb7\xbe\x92\x22\x8a\x95\x72\x65\xb5\x62\xe4\xf3\x4f\x1c\x69\x98\x5d\xb0\x49\xc7\x7f\x7e\xfa\x4e\xf1\xb1\xa7\x2b\x72\xdb\x9e\x6d\xd8\xd1\xc1\x2e\x2c\x75\x0e\x70\xe8\x1c\xa5\x6a\xd1\x96\xad\x58\xab\xfa\x65\xdc\x50\x1c\x86\x17\x81\xbf\xc5\xfb\xbb\x54\x2d\x62\xdf\x17\xf6\x8e\xd5\xa2\x06\x75\x1c\xfc\x96\xb6\x75\x3b\xc6\xed\xb5\xca\xde\x85\xad\x2e\xb6\xdf\xdb\xd3\xe4\xe4\xdd\x69\x80\x17\x22\x24\x72\x9f\xe1\xf4\x1c\x6a\x95\x92\x2b\x0e\xed\x07\xbf\xf3\xb0\x09\xcc\xa3\xf4\x4e\xa0\x45\x0f\x30\x81\x90\xba\x0b\x62\xb1\xa7\x7b\x58\x09\xdc\x93\x3c\x6d\x21\x22\x59\xa3\x99\xac\x35\x29\x56\xb8\x27\xf4\x5e\x98\x18\xb2\x0e\x5c\x54\xb5\xc1\x23\x96\x9a\xbc\xb1\xc8\x96\x54\x2c\x1c\x94\x94\x45\x02\x59\xf4\x5a\x18\x7a\x67\xbf\xda\x8a\x66\x3a\xa3\x15\xcb\x7d\xf9\x30\xc9\x65\x8d\xdb\xfe\x5f\xff\xfa\x90\x70\xf6\x9a\xfc\xba\x33\xb9\x29\x39\xf3\xd2\xdb\xc3\x81\x5d\x05\xc7\xbc\x34\x6b\x0f\xd3\x21\x51\x6c\x41\x55\x5e\xe0\x9a\xec\xc8\x39\xb9\xed\xd0\xd9\x35\x87\x81\xdd\x71\x6d\x34\x41\x51\xce\x08\x69\x76\xd9\xb9\x8e\xed\x42\x08\xfd\x19\x6b\x67\xa8\xbe\xb1\xb6\xcd\xea\xe1\x49\x4e\x0d\x9d\x74\x8c\xc5\x91\xcb\xda\x4e\x7c\x93\xe5\x09\xf5\x4a\xa9\x35\x83\x47\xbf\x52\xb5\x10\x36\x30\xa6\xcd\xff\x15\x17\x13\x3a\x81\x96\xbc\xd8\xc8\xf3\xf9\xbc\x68\xa2\xbb\x97\xf7\xb5\xfd\x59\xa3\xdc\xdd\xb7\x03\xe3\x10\xe2\x4b\x9a\xb8\xb4\x31\xcc\xbe\x35\x72\xab\xff\x31\xaa\x3e\x58\x8c\xb3\x8b\xeb\x0f\xff\x75\xf9\xfe\xfc\xe2\x3a\x18\x8e\x60\x06\x30\x52\xef\x33\x1c\x71\x37\xfd\x3e\xc3\xd1\x9a\x81\x18\x20\xd2\xa6\xe1\xe8\x9b\x01\x8c\xe4\x6d\xc3\xd1\x37\x03\x98\x95\xdd\x36\x1c\x3b\xcc\x00\xd2\x8b\xe8\xae\xef\x4e\x33\x80\xd2\xce\x1d\xc3\xb1\xdb\x0c\x20\xa4\x6e\x1b\x8e\xbe\x19\x40\xdd\xaf\x6d\xc3\xd1\x31\x03\x48\x93\xbf\x6d\x38\xba\x66\x00\x21\x74\xb7\xe1\x18\xcd\xc0\xe7\xfc\x28\xca\x0c\x30\xb1\x8a\x34\x01\x21\xeb\xd9\x51\x2e\xcd\xb9\x40\x91\x9c\xf5\x9a\xcc\x76\xe8\xfb\x52\x1c\xaa\xe7\xb1\x9f\x7d\x98\xbd\x58\x7d\x47\x15\x51\xac\x52\x4c\x43\x5c\x85\x2c\xeb\xd8\xb5\x41\xc4\x0b\xc5\x51\x17\x12\x42\x5b\xc4\xf0\xb3\xab\x8a\x7d\xa4\xba\xd6\x64\x35\x64\xdd\x87\xa5\x94\x55\x03\xd3\xa6\xdd\x10\x25\x27\xff\x3c\x3f\x3d\xbb\xb8\x3e\x7f\x73\x7e\xf6\xe1\xd1\x0a\x57\xa2\x1a\xb9\xf6\xdd\xd5\x34\x9e\x9a\x1b\x3f\xef\xaf\xa1\xc5\xba\x5e\x06\x6c\xc5\x65\x0d\x10\x77\x00\x9f\xa4\xdc\x5f\xbd\xa5\x5b\xd1\x22\x81\x07\x5a\xac\xa1\x41\x2b\xcf\xd2\x1e\x43\x3d\xdd\x99\xa9\x40\xcb\x4d\xea\xa8\xba\xf1\x33\xee\x2a\x5a\x66\xd2\x6c\x87\x1b\xf7\xe7\x3c\xf0\x1b\x9f\xda\xe5\x75\xe3\x67\x1d\xdf\x98\x9d\xbf\xc7\xfd\x45\x8b\xfc\x99\xec\x09\x5a\x66\x70\x9e\xfb\xd5\x4f\xe8\x46\x48\x69\xd4\xee\x1b\x25\xcb\x24\xaa\xf7\xca\xbd\x54\x79\x68\x13\x7a\x91\x76\x39\x31\x7b\x7a\x38\x38\xaf\x3f\x3a\x69\x2b\x9f\x1a\x08\x2d\x5b\xd0\x22\xad\x3c\xa0\x39\x8c\x33\x9b\x51\x2d\xf4\x53\xf4\x9d\x77\xd5\x50\xef\x68\xf5\x77\xb6\xfe\xc0\x22\x7a\x25\x6d\x9e\x07\x56\xb0\xcc\x3a\xb3\xe4\x86\xe1\x8b\x27\x89\x7f\xc9\x25\x27\x61\x9a\x31\x4d\xa6\x12\x2c\x39\x89\xee\x37\xe7\xc6\x24\x72\x59\x52\x6c\xbd\x1d\x37\x0c\x5d\xce\x1f\xc6\x56\x0b\xfd\xd8\x0d\x27\x21\x4a\xb4\x27\x28\x66\xbf\x49\x9a\x6e\x71\x6e\xc4\xf8\xf5\x61\xec\x44\x8e\xc5\xaf\x55\x17\x79\x06\x69\x95\x68\x91\x4f\x04\x87\xd6\x1f\xbb\x51\x69\xd1\x62\xd3\xa0\xda\xfa\x23\x06\xe3\xd6\x1f\xc9\xce\x6f\x00\x86\x27\x3d\xc3\x0e\xf3\x1f\x7f\xdd\xbb\xfe\x56\xa3\xea\xa3\xa5\x3a\x4e\x58\xab\x8f\x02\xc4\x2a\x5a\xa4\x0f\xd8\x92\x6c\x6a\x0c\x87\x07\x09\x07\x37\xa5\xcd\xde\x6b\x8c\x76\xd4\xf7\x39\x2e\xa0\xa6\x9f\x65\xfe\x3a\xb4\x93\x88\x53\x01\x25\x33\x34\xa7\x86\x4e\xad\x36\x39\xec\xff\x11\xe0\xc6\x71\xd7\xb6\x91\x57\xd0\x19\x2b\x74\xe7\x07\xc0\x79\x74\xd0\xfd\xb8\x9f\xd0\x15\xcb\xa6\x42\xe6\xec\x02\xbe\x00\xfe\xe8\x43\xeb\x63\x07\x45\x83\xff\x21\xee\x37\x80\x09\x7d\xea\xaa\xfa\x0e\xc3\x1f\x2b\x99\x9f\x5f\x26\x11\x0c\x92\x74\x44\xfb\xd6\x27\xe6\x86\xc1\x61\x45\x72\xe7\x85\x91\xca\x19\x6b\x2d\x50\x52\x25\xed\x65\xc6\xab\x53\x77\xa3\x75\xb6\x64\x25\x8d\x8a\xf2\xc2\x78\x13\x16\x9f\x70\x1d\xd1\xe1\xa4\x3f\xb8\x00\x36\x7b\x1b\xff\x27\xe9\x5b\xec\x86\x0d\xd6\x57\xaf\x5e\x3c\x19\x77\xb4\x39\xb7\x49\x8f\x0a\xec\x45\x22\x97\xd4\x99\x81\xc6\x91\x4f\xb2\xaf\xcb\x4e\x65\x29\x39\xbe\x3c\x8f\x16\xba\x72\x77\xe3\x49\x6c\x6b\x80\xfb\xbe\x79\xa2\x76\xbd\x81\x23\x6f\xb2\x3e\xc7\x1d\x41\xe0\xe0\x08\xb2\xb5\xeb\xcb\x10\x77\x5f\xa9\xc8\x03\xa4\x5a\x93\x7d\x27\x70\x9a\x55\x75\x9c\x01\xf4\x72\x4a\x56\x4a\xb5\x3e\x0c\x7f\x6c\xda\x85\x4d\xb4\x91\x8a\x2e\x22\xcd\x77\x98\x36\x4c\xb7\xfd\x93\xfb\xd1\x64\x8b\xb2\x3d\x6b\x7c\xf6\x99\x78\x04\x77\x83\xa6\x0e\xde\x1e\xaa\xf3\x4e\x3b\x9e\x94\x97\x10\x8e\xe7\x13\x70\x12\xb2\xb8\xd6\x86\xfd\xd1\x57\x13\x27\xd1\x0f\x46\x61\x40\xb2\xa4\x59\x7b\x64\x93\xbb\xfe\xf0\xbc\xdc\x87\xb8\x0a\xe7\x5d\x03\xea\x2c\xc4\x8a\xac\xa8\x42\xb6\xd6\x6e\x47\x32\xbb\x9e\xf3\x15\xd7\x32\x52\xa5\xde\x57\x99\x9f\xc4\xae\xfb\xa6\x3b\xae\x06\x35\x95\x53\xc9\xee\x2a\xe8\xc1\xda\xd8\x81\xf8\x1c\x4c\xde\x7d\x67\x79\x85\xa7\x99\x73\xa3\xa2\xc6\x30\x25\x5e\x93\xff\xde\xff\xc7\x6f\x7f\x9a\x1c\x7c\xb3\xbf\xff\xc3\xcb\xc9\x9f\x7e\xfc\xed\xfe\x3f\xa6\xf0\x2f\xbf\x39\xf8\xe6\xe0\xa7\xf0\x87\xdf\x1e\x1c\xec\xef\xff\xf0\xf7\x77\xdf\x5e\x5f\x9e\xfd\xc8\x0f\x7e\xfa\x41\xd4\xe5\x8d\xfb\xd3\x4f\xfb\x3f\xb0\xb3\x1f\x3f\x53\xc8\xc1\xc1\x37\xbf\x8e\x9c\x38\x15\xeb\xf7\x51\xae\x04\x01\x0d\x18\xdf\x45\x7e\x5b\x5a\x82\xeb\x42\xc8\xdd\xa4\x4d\x4f\x4e\xb8\x30\x13\xa9\x26\x4e\xf0\x6b\xe0\x85\x4d\xe2\xf2\xa4\xd5\xb3\x1f\x12\xd8\xa4\xfe\xfc\x5a\x37\xfb\x49\x28\x32\x57\xa6\xff\xb4\x5f\x94\xdc\x1c\x7b\xec\x62\xd1\xef\x03\x90\x86\xfa\xa5\xf8\x3c\xe3\x03\xd5\xcf\x8d\x90\x0c\x71\xa7\x28\x5d\x94\x3b\x57\xb2\x0c\xdd\x01\x00\xa2\x05\xec\x84\xd1\x62\xfd\x3c\x6f\x18\xfa\xbd\x3a\x8c\xf1\x41\x0d\x33\xc6\x07\xb5\xb8\x31\x3e\xa8\x0d\x1b\xdd\x07\x35\x47\x10\x35\xbe\xa6\xed\x1a\x4c\xac\x70\x10\xa8\x9d\x18\xf9\x90\xc3\xea\x34\xaa\x45\x7c\xdb\x4e\xa4\xfd\x36\x60\x1e\x21\xd9\x1b\xbf\x16\x77\xda\x56\x63\x61\xd3\x1b\xe5\x6e\x2c\x31\x39\x2e\x0a\xc2\x05\xd6\x78\xc1\x24\x43\x65\x90\x62\x2e\x9d\x14\x58\x61\x57\x38\xf8\xe9\xed\x92\x6d\x2c\x21\xb0\x1f\x1a\xaa\x0c\x17\x0b\xcc\x72\x42\x77\x15\x70\x47\x43\x81\x0c\x17\xa4\xac\x0b\xc3\xab\x82\x91\x88\x40\xd6\xc1\x0e\x8b\x9a\x11\xaa\xb5\xcc\x38\x0d\x95\x73\xf0\xbf\x14\x14\xc5\x2c\xea\x23\x05\x58\x55\x43\x6f\x00\x85\x9c\xb1\x9c\x89\x8c\x4d\xc9\x77\xf6\xd7\x30\x16\x25\x9c\xa4\xd9\xda\xee\xcd\x99\x58\x35\x35\x53\xb5\x2b\xd3\xc1\x1c\x2a\xbb\xa2\xbb\xe7\xf9\x9f\x5b\x24\x62\xd5\x94\x07\x59\xb6\xb5\x22\x28\xcd\x09\x7e\x6b\x93\xc9\xa7\x50\x8e\x23\xe7\x2d\xee\x02\x55\xd5\x13\x17\xb9\xc4\x46\x0b\x0d\x8a\x31\x22\xe0\xdc\x0a\x13\x9a\x05\x89\xe9\xee\xe4\xc2\x02\x70\xeb\x91\x32\x9e\x08\x50\x34\xd6\x5d\xbf\x97\x35\x2d\x32\x41\xd3\x75\xd3\x9f\x9e\x9b\xfd\x00\x2e\xf6\x0e\xf7\xda\xb9\xc7\x51\x52\x63\x5d\xeb\x24\x6e\x75\x0a\x97\x7a\x97\x3b\x1d\x51\x06\xdb\x8e\x1e\x36\x2d\x89\x0b\x1c\xef\xfe\xc6\x03\xc9\x2a\xc5\xe6\xfc\x2e\x89\xce\x3c\x6e\xd9\x67\x09\xcf\x99\x30\x7c\xce\x63\x5a\x02\x4b\x3b\xb9\x8a\x09\x00\x11\x00\x21\x96\xf5\x0b\x22\x9b\x10\xb5\x40\xf2\xa7\x56\x06\xe7\x52\x34\x29\x0d\xd8\x55\xaa\xe4\xd4\x68\xbd\x46\xeb\x35\x5a\xaf\x4f\x8d\x27\x6f\xbd\xbc\x3e\x08\x21\xfb\xe3\x9a\x1f\xe0\x6e\x89\xa5\xa7\x39\xed\x30\x87\xc1\x1d\x47\xa7\x6b\x23\x98\xaa\x51\x89\x98\x6e\xcf\xd4\xc6\x6a\x1a\x49\x68\x51\xc8\x5b\x84\x44\xa0\x9d\x54\xa4\x60\x2b\x56\xf8\x70\x88\x94\x54\xd0\x05\x70\x67\xe2\x22\x98\xd0\x80\x4b\x2a\x62\x15\x8e\xe2\x39\xdb\xec\x7c\x85\xe2\xd7\x11\x24\x30\x18\x82\x38\x25\x8b\x82\x29\x4d\x0a\x7e\xc3\xc8\x29\xab\x0a\xb9\x1e\xce\xf7\xe9\x06\x74\x6f\x33\xd4\x58\x35\x75\xc5\x0c\x06\xa7\x1c\xd3\x45\x26\x50\xf2\x3b\x8e\xd9\xd8\xc3\x0d\x0c\xff\xc0\x21\x4f\x2a\x47\x5a\x4b\xde\xa3\x1a\xf6\xca\x39\x39\x2e\x6e\xe9\x5a\x1f\x92\x0b\xb6\x62\xea\x90\x9c\xcf\x2f\xa4\xb9\x74\x49\x04\x8c\xc3\xd3\xad\x61\x75\xa2\x09\x9f\x93\xd7\x05\x35\x4c\x1b\x62\x28\x46\x89\x72\xdd\xed\xf6\x20\x55\x6f\x92\x6d\x47\xd7\x34\xdd\xf3\xe3\xe9\xe9\x41\x52\x43\x4e\x8f\x00\x10\x45\x1c\xb4\x22\x50\xf8\x46\x1e\xb1\x63\x47\xea\xeb\x28\x34\x1d\x47\x6c\xd0\x18\x98\x04\x23\x34\xd4\x08\x9d\x56\x21\x75\xc7\x05\x51\x4c\x57\x52\x68\x86\x53\x41\xad\xba\x69\xbe\xd9\x25\x80\xf5\xa3\xe6\x02\x91\xfe\x6c\x9c\x27\x5b\x49\x6d\x80\x2b\x19\xe7\x60\xf4\x95\xcb\x65\x10\x06\x04\xdc\xb4\x28\xd0\x8e\x00\x2f\x4b\x96\x73\x6a\x58\xb1\x26\x74\x6e\x98\x22\x34\x9a\x7a\xc2\xce\x49\x31\x1a\x18\xc7\x81\x57\x19\x78\xbd\x51\x54\xe3\xed\xd8\x4a\xff\xbb\x06\xf1\x74\x68\x4f\xc2\x76\x38\x58\xad\xa7\x47\xdf\x22\x1d\x47\x0a\xf5\x02\x5b\xb5\x0f\xde\x77\xd4\xe5\x24\x2d\x66\xa1\x5d\x80\x59\x21\xb3\x1b\x4d\x6a\x61\x38\xd6\xab\x77\xbd\x7e\xe4\x0d\xc9\x64\x59\x15\xa0\x3c\xe3\x28\x21\xc9\xcf\xd3\x42\xee\xd2\xc8\xcd\xbf\x4e\x1a\x25\x31\xb1\x73\xd2\x47\xbf\x6a\xff\x27\xf8\x0b\x5c\x8c\x10\x1d\xc3\xc6\x47\xb0\xec\x8e\x65\xf8\xb8\xa2\x77\xf5\xdf\x0b\x06\xa7\x36\xaa\xe9\x3a\x21\x52\x34\x85\x00\x73\x69\x9d\x56\xa0\x45\x8f\xeb\xc0\x4c\x36\x5a\x87\x9d\xdd\xb1\xac\xf9\x73\x4c\x28\x0b\x7d\x10\xb3\xd0\x31\xc5\x9a\x26\x3c\x0c\x26\x09\x48\x2b\x0d\x3c\x0a\x4d\xf2\xd9\x1d\x1b\x0d\x82\x41\x62\x0c\x33\x86\x1b\x4e\xd1\x38\x61\x05\x17\x48\xf3\xdf\x1d\x9e\x42\xb4\xdb\x9c\xa6\xb9\xdd\xb1\x00\x13\x2b\x6c\xab\x1f\x72\xa4\xcc\xd0\x7f\x33\xac\x42\xfc\x9a\x2a\x29\x0d\xd9\xdf\x3b\xda\x3b\xd8\x42\x03\x44\x82\x17\x5d\xdf\x49\xe7\xc0\x39\x62\x22\x3f\xeb\x48\xa9\x1c\x3a\xa8\x57\xd0\x3e\x9b\x65\x7b\xf9\x21\xe1\xb1\x40\x14\xcf\xce\xaa\x6a\x11\x4e\x42\x5c\x55\x13\x71\x4c\xb4\x87\x44\x4b\x62\x14\xcd\x79\x92\xea\x02\x90\x69\x27\x68\x54\xed\x9d\xec\xfd\xbd\x9f\xf6\x62\xcf\x29\x33\xd9\x01\xb9\x95\x62\xcf\xc0\x71\x9d\x92\xeb\xd8\x5b\x55\x6b\x16\xc8\x78\x0f\x81\x45\x5f\xb0\x78\x40\x8e\x24\xec\xae\x2a\x78\xc6\x4d\xb1\x06\xe7\x92\xc8\x3a\x76\xdf\x81\x6d\x9e\x9a\xc0\x1b\x7c\x76\x17\x7d\x92\x5c\x45\xb3\x35\x62\x2f\xc1\x15\x74\x0e\x67\xa4\x50\xaa\x49\xc1\x57\xec\x68\xc9\x68\x61\x96\xeb\xc1\x1d\x6c\xb6\x87\x90\x62\xf2\x6f\xa6\x24\x30\x1b\x0b\x2f\x37\x0e\xc5\x19\x03\x68\xe8\x0e\x34\xb8\x61\x7b\x32\x51\xb9\x57\xeb\x2f\x7e\xcb\x90\x71\x11\xd9\x6a\xe2\x7a\x7d\x7d\xf9\x2d\x33\xc9\x1c\x0f\x3b\xbb\x50\x7a\x07\xaf\x5a\x4c\xcd\xa5\x2a\x1f\xd9\x03\x89\x07\x89\x4f\xa0\x63\xec\x23\xbb\x40\x4b\xa9\x23\xf6\x9d\xec\x6e\xe0\x8b\x63\x0e\xed\x0e\xd7\x6f\x4b\xb0\xcc\xee\x78\xb2\x32\xf4\xb6\x53\x18\x39\xbf\x9c\x92\xff\x92\x35\x34\x4d\xa2\xb3\x28\x4f\xde\x8e\xd0\x3b\x45\x33\x43\x5e\xd8\x45\x78\x11\xf3\xd0\xea\x86\x3d\xf7\x7f\x63\x34\x77\x4d\x7c\xb4\x61\x14\xc5\xed\xdd\x8e\x44\xd0\xdd\xce\xbc\x52\x7a\xce\xb5\x36\xb2\x24\x4b\x27\x38\x7e\xa3\x3b\x24\xc9\x5e\x77\xc4\x22\xf7\xad\x5e\x73\xef\x0b\x9a\x28\x56\xa5\xb0\x76\xfe\x6b\x7f\x41\xd6\x68\xcb\x12\xb8\x93\x12\x29\x35\xc8\x9d\x31\x4d\x28\xc9\xe0\xa8\x44\x8b\x74\x8b\x6f\xcf\x8a\x27\x36\x8c\x96\xc8\x85\x3b\x24\xae\x13\x5b\x12\xbb\x1e\x5d\xcc\x44\x12\x15\x34\x91\x18\x52\xe8\xbe\x90\xe1\xad\xd3\xb6\x47\xaa\xfa\x28\x92\xa8\x92\x86\xec\x00\x90\x24\x10\xd9\x9c\x52\xf7\xd8\x99\x60\xf9\x49\xca\x1a\x0e\x12\x4b\x3f\xdd\x1d\x0f\xbf\x7c\x29\x0e\x1e\x49\xb7\x7e\x55\x34\xfd\xcc\x36\xf9\x8c\x6b\xcb\x88\x6b\x7b\xd4\x1d\xd2\x99\x4e\x50\x67\x9a\xa9\x15\xae\x60\xa2\x1d\xa9\x96\x4c\x62\x9f\x6f\xc2\xd8\xc1\x11\xaf\x88\xa8\xcb\x59\xb4\x91\x6a\x18\xdb\x94\x49\xbd\x0d\x9d\x36\x0f\x17\x29\xa6\x1a\x20\x2c\xc1\x41\xa2\x62\x11\x7b\x2f\x5e\xd9\x6f\xfe\xfa\x7f\xff\xef\xdf\xfd\xef\xa9\x5b\x56\xfb\x1b\x91\x32\x67\x8c\x50\x41\xce\x8f\x2f\x8e\xff\x79\xf5\xdd\x09\xb0\x67\xc7\x9d\xc2\x04\xc5\xfc\x29\x4b\xf9\x13\x16\xf2\x3f\x60\x19\x3f\x10\x96\x45\x6a\xf8\x3e\x2e\x0b\x04\xc6\x67\xb4\x6b\xed\x08\xb3\x7d\xa4\xe8\x9e\x0d\x13\x64\xb2\x6d\x4c\xdc\xe3\x19\x4f\x10\x38\x3c\xba\xf6\x34\x59\x75\x25\xb3\x9b\x64\x59\x9e\xbd\xeb\x93\x4b\x27\x30\x49\xa2\x87\x8a\xf0\xc0\xc4\xc5\x4a\x16\x2b\xbb\x99\x94\x5c\x9f\x5c\x46\x1a\x8b\xa9\x95\x01\x2f\xac\x2e\xef\xbd\x8e\xaa\xe4\x6c\xa8\x99\x3c\xb4\x93\x97\x55\x11\xf3\xa2\x4c\xa0\x57\x80\x62\xb4\xe0\xda\xf0\x0c\xe6\x5a\xa0\xfa\x4b\xf7\x87\xfd\x5e\x3c\x9e\x73\xcc\x8f\xb5\x23\x71\x7e\x6c\xef\x7d\xa2\xaa\xe7\x26\xd1\xd6\x49\x95\x45\x27\x4d\x0e\x7b\xa4\x3f\xf1\x0c\x95\x3e\xd1\x16\x57\x72\xfe\x44\x3d\x47\x70\xc3\x70\xad\x40\xbb\x43\x74\xba\x14\x79\xcf\x31\xf6\x05\x05\xfc\xce\x6d\xcf\x31\x52\xac\xff\xe0\xbe\xe7\x18\x9b\x97\xb0\x7e\xe7\x96\xe7\x98\xc8\xb7\x1d\x3d\xc7\xcf\x1b\x0f\xe0\x39\x56\x8a\x5d\x19\x59\x25\xc1\xd9\x39\x51\x49\x51\x76\x33\x36\x97\x8a\xa5\x81\xd9\xb5\x00\x38\x92\xd7\xa0\x8c\xa9\x88\x60\x56\x0d\xcf\x5c\xb2\x0b\x57\x43\x97\xec\x13\x70\x59\xb2\x65\x78\x55\x15\x4c\xeb\x23\x80\xc6\xd5\x95\x4b\x52\x22\x85\xce\x29\x2f\x6a\xc5\x0e\xed\x4e\xb3\x12\xf6\xea\x30\x96\xe4\xd1\x6e\x06\x13\x4e\x14\x33\x99\x83\x51\x78\xd4\x22\x7e\x7f\xac\xcf\xe7\x0e\x8e\xeb\x68\x1b\xdf\xd6\x2b\x53\x54\x2f\x19\x34\xf3\x64\x77\xdc\x68\x37\x51\xc5\xa8\x46\x73\x44\x03\xd4\xc5\x1f\x24\x70\x81\x35\xa9\xa8\xd6\x2c\xc7\x5b\x83\x0e\xe4\xd3\x4d\xf0\x52\xe6\x7b\x7b\xba\xfb\x33\x48\xc9\x0b\x45\x33\x46\x2a\xa6\xb8\xcc\x09\xb0\xae\xe7\xf2\x56\x90\x19\x5b\x70\x81\x8d\x00\xfc\x8d\xb4\x93\x0e\x17\xde\xba\xb0\x2c\x02\x48\x15\x3a\x26\x4f\xc9\x87\x5e\x47\x57\xbc\xd5\x92\xb5\xc9\x64\x6b\xad\xfd\xea\x1e\x46\x48\x6c\x91\xa4\xc0\xd6\x00\xd7\xbc\xa6\x45\xb1\x6e\xd5\x0a\x52\xb2\x27\x26\x31\x0f\xb5\xf1\xcf\x0c\x53\x6b\x2f\x6b\xac\xc4\xee\x05\xed\x2e\x05\x5e\x37\x29\x46\xb3\x65\x5c\x31\xc5\x08\xdd\xfd\xc4\x18\xa1\xbb\x23\x74\xf7\xde\x31\x42\x77\x47\xe8\xee\x08\xdd\x1d\xa1\xbb\x23\x74\x77\x84\xee\x0e\x1c\x23\x74\xf7\x53\x63\x84\xee\xde\x3b\x9e\xe4\xd3\xc4\x08\xdd\x1d\xa1\xbb\x9f\x3d\x46\xe8\xee\x08\xdd\x1d\x26\x77\x84\xee\xa2\xc6\x08\xdd\xfd\xd9\x31\x42\x77\x63\xc6\x08\xdd\xc5\x8e\x11\xba\x3b\x78\x8c\xd0\xdd\x11\xba\x1b\x31\x46\x00\x06\x62\x8c\xd0\xdd\x04\x81\xc3\xa3\x6b\xcf\x11\xba\x3b\x42\x77\x3f\x73\x8c\xf9\xb1\x76\x8c\xd0\xdd\x88\x31\x42\x77\x3f\x39\x46\xe8\xee\x08\xdd\x8d\x90\xf5\xf4\x3c\xc7\x00\x11\xbd\x54\x72\x16\x4d\x2d\x7d\x09\xe0\x28\x9e\xb9\x8c\x9a\xbd\x27\x31\xc0\xcb\x30\xb5\x29\x39\xe9\x63\xe6\xa0\xbf\x95\xa7\x8f\x44\xc8\xf5\x98\x50\x37\x47\xa0\xc6\x9c\xee\x60\xbb\x45\x08\x1e\x08\xe9\x0a\x84\xce\xfa\xa8\x92\xee\xff\x6b\x01\x5d\x1d\x24\x97\xcb\x4e\x62\xb9\x72\x1f\x85\x75\x15\x0f\xdf\xba\x17\xba\x45\x24\x8a\xc6\x99\xb4\x81\xfe\x26\x6c\xab\x0f\xbe\x42\xca\xee\x43\xb6\xfa\xc0\x2b\xac\xe7\x8f\x86\x6b\x3d\x01\xe0\x5e\x34\x44\xeb\x1e\x78\x56\xa4\xf5\xda\x80\x66\x05\x70\x55\x84\xc4\x9d\xb0\xac\xc8\x59\x6e\x41\xb2\x02\xa8\x2a\xc1\x97\x03\xf6\xb4\x0b\xa8\x8a\x7c\xe5\xef\x40\xb1\xba\x60\xaa\x08\xa9\x1d\x18\xd6\x36\x90\x2a\x66\xa7\xcc\x2e\x10\x95\xc7\x00\xc5\x04\x97\x3d\x00\xd5\x0e\x08\x54\x84\x6c\x00\x4f\x25\x86\x3f\xed\x84\x3e\xc5\xf9\xaf\x3b\x60\x4f\x01\xb8\x14\xb3\xb0\x2d\xe4\xa9\x0b\x5a\x8a\x39\x02\x0d\xdc\x69\x13\xb0\x14\x95\x02\xc9\x53\x83\x95\x52\x3c\x0d\x47\x3f\x0b\x47\x7a\xaa\xbe\x4c\xe8\x7a\xa9\x98\x5e\xca\x02\x69\x0a\x7a\x66\xe0\x1d\x17\xbc\xac\x4b\xab\x73\xb4\xd5\xdb\x7c\x15\x59\xc3\xa4\x1b\xb4\xaa\x73\x02\xe1\x4d\x19\x6d\xf1\x40\xa3\x28\x96\x83\x74\x7b\xc4\x80\xd0\x7d\x49\x57\x78\x57\x5f\xd7\x59\xc6\x58\xce\xf2\x5e\x5e\x93\xfc\x6e\x1a\xd6\x02\x29\xd7\x35\x48\xe5\x9a\xbc\x8a\xf1\x30\x62\x22\xa2\xb9\x54\x25\x35\x20\xe3\x77\x5f\x21\x24\x44\x61\xdf\x1e\x04\xf7\x96\x1c\xf3\x16\xed\xc6\xc5\xe5\xf2\x22\xf2\x78\xf1\xfe\x63\x5c\xfe\x6e\x37\xb6\x2d\xce\xc6\xed\xc2\xb5\xc5\x49\x7c\x00\x4c\xdb\x4e\x3c\x5b\x17\xf9\x15\xe7\xe9\xc6\x61\xd9\x12\x21\x5e\xa3\x31\x6c\x0f\x83\x5f\xdb\x8d\x5d\x03\xed\x12\xe3\x5c\xf4\x71\x6b\xf1\xc8\xb3\x27\xe1\x5a\x3c\x04\xda\x6c\x1b\x69\xe6\x17\x2b\x2e\x8b\xdd\xa0\xcc\xd2\xa1\xc4\x12\x21\xc4\x52\xa0\xc3\xa2\x91\x61\xf1\xa8\xb0\x54\x88\xb0\x14\x68\xb0\xad\x2e\xa0\x09\x4e\x10\x09\x8d\x1b\x93\xe0\xab\x53\x65\x8f\x93\xa0\xbf\x1e\x76\xb9\x52\xa0\xbe\x12\xac\x57\x1c\xda\xeb\x61\x90\x5e\x29\x51\x5e\x29\x96\x28\xea\x8d\xee\x61\x90\x5d\x3b\x51\x5d\x04\x5d\xff\x4e\x36\xd3\x5d\xd3\xee\xcb\x5a\x84\xd0\x0d\x34\x57\xf7\x55\x2d\x42\x6a\x83\xe4\x4a\xfb\xa2\x16\xf9\x9a\x96\xea\x25\x2d\xd1\x2b\xda\x03\x61\xaf\x62\x71\x57\xbb\x31\x57\xd6\x07\x89\x38\x10\x5b\x78\xab\x16\x31\x15\x21\xb5\x9b\x93\x88\x43\x4b\x45\x6e\x28\x17\xdc\x70\x5a\x9c\xb2\x82\xae\xaf\x58\x26\x45\x8e\xf4\x26\x36\x7a\x55\x7b\xb4\xc0\x9c\x68\x27\x14\xf9\x7d\x2e\x13\xd4\xe7\xba\x58\x52\x4d\xf0\x6f\x97\xa4\x25\x4e\x09\xcf\xa3\xde\x31\x25\x14\x1e\x1f\xed\x7a\x20\x9f\x2f\xc9\x93\x7b\xc2\x24\x4f\x22\xe5\xe4\x28\x3f\xd2\x1d\xaf\xbf\xc9\x5b\x22\xe7\x86\x09\xb2\xcf\x45\x38\x61\x07\xd8\xec\x53\x93\x6c\x6a\xf3\x99\x4d\xd2\x10\x2f\xf3\xd5\xcb\x30\xb1\x26\xe5\x18\xe5\x98\x3d\xe7\x94\x23\x24\x63\xb5\x7e\x9a\x19\x6d\x3f\xb9\x87\x4a\x69\x7b\xf1\xf3\xba\x70\xca\x0c\x9b\xbf\x81\x64\xb8\x4f\x90\xf7\x73\xda\xc8\x63\x41\xc8\x3b\xef\xe6\xbc\x82\x2f\x6f\xb4\x21\x15\x39\xf1\x74\x67\x68\xc9\xdd\x03\xff\xac\x8f\x6e\x24\x8a\xf8\xa1\x10\xc4\xf7\xa2\x87\x1d\x06\x18\x29\x75\x0b\x39\xdc\xe2\x7f\xb1\x12\xfb\xa8\xe1\x2e\xf6\x37\x62\x8e\x6d\x57\x66\x3c\xee\x77\x7c\x23\xc0\xfd\xb7\xf7\xe2\x7b\xe1\xb9\x20\xc2\x25\xde\xc0\xf6\xa6\x2a\x83\xef\x97\xc0\xc7\x62\xc4\x9f\x4c\xb4\x1f\xd0\xb8\xb1\xb9\xb1\x31\xda\x1f\xa3\xfd\x4f\x8c\x07\x88\xf6\x0d\x2f\x99\xac\xcd\x93\x0d\x38\x6f\x97\x3c\x5b\x76\x7d\x41\x5e\xa2\x4d\xb5\xac\xcd\x86\xbf\xe6\xa7\x98\x10\x8a\x30\x46\x9d\x1b\x03\xf7\xa6\xb1\x23\xa1\x1a\xcf\x7e\xdb\x20\x64\x09\xd5\x84\x92\xd3\x8b\xab\x7f\xbe\x3d\xfe\xeb\xd9\xdb\x29\x39\xa3\xd9\x32\x4a\x34\x17\x84\x82\x65\x03\x15\xb6\xa4\x2b\x46\x28\xa9\x05\xff\x57\xcd\xb0\x76\x61\xbf\x99\xdf\x41\x12\x4c\x77\x84\x06\xb2\x36\x09\xa1\x1b\x7a\x9b\xf8\x96\x6b\x63\x37\x11\x64\x79\x9e\x31\x89\xca\x07\xce\x95\x2c\x37\x4d\xdb\x99\x15\xe6\x5c\x6f\xa4\x37\xb7\x64\x8a\x91\x05\x5f\x79\xe4\xb3\xc3\x80\x12\x9a\x47\xb0\xca\x59\x2d\x60\x2f\x8e\x0d\x0e\xe8\x0c\x00\x85\x4b\x46\x04\x33\xf6\xd2\x37\xa9\x4c\x1c\xba\xb2\x43\xfe\x4d\x6a\xcd\xf4\x21\x99\xd5\x00\x0e\xad\x14\x2f\xa9\xe2\x28\x08\x46\x67\xc2\xb4\x98\x92\x0b\x19\xc2\xa3\x35\x2c\x2d\x26\xdf\x64\xbd\x19\x58\xda\xd3\xf7\x67\x57\xe4\xe2\xfd\x35\xa9\x14\xf0\x04\x63\x91\x95\x20\x11\x8e\xc0\x8c\xd9\x59\xb9\x63\x94\x4f\xc9\xb1\x58\x63\xf7\xde\x19\x19\xae\x89\x8d\x87\x98\xb0\x62\xfd\xf3\x54\x8e\x4e\x3e\xbd\x78\x39\x85\xff\xf7\xc2\x9e\x21\x65\x5d\xb9\x06\xae\x1b\xa3\x68\x42\xd1\x88\x73\x0f\xf9\xac\x60\xed\x7d\xf0\x27\x0b\xe3\x2d\x25\xd3\x2f\x38\x54\x06\x1a\x8d\xb1\x01\xb1\xf7\xeb\x7a\x69\xcf\x88\x62\x95\x62\x9a\x09\x64\xcc\x42\x9b\x8b\x0a\x27\x0e\x14\xbc\xd5\x30\x45\x64\x61\x5b\x64\xb4\x1b\x13\xeb\x4e\xda\x99\x5f\xe2\x2e\x4a\x6c\xc0\xdb\xfb\x7d\xac\x5b\xbe\x33\xfc\x9a\xc7\x55\xec\x36\xf6\x28\x5c\xfc\x4a\xe6\x7b\x9a\x9c\xe3\x71\x4f\xfe\xd6\x4f\xc9\xf5\x92\xeb\x36\xb2\xb1\xbe\x22\xc7\xd3\x3d\xc1\x59\x74\x0f\xcb\x87\xe4\x25\xf9\x33\xb9\x23\x7f\x86\xe0\xeb\x6b\x6c\x8c\x94\x22\xc0\x89\x4d\xed\xb9\x3c\xc8\xf9\x65\x92\x13\xf1\xfd\x92\x1a\x90\x47\xce\x2f\x63\xc0\x8d\x33\x2e\x72\x38\x0a\xec\xce\x30\x25\x68\x11\x42\xf3\xb8\x95\x8e\x08\x01\xed\x47\x3d\xf9\x8b\xe3\x18\x2c\xce\xe7\x68\x89\x8d\x97\x7e\x48\x4c\xef\xea\xa0\x25\xc2\x95\xdb\x79\x75\xd0\x22\xdd\x95\x23\xe7\x73\xc8\xb5\x5d\x78\x4b\xc1\x75\x67\xf6\xf8\x25\x6d\xbe\xba\xa4\x26\x5b\xf6\xcd\x1a\x3e\x15\xf2\xce\x5e\x89\x96\x7a\x9f\xe4\x12\x72\xcb\x51\xa4\xc1\x76\xaa\xcf\x5b\xf1\xc4\x40\xee\x7a\xf7\xe9\x7c\xbe\x79\x72\xd1\xab\x7a\x5f\x1a\x2c\x8a\x91\xd8\x07\xa3\x9d\xc6\x1a\x95\xcc\x5d\xe4\x8b\x96\x69\x17\x2f\xef\xf8\x47\xbd\x00\x18\x6f\x39\xbb\x81\xb3\x67\x74\x8a\x2d\x1e\x74\xaa\xdb\x5a\x86\x8c\x0a\x57\x74\x3d\x67\x4a\xc5\x1c\x7d\x49\x66\x6b\x40\xae\xf1\x8c\x45\x5e\x82\x08\x9b\x50\x29\x69\x64\x26\xd1\xa4\x1e\x7d\x70\x9f\x17\x06\xcb\x1d\xf3\x7c\xd5\xbe\x68\x7e\x3c\xbd\x3c\x24\xd7\x27\x97\x87\x44\x2a\x72\x75\x12\x83\xaf\xe9\x66\xee\x5e\x5c\x9f\x5c\xbe\x78\xb4\x45\x27\x21\x2e\x7c\x8d\xa2\x09\xea\xa5\x71\x6d\xc8\x39\x29\x69\x35\xb9\x61\x6b\x84\x57\x1d\xeb\xd3\x4f\x9a\x13\x94\xe0\x33\xdc\xc2\x96\xb4\x1a\x28\x4b\x31\x9a\xf3\x27\xca\xdc\xe0\x6f\x78\x3b\xc7\x4d\x0a\x07\x84\x4c\xd0\x3f\xa5\x5c\xb1\xdc\x05\xef\xe1\x37\x98\xc8\x2b\xc9\x71\x11\xeb\xc8\x04\xf1\xe9\x31\x32\x41\x7c\xde\x18\x99\x20\xfa\x63\x64\x82\x88\x90\x39\x32\x41\x8c\x4c\x10\x6e\x8c\x4c\x10\x23\x13\x04\x72\x8c\x4c\x10\x9f\x9e\xdc\xc8\x04\xf1\x6c\xb1\xad\x23\x13\xc4\xa7\xc7\x88\xf2\x1c\x99\x20\x46\x26\x88\xad\x31\x32\x41\x3c\xb6\x6b\x31\x32\x41\x8c\x4c\x10\x61\x8c\x4c\x10\x03\xc6\xc8\x04\x31\x6c\x8c\x4c\x10\x9f\x1c\x4f\xac\x36\x64\x64\x82\x18\x6b\x43\x3e\x57\xce\xd3\xab\x0d\x21\x23\x13\x04\x6e\x8c\x4c\x10\xc3\xc7\xc8\x04\x31\x6c\x8c\x4c\x10\xc3\x65\x8e\x4c\x10\xed\x18\x99\x20\x46\x26\x88\x67\x7a\x74\x47\x26\x88\x91\x09\x62\xf7\x18\xdf\x08\x46\x26\x88\x61\x63\x64\x82\xc0\x0b\x1d\xa3\x7d\xbc\x9c\xa7\x17\xed\x8f\x4c\x10\x23\x13\xc4\x27\x47\x8c\xeb\xa6\x98\x96\xb5\xca\x30\x26\xb2\x7f\xae\x4e\x64\x59\xd5\x86\x91\x0f\x41\x60\x63\xf7\x11\xdf\x34\x5b\xbb\x82\xab\x8e\x76\x7c\x0c\xd8\x74\x26\xc5\x9c\x2f\x6a\x05\xc5\xf7\x47\x25\x15\x74\xc1\x26\x99\xfb\xd0\x49\xb3\x72\x93\x66\x96\x47\xcf\x0a\x3a\x5d\xf0\x92\x63\x18\x24\xc8\xd6\xde\xbf\x05\x49\xed\xfb\x68\x04\xbc\xa5\xa4\x77\x10\x10\xd1\x52\xd6\xc2\xb8\x3a\x01\x58\x6f\xa4\xcc\x66\x97\xdc\x3b\xb7\x0d\x09\xdb\x43\x10\x01\x11\x78\x02\x47\x87\xa4\x70\xce\x5b\x2e\x8d\xcb\x68\x6f\xb9\xa2\xc6\x30\x25\x5e\x93\xff\xde\xff\xc7\x6f\x7f\x9a\x1c\x7c\xb3\xbf\xff\xc3\xcb\xc9\x9f\x7e\xfc\xed\xfe\x3f\xa6\xf0\x2f\xbf\x39\xf8\xe6\xe0\xa7\xf0\x87\xdf\x1e\x1c\xec\xef\xff\xf0\xf7\x77\xdf\x5e\x5f\x9e\xfd\xc8\x0f\x7e\xfa\x41\xd4\xe5\x8d\xfb\xd3\x4f\xfb\x3f\xb0\xb3\x1f\x3f\x53\xc8\xc1\xc1\x37\xbf\x46\x07\x87\x11\xee\x47\x1a\xe7\x23\x89\xeb\xf1\x00\x8e\x87\x47\x97\x24\x51\x0f\x1f\xbc\xac\x34\x0a\xc2\x67\x4c\xd2\x2b\x88\x60\xaf\xa0\x82\x38\xcc\x19\x9f\x84\x94\x25\x37\x86\xe5\x90\x32\xea\xd0\x8b\x60\x71\xe0\xdc\xf4\x9a\x71\x7b\x95\x0b\x05\x46\x68\x08\x34\xd7\x5d\x5c\x75\xa7\x52\x56\x9a\x25\x53\xb7\x1c\xfd\x1e\x64\x03\x24\xd1\x66\x33\x40\x09\x4e\x72\x36\xe7\x02\x9d\x20\x01\x27\x6e\xb0\xff\x36\xaa\xe1\x51\x0d\x0f\x91\xf2\x94\xd4\xb0\x66\x59\xad\xb8\x59\x9f\x48\x61\xd8\x1d\x22\x21\xd2\xd7\xc2\x57\x5e\x1c\x91\xf0\x37\xd8\x3a\xa7\x4a\xe6\xa1\xaa\x4d\xd5\x02\x4a\xd7\x23\x5d\xaa\xcf\xb9\xc7\x95\x2c\x78\xb6\x3e\x0a\x4b\x02\x17\x96\xdd\x99\xa3\x07\x8b\x01\x0c\xd5\x37\xad\xfa\x60\x13\x1b\xf9\xb5\x5a\x62\x6b\x1e\xcf\xca\xf1\x07\x4f\xf8\x52\xf1\x15\x2f\xd8\x82\x9d\xe9\x8c\x16\xa0\x1f\x53\xd8\xfa\xe3\x7b\x64\xe3\xdf\x87\x8c\x92\x85\x26\xb7\x4b\x66\x6d\x12\xa1\xf6\xdb\x21\xf5\x96\x51\xac\xd0\x05\xe5\x82\x94\xf6\x18\x54\x61\xa2\xf6\x36\x58\x8b\x85\x36\xf8\x15\x55\x4c\x98\x30\x39\x4f\x30\x34\x93\xb2\xf0\x25\x76\x68\xcc\x75\xb3\x02\xbe\x96\x58\xc8\x7f\x0a\x76\xfb\x4f\x3b\x73\xec\x5c\xe7\x05\x5d\x34\x9c\x65\x9a\x99\x00\xf6\x8a\xa9\xc8\x26\xee\x54\xba\x8f\x4f\x7c\x08\xa0\xa6\xaa\x66\x84\x16\xb7\x74\x0d\x47\x21\xcd\x7c\xb9\x7e\x4d\x5e\x1d\x80\x1a\xa3\x9a\x34\xf3\xcd\xc9\x57\xd8\x27\xf2\x25\xd5\xe4\xe4\xf8\xf2\x9f\x57\xff\x75\xf5\xcf\xe3\xd3\x77\xe7\x17\x31\xee\x84\x3d\x3d\x0c\x75\xc8\x33\x5a\xd1\x19\x2f\x38\xde\x8b\xd8\xc2\x5d\x76\x45\x46\x38\x85\x79\x7e\x94\x2b\x59\xb9\x3d\x54\xb5\x00\x5a\xbf\x96\xff\x06\x9b\x49\xee\x66\x0d\x3b\x0c\x81\xf6\x70\x63\x93\x91\xf3\xde\x27\x93\x85\xa2\xc2\x7a\xf3\x90\x99\x8a\x78\xed\xf6\xd0\x1c\x55\x0b\xc3\xcb\xe7\x5b\x7c\x4d\xf3\x54\x85\xd7\xc7\x79\xce\xf2\x14\xc7\xeb\x29\x16\x1e\x9c\x84\xcf\x8a\xa9\xb8\x21\x2d\x6b\x22\xb9\x7c\x7f\x75\xfe\x7f\xa7\x59\x2d\xe2\x57\x2c\xe6\x01\x2b\x01\x67\x8b\x92\x55\xa2\x93\xf4\xc1\xb3\x77\x8c\x67\xe9\xe7\xc6\x2f\xf4\x2c\x35\x9e\x5c\x0a\xcc\xd4\x87\x5a\x74\x74\x35\x9a\xc0\xa0\x9d\x13\x29\x65\xce\xa6\xe4\xd2\x39\x48\x4c\x27\x91\xd9\xa1\x8d\xa3\x8a\x11\x2b\x58\x18\x4e\x0b\xb4\xab\xc9\xfe\x55\xf3\x15\x2d\x98\x2b\xf0\x03\x0a\x87\x2e\x7f\x60\x02\xdb\x3c\xa7\x85\x8e\x32\x7a\x78\x9f\xc8\x3a\xa7\xef\x64\x2d\x52\xe0\x93\x1a\x59\x24\x67\x42\x9a\xa8\x7c\xa6\xfd\x2e\x20\x7c\x54\x32\x23\x2e\xa7\x19\x05\xc5\x0e\xd8\xbc\x8e\x53\x05\x0e\x1c\x9e\x34\x99\x38\x17\xdc\xef\xe3\x65\xf3\xed\xee\xed\xb7\xd6\x51\x9f\xbf\xe5\x12\xc5\x42\x59\xec\xf7\x2b\x46\x73\x60\xf2\xa9\xa8\x59\x3a\x9c\x5e\x49\xf5\x0d\x3a\xf7\x08\x62\x7c\x4c\xe7\xb3\xc4\x8e\x80\xa7\x59\x8c\x6b\xbc\xf2\x9b\x33\x6a\x6a\xc5\x5c\x54\xe6\x8a\x01\x99\xa0\xb3\x02\x8b\xac\x8e\x54\xa4\x76\xed\xde\x8b\x62\xfd\x41\x4a\xf3\xa6\x61\x5b\x49\x70\x69\xbe\xf7\x11\x7c\xff\x61\x37\x22\xd0\x02\x88\x5c\x3e\x81\x8d\x06\x65\x15\x4f\x0e\xe3\xcf\xb8\x3d\xee\x8f\xa8\xaa\x54\x2d\x8e\xf5\xb7\x4a\xd6\x48\xcf\x68\x2b\x78\xfb\xf6\xfc\x14\x34\x7a\x2d\x22\x82\x17\x26\x8c\x5a\x03\x13\x5a\x8a\xb6\x0f\xa4\x9b\x2f\xf8\x68\x4d\xe2\xc6\xfd\xc7\x2a\xaa\x39\xa9\x85\x66\x66\x4a\xde\xd1\x35\xa1\x85\x96\x21\xc9\x81\x36\xb9\x97\x80\xc8\xef\xa6\x62\xa7\x04\x98\x45\xd1\xc1\x25\x17\x64\x26\xcd\x92\x6c\x88\x8d\xa0\x12\xdd\x9e\x23\x30\x44\x45\x01\xe9\xdb\xce\x1c\x5c\x6c\x4e\x15\xab\xf1\xe9\x0d\xd3\xa4\x52\x2c\x63\x39\x13\x59\xd4\xfd\x4a\x84\x98\xf9\xfa\xf7\xd8\x1b\x7a\x21\x85\x55\x92\x09\xee\xe8\xb9\xc8\x79\x46\x8d\xcb\x42\x9a\x24\x09\x06\xc0\xea\xf9\xcc\x16\x05\xf2\x20\xab\x22\x91\x62\x6b\xcd\x14\xbc\x8a\x1a\x55\x33\x77\xb0\xfe\x5e\xcf\x58\xc1\x0c\x96\x6c\x91\x04\x06\x68\x6a\x1c\xb3\x19\x2f\xe9\x82\x11\x6a\x82\x1a\xc0\xe7\x98\x98\xd0\xd6\x9c\xc2\x4a\x72\x43\x72\xc9\x1a\x4a\x2e\x6c\xb2\x43\x93\x8f\xe7\xa7\xe4\x25\xd9\xb7\x6b\x78\x00\xfe\xc4\x9c\xf2\x02\xcf\xcd\x01\x55\x03\x1b\xfe\x0f\x9f\x87\xe9\x62\xad\xd7\xb9\xd7\x7d\x44\x2a\x67\xbe\x0e\x89\x90\x44\xd7\xd9\x32\xac\x35\x3e\x07\x1b\xd2\xc5\xbe\x02\x08\x70\x34\x5e\xc1\x22\x25\x36\x6a\xf9\x3e\x05\x8b\x5d\x5b\x27\x74\x97\x82\x45\xbf\x4f\xe6\xf7\x29\xd8\x28\x44\xe2\x13\x57\xb0\x91\x0e\xcc\x47\xcd\x54\x22\xff\xe5\xe3\x13\xf7\x5f\xba\x21\xae\xd5\x95\xed\xce\xe2\x1d\x04\xa7\x10\x4b\x66\x68\x4e\x0d\xf5\x7e\x4d\x2c\x87\xe8\xb6\x4f\x34\x5e\xbe\xa7\x79\xf9\x1e\xd3\xbb\xd1\xec\x2d\x17\xf5\x9d\x2b\x58\x49\xf5\x80\x74\x75\x06\x42\x49\x16\xb7\xc4\x70\x74\x69\x55\x15\x1c\x18\x25\x37\x6a\x28\xa2\x0c\x67\xb7\x51\x40\xbc\x72\x08\xe1\x0c\x18\x4e\x5a\x14\xd2\x3a\x78\x36\x66\xa5\x22\x97\x58\x24\xfb\xc6\x22\x42\xb2\x83\xf5\xda\xe4\x4d\xe1\x92\x63\xef\xda\xa8\x1a\x9e\x81\x6a\x78\xd4\x87\xbf\x82\xad\x18\xba\xaf\xc1\x66\xf7\x41\x2b\x8b\x70\x1d\x8e\x75\xc4\xeb\x01\x4c\x8b\x14\x74\xc6\x0a\xe7\xf9\x3b\x15\x91\xa0\x1e\x2e\x5a\xb9\x24\x79\x26\x53\xb2\x48\xc5\xf7\xf1\x41\x16\x50\x0c\x43\x13\x2c\xbb\x9d\xd6\x2f\x78\xd5\x41\x44\x9a\x55\xbf\x5e\x57\xc9\x56\x1d\x9e\x0c\x7e\xb9\xab\x5e\xa3\x03\x07\xb2\xb9\xea\x36\x06\x49\xb5\xea\xe0\xd8\xff\x32\x57\xfd\x96\x8b\x5c\xde\xea\xb4\x0e\xdf\xf7\x4e\x68\xb0\xa6\xd8\x32\x76\xcd\x8c\xe1\x62\xa1\xbb\x4e\x1f\x2d\x8a\x04\xa0\xa1\x5d\x5e\x9f\xc7\xc6\x62\x9f\x72\x42\xd3\xcf\x6d\xaf\x24\x32\xed\x52\x6b\x5f\x97\xd0\xf1\xa2\xb0\x3e\xe4\x76\xd2\x79\x97\x17\x15\xf1\xa6\x37\x7a\x51\x9f\x1a\x8b\x52\xd3\x13\x65\x3f\xc2\x70\x5a\x5c\x55\xd8\x1e\x26\x64\xf3\xe2\x7d\xfb\xee\xea\xb8\x2f\x38\x42\x3f\x71\xc0\x5a\x2a\x97\xa0\xb5\x92\x09\xcd\x4b\xae\x35\x3e\x8b\x68\xc7\x2d\x9b\x2d\xa5\xbc\x21\xfb\x01\x7d\xbd\xe0\x66\x59\xcf\xa6\x99\x2c\x3b\x40\xec\x89\xe6\x0b\x7d\xe4\x15\xd3\xc4\xae\x17\x16\x93\x09\x5f\x22\x0a\x2e\xfc\x9b\x2d\xc4\x4e\xc2\x68\x22\xf1\xed\x10\x49\xbb\x24\x59\xb3\xda\x70\xe2\x23\x44\xba\xc6\x6d\x0e\x60\xb8\x63\x23\x2f\xe2\xf8\x0b\x80\xf1\xf2\x51\xed\xfa\xf6\xa1\xbf\x88\x22\x54\xfd\xc4\xc1\x8f\x5c\x2f\xd7\x08\xc6\x91\x6d\xf8\x7c\xa1\xfd\x8d\x08\x89\x1b\x27\xc5\x27\x0b\x1f\x37\xac\x08\x89\xda\x84\x3b\x01\x09\x5b\x2f\x32\xea\xca\x36\x1e\x44\x9b\xfa\xed\x24\x71\x23\x44\x6f\xa6\x7f\x9b\x44\x6e\x84\xcc\x4d\x04\x72\x92\x34\x30\x79\xc0\x54\x30\xf9\xec\x74\x70\xc4\x0f\xf4\x1d\x96\x44\x5e\x00\xb9\x3f\xf5\x13\xa9\xd0\x1f\xcc\x71\x21\xc9\x9c\x17\x12\x77\xf1\x3d\x5d\x59\x92\x96\x7e\x57\x1d\x59\x84\x87\x27\x6c\xc4\x57\x85\x47\x6f\xbb\xa3\x8e\xb4\xb2\xa1\x82\x2b\xd6\x81\x78\x93\xff\x1b\x77\xd6\xfb\x2d\x60\x85\x74\xb5\xad\x1d\x26\x4b\x84\x4c\xdf\xd3\x2b\x27\xb5\x30\xbc\x08\x88\xa6\xb2\x2a\xac\xe7\xd2\x9b\x3d\x72\xc6\x20\xb1\xd3\x35\xf0\xb0\x59\x9e\x98\xe6\x86\x9e\x0b\xf4\x90\xfc\x4f\xad\x0d\xa1\x4d\x49\x51\x20\xb4\x83\x9d\x44\x08\x0f\x5c\x7b\x80\x8f\xf3\xad\x5c\x81\xcf\xde\x48\xfb\x11\x2b\x9e\x63\xa4\xe6\x7c\x3e\x67\xa1\xa8\x6a\xc6\x48\x45\x15\x2d\x99\x01\xb8\x2b\x16\x23\x31\x63\x0b\xee\x6a\x4e\xe4\x9c\x50\xbb\xa0\x7b\x7b\xba\x65\x49\xc3\xe8\x0f\xa8\x64\xe1\x86\x94\x7c\xb1\x34\x70\xc9\x09\x25\x85\x14\x0b\xe0\xc2\xc1\x41\x04\x0a\x49\x73\x02\xba\x5e\x2a\x72\x4b\x55\x49\x28\xc9\x68\xb6\x04\xec\x05\xea\x45\x36\xaf\x15\xb4\x23\x34\x8c\xe6\xeb\x89\x36\xd4\xd8\x58\x97\xb9\xba\x68\xb7\x73\x08\xa9\xd9\x16\x27\x8b\x3b\x03\x90\x71\x99\x31\x83\xe9\x0e\x1e\xe0\x90\x1e\x03\x19\xfc\xe1\xae\xb2\x89\x90\x3a\x2f\xe8\xe2\xa9\x91\x00\x8d\xdd\x33\xfd\x18\xbb\x67\x7e\xee\x18\xbb\x67\x7e\xf6\x18\xbb\x67\x8e\xdd\x33\xc7\xee\x99\x63\xf7\xcc\xb1\x7b\xe6\xc6\x18\xbb\x67\x8e\xdd\x33\x7f\x66\x8c\xdd\x33\x3f\x2d\x70\x64\xc6\x46\x8e\xb1\x7b\xe6\xd8\x3d\xf3\xfe\x31\x76\xcf\x7c\x6c\xd7\x62\xec\x9e\x39\x76\xcf\x0c\x63\xec\x9e\x39\x60\x8c\xdd\x33\x87\x8d\xb1\x7b\xe6\x27\xc7\x13\xeb\xa7\x31\x76\xcf\x1c\xfb\x69\x7c\xae\x9c\xa7\xd7\x4f\x83\x8c\xdd\x33\x71\x63\xec\x9e\x39\x7c\x8c\xdd\x33\x87\x8d\xb1\x7b\xe6\x70\x99\x63\xf7\xcc\x76\x8c\xdd\x33\xc7\xee\x99\xcf\xf4\xe8\x8e\xdd\x33\xc7\xee\x99\xbb\xc7\xf8\x46\x30\x76\xcf\x1c\x36\xc6\xee\x99\x78\xa1\x63\xb4\x8f\x97\xf3\xf4\xa2\xfd\xb1\x7b\xe6\xd8\x3d\xf3\x93\x23\xc6\x75\xd3\x26\xe7\x88\xb6\x29\x0f\xc3\x8b\xea\xd1\xb2\x1d\xae\x99\x59\x3d\x9f\x33\x05\x6e\x37\xcc\x14\x95\xb8\xd9\x4d\xd3\x3b\x0d\x65\x0a\x18\x99\xce\xf1\xd3\xcc\x1c\x02\x85\xab\x76\x85\xd3\x30\x45\x1c\xe0\xb1\x3f\x45\x4f\xb9\x03\xcd\x42\x14\xd3\xb8\xf8\x9a\x0b\x72\xf6\xfe\xcd\x34\x01\x25\x6c\x0c\x9b\x1a\xac\xc9\x7b\x91\xc5\x16\xeb\xb4\x87\x2c\x8e\xd9\x28\xb0\x1a\xf9\xb3\x96\x15\x52\x3b\x6c\xad\xdb\xbc\x6c\x49\x85\x60\x98\x02\x15\xa7\x10\xb9\x81\xb4\xdb\x8c\x31\x41\x64\xc5\x84\xc3\xff\x53\xa2\xb9\x58\x14\x18\x0b\x40\x8d\xa1\xd9\x72\x6a\xbf\x5f\x84\x03\xe6\xbb\xc9\x34\xb3\xc6\x5c\x35\xa3\x18\x2d\xdd\x41\x53\xac\xa4\xdc\x4d\x97\xd0\x4c\x49\xad\x49\x59\x17\x86\x57\x11\x13\x26\x9a\x41\x99\xb5\x76\x35\xff\xe1\x10\x10\xd4\x75\xd3\xcc\x81\x3d\x81\xbb\xb3\x59\x03\xbf\xbc\x28\x17\xac\xbd\x6a\x10\xc0\x1f\x42\x23\xc1\xb2\x32\x6b\x57\x10\x85\xbc\xc0\x73\xae\xb4\x21\x59\xc1\x21\x82\x83\x75\x60\x60\xc9\x60\xce\x18\x04\x30\x15\xb9\x95\x2c\xfc\x1e\x69\xbf\x49\x22\x07\x07\xb4\x42\x39\xfc\x50\x96\x13\xea\xbe\x58\x98\x6e\xce\xb5\x0f\x28\x34\x6a\xa2\x81\x4d\xdd\x5d\xae\xb0\x47\x70\xbd\x72\x24\x2d\x70\xf8\x66\x2f\xa4\x33\xe5\x88\xfb\x0f\x04\xe8\x3e\x2b\xde\x98\x00\x47\x5d\x1e\x14\x24\xea\xfb\xb7\x8b\x71\x03\x19\x2e\x18\x08\x84\xc8\x8e\x49\x81\x6b\x2a\xd8\xca\x5a\x2f\x96\x31\xbe\xb2\x4e\x38\x42\xe4\x4e\x7b\xf0\x45\xcd\x81\x61\xaa\xe4\x02\x8a\xb6\xde\x31\xad\xe9\x82\x5d\xa2\x5e\xbf\xef\x8b\xad\xe1\x01\x3c\x1c\x46\xf4\x35\x2e\x20\xc0\x6e\x9d\xdb\xb6\x04\x61\x0f\x55\x1e\xda\x7e\x34\x29\xdd\x57\x37\xbc\x28\xb7\x8a\x1b\xc3\x50\x8e\x8d\x76\xdd\x16\x00\x38\xb4\xc9\xc4\x83\x9b\x68\xa7\xbc\x82\xbc\x0b\x13\x75\x13\xb4\x3f\x67\x9d\x54\x91\xa3\x72\x5c\x0e\xe5\x34\x53\x9c\xcd\xc9\x9c\x43\x15\x03\xe0\xed\x0f\x1d\xbb\x2f\xc5\xcc\x96\x0a\x42\xb5\x66\x0a\xd6\xd5\xe3\xad\xc3\xfa\x4e\xc9\xf7\xe8\x3a\x53\xa3\x6a\x91\xd1\xb6\x57\x16\x11\x32\x67\x84\xcf\xc9\x02\x90\xfd\x18\xad\x03\xbd\xf9\x7e\xff\xf2\x4f\x5f\x93\xd9\xda\x06\x1a\x80\x65\x31\xd2\xd0\x22\x4c\x18\x21\xb4\x60\x62\x61\x4f\xbb\x33\xd9\x7d\x4a\xa1\x88\x32\x5b\xe8\xaa\xee\x6a\x5f\x5f\x7d\x75\x33\xeb\xc5\x64\x08\x89\x47\x39\x5b\x1d\x75\x6e\xc0\xa4\x90\x8b\x4e\x33\x7c\x84\xc4\x50\xaa\x89\x2d\x54\x44\x85\xf9\x3b\x14\x17\x74\xf4\x8c\x54\x5d\x81\x38\x9d\x2c\xe5\xad\xeb\xa6\xd2\xfe\x0e\x62\x69\x82\x76\x69\xeb\x0e\x2b\x59\xd5\x85\xab\x6c\x7d\xc3\x51\x0e\x1d\x68\xaa\x5a\xb3\x4d\xee\x99\x7b\x74\x39\x4e\x39\x84\x69\x6e\x04\x42\x4e\x49\x44\x2c\x84\xf4\xc4\x0d\xfe\x75\xa9\x61\x3e\xaf\x15\xaa\xf2\xf1\x0d\x2d\x8a\x19\xcd\x6e\xae\xe5\x5b\xb9\xd0\xef\xc5\x99\x52\x52\xf5\x56\x08\x73\x8f\xa9\xf5\x1a\x97\xb5\xb8\x71\xcd\xc0\xc3\xc7\x17\x72\x41\x64\x6d\xaa\x1a\x15\xfd\xcd\x37\x8f\x53\xb3\x26\x73\xdc\x39\x68\x5c\x64\xef\x94\x76\x66\xca\xee\x38\xee\xe9\xe3\x96\x5b\x05\x26\x08\xb3\xeb\xe8\xb4\x62\xfb\xd5\xb8\x60\xa1\xa3\xbe\xbe\x7a\xf9\xfb\x3f\x3a\x85\x4b\xa4\x22\x7f\x7c\x09\x45\x99\x28\xf7\x16\x5c\x01\xf0\xbf\xb8\x26\xba\xa4\x45\xc1\x54\xac\x62\xb4\xd7\xb1\xa3\x08\x1b\xb5\xf6\x45\xb5\x9a\x89\x55\x60\x0f\x98\xfc\xb9\xbe\xfe\x2f\xc8\xfc\x70\xa3\x59\x31\x47\x79\xe5\x85\x96\x6d\xbf\xa3\x3d\x70\xa6\xf7\xbc\x2f\x62\xa3\x49\x8c\x0a\x78\xdc\x74\xca\x4a\x16\x75\xc9\x4e\xd9\x8a\x67\x98\x67\xad\xde\xd6\xf5\x64\xe1\x2b\x9f\x0b\xae\x81\x90\x7e\x56\xc8\xec\x86\xe4\x5e\x5c\x0b\x6b\xc7\x78\x21\xeb\x58\x5e\xc9\x98\x22\x04\x74\xf1\xc1\xbd\xab\xdb\x96\x0e\xa0\x12\xbc\x94\x94\xb4\xaa\x1a\xd2\x0f\x45\x6f\x7b\x8b\x8d\x92\x69\x35\x2f\x17\xdd\xb8\x15\x73\x19\x22\x1f\x87\x63\x9e\x86\x27\xfe\xeb\x91\x3e\x07\xba\x2e\x21\xf6\x55\xb9\x9d\x35\xf6\xe1\xab\x77\xcc\x5a\x71\xb1\xdc\x05\x15\xc8\x70\x45\xeb\x89\xfa\x4b\x74\x98\x91\xdc\x3c\x9b\xb0\xd7\x1e\xe8\x08\x56\x31\x23\xb1\x8f\x8e\xd1\x2f\x7d\x31\x55\x20\xbd\x9d\x13\xcd\x9b\x6a\x49\x0d\x2a\x59\xe1\x46\x97\xe4\x8f\x92\x8a\x29\xcd\xb5\xf5\xd1\xbf\x03\x05\x74\x52\x50\x8e\x7d\x38\x6b\x1e\x4f\x2a\x89\xdd\xaa\x88\xe5\x76\x0a\x14\x9a\x13\xc6\x5a\xba\x4b\x99\x7b\x71\x60\x98\x20\x6d\x82\x7a\x51\xd9\x4a\xb3\xc4\x52\x52\x24\x73\xff\x1e\xd3\xd4\x7d\xd7\xee\x54\xbc\xa5\xb3\x52\x1a\x53\xe7\x24\x7b\x63\x85\x94\xf8\x7c\x0d\x1c\xac\xc5\x73\xb3\x6f\xcd\xa4\x93\x28\x49\x30\x6c\xde\x57\x89\x31\x6e\x6d\xac\xda\xbe\x54\x2c\x99\x57\x0a\x68\xa9\x6d\x9a\xc5\x67\x62\xa7\x1e\x2c\x2a\xd0\x9d\xea\x9a\xa9\x92\xbd\xd7\x7b\x8f\x66\xe4\xdc\x26\x2a\x59\xd1\x05\xe4\x0e\x92\xec\xe5\xa6\xd0\x08\x84\x97\x4b\x6b\x30\x0d\x69\x33\x90\x8b\x65\x42\x74\xa3\xf2\xb3\x62\x79\x4b\x81\xbe\x94\xc0\xb0\x90\xe2\xc8\xf9\x84\x89\x23\x6e\xbc\x8d\xa8\x8b\xa6\x4a\xd6\x22\xf7\xaf\xc1\x0d\x04\xe1\xdd\xc6\xc2\x5e\xe0\x19\xcc\x20\xcd\xe3\xb8\xda\x81\x08\xcf\x15\x4a\x72\x8d\x25\xc3\xf3\x32\x05\x79\x35\x7d\xf5\xf2\xf9\xfb\x6c\xb0\x26\x89\x7c\xb6\x8b\xc6\x67\x73\x56\xee\xd1\x56\x27\x34\x4c\x4e\xb2\x42\xef\xfc\x93\x54\xd3\xd9\x18\x7f\x68\x42\xb7\x4e\x10\x75\xab\xb8\xf1\x37\xe8\x96\x47\x14\xaa\xed\x43\xd2\x86\x48\xd5\xa5\x20\x3e\x68\x73\x79\x11\x21\x49\x4c\xc7\xe5\xf8\x96\x85\x84\xe8\x7a\xf6\xe4\xec\xae\x33\xb0\x4e\xa9\xee\x7a\x4f\xc5\xaf\xb7\x97\xbc\x6d\x82\xd1\x12\xbb\xd8\xc3\x17\x2f\xc8\xbe\xfb\x85\x3d\xc7\x66\x77\xf0\x68\xd7\xd3\x6f\xeb\xd9\x5d\x85\x6e\x2a\xd3\xdb\xda\xb3\xbb\x8a\x8a\x9c\xe5\x2e\xe0\x8f\x70\xad\x49\x20\x9d\xde\xb5\xc7\xf1\x66\x73\x4f\xf7\xf7\x18\x2d\xb1\xeb\x9e\xfd\x95\x2d\xe9\x8a\x01\xe7\x1f\x2f\xa8\x8a\x50\x4f\x46\x92\x2b\xb7\x33\x64\x56\x1b\xc2\xc4\x8a\x2b\x29\x4a\x16\x41\xec\xbe\xa2\x8a\xd3\x59\xc1\x88\x62\x40\x1c\x9c\x31\x4d\x7e\xbd\xff\xdd\xf1\x07\x80\x59\xe3\xdb\x47\x50\xc5\x08\x0b\xbb\x5e\x6b\x28\xcf\x4d\x74\x0b\x3b\x9f\x3d\xdd\xb8\x40\x78\x15\xbd\x71\xf1\xc2\x3a\xdb\x1b\x80\x5f\x03\x91\x37\xfb\x65\xd7\xa3\xac\x4d\x4d\x0b\xa0\x7d\xcc\x8a\x5a\xf3\xd5\x63\xd8\x5f\x4f\xc3\x79\xca\x11\x37\x7b\x83\xbe\xb4\xbd\x34\x5b\xdc\x9e\x48\x0a\x6f\x70\x2f\xd3\xb5\x94\xf4\xc0\xcb\x3d\x1d\x8a\x55\x7a\xad\x81\xd0\x8f\x72\x9e\xb6\x7a\x06\x93\x9b\xf3\x45\xad\x1c\x91\x0e\x4e\x05\x75\x9a\x59\x97\x80\x22\x79\xac\xe7\x39\x21\x73\x36\xb4\xa5\x45\xbf\xf0\xc5\x0b\x70\x54\xd6\x1d\xc2\x38\x9d\x2d\x59\x5e\x0f\x7c\x01\x76\x74\xee\x32\x27\x52\x18\x49\x68\xd3\x12\x0b\xe6\x09\x30\x3a\x3e\xf8\xb9\x56\x48\x31\x81\x07\x65\x77\xb6\xc2\xbc\x54\xe0\x63\x0d\x7f\x31\x4c\x6a\x7f\xa6\x90\x7e\xb6\x73\x3c\x24\x54\xeb\xba\x74\xaa\x6f\x20\x67\x28\x37\x64\xce\x0d\xe0\x06\x65\xad\x32\x16\xb2\x3a\x56\xe9\x0d\xe2\xc9\x42\x9f\x84\x2b\x56\xc0\x55\x46\x9f\x86\xbd\x8b\x8e\x14\x77\x24\xb4\xff\xd3\xa0\xa5\xf0\x57\xce\x17\x02\x01\x0a\xb9\x29\x06\x96\xf0\xe6\x3e\xe7\xc3\x16\x57\x0a\xe8\xee\x6f\x4f\x51\x33\xbf\xce\xaf\x40\x98\x45\x86\x45\x9e\x56\x1a\xb0\xe2\xd3\x19\x2b\xf4\xe6\x04\x67\xed\x51\x1b\xe6\x52\x00\x25\x8e\x3f\x4e\x83\x0b\x49\x82\x72\x82\xf8\xfc\x88\x6a\xcd\x17\x62\x52\xc9\x7c\x62\xa5\x1d\x0d\x41\x32\x21\x33\x92\x34\x0f\xfc\xc1\x97\xc8\x04\x1f\xea\xf4\xca\x15\x53\x4b\x46\x07\x25\x40\x37\xb0\x9d\x5e\x02\x51\xac\x52\x4c\x03\xf8\xc8\xf1\xdf\xb9\xdb\x38\x6c\x0f\x83\x30\xaa\xb5\xcc\x80\xbf\xc2\x61\x50\x54\xed\xba\x2a\xd0\xc1\x6f\x1d\xf6\x78\x51\xb2\xe0\x2b\x26\xc8\x07\x67\xe3\x4e\x0a\xaa\x75\x2f\x81\x32\x18\x8d\x37\x63\x84\xd6\x46\x36\xe8\x2d\x42\x4d\xdb\xbb\xcc\x81\xac\x67\xc3\x7c\x57\xbb\x66\xdd\xf9\x75\xc4\x59\xab\xa7\x24\x60\x5a\x06\x89\x3c\x9f\x7f\x9e\xd4\x61\xda\x56\x87\xce\x09\x87\xed\x76\x95\x3e\xa9\xda\xf6\xf9\x19\x24\xf3\x52\xe6\x24\x03\xf0\x66\xb0\x84\x1e\x82\xd9\x9d\xfa\x20\x89\xbb\x3e\x33\x54\x53\xd8\x9b\xd9\xf9\xc9\x41\x72\xc3\xf4\xbc\x0e\xb4\xc1\x8a\x4b\x1d\x36\x07\xb7\x50\x8c\xe6\xc3\xb6\x5e\x33\x03\x36\xba\xb7\x51\x0e\xae\x13\x3c\xa6\xa1\x08\x7d\x67\x3d\x1a\x57\x0b\x5a\x19\x55\x2c\x3b\x24\xcd\x75\xc5\x1c\xf9\x50\xe8\xd1\x74\x32\xca\xd9\x9c\x8b\xf6\x57\x32\xa9\x14\xd3\x95\x14\xf9\x50\x5f\xbb\xfb\xe9\x87\x6d\x1a\xc9\xda\xf6\x4e\x0d\xcc\x20\x91\xb5\xb0\xd3\x85\xdc\x6e\xcb\xf8\xfd\x6f\xa6\x64\xd7\x38\x0c\x92\xd8\xe9\x27\x38\xbd\xf9\x23\x58\x11\x26\x96\x54\x64\xce\xd5\x38\xba\x61\x95\x3e\xd2\x7c\xe1\x8c\xc6\x57\x2f\x5f\xfd\xe9\xe5\x57\x5f\x7d\x0d\x66\x24\x9c\x8f\x69\x39\x6c\x1f\xfb\x49\x5e\x5a\x54\x4b\x3a\x71\xad\xa8\x29\x60\x3c\xff\xde\xd8\xb4\x41\x62\x57\xaf\xa6\xaf\xbe\x3e\x24\x9e\x60\x1f\xba\x6a\x2c\xa5\x90\xca\x61\xaa\x1d\xa1\xdc\x50\xbf\x8e\x1a\xaf\x18\xc2\x81\x6b\x8e\x9a\xef\x8d\x32\x08\x10\xfc\x68\x66\xb4\xa2\xc6\x30\x25\x5e\x93\xff\xde\xff\xc7\x6f\x7f\x9a\x1c\x7c\xb3\xbf\xff\xc3\xcb\xc9\x9f\x7e\xfc\xed\xfe\x3f\xa6\xf0\x2f\xbf\x39\xf8\xe6\xe0\xa7\xf0\x87\xdf\x1e\x1c\xec\xef\xff\xf0\xf7\x77\xdf\x5e\x5f\x9e\xfd\xc8\x0f\x7e\xfa\x41\xd4\xe5\x8d\xfb\xd3\x4f\xfb\x3f\xb0\xb3\x1f\x3f\x53\xc8\xc1\xc1\x37\xbf\x1e\xa6\xe0\x86\x97\x66\xc7\x94\x63\x47\x94\x60\x27\x2b\xbb\xae\x14\xb3\xf1\x08\x97\x62\x38\xb4\xbb\x9f\x3c\xdd\x10\x14\x5a\x31\xba\x3f\x0d\xf6\x2e\xc2\xbc\xc4\xc2\x3a\x27\xda\x39\x2c\x85\xbc\x85\x52\x23\x2e\x15\x37\x03\x43\xfc\xf7\x02\x1e\x1e\x2e\xd8\x8a\xa9\xc3\x30\xdb\xb7\x56\xe0\x65\x90\x87\xcb\x87\x1b\xb9\x53\x9a\x6f\xf8\x67\xad\xd0\xe0\x3e\x4d\xbb\x75\xd3\xb6\x5e\x19\x66\x6a\x1a\x1d\xb4\xa5\x57\x2e\xa4\xb8\x6c\xd6\x3b\x7c\xc0\xb0\x19\x7b\x6d\xf4\xd0\x81\x61\xd8\x7b\xf4\x31\xbd\x86\xb2\x7d\xbf\x45\x60\x6f\xa7\xe4\x3b\xaa\xb8\x1c\x88\xb8\x77\xe8\x17\xe8\x1f\x27\x05\xf8\xe7\x0e\x0b\xdf\x58\x16\x08\x0b\x07\x3a\x18\xa6\x3b\xb9\x86\x7c\x23\x3c\x7d\xa2\x36\xe6\xb8\xf1\xd9\x4e\x5a\x9f\xad\xeb\x6e\x72\x63\xef\xda\xca\x7e\xc2\x30\x4f\x40\xdb\x93\xe4\xea\xf5\x5c\xb3\xef\xce\xd7\x3b\x47\x13\xd7\x77\xb8\xe3\x5b\x86\x48\x40\x77\x17\x16\x7e\x32\xac\x05\xf8\x36\x17\x74\xe8\x43\x22\xb0\xea\xf2\x45\xa8\xad\x86\x73\xe0\x32\x32\x9d\xbf\xc5\xe8\x19\xac\x31\xc0\xd1\x19\x54\x9b\xab\x80\xbe\x16\xfd\x7e\x8b\x4d\x5b\xc8\xc1\x19\xc5\x4a\xe6\x7b\xba\x5d\x39\xf2\xc2\xdd\x13\x70\xde\x26\x99\xe2\x86\x67\xb4\x18\x96\x25\xb7\x7a\x2f\x88\xc9\x8a\x5a\x1b\xa6\x5a\x49\x90\xd6\x36\xb7\xc3\x00\x0b\xf0\xa5\xb4\x20\x37\x6c\x7d\x2b\x55\x1e\xe2\x8e\xf0\xd5\xed\x39\x18\x48\x4a\xe3\x3f\x9b\x33\x6f\xae\x5c\x5b\x34\x55\x32\x45\x66\x2c\x3c\x40\x44\x08\x5e\x4f\xc9\xb1\x58\x7b\x44\x85\xe8\xb2\xd3\xf8\x90\x61\xa8\x3d\x80\x58\xcd\x65\x00\x7a\x17\xca\xbb\x88\xf0\x15\xc3\x1d\x56\x3b\xb3\xe9\x3d\xc9\xf4\x4a\xe6\xcd\xd7\x0c\x4b\xc2\xf9\xbc\x79\xc8\xa3\x4b\x45\x5c\x67\x20\xd0\x92\x8a\x39\x7a\x8a\x41\x22\xbd\xa8\x07\xb7\x59\x36\x76\xe5\x82\x69\xfd\xad\xbd\x52\xf8\xa4\x50\xff\x8e\x52\x08\xe0\xbc\xe4\x41\xdf\xbd\x80\x9b\x1d\x16\x94\x59\xe5\xe7\x40\x40\xd6\xed\x92\x79\x2b\x75\x98\x4e\x3d\x86\xff\x18\x4a\xcd\x69\xbe\x76\x1d\x36\xed\x24\xb9\xe9\xd4\xc8\x0c\x4c\x38\x28\xe6\xa5\x1d\x5f\x9c\x86\x62\x4f\x17\x8b\x68\x64\x9b\xe6\xa6\x91\x84\xff\x46\xbf\x1a\x90\x73\xf0\xdd\xb0\xd8\xbf\x6a\x3a\x2c\x8a\x37\x92\xbc\xb8\x56\x35\x7b\xb1\x2b\x43\xfa\xe9\xc0\x96\x99\x5b\xa9\x6e\x8e\x5e\xbe\x7c\xf9\x07\x88\x6b\xe1\x93\xff\xd7\x57\x7f\xfd\x5f\x5f\xfd\x75\x5a\xe6\xc3\x03\xbc\xa1\xb0\x58\x04\x20\x76\x13\x69\xfc\xa1\x7b\xc6\xc3\x76\x0f\x7d\x61\x75\x1b\xe3\x5f\x81\x81\x70\x0c\x8e\x54\xb3\xe7\x88\xcc\x2d\x02\xc4\x8a\x83\xaf\x4e\xda\x69\x5e\xaf\xab\x81\x46\x13\x8d\x3e\xed\xfd\x66\xfc\x73\x6a\x2b\xcb\xed\x03\xaa\xee\x5f\x3a\xf8\xb1\x93\xd5\x01\xd3\xef\x69\xe4\x4e\xba\x01\x15\x57\x60\x56\xe1\x79\x04\xcc\xe9\xba\x42\x57\xa2\x0d\xd6\xe1\x40\x9f\x11\x19\x23\xef\x7d\x70\x62\x48\xe5\x42\x64\x48\xa3\xf7\x4a\xd8\x07\xda\xc4\x00\x55\x72\x51\x82\x0f\x71\x8f\x81\x43\xe9\x90\xbc\x17\x6f\x5c\xd1\xef\xb0\x77\x66\x88\x90\x5b\xc6\x0c\x23\xbd\xc0\xa4\x3c\x62\x47\xbf\xf2\x2b\x3a\x71\x4b\x31\x5c\xc9\x0d\xdd\xc0\x4e\x2e\x34\xca\x53\xde\xfb\xb0\x21\xc9\x5f\x95\xa1\xa8\x59\xda\xcf\x4c\x7b\x8f\xcb\x6f\x27\x3c\xb7\x39\xa3\x31\xcc\xb4\x2b\x59\x57\x87\xde\x9f\x6d\x51\x62\xa1\xad\xb7\xaa\xc5\x70\xf6\x2f\x38\x5a\xce\x9d\xeb\x4f\xb9\x79\x1a\x86\x0b\x39\xf8\xc9\xda\x15\xf0\xe4\x24\x73\xe9\xe9\xe0\x1d\x3a\xda\x17\xf7\xea\xa1\x6a\x31\xf8\x71\xc6\x65\xa8\xa5\x22\x9d\x67\xf6\x17\x05\x5b\xd0\x6c\xfd\x02\xff\xf4\xd1\x83\x6d\x84\x78\x41\x13\x2a\x80\xbe\x96\x67\xdc\xb8\xef\x18\x7c\x7f\xa1\x10\x1c\x2a\xcc\xc1\x87\x77\x4a\x13\xdc\xe8\x5a\x23\xe2\xaf\xe0\x1e\x07\xc6\xaf\x25\x15\x39\x94\x6d\xa3\x1c\x13\x99\xb3\x23\x2f\x69\x02\x9f\x87\xca\xb4\x37\x7d\xc5\x9b\x7e\xde\xd1\x69\xf6\xdf\x23\xd2\xde\x03\x15\x46\x03\xcd\x48\x18\x57\x77\xcf\xf8\xd0\x67\xa2\x9c\xeb\x0a\xee\x99\x7b\x4d\x08\x42\xdb\x79\x0e\xbe\x29\xf7\x84\x67\x4d\xa4\xd5\xfc\xe0\xd0\xb0\x32\x1c\x42\xd4\xd4\x70\x9b\xc5\xb2\x1a\xa2\x57\x29\x0c\xbb\x1b\xc4\xa3\xdb\x57\xee\x57\x7d\x41\x64\x29\x8b\x1c\xa0\x35\x2e\x09\x3b\xf0\xb9\xd0\xc9\x22\xd4\x18\xc5\x67\xb5\x8d\x33\xa8\xc8\xa1\x0b\xb3\x7f\x43\x1d\x8e\x2b\xf3\xb9\x36\x3d\x25\x2d\xff\x53\x17\x82\x08\xba\x64\x4a\xc8\x15\x1b\x08\x76\xb2\x4e\x5f\x67\x2d\xc0\x37\x09\x1b\x09\xf9\x31\x7b\x67\x07\x89\x64\x34\x5b\xfa\x74\xe0\x17\x78\xa4\xc2\x3a\xd1\x73\xfd\xad\x35\x9a\x43\x9d\xe7\xde\xb1\x79\x71\xdc\xe4\x94\x74\x5d\x79\x3a\xf3\x81\x31\x24\x09\xe6\xdb\x69\x7f\x5a\x55\x05\x77\x95\x9b\x11\x1e\x22\x71\x11\x2f\x75\x46\xfc\x4a\x96\x0d\x70\xd9\xae\xb2\x76\x7d\x10\x87\x7b\xd0\x4b\x06\xca\xbb\x70\x2f\xd7\xd9\x12\x48\x97\xe1\xc5\xfe\xd6\x4e\x71\xc9\xab\xc1\x32\x21\xdb\x4d\x4d\x33\x3d\xc0\x2c\x59\x71\x81\x90\x6a\xb0\xc4\x4a\xe6\xaf\xc9\x3f\x04\x79\xe5\x92\xd1\xf2\x16\xb0\x2e\xdf\x9e\x9f\x06\x0d\x87\xfa\xee\x37\x57\x70\x5c\xc8\x57\x4e\xaa\x66\x66\xc1\x73\x32\x73\x5d\xd0\x35\x1b\x8e\x83\xde\x17\xec\xd6\xd5\xd3\x7a\xe8\x44\xf3\xf0\xbf\x0a\x75\xa0\x08\x52\xab\xee\xe2\xf9\x29\x1f\x90\xdf\xb9\x39\x57\x4c\x61\xf2\xf2\x20\x96\xbb\x9a\x33\xf2\xfe\xc3\x5e\x00\x11\xdd\x4e\xd4\xed\x64\x32\x99\xd8\xb5\x3e\x1f\xa6\x21\x48\x40\x14\x1c\xf6\xce\x54\xe3\x02\x96\x32\xe7\xf3\xe1\x68\xf5\xde\x49\x04\x95\xdb\x7e\x32\x78\x1e\x54\x0c\x17\xea\x76\x63\x3a\x14\xe1\x1d\xc3\x74\xdc\x79\x14\xf8\xfa\xf7\x18\xa5\x76\x02\x37\x13\xc7\xd9\xd5\xb7\x8b\x3b\x04\xfa\xa4\xf3\x70\x85\x34\x63\x4b\xba\xe2\x12\xf8\xb8\x41\x77\x40\xe5\x73\x77\xbf\x86\xdf\xf5\x66\x7f\xc3\xb3\x99\xbf\x3c\xbe\x99\x13\xa4\xdf\x07\x4b\x65\x77\x95\x74\x2d\x4a\x81\x1f\xe2\x52\xe6\x71\xf8\x36\x02\x80\xca\x62\x0d\xca\x7d\x6d\x75\x5c\x4f\x19\xfb\xa8\xcd\x35\xd5\x18\x2c\xd8\xef\x10\x99\x51\x3b\xe5\x66\x39\xf7\x37\x8e\x3f\xa2\xa4\xe7\xdc\xdf\x48\xc8\x91\x0a\x49\xd8\x7c\x6e\x43\x55\x29\x08\xab\x96\xac\x64\x0a\x61\xe9\x7a\x1f\xee\xd9\x10\x5f\x5b\x8f\x49\x59\x65\xe0\x30\x5a\x25\xad\x86\x1f\x2e\xfb\xb9\xe0\x03\xe5\x5c\x4d\xc9\x77\xb4\xe0\x79\x70\x5f\xac\xde\x7a\xf1\x5e\x7c\x90\xd2\xbc\xe3\x1a\x82\xd6\xe1\xf5\x1a\xf0\x1a\xe5\x12\x22\x2f\xb6\x1f\x39\xf0\x3d\x29\x8c\x6c\xc5\x0e\xe5\xf8\x43\xa3\x48\x54\x2d\x8e\x13\xb8\x3f\xd6\xa8\x58\xbb\xda\x64\x18\x18\x61\xc2\xa8\x75\x25\x39\xa2\x30\x68\x93\x86\x25\x50\xcb\x4e\xc9\x47\x1b\x11\xfb\x78\x14\x91\xeb\xf4\x14\x56\x0d\x2c\xe3\x1d\x5d\x3b\xb2\x2c\x07\xc2\xc3\x38\x56\x1b\xe1\x82\xcb\x93\xf8\x7e\xd5\x33\x89\xe0\x30\xd8\x8c\x3f\xec\x71\xbb\x84\xee\x68\xdd\xbf\x1e\x5e\x38\xd2\xa2\x0b\xdb\xb3\xba\x3d\xff\xe1\x62\xe9\x0d\xd3\xa4\x52\x2c\x63\x39\x24\xed\x1d\xee\x9c\x1a\x3c\x01\xc5\xe3\x18\x4c\xb8\x09\x17\x12\x94\x43\xd4\x5d\x38\xef\x3c\x9d\x7b\x16\x20\x7c\x01\x11\x3c\xef\xda\x2b\x45\x35\x14\x0c\x88\x89\x92\x12\x32\x43\xca\xd1\x38\xab\x1a\x41\xdc\xbc\xe5\x6a\xad\xac\x96\x0c\x0f\xdf\x50\x03\x34\x5c\x2d\xb6\x29\x27\x1b\x84\x0a\x5d\x2b\xe6\x56\x80\x1b\x92\x4b\x84\x97\x60\xf5\xaa\xff\xf4\x8f\xe7\xa7\xe4\x25\xd9\x87\xc2\xb8\x86\xcc\x12\xc3\x52\xe0\x92\xef\x7d\xed\xc2\xe7\x61\x8a\x53\xb4\xfb\x4a\xa4\xf2\x2c\xda\xd6\x3e\x82\x39\xf3\x6b\x8a\x71\xb2\x43\x02\xc6\x37\x1e\x64\xf9\xa8\xaa\x1e\x40\x55\xe1\xf4\x12\xa6\x54\x1d\x74\xcb\x47\xcd\x06\xd7\x3b\x6e\x19\xd9\x8f\x5f\xc0\xc8\xa2\x39\x01\x5c\x33\x5d\xd5\xdf\x35\xd0\x26\xa4\x64\x86\xe6\x14\xc1\xa5\xe1\x8c\x75\x10\xb8\x75\x0f\x30\x6d\x47\x3e\x75\x0f\xa2\x0f\xda\x3d\xf7\xa0\x3d\xd7\xc3\xd5\xd6\xcf\xdc\x03\x77\xae\x87\x07\x4c\xcf\xdf\x64\x6b\xf6\x96\x8b\xfa\xce\xa5\x41\x07\xbf\x9c\x6f\xdd\xad\xab\x33\x10\xe7\xc8\x9e\xef\x50\x24\x38\x33\xe6\xd3\x76\xf9\x76\xda\x6e\xea\xdf\xa6\x9a\x7c\x3b\x4a\x2f\x6e\x35\xf4\x09\x5d\x73\x1c\x7f\xec\xf0\xb3\x4a\x14\x15\xb9\x2c\xb7\xbe\xde\x1e\x0a\x46\x11\x64\x2f\x9d\xde\x6e\x3b\x6e\xeb\xce\xdb\x37\xfc\x3e\xdc\x7f\x5b\x9f\x9b\x15\x4a\x76\xfb\x50\x6c\x6d\x31\xb4\x67\xf0\x1e\x12\xcd\xa2\xf7\x16\xa0\xed\x5c\x37\x07\x70\xf8\x33\x4b\x33\x21\x3a\x63\xc5\x56\xf2\x3c\x92\x52\x37\x92\xca\x44\xc9\x02\xc5\xc1\xd4\x5b\xa3\x0f\xb2\xf0\x15\xed\x61\x91\xac\xd8\x5f\xcc\x1a\x19\x14\x74\x69\x53\x83\xaf\xab\x8d\x35\x32\x43\x51\x58\x61\x3c\xc5\x35\xaa\x11\xde\x23\xd9\x5c\x23\xeb\x82\xf6\xd7\xc8\x8a\xfd\x45\xac\x51\xf7\xd5\x0d\xf2\x59\x71\xfe\xc0\x71\xc3\xef\x0d\x2f\x72\x3a\x98\x75\x8c\x4f\xdc\xf6\xc8\xf2\x2e\x36\xb8\xef\x5c\xb8\xe7\xd1\x66\xb9\x86\x5b\x28\x2e\x9a\xc2\xbc\xad\xc5\x77\x18\xfc\x92\xaa\xe1\xef\x1c\xdf\x9e\x9f\x4e\xc9\xa6\xb3\x62\xc3\x5a\xbf\x14\xd8\xe7\x28\x9a\xe7\xde\x2f\x12\xeb\x58\x63\x87\xe1\x7d\x45\xb2\xbe\xc6\x75\xaa\x8c\xf0\x6e\xd7\x3a\x33\x45\xdc\x31\xbe\x72\x32\x00\xc4\x40\x68\x38\xd3\xc3\x33\x31\xb4\x64\xba\xa2\x19\xcb\xc3\xac\x1c\xa0\xac\xc3\x31\x31\xfc\xb2\x5f\x36\x45\x7d\xb5\x68\xfa\x88\x37\xf2\xf7\x07\xd6\xf9\x93\xfb\xfc\xe3\x03\x4f\x95\x33\xa7\x88\x06\x77\x46\x92\x82\xd6\x22\x5b\x3e\xf9\x53\xba\x63\xdb\xc3\xf3\x1c\xa1\xe4\x86\x29\x5c\x7b\xc7\x8a\x2a\x5a\x32\xc3\x54\xe0\x10\x41\xa4\x9e\xa2\xc8\x84\xf1\x54\xc2\x48\x2a\xe0\x09\x32\x44\x8f\x23\x10\xc6\x53\x75\xf6\xe9\x8f\x5a\x42\x74\x37\x1d\x2c\xd1\x9b\x91\xa8\xad\x26\xf1\xcc\x7f\xb0\xfa\x09\x96\xe2\x3b\x08\xdd\x9e\xeb\x5a\xdc\x72\x91\xcb\x5b\x9d\x2a\xb5\xf1\xbd\x13\xd7\x12\x58\x05\x10\xd9\xf0\x7c\xc1\xc3\xa6\x37\xa4\xfb\xe0\x1d\x7d\x3a\xf6\x74\x74\xe8\xdd\x85\xf0\x4e\xff\xc3\x93\x7e\xcf\x24\xc7\xb0\x28\x35\x3d\x51\x76\xca\x86\xd3\xe2\xaa\x62\x59\x74\x10\xf4\xed\xbb\xab\xe3\xbe\x48\xd4\xd5\xe6\x9a\xdc\x42\xd9\xa1\xdd\x60\x2b\xb3\x43\x8e\x73\xcb\x66\x4b\x29\x6f\x50\x72\xf7\x3b\xe0\xec\x65\x3d\x9b\x66\xb2\xec\xd4\x58\x4c\x34\x5f\xe8\x23\xaf\x1d\x26\x76\x75\x70\xfc\x98\x5c\x40\x53\xb0\xed\xe6\x76\xfe\x63\x50\x42\xb3\x66\x55\xe1\xec\x7a\x74\xbf\xef\x6a\xb4\xbd\xec\x17\x38\xa6\x7e\x4f\x8e\xf0\xc5\x23\xf0\xed\xa3\x38\x14\x17\x1e\xc6\x27\x8e\x23\x7a\x5d\x3c\xdf\x46\xe8\x8a\xd2\x1c\xcc\x76\x5f\x50\x62\x61\x2f\xdd\xdb\xce\x97\x4f\x9f\x85\x97\xb3\x24\x6b\x0d\x2f\x68\x5e\x98\x55\xaa\xde\x2c\xe2\x4c\xfb\xae\x57\xb8\x34\x1d\x84\xb6\x5e\xe2\x42\x74\x8f\xce\xd6\xfc\xcc\x8b\x1c\xe1\xc3\xe3\x41\xe2\x9e\xbd\x93\xbe\xca\x11\x17\x12\x6e\x3d\x0f\x34\x66\x1a\x25\xf1\x41\x5f\x08\xc8\xc3\xbd\x12\x90\x04\xef\xd5\x04\x5f\x4b\xa1\x56\x3c\x63\xc7\x59\x26\x6b\x11\x51\x4a\x71\xca\xec\xe4\xa9\x61\xf9\x55\x4f\xe2\x50\xca\x54\x4a\x72\x90\xe4\x88\x0b\x69\xc1\xa9\xa3\xb7\xec\x4b\x1d\xce\x01\xd2\xce\x0f\x52\xa3\x1b\xdf\xed\x95\x84\x36\x8c\x62\xca\x17\xa2\xd6\x3c\xae\x3e\x71\x7b\x5d\x30\x4d\xd2\xba\x66\x64\x63\xff\x9c\x31\xf0\x2a\x70\x90\xd0\xc0\x53\xfb\xb9\xa5\xa4\x86\xea\x9b\x96\x46\x94\x41\x71\x7c\xa3\x5c\x3b\x7f\xef\x97\x6f\x42\xdd\x0c\x11\xd4\xa2\x43\xf7\x6b\x49\x15\xbb\x74\x8a\xfa\x22\xa4\xc7\x22\xb6\xcc\x8a\x23\x94\x68\x2e\x16\x05\x6b\x12\xc5\x4d\xe2\x6d\xd0\x22\xcf\x98\xb9\x65\x9e\x7b\x61\xd3\x20\xe9\xb6\x1a\x64\x90\x4c\xe0\x1f\x32\xbe\x98\xcf\x2a\xe4\x8d\xa6\xdb\x90\xe0\x9d\x0d\xe5\x57\x96\x64\xc5\xd9\x2d\x28\x64\xcd\x17\x82\x16\xe1\xcb\x99\x27\x16\x02\xa6\x93\x41\x32\xfb\x5f\x0a\x14\xcb\xf6\x20\x57\x32\x3f\x6c\x3a\xd2\x40\x36\x7e\x90\xd4\xb0\x21\x5b\x59\xfb\x6e\xb5\xea\x30\xa5\x06\x64\xb8\x2c\x27\x97\xe7\xa7\xe4\xd5\x94\xfc\x4d\x6a\x63\xff\x15\x18\xdb\x77\x1d\xae\x61\xab\xe0\x09\xbc\xad\xf9\x73\x36\x79\x47\xb9\xd8\xd0\xbd\x72\x8d\x3e\x86\x5f\xad\xa1\x90\x29\x5d\xcf\x72\x59\x52\x3e\xa8\xff\xd2\x27\x8a\x2e\xe7\x75\x51\xac\xc9\xbf\x6a\x5a\x0c\x67\x0c\xb9\x94\x39\xb4\x45\x02\x8d\x18\x0e\xfb\x8b\x3f\x87\xbf\xfa\xcb\xf4\xcf\xcd\x8c\xff\x32\xfd\xf3\x50\x26\xdd\xe6\x8e\xff\x65\xaa\x57\xd9\xf4\xcf\x9e\xe1\x88\x78\x81\x0d\xc6\x7c\xd8\xe3\xc1\x3d\x55\x9d\xf6\x50\x00\x8a\x9f\x7a\xf9\x83\x73\xa4\xd4\x58\xbd\xf2\xe0\xf5\x9c\x9d\x0e\xde\xdf\x2a\x9a\xb1\x4b\xa6\x38\xb8\x6c\x52\xe4\x78\x06\x9d\x70\x05\x48\xee\x39\xa9\xed\x85\xd6\x4e\xe8\x40\x3b\xe6\x16\x55\x30\x96\x3b\xf7\xdc\xcf\x97\x91\x85\x9d\x2e\x1c\xb7\x61\x1a\xd6\xfa\xd0\x40\x6f\x94\x29\x46\x5d\xd1\x09\xc9\x59\xc1\x5a\xf6\xde\xa9\x4b\x6a\x0e\x92\x1a\xf8\xa1\x84\x14\x13\xc1\x16\xd4\xf0\x15\x0b\x8f\x59\xae\x18\x6c\x78\x72\xca\xd1\x2e\x35\x30\x67\x3f\x49\x5e\x96\x2c\xb7\x2e\x5a\xb1\x1e\x8c\xa3\x05\xc3\xe2\xdc\x68\xae\x89\xe0\xc5\xa1\xef\x9e\xea\x10\xfb\xb0\xa4\xa4\x82\x23\x30\x30\x8d\xda\x66\xfc\x1a\x5f\x0e\xbe\x1a\x2d\xd2\x07\xd9\x3b\x0e\x10\xa1\x73\xd3\x10\xc7\x79\x2b\x36\x48\x74\x60\xe3\x6e\x19\x3d\xa0\x62\x45\x33\x61\x08\xed\xde\x88\x61\xaa\xc0\x19\xd6\x60\xfb\x1c\x66\xcc\x59\x73\xec\x44\xed\xac\xe6\x52\x65\x7c\x56\xac\xc9\x92\x16\x0d\x9f\x38\x25\x37\x76\xc5\xdd\x4f\x0e\x3b\xfe\x57\xcc\x74\x8f\x41\x21\xc5\x02\x16\x93\xfa\x18\xfb\xae\x02\xe6\xe5\x61\x56\xd0\x9a\x9d\xba\x72\xdf\x6c\x23\x86\xb5\xac\x63\x81\xae\x46\x92\xdf\xbd\x0c\x5b\xfe\x85\x89\x01\x07\xbc\x20\x1b\x59\x30\x77\x42\xf1\xda\x72\x27\x75\xc1\x9e\xee\xca\x1e\xbe\x00\x5f\x9a\x9a\xea\x3a\xf4\x40\xb0\x67\xeb\xba\x99\xf9\xd0\x18\xd4\x1a\x3e\x43\x81\x7c\xc1\x6a\x7b\x27\x07\xca\xf9\xd7\xc4\x7a\x82\x66\x78\x83\x0d\x12\x68\x53\xdc\xbd\x54\xbc\x2a\x18\xf9\xf3\x0d\x5b\x1f\x3a\x36\x4a\x57\x65\xf7\x97\x81\x32\xdb\x46\x47\x0d\x4b\x92\xac\xec\x64\xa5\x22\x7f\x0e\xff\xf6\x97\x61\x77\x13\x9d\xfc\xc7\xa7\xfe\xdd\xc7\x47\xbe\x83\x9f\xb9\x3a\x45\x3c\x99\xa5\x1b\x6e\x7f\x7d\xd1\xa3\x91\x6e\x61\xa7\xe4\x0c\x48\x5b\x4a\x46\x07\xd3\x9c\x91\xb0\xf7\x10\xa2\x75\xc5\x6b\xcf\xf4\x1a\xf1\x8c\x46\x5c\x4d\x3f\xeb\x55\x3d\x5e\xc8\x2b\x4f\xc5\x01\xcc\xc7\x73\xa6\xda\xbf\xc1\xfc\x82\xc8\xc9\x85\x3c\xbb\x63\x59\x6d\xbe\x14\x01\x97\x1b\x37\x0c\xd1\xb0\xb1\x77\x28\xfe\xce\x1a\x66\x6a\xb7\xf2\x37\x0c\xf3\x32\xdc\x14\x77\xb5\xda\xb0\x83\x84\xc3\xe4\xea\x3a\xe7\x69\xeb\x74\xdc\xb0\xf5\x40\x32\x46\x37\x7c\xaf\x8a\x1b\xf7\xcd\x9e\x10\xa9\xd1\x07\xd6\x39\x44\x08\x9d\x31\x72\x76\xc7\xb5\xd1\xff\xc7\x69\xd5\x4c\x96\x33\xef\x99\xa0\xaf\x43\xb8\x56\xf0\xcd\xe1\xe0\x8a\x1c\xfe\x88\xfb\xf8\x88\x43\x16\x16\x28\xf2\xa4\xbd\x0f\xeb\xdc\xe9\xe1\x82\xe9\x26\x7b\xc3\xd6\x7b\x9a\x28\x56\x38\x9b\xbb\xe4\x55\xaf\x5d\x04\xe6\x5c\xb8\xb2\xe8\xf0\x9d\x4e\x47\xb8\x3d\x85\x55\x3f\xb3\x81\x32\x46\x6e\xf7\xc5\xc2\x09\x09\x62\x39\xd0\x6a\xf2\x15\x2d\x70\xbd\x02\x8d\xb4\xde\x7c\x9e\x51\xe5\x70\x67\x9e\xb1\x59\xfb\x6e\x57\x98\x75\x05\x6a\x49\xeb\x5f\x7a\x6b\xde\xde\x37\xc7\x11\x81\xc3\x4b\x19\x9e\xd5\x05\x55\xc4\x5a\x9c\x05\xaa\x0f\x5d\xc4\xc9\x6d\x95\x11\x22\x54\x76\xa3\xef\x3d\x6d\xca\xeb\x9c\x65\x94\xd2\x0c\x31\x17\x24\x26\xa1\x58\xb4\xa7\x42\x11\x32\xf7\xfb\xdd\xb9\xe4\x3c\x58\xea\xc6\x40\x61\x6c\x68\xdb\x2b\xc5\xf4\x7a\x85\xf0\x05\xf0\xee\x63\x5e\xdd\x5b\xa7\xb1\xb1\x3d\x53\xf2\xd7\x86\x2c\x0b\x33\x4b\x47\x3a\xd3\x74\xc4\xf6\x2b\x01\x16\x24\xfc\x1a\x72\x97\x9c\xd9\x99\x4b\xc5\x56\x4c\x91\xfd\x5c\xc2\xaf\xb0\x15\xcf\x70\x3d\x61\xff\x1f\xa6\x24\xa8\x96\x26\x09\xe1\x95\x3c\x96\x8a\x87\x74\xfb\xcf\xbc\x24\xfb\x30\xb5\x6e\x12\x02\xb3\x45\x1e\xab\xe0\xb8\xc6\xb1\x17\xf7\xcb\x43\x85\xd1\xa8\xb9\x1d\x88\xb9\x9e\x6b\x84\x03\x2e\x91\x4d\xbf\xa8\x89\x73\xe4\xd4\x7b\x24\x98\x1b\x19\xac\x29\xd7\xde\xa6\x1c\x76\x5f\x5f\xb1\xcd\x72\x67\xac\x71\x8b\x9a\x2b\xff\x3f\x56\x97\x50\xa2\xd8\xc2\x6a\x72\x84\x50\xa7\xbb\xbf\x90\xe6\x37\xb2\x92\x85\x5c\xac\xaf\x2a\xc5\x68\x7e\x22\x85\x36\x0a\x8c\x18\xbe\x45\xc6\x7d\x12\xfd\xff\xd9\x6c\x60\xbe\x68\x29\x6f\x09\xf5\xdc\x66\x72\xee\xda\xb9\xc8\x7a\xb1\x74\x9d\x39\xe1\x47\x08\xcd\x94\x1c\xc8\x9e\x19\x3e\xdc\xa7\xb2\xf5\x94\x5c\x35\xdd\x34\x41\xad\xa0\x9a\x7e\xc2\xec\xe0\x91\xec\x96\xae\xbd\x4a\xa5\x33\x9e\x33\x1d\xd4\x43\xd6\x2e\xc8\xd0\xa6\x13\x5d\x53\xb2\xd9\x1f\xca\x27\xfe\xe3\x1a\x44\x9d\xad\x98\xb8\x94\xb9\x76\x5b\x87\xe9\xca\x42\xc8\xb1\x75\x83\xee\x3d\x02\xd6\x55\x3c\xbe\x38\x1d\xd6\x13\xf6\x91\x72\x3f\xf7\x7c\xc4\xc0\x7b\x19\x82\x71\x0d\x07\xb9\x3d\xb2\x4d\x82\xc5\x1e\x99\xa1\xd9\xa4\x52\xfa\x34\x8d\xeb\xa1\x18\xd6\xfb\x0b\x25\x66\xb0\x14\xe7\x25\xbd\xbb\xba\x61\xc3\x08\x03\x27\xcd\xc7\xfd\x7d\x60\xa4\x3d\x81\x44\xf5\x47\xa1\xa9\xe1\x7a\xce\x07\xbf\x2f\xe3\xd3\x4f\x50\xde\x86\xe9\x3f\xeb\x46\xbf\xc2\xb5\x2b\xcb\x5e\xfc\x5a\x23\x0a\xc9\x48\xe8\x27\xd4\x3f\x76\x53\x57\x47\x83\x48\x3e\x92\x26\x09\x05\x1e\xae\x2b\xe8\x0b\xed\x71\xe1\x96\x67\xae\x7d\x3c\x6e\xaa\x39\x73\x0f\x16\x4e\x2d\x89\xba\x9c\x31\x15\x94\x3f\xc6\xd3\x85\x67\x00\xae\xfa\xcd\x10\x9b\x93\x85\x90\xe8\x8c\x06\xd6\x46\x23\xcb\x59\xe2\xaa\x44\x60\xbb\xce\xee\x6c\x00\xa6\x31\x75\x01\x6e\xf4\x0e\xe7\xa6\x48\x94\x44\xe2\x8a\x4a\x43\xc9\x64\xff\x28\x21\x25\xf6\xba\x4d\x43\x16\xbf\xfb\x37\x48\xa1\x28\xdb\xd5\x0e\x7c\x55\x97\x1b\xc8\xda\x2e\x37\x36\xeb\x53\x53\x2c\x72\x6f\x99\x23\x1a\x64\x77\x47\x97\xcb\xc0\xbf\xe6\xe9\x43\xa8\x41\x5b\xe3\x20\x96\xc4\x27\x9c\xa9\x68\x63\x00\xf8\x11\xc8\x88\x21\xaa\x20\xda\x99\xba\xcc\xa8\x15\xee\xe6\x89\x3b\x16\x91\x3a\xc1\x0d\x7c\xa1\x9b\x1b\x13\x64\x1e\xdb\xfd\xb7\x61\x61\x91\x02\xe2\xd4\x9a\x1b\xa8\xcc\x7e\x3b\x7a\xd7\xe3\xa6\xc9\xf1\x47\x48\x0c\x45\xee\x56\x58\x93\xed\x8f\xbe\x1e\xa4\x29\xa2\xc2\xbe\x13\x84\x11\x59\x68\xe7\x06\x3e\xd5\xdd\x8e\xde\xd2\xcb\xed\xa4\x77\xdc\x5a\xed\x4e\x7f\x47\xca\x04\xca\xb6\x79\xb8\xf5\x2e\x1d\x1e\x25\xb2\x9f\x4a\x3f\x17\x87\xe4\x42\x9a\x73\x81\xd7\x78\x76\x74\x32\xf2\xa7\x92\xe9\x0b\x69\xe0\x6f\x1e\xfd\xd0\xb8\x65\x4b\x76\x64\x7c\x26\x10\xba\x69\xc4\xed\xab\xb5\xcc\x76\x5f\xdd\xf7\x45\x2a\x75\x37\xfc\x0b\x5a\x37\xfb\x74\x1e\x37\x4b\xa9\xfc\xd9\x68\xd3\x57\x3a\xc2\xa9\x08\xa3\x8b\xf4\xf2\x3d\x00\x10\xcc\x4a\xdd\xb1\xf9\xdd\xee\x38\xc6\x7e\x7b\xf7\x24\x77\x97\x20\xc1\xce\x87\x25\xf0\x9f\x3f\xb8\xeb\xee\x6e\xa9\xd0\xd0\xae\x2a\x80\xfe\x20\xaf\xa3\x2e\x0e\x71\xca\xc7\x28\x6a\xd8\x82\x67\xa4\x64\x6a\xc1\x08\x34\xd9\x88\xbf\xd4\xb1\x47\x28\xca\x3b\xed\x4e\x04\xad\x5d\x20\x18\x81\x70\x39\x59\x68\xe3\xa4\x81\x6e\x41\x7e\x59\x49\x21\x69\xf9\xff\x36\xc0\x9c\xff\x8f\x54\x94\x2b\x3d\x25\xb8\x2a\x49\x12\x40\xfe\x5d\x89\x1e\xf2\xd7\x99\x72\xc4\x6c\x7b\x4f\xad\x8e\x70\x85\x30\x47\x8e\x83\x94\x2a\xe7\x5b\x81\xe2\x21\xb9\x5d\x4a\xcd\x22\xbc\xce\x26\x11\xfa\xe2\x86\xad\x5f\x1c\xf6\xd4\x0d\x3e\x0c\x7d\x71\x2e\x5e\xb4\x48\xff\x04\xda\xb5\x09\x65\x20\x5f\xfb\x02\x24\xbe\x78\x5a\x11\x69\x44\xe0\x11\xdf\xd9\x7f\x73\x32\xa8\xdb\xef\xf3\x8a\x91\x99\xb6\xbd\x77\x4e\x4c\xfb\x4c\x81\x0c\x01\x72\xb6\x50\x0c\x0a\x9c\x5c\xfe\x1f\xde\x04\x4a\x07\xd0\xae\x05\x5b\x31\x51\xa0\x52\x4e\x5c\xfb\x3e\x40\xf9\x94\x9c\x9b\xbd\x3d\xed\x6f\xfd\x1d\x2f\xeb\xd2\x91\xf4\x1b\x5c\xc6\x2d\xe7\xf3\xd0\x36\x33\x94\xff\xf4\xf2\x6e\x58\x6d\xdc\xb4\xdf\xe7\xc2\x61\x1d\x6f\x65\x7c\xd2\xcd\xc1\x2b\x36\x32\xdf\xc8\x66\x8e\x84\xbc\x91\x8a\xb0\x3b\x5a\x56\x05\x3b\x74\x0f\x37\xbf\x9b\xfc\x5b\x0a\x16\x1e\x54\x30\x3e\x78\x38\x48\xbe\xd8\xc9\x48\xf2\xca\x29\x95\x2a\xb0\x16\x21\x5f\x45\xa1\x18\xa9\x97\x5d\x6e\x1e\xc0\x30\x2a\xe4\xd5\xd1\xab\xa3\x97\xaf\xc9\x4f\xc4\x7e\xf0\x2b\xff\xcf\xaf\xfc\x3f\x7f\x47\x7e\x42\x88\xfc\x89\x10\x72\xb9\xf1\x4f\xf7\xf7\x13\xc2\xe7\x61\x65\x30\x29\x5c\x6d\x17\x91\x8b\x4c\x96\xfe\x54\x01\xfa\x06\xd4\xea\x8c\x35\x8f\x75\xc8\x7c\xb3\xfb\x60\x60\x29\xca\x64\xc9\x60\x65\x5e\xfd\x9f\x20\x15\xe7\x8f\x70\x43\xa4\xf0\xb2\x5f\xed\xc3\xd2\x1e\x90\x5b\xe8\xa9\x58\xd2\x1b\xec\xc3\xf8\x71\x66\x6a\x5a\xd8\x45\xdc\xff\x6a\xf2\xf2\x80\x48\xd1\xfb\x01\x84\xd4\x15\x97\x05\x35\x2c\xec\xcd\xfe\xab\x83\x69\x82\xcd\xfa\x6a\xc7\x66\x45\xee\x13\xac\xa6\x55\x23\xf6\x53\x83\x0a\xa4\x4d\xee\x0b\x21\xd1\x71\x41\x34\xbd\x4a\x9b\x1a\x92\x57\x70\x5b\x5f\xe2\xbe\x5c\x48\x13\x40\xb4\x83\x5b\x71\x24\x44\x81\xfc\xee\xab\xc1\xe8\xaf\xe6\x9d\x2d\x1a\xf7\xd5\x48\x0a\x88\x10\x9c\xa3\x27\xe7\xd0\xca\xd4\xa9\x3c\x3d\x25\x17\x32\x0f\x9d\x11\x96\x74\x85\xc2\x1e\xfb\xb4\x9c\x6f\xb0\xcf\x75\x93\xc3\xe5\xc0\x72\x91\xa1\x68\x2e\x3a\x58\xe9\x4c\x42\xb7\x1f\xe5\xa0\xfe\x33\xe6\x9d\x73\x0c\x0c\x84\x42\x37\x04\xff\xb2\x4b\xbe\x6f\x65\xe3\xa8\x95\x89\x2b\x0f\x70\x93\xfd\x8b\xeb\x09\xf1\x62\x56\x67\x37\xcc\x38\x9f\x17\x85\xa2\x82\x3e\x44\x55\x6d\xc8\x8c\x16\x54\xd8\x28\x37\xc1\x6b\x9d\x91\xae\x50\xd6\xcd\x0e\xae\x7a\x92\x9b\xfe\x65\x20\x35\x6e\x6c\x3d\x3e\xc7\xba\xa7\xdf\x6f\x0a\x6c\x4b\x13\x10\x0b\xe2\xc1\x08\x39\xa3\x45\xa8\xbe\x82\xfe\xfb\x4d\x3b\x0b\xb1\xb7\x87\x09\x0a\xdc\xfc\x3c\x12\xce\xf9\x26\x2d\xe2\x65\x4a\x26\x08\x91\xa7\xf2\x42\x9a\x00\xce\x21\xfb\x1e\xf1\x78\x40\x0c\x2b\x0a\xac\x8f\xde\xf4\x16\x05\x75\x6d\x64\xf3\x17\xf6\xf3\x27\x0d\x14\xe8\x58\xac\x6f\x51\xb1\x5f\x33\xb7\xce\x2f\xd9\x5f\x31\x68\x64\x91\x1b\xdc\x78\xbb\xd7\xd1\x33\x54\x93\x17\xbd\x83\x31\xbc\x2d\x15\xb4\x4a\xb0\x5a\x10\xfc\x29\x3e\x27\x55\x41\x33\x57\x4d\xe8\x6c\x38\x42\xa2\x3d\x4e\xd2\xfb\xfd\xc1\x4b\xf7\xbe\x86\x26\x2f\xbc\x73\xf1\x62\xf4\xd9\x87\x8d\xdf\x59\xcf\x34\xb5\xcf\x7e\x09\xff\x6f\xdb\x77\x3f\x9f\x93\x2d\xad\x83\x73\x8a\xfc\x9a\xf6\xae\xf2\x61\xec\xe9\xda\x19\x00\x04\x77\xfe\x2b\xf0\x88\x7f\x87\xc3\x5a\x87\x38\xe0\x77\x47\x5f\x1d\xbd\xda\xb7\x6b\xfe\xd5\x81\xbd\x67\x3d\xef\xfb\x15\x46\xb6\xf7\xd7\xc3\xec\xbc\xbe\xe4\x4c\x77\xfd\x6f\x84\xdc\x73\xe1\x20\xa8\xe4\x56\xaa\xdc\x83\x5b\x03\x19\x40\x86\x7a\x19\x71\xba\xca\x7a\x30\x65\xb0\xed\x87\x64\x56\x77\xfa\x32\x23\x84\xde\x4a\x6b\x57\x20\x00\xb2\xba\xec\x37\xa5\x54\xec\x37\x9d\x5f\x40\x7d\xfa\x46\x20\x80\x68\x1a\xec\x06\xd2\xda\xdf\x4d\x3a\x14\x7b\x05\xd7\x66\x52\xd2\x6a\x72\xc3\xd6\x83\x72\x61\x58\xa0\x5b\x1c\xcc\x6d\x7b\xee\x6e\x11\x4a\xfa\xf9\x3d\x78\x5d\x33\x46\x3c\x60\x78\xef\xad\x87\xfe\x78\x41\x1e\x04\x02\x01\xe3\xa0\x3d\x2c\x1d\xe4\x0c\xe0\xb0\x2d\x91\xcb\x8c\x15\xd2\x35\x09\x75\x75\x4f\x83\x44\x0e\x60\x1b\xca\xa4\xc8\x58\x65\xf4\x91\x36\x52\xd1\x05\x3b\xf2\x9f\x33\x9c\xf2\xe4\x4b\x23\x5d\xbf\x73\xdd\x34\xbb\x85\x66\x8e\x7e\x71\xe0\x0d\xf2\x5d\x39\x03\x47\x90\xdb\x47\x9f\xf8\xa4\x19\x50\x05\x0c\x15\x39\x5b\xf7\x09\xdf\x3b\xf4\x06\x4f\x1c\xec\x3a\x98\x1b\x05\x0f\x83\xa1\xb7\xfa\xac\xa0\xda\xf0\xec\xaf\x85\xcc\x6e\xae\x8c\x54\xd1\xd1\xc6\xf1\xf7\x57\x5b\x32\x11\xba\xb9\x7b\xa6\x04\x39\xfe\xfe\x8a\x9c\x72\x7d\x43\x14\xd3\xb2\x56\x03\x69\x89\xdc\x70\x5d\x01\x75\xaf\xa2\x9e\x92\x1b\xd7\x90\x70\x6f\x0f\x17\x0b\x69\x7b\x4e\xb3\x25\x17\x2c\x3c\xfe\x88\xa6\x7d\x2f\x0a\x2e\x12\xce\x68\xa4\xee\xf8\x15\xbd\xd5\xcc\x6d\xc3\xcc\x6e\x83\xfd\x9f\x19\xd6\xb0\x3d\x02\x89\xba\xfb\x8c\xf3\xd3\xc1\xff\x69\x1c\x26\x6c\xae\xaf\x91\x5d\x61\x36\xaf\xc1\x1b\x5e\x30\x57\xd0\x85\xef\x08\x43\x36\x9a\x4a\xc3\x09\x5e\xcb\x9a\xdc\x52\xf4\x9b\xaa\x91\xce\xda\x4d\xc9\x35\xaf\x5e\x93\xb3\x4e\xc7\x4c\x3c\x6e\x6d\xde\xff\x58\xf0\xdb\x43\x6f\x05\xa4\x48\x5f\xf4\x02\x37\xcc\x3d\xcf\x5a\x43\x8c\x2d\x91\x73\xe3\xcc\x85\x7e\xfa\x35\x79\xc1\xee\xcc\xef\x5f\x1c\x92\x17\x77\x73\x6d\xff\x21\xcc\x5c\xa3\x22\x4a\x3b\xce\xcb\xaa\xe0\x19\x37\x36\x00\x16\x73\xa6\xda\x14\x9e\xfb\x19\xec\xab\xf2\x66\x0f\xc2\xf4\x0a\x01\x39\xb3\xeb\xf7\xa7\xef\x5f\x43\x22\x28\x97\xe4\x96\x91\x4a\xb1\x15\x13\x86\x30\xa5\xe4\xc0\x42\xa2\xce\xe7\x0a\x4f\x92\xd7\x1c\x25\xa0\xe2\xcb\x64\x59\x29\x59\x72\x8d\x07\xc0\xb8\xc7\x4e\x50\xd2\xc3\x35\x20\x89\xc7\x97\x40\x75\x36\xa8\x85\x04\x7a\x05\x88\x65\x82\x40\x2c\x3f\x2d\xb9\x57\xab\xe0\x31\x8e\x5e\xab\x9c\xcf\x89\x74\xcf\xc9\x3d\x32\x2d\x3c\xb2\x22\x28\x2c\xab\x11\xfc\x8c\xc5\x60\xce\xd5\x76\xb4\x3a\xe0\x8d\x54\x41\xe0\x51\xce\x56\x47\x3a\xa7\xaf\xb0\xc0\x49\xbb\x7c\xee\xaa\x3a\xb5\xd5\xee\x10\x2a\x57\x63\xc7\x8b\x57\x2f\xa6\xe4\x8a\x97\xbc\xa0\xaa\x58\x1f\x76\x77\xac\x91\x8e\x55\xd7\x52\x35\x9f\x0c\xe0\x95\x97\x2f\xc8\xbe\xe3\xa9\xc2\xa2\x55\xa8\x20\x05\xa3\x2b\x16\xe8\xbd\xa0\xf3\x85\x43\xc4\x1d\x20\x02\x6a\x12\xfd\xa0\x45\x22\x1f\xb5\x08\x38\x30\x34\x7f\x2f\x0a\x24\x40\x7c\x83\x6a\xd5\x9f\x8e\x17\x46\xd5\xec\x05\xfe\x9a\xcd\xa5\xca\x9c\xaf\x09\x99\xb1\x25\x23\x1f\xfc\x2c\x63\x1b\x8e\x70\xe1\xe3\xb9\x77\xf6\xba\xc1\xc5\x73\x93\x8d\x40\x74\xee\x52\x05\x70\xe2\x80\xd4\x13\x6d\x71\x9f\x84\x6f\x4c\xa2\x9a\x33\xbb\x11\xdc\xdc\x14\x27\xec\xa3\xe0\xff\xaa\x19\x39\x3f\xf5\x5e\x23\x72\x6d\x2b\xa6\x34\xd7\xc6\xda\xf3\xbc\x1b\x71\xe1\x6d\x8d\x0d\xde\xf6\x8f\x4b\xfa\x6f\x29\xc8\xd9\x5f\xaf\xfc\x47\x1f\x38\x8f\x06\x7d\x58\x9f\xca\xe6\xa3\xdc\x02\xfa\xef\x5a\x31\x1b\xd0\x46\x46\xdb\xc7\x41\x4e\x5c\xdd\x83\x8d\xb0\xad\x24\x72\x4a\x0d\x75\x81\xb6\xb3\xb9\x12\xfb\x06\x0d\x7e\xbb\xd5\x52\x33\xa8\x1d\x0d\xfc\xdd\xe8\xb6\x6d\x8f\x16\x88\xda\x3b\x80\x6a\x8d\xe1\xfe\xd3\x8f\x1f\xce\xbf\x70\x08\x9b\x81\xa7\xbb\x78\x27\xf3\x24\x71\xec\xdf\xec\x46\x9e\x38\x99\xa4\x44\x0b\x25\xe4\x42\x0a\x76\x08\xc6\x8a\x58\x6b\xe5\xff\xf5\x7b\xc5\xcd\x30\x72\xe7\x76\x44\xba\xe5\x61\x67\x13\xac\x92\x75\xca\x2f\x3a\xc4\xf5\xa8\x9e\xf3\xed\xac\x42\x2c\x34\x2b\xe4\x8c\x78\xfd\xf5\x58\x2b\xf4\xf1\xc3\x79\xa2\x05\xfa\xf8\xe1\xfc\x97\xb4\x38\xc9\x52\x45\x1b\x99\xa2\xe8\x08\xec\x9d\x2f\x47\xa1\x9d\x58\x1a\x1b\x25\xda\xf9\xb4\x5d\x32\x77\xe6\x64\x90\xa2\x7d\x26\x87\x9c\xdd\x4d\x9f\x63\x36\xe6\x31\x4e\xdc\x0d\x17\xc8\x3a\xdd\xbe\x4a\x3f\xf3\xa4\xc6\x71\x15\x50\xd0\x2d\x20\x7f\x4d\xca\xba\x30\xc0\x21\x0b\x17\xd2\xde\x50\xac\xc4\x8a\xa9\x70\xa1\x89\xef\xa8\x41\xc8\x29\x73\x50\x25\x74\x85\xb2\x2f\x7b\x69\x66\xd7\xfd\x19\xa4\xc8\x66\x72\xef\xa8\xa0\x0b\xbb\x08\xe0\xcf\x91\xd2\xfd\x11\xab\xdc\xac\xef\x05\x33\xdc\x77\x60\x1a\x11\x04\x12\xba\xa2\xbc\xa0\x33\x5e\x70\x74\x74\xa7\x99\x39\x98\x86\x10\x0c\x82\x3b\xe8\x25\x92\x3f\x8a\xe9\x4d\x18\x58\x77\xa9\x1f\x21\xa8\x44\xae\xcf\xbe\x9d\xd3\xd1\xad\x75\x47\x0e\xa6\x6d\x4c\xbd\x64\xe8\x10\x05\xb8\xa0\x5c\xb8\xde\x0b\xd3\x7d\x13\xcc\x34\x51\x7a\x8c\x22\xc2\x85\xad\x70\xd4\xad\xcd\x4a\x11\xba\x58\x39\x89\x42\x17\x10\xe5\x3b\x06\x8d\xd1\x0b\x8c\x09\xd1\x2c\x53\xcc\x20\xe3\x17\x50\x10\xa8\xff\x36\x2e\x82\x19\xb5\xc3\xf3\xd5\x0e\x04\x4c\x4d\x38\x74\x09\x76\xb0\xdb\x5a\xd2\x09\x46\xbf\x78\x74\x09\x62\x9c\xce\xb8\x8a\x72\x03\x42\x5f\x32\x88\xfc\xac\xb6\x18\x4a\x34\xd6\x4c\x2d\xce\x9a\x36\xf7\x34\xc1\x72\xbb\x8e\x60\xe8\x5e\xa0\x11\x5f\x92\xb1\x6a\x39\x8f\x25\x0e\x3e\x61\xd5\xf2\xcd\x55\x1f\x90\x64\xff\x0e\xf1\x31\x6f\xae\x7a\x56\xc4\xd9\x04\x38\x44\xb0\xde\x28\x5b\xe5\x3b\x59\x14\x7c\xce\x0c\x47\x2c\xf1\xa3\xd9\x91\x52\x0a\x6e\x30\x6f\xbb\x91\xcc\x63\xfe\x67\x53\x44\x3d\x1f\xc2\xe7\x93\x77\xd8\x8f\x71\x03\xf8\xaa\x32\x59\x14\x2c\x83\x17\x3e\x39\x87\x23\x86\x5f\x23\x37\x76\xbc\x69\x78\xa8\xba\x9e\xde\xfc\x11\x12\xdb\x3e\x85\x7d\xe4\xae\xca\xd1\x87\xb3\xe3\xd3\x77\x67\xd3\x32\xff\xd5\x52\xde\x4e\x8c\x9c\xd4\x9a\x4d\xb8\x89\xf1\xe8\x1f\x89\x64\x2c\xfa\x81\xdd\x2c\x53\x1c\x91\xb6\x55\xdd\x47\xcd\x90\x30\x7b\x12\x00\x07\x1e\x52\xaa\xa4\x34\x87\x44\x51\x80\x58\x9b\x25\x9a\x6a\x26\x74\x93\x73\x67\xcd\x28\xc6\x0e\xe3\xdf\xd6\x07\x35\xac\xec\xcc\xe5\xc9\x44\x7f\x7b\x5b\xdd\x05\xd1\x7b\xe6\x1d\xc4\x7b\x5c\x3d\xa4\x54\x68\xd5\x7e\x8f\xab\x87\x0f\xe4\x8d\x6f\xd7\xd5\x73\xf5\xd2\xbd\xa6\x7d\x79\xb5\x13\xeb\x6b\xe2\xc2\x51\xf2\x33\xa7\xe9\xaa\x91\x1b\x81\x5c\x01\x20\x88\x59\xda\xb3\x75\xc3\xd6\x04\xc8\xa1\xe6\x68\x96\x91\x8f\x9a\xa9\xc3\xee\x23\xfa\x11\x33\x19\x6c\xca\x51\xad\x99\x9a\x46\x79\xc7\x4f\xc2\xfa\xe0\x3d\x60\xf8\xf4\x0f\x6c\xfe\x10\x87\xe0\x03\xc3\xa2\x1f\x80\xc2\x29\xf0\x63\xf8\xfc\x01\xad\xcd\xd2\xd5\x0b\x47\x00\x78\xdc\xf7\x02\x8e\x67\xf3\x54\x20\x25\x7a\xee\xaa\x27\x71\x0c\x22\x78\x65\xe2\x19\x21\x05\x3a\x8e\x22\x5b\x27\xa9\xf3\x24\x88\x96\x48\xc2\x11\x32\x83\x11\xa0\x72\xc5\xd4\x8a\xb3\xdb\xa3\x5b\xa9\x6e\xb8\x58\x4c\x6e\xb9\x59\x4e\xdc\xea\xea\x23\x68\x00\x7b\xf4\x2b\xf8\x47\xc4\xec\x1c\x16\xf4\x38\xcf\x7d\x15\x59\xad\xd9\xbc\x2e\x5c\x25\x55\x14\x07\x1e\xad\xf8\x77\x4c\x69\x2e\xc5\x21\xbc\x7c\x1c\x92\x9a\xe7\xdf\xe0\xce\x15\x89\x57\x31\x56\xc5\x26\xf7\x31\x15\xfe\xc2\x5a\x5d\xa2\x68\x2e\x81\xd7\x5b\xc1\xb1\x4d\xe0\x10\xd2\xbc\xe4\xe2\x69\x68\x01\x5c\x12\x81\x8b\x1c\xb3\x4f\xfd\x3d\x3a\x01\x29\xb1\xfd\xb3\xdc\x5c\x02\x66\xb3\xa9\x3a\xa1\x21\xa3\x8c\xa4\x32\x09\x15\x2b\xba\x57\x7d\xd2\x55\x0e\x98\x84\xf7\x3d\xdb\x5c\xae\xf5\xbf\x8a\x89\xfb\x92\x49\x95\xb7\xfb\x3c\x96\x92\x7c\x6a\x3c\xb5\x52\x92\xb6\xf0\xe3\xb9\x01\x04\x76\x17\x6d\x20\xc5\x7a\x70\xc1\x2e\x98\x00\x7e\x61\x1b\x70\x41\x12\x98\xc0\x67\x79\xe3\x09\x6f\x26\x19\x43\xfa\x01\xe3\x17\x11\xd2\x3f\xc8\xe9\x89\x8d\xe2\x93\xc7\x6f\x95\xe4\x78\x8a\x4c\xa8\x0e\xf5\x81\x96\xb3\x5a\xe1\xf5\x08\xaf\xd3\x2a\xaa\x68\xc9\x0c\x53\xae\x1b\x8b\xfd\x8d\x4c\x0a\xe1\x1a\xfc\x22\x65\xbe\xaf\x98\xb8\x32\x34\xbb\x89\x42\x51\x8e\x31\x57\x6f\x8c\x31\xd7\x53\x88\xb9\x52\x56\x47\x04\x8a\x81\x3c\xdc\x3c\xac\x5e\x05\xb6\x37\x5f\xe6\xd5\xf2\x16\x38\x55\xfa\x1f\x61\xef\x33\x29\xe6\x7c\xf1\x8e\x56\xb1\x6f\xb5\x41\x4e\x24\x00\xa8\x9d\x50\x78\x9e\x05\xaa\xcc\x4a\x56\x75\x81\xed\x44\xca\xb5\xdf\xdb\x2f\x1b\xe6\xc4\xa9\x52\x1f\xfd\xa7\x42\xfe\xb7\x76\xb4\x94\x39\x23\x33\x1e\x63\x4a\x6b\xcd\x6c\xec\x9a\xf9\xe6\xa9\x10\x78\xd8\x70\xc1\xcf\x19\x7d\x71\x9a\x50\xc6\x51\x70\x06\x12\xe2\x97\x48\x5a\x42\x3b\x5e\xfe\xe1\x0f\x7f\x98\xf6\x90\x43\x2f\xbf\xfe\xfd\xef\xa7\xe4\x94\x2b\x60\xe1\xe2\x68\xdd\x6d\x6d\x41\xa0\x21\xa1\x66\x09\xb4\x8f\x40\xfa\x09\x9d\x83\xe3\x4a\xe5\x1d\x55\x96\x75\x23\x5d\x07\x02\x52\xf2\xc5\x12\x9b\x09\x72\xec\x93\xf6\x5e\x15\x3c\x33\x8e\xe6\xcf\x99\x1a\x09\x87\x02\x9f\xb4\xa2\xe1\x6b\x9b\x62\x6f\x38\x5d\x87\xa4\xe0\x28\x66\x5b\x02\x91\xf6\xb7\x4a\xd6\x55\x4b\xbf\xae\x98\xae\x0b\x83\x64\xaf\x22\xee\xfb\xdd\xe7\x36\x27\xdf\x2e\xee\xb3\xad\x63\x8d\x78\x9b\xef\xa9\x84\xf3\x5e\x70\x7b\x88\x65\x13\x25\xae\xed\xd2\xc4\x5d\xd9\x8a\xf2\x86\x9c\x07\xca\xcf\xc0\x8d\x41\x8a\xf5\xf5\x37\xcd\xab\x4b\xde\x5a\x19\xf4\x9d\x75\x5c\x66\x95\x92\xff\xe3\x50\xf3\xc0\x32\xda\x5a\x7f\xa4\x5c\x60\x51\x85\xf3\xef\x1a\x1a\x00\xc6\x2d\xaa\x79\x54\xe0\xa3\xb5\x51\x8a\xef\xab\x16\xd5\xac\x9f\xb8\x36\x34\x9d\xfd\xb6\xe2\x0a\xae\xed\x22\xdc\xb0\x35\x5e\x0b\xde\xbb\xa2\xcd\x6f\xa1\xe3\x2b\xb3\xd4\x4e\x0f\xd4\xa2\x33\x53\xf8\x4d\x6c\x70\x22\x8d\x9b\x2d\x78\x28\x40\x70\x40\x7d\xa7\x2f\x6c\xb8\x1f\xbe\xd2\xd3\xfc\x7b\xea\x67\xff\x0b\xe8\x78\x1f\x56\xb0\x39\xee\x87\xf1\x47\x54\x33\x53\x57\x6e\xbb\x80\xd9\xc3\xae\x29\xd3\xda\xb5\x7f\x47\xca\x2c\xa9\xba\x61\xb9\x37\x23\xb4\x98\x92\x4b\xbb\x65\xd0\x42\x07\xaf\xab\x5d\x93\xae\x95\x03\x61\x96\x74\x0d\xcb\xe9\x83\xf5\x88\xe7\x95\xbd\xe9\x74\xcf\x19\x6a\xa9\x88\x36\x54\x19\x2c\x9d\xa7\x1d\x56\xda\x73\xef\xff\xf8\x8e\x56\xda\x75\x12\xe2\x62\x11\xd1\x83\xc5\x67\x57\x60\x6d\xbd\x53\x44\xfd\x59\xfd\x8f\xed\x85\x68\x17\x03\xab\xf6\x9e\x58\x1f\xc4\x6b\xdf\xe1\x32\xb2\x5f\x9e\x37\x10\x8f\xde\x77\x2e\xa6\xea\x99\xdc\x1f\x56\x45\xad\x4d\xeb\x98\xb6\xc1\x95\x89\x6d\x3c\x66\xdd\x91\xc3\xa6\x9d\x99\x8f\xa9\xa2\x24\xf6\xe2\x31\x1f\x59\x45\xb6\x87\xb3\xba\x7d\xc3\x27\x89\xb2\x72\x6e\x74\x62\xe7\xc6\x41\xa9\x35\xfe\x05\xc7\x8d\x36\x10\xdb\x08\xa9\xa2\xa4\x6e\x87\x63\xd8\x46\xdc\xed\xd8\x19\x94\x45\x49\xb4\x01\xdd\x56\x68\x16\x25\xb1\x0d\xeb\xfa\x01\x5a\xdc\x09\x8d\x0b\xee\xdc\x88\x0f\xf1\xdc\x88\x0d\xf4\xdc\xc0\xc3\xa1\xdd\xd8\xd2\xe5\xc1\xbf\x8a\xd3\xe6\xe0\x48\xcd\xdb\x23\x66\xe4\x20\xb2\xe0\x5d\xc3\x34\x86\x66\x4a\xde\x79\xbf\x6f\x20\xf5\xef\xe6\xa0\x82\xd0\x99\x96\x45\x6d\x5c\x92\x06\x04\x47\x2b\x2c\xef\x8c\xb6\xa9\x9f\xb8\xc6\x78\x6e\x80\x47\xd9\x7c\x77\xb4\x83\xea\x06\x84\x61\xce\xbf\xc3\x7b\xac\x5e\x54\x9c\xf1\xc5\xbf\x0a\xdd\xfb\x22\xd4\xbe\xeb\xa4\x4b\xd4\x3f\xea\x6b\xd0\x83\xbc\x04\xa5\x7c\x05\x8a\x3c\x03\x32\xca\x59\xea\x57\xb6\x79\x02\xb6\xdb\x25\xf3\xb5\x18\x58\x45\xd1\x3e\x5c\x48\x45\xac\xf9\x80\x14\x83\x77\x9b\xd0\x61\xd6\x9c\x0b\x64\xde\x23\xe6\xf5\x3d\xd3\x3c\xf6\x19\xe7\xea\x9c\xec\x9f\x34\x34\xdb\xf8\x92\xca\x73\x61\x98\x9a\xd3\x8c\x1d\x74\x91\x77\x81\x10\x02\xe9\xe1\x70\x4d\x96\x54\xe4\x85\x03\x27\x51\x41\xd8\x9d\x61\x4a\xd0\x02\xe6\x9d\x2b\xbe\x42\x19\xec\xfd\xe3\xa2\x5a\x52\x32\x67\xd4\xd4\x8a\x21\xfa\x2e\x3c\x1e\x9f\x15\xee\x93\x23\x5f\xa6\xe0\x47\x53\xd4\x73\x83\xa0\x90\xda\x1c\xcc\x94\xde\x0e\x6f\x0f\xda\x43\x10\x9a\x83\xd9\xb3\x82\x7f\xde\x68\xde\x0d\xa7\x56\x4b\x80\xbb\x0a\xde\xfa\x5a\xd6\x58\xbf\xd0\x41\x72\xe7\x52\xb9\xce\x1c\x52\x29\xeb\xa8\x43\xba\x18\x5d\xa0\xa6\xd8\x82\x6b\x03\x3d\x80\xbc\x53\xe2\x3b\x7e\x3c\x0a\xaf\xcd\x93\x65\x52\x4a\xcf\x4d\x34\xf7\x99\x5e\xb9\xe2\x79\x88\x5e\xa1\xf4\x22\x2a\xd6\xe6\x9a\x54\x54\x7b\x40\x11\x14\x99\x68\x2d\x33\x4e\xf1\x4f\x8a\x9d\x7b\xe1\x72\xd4\x10\x13\xe7\xcc\x30\x55\x72\x81\x86\xa0\x76\x48\x40\xbb\x94\xe1\x92\xd0\xaa\x2a\xd6\x8f\x72\xf8\x84\xcc\xd9\x65\x3d\x2b\xb8\x5e\x5e\x25\x44\xa1\x5d\xec\x10\x8b\xdf\x5d\xba\x5d\x47\x14\x55\xed\xb5\x85\x67\x23\x9a\x09\xcd\x23\x62\x3c\xeb\x13\xdb\xd8\x95\x4b\x01\x7d\xfd\xa8\xd6\x61\xa6\x27\x57\xc3\x29\x10\xdd\x08\x9a\x59\x02\x0b\x78\xc1\x0c\x6b\x94\x76\x67\x7d\xbf\x8b\x7a\x86\x13\x39\xc8\xfa\x28\xaa\xae\x34\x92\xd1\xa2\x40\x3b\xd0\x90\xf6\x69\xfa\x8c\x07\x1f\xd6\x25\x41\x48\x89\x0e\x27\x67\x41\x57\x70\xab\x46\x02\x36\x11\x8a\xcc\x9c\x3f\x10\xa1\x96\xda\x23\xb5\x71\x38\xd0\x0f\x3d\xd2\xb5\x15\x10\x44\x8a\x20\xfa\x90\xd0\xa2\x88\x3b\xb9\xcd\x3d\x70\x4d\x33\x9d\xda\x7b\xa4\x26\xe6\x23\xf0\x71\x04\x3e\xde\x33\x9e\x0e\x9c\xfe\xca\xa7\xca\x9d\x11\xa1\xf9\x44\xe2\x71\xea\x0e\x68\x57\x2b\xa7\xe6\x83\x4b\x1a\xf7\x6e\xb7\xc5\xd0\xd4\x47\xeb\x7f\xf1\x80\x98\x34\xb8\xd3\x63\xe3\xbb\xe6\xa7\x80\xce\x7c\xb7\x21\x12\xfb\x24\x6f\xa4\x62\xda\x1b\xc6\x89\x7f\x06\xc9\x3a\x9a\x28\x0a\x98\xd5\x28\xd4\x8e\xe9\xf6\xbf\x85\xdd\xde\x10\x05\xd9\x00\xc8\x8b\xda\xd3\x24\x97\x59\x5d\x32\x61\x62\x6a\xa0\xed\xf1\x6b\x2b\x8f\x1c\x95\xe5\x23\x19\x02\x9a\xe7\xdc\xd9\xf8\xcb\x68\x93\x10\xa1\x39\x72\x79\x2b\x6e\xa9\xca\x8f\x2f\x11\x94\xbd\xfd\x30\xbb\x95\x14\x07\xce\x0d\x53\x22\x56\x12\x9d\xc9\xda\x04\x12\x3d\x6c\x42\x67\x03\xdd\x3b\x62\x75\x47\xac\xee\x88\xd5\x1d\xb1\xba\x23\x56\x77\x13\xab\x6b\xe5\xb8\xdc\x41\xe1\xba\xa4\x62\x83\xf0\xae\x0a\xf7\x05\x2f\x73\x2c\x2f\xce\xd3\x81\xb2\x75\x4c\x9c\xf3\xcd\x22\xb8\x7e\x7a\xdd\x2a\xfb\x99\x10\xb4\x44\xa7\x7d\xdb\x9b\x17\x5d\x7b\xd8\xb4\x96\x8c\x02\x58\x3f\x09\x98\xdd\x23\x43\xe5\x60\xfd\xd0\x69\x42\x37\xee\xe1\x26\x8c\x7a\xba\x77\x6d\xe2\x1d\xae\x9c\x15\x79\x7c\x32\x00\xba\x18\xbf\x76\x9d\xd2\xa9\x10\xd2\xf9\xeb\x3a\x12\x17\x44\x67\xac\xd0\x87\xfe\x05\x43\xe4\xf0\x2f\xba\xa2\xa8\x9e\xae\xed\xb0\xf6\xb9\x09\x07\x12\x80\x79\xa2\x8e\x38\x49\x70\xcc\x09\x1c\x75\xd8\xc9\x4b\xfc\x79\x27\x89\xce\x3c\xe9\x25\x49\xe2\xe4\x6c\x86\xc6\x4e\x66\xa4\xc8\xe6\x49\x4f\x67\x4b\x56\xd2\xe8\x93\x6f\xc7\x9b\xb0\xf8\xd6\x8e\xde\x2a\x6e\x0c\x8b\x9f\xa6\x75\x2a\x99\x2a\x35\x91\xf3\x86\xb0\x27\x0e\xb6\x49\x9c\xdb\xfe\x62\xf5\x0a\xfd\x30\xd5\x88\x49\x81\x97\x25\x41\x47\x5e\x46\x02\xd1\xc8\xe6\x51\xb9\x74\x18\xb2\xf8\xd5\x02\xab\x6a\x75\xa4\x91\x44\x83\xda\x4c\xb2\xaf\xdd\x12\x16\xeb\x2f\x45\x0b\x5d\xb9\xbb\xf1\x24\xb6\x75\x84\x41\xa3\xc7\x08\x83\x1e\x61\xd0\x23\x0c\xfa\xb3\xc7\x13\x84\x41\x27\x72\xd1\x83\x33\xe1\x53\x1f\xa9\x60\xd5\xa2\x03\x71\x45\xc7\xe6\x61\x38\x3e\x2b\x9f\xfd\xf3\x6c\x61\x42\xc6\xdd\x2b\xab\x47\x03\xaa\x5a\xaa\xc8\xda\x3c\x3f\xcd\x25\x23\x7b\x7b\xd3\xe9\xde\x5e\xc0\x69\xe3\x6b\x08\x9b\x49\xd6\x66\x3e\xf9\x23\x61\x22\x93\xb9\xfd\xf6\xeb\xc8\xab\x3a\xe7\x4a\x1b\x48\x5a\xb4\x00\xe4\x54\x7b\x5e\xfa\x7d\x49\x05\xfc\x76\x6b\x19\x7f\xfd\x23\xbd\x8c\xd0\x6e\xf6\x4d\xf2\x20\xbb\x09\x8f\x63\xb5\xaf\x6b\x87\xeb\x37\x34\x0b\xc8\xd7\x38\xc5\x00\x31\x76\x90\xad\x49\xc1\x4b\x7c\x0a\xdf\x0d\x6b\x6a\x6c\x0c\xca\xb4\xd1\x64\xdf\x09\x9c\x66\x55\x1d\x6b\xce\x40\x4e\xc9\x4a\xa9\xd6\x87\xcd\x0f\x58\xc1\xc9\x66\xeb\xa5\x1f\xd8\x98\x3e\x4a\x68\x56\x2b\xc5\x84\x29\xd6\xbf\xc4\xcc\x40\x38\x2c\x4f\x20\x31\xd0\xdc\x01\x7c\x13\x9a\x76\x6c\x50\xb1\x06\xd1\xd1\xa1\x14\x60\x6d\x9a\xb5\x8f\xe0\x61\x6f\x87\x27\xc1\x3d\x6c\x20\x5e\xd1\x12\xe7\x52\x11\x26\x56\x64\x45\x95\x8e\x39\xa9\x24\x65\x2c\x9f\xf3\x15\xd7\x32\x52\xc1\xdd\x07\x4b\x49\x12\xcb\xcb\xda\x54\xb5\xf1\x7e\x63\xaa\x44\x12\xbb\xab\xa4\x66\x79\xab\x95\xe3\x34\x27\x69\xc3\x2b\xd7\x5b\xff\x15\xb6\x15\x69\x18\x15\x35\x86\x29\xf1\x9a\xfc\xf7\xfe\x3f\x7e\xfb\xd3\xe4\xe0\x9b\xfd\xfd\x1f\x5e\x4e\xfe\xf4\xe3\x6f\xf7\xff\x31\x85\x7f\xf9\xcd\xc1\x37\x07\x3f\x85\x3f\xfc\xf6\xe0\x60\x7f\xff\x87\xbf\xbf\xfb\xf6\xfa\xf2\xec\x47\x7e\xf0\xd3\x0f\xa2\x2e\x6f\xdc\x9f\x7e\xda\xff\x81\x9d\xfd\xf8\x99\x42\x0e\x0e\xbe\xf9\x75\xe4\xc4\xa9\x58\xbf\x8f\x32\xec\x04\x34\x60\xaa\x70\xa3\x2b\x2d\xc1\x75\x21\xe4\x6e\xd2\x22\xe5\x26\x5c\x98\x89\x54\x13\x27\xf8\x35\x31\x2a\x32\x97\x10\x8e\x63\x5a\x3d\x9b\x26\xbc\xe9\xce\xaf\x4d\xad\x3d\xa2\x22\x03\xbc\xec\x29\x8f\x66\x04\x3f\xf3\x72\x62\xa9\xea\x0c\x2b\x2b\xa9\xa8\x5a\x93\xdc\x23\x14\xd6\x49\x7a\x8a\x75\x9a\x8a\x0d\x46\x6e\xfa\x0a\xab\x40\xe9\xfe\x2b\x58\xb3\x9c\xab\x2f\x4c\xf1\x1d\xd9\x29\x8c\xe5\xbc\x2e\x53\x40\x69\xbe\xb7\xdb\x01\xe5\x23\x72\x1e\xd9\x27\xd8\x4d\x2a\x40\x96\x66\x34\xbb\x71\xe0\x8f\x66\xef\xf1\x00\x73\xd6\x6d\x04\xf3\xe2\x85\xaf\xd2\x28\x19\xc5\xe3\x3d\x5c\x02\x15\xea\xaa\x64\xce\xec\x91\x0a\x3f\xe1\xbe\x23\x1a\xf7\x23\x3c\x7c\xdd\x97\x17\xef\x7b\xf1\x07\x48\xb9\x52\x91\x77\x10\x28\x3c\xe2\x89\x27\x09\x7a\xd7\xf0\x7f\xb3\xb7\x36\xaa\x4a\x71\x78\xaf\xa5\xa1\x05\xa1\xbe\x71\x21\x36\xc3\x5c\xc8\x8c\x16\x4d\xe5\x65\xd7\x65\x8e\x49\xae\x37\x3a\x34\x54\xc8\xd9\x53\x6c\xbf\xde\x05\x95\x48\xa9\x5c\x13\x5a\x68\x57\x41\xc4\x33\x3a\x2b\x18\xcc\xd3\x85\x90\x51\xf7\xd6\x4d\xb0\xa4\x77\xbc\xac\x4b\x52\x6b\xbb\x16\xe8\x67\x4a\x37\x9f\xa0\x11\x9a\xa5\xb8\xb5\x9a\x01\x0f\x7c\x82\x46\x73\x5c\xc0\x04\x7b\xa0\x3a\x34\xe6\x8b\x91\xab\x70\x1e\x3b\x4f\x59\x11\x7d\x6e\x03\xce\x4b\xd7\x90\x03\xf3\xeb\x10\x95\xdf\x90\x73\xa8\x23\x69\xa2\x4e\x4d\x80\x3f\x0a\xd5\x99\xd9\x8d\x0d\x7d\x2a\x78\x91\x42\xa1\x82\x21\x59\xfa\xe3\x6d\xe5\xd6\xc2\x97\x79\x27\xa2\x1f\xd8\xad\xe6\x6a\xcd\xd4\x64\x51\xf3\x3c\x95\x82\x7b\x66\x71\x46\x44\x74\x91\x22\xa6\x48\x10\x49\x24\x8e\x1f\xe6\x59\xa4\xfb\xfb\xe6\xa4\xdf\x51\xf7\x0d\x9f\xa1\xf4\xc1\xc9\x92\x0a\xc1\x8a\x4e\x88\x60\xaf\x88\xd5\xe0\xbe\x39\x0e\x42\x26\x10\xc9\xf9\x96\x38\x7b\xfd\x9e\x38\x48\x5c\xb1\x59\x32\xd1\x04\xff\x8f\xd6\xf5\x7d\x6c\x3e\xf3\x69\xa1\x5f\xa2\xf9\x4c\xea\x0a\xf0\xed\xb6\x33\xbd\x06\x32\x58\x2f\xa8\xdf\x76\xc6\x17\xca\x2d\xe5\x2d\xc9\xb1\x10\xd4\x5b\xe0\x3c\x5d\x31\x61\x1c\xfb\xa7\x0e\x08\x97\xe8\x7d\x9b\x2b\x59\x42\x45\xaf\x92\x25\xd7\x36\x14\x00\x3f\xc6\x5d\xda\x47\xf1\xc1\x8b\x1a\x09\x69\xbb\xaf\x0a\xe3\xcd\x09\x31\x54\x2d\xd0\x65\xae\x45\x2d\x88\xa8\xcb\x19\x8b\x8a\x49\x1e\x13\xc7\x3e\x76\x04\x7a\x88\x8e\x40\x8f\xd3\x9e\xc7\x1d\xe5\xef\xbf\xbf\x48\xd2\x88\x3d\xdd\x2d\xb9\x95\xaa\xc8\x6f\x79\xee\x98\x60\x34\xd9\xb7\x53\x3c\xf8\xcf\xeb\x7f\x7e\x7b\xcb\xf3\xf4\x5b\x13\x05\x27\x83\xad\x21\xb0\x37\xbe\x63\x0a\xb7\x81\xda\x3e\x4c\x15\x9b\xf1\x39\xe3\x00\x76\x02\x19\x0e\x46\x52\xce\xb8\x88\x29\x22\x95\xf3\xce\xe1\x86\x58\xd5\x6a\xde\x38\x2a\x2f\xcd\xcc\x21\x99\xd5\x0e\x9c\x31\x93\x66\x49\x34\x2f\xeb\xc2\x50\xc1\x64\xad\x8b\x75\xd4\x25\x7e\x7e\x07\x74\x5e\xb0\x3b\xa7\xc3\x62\xa3\x90\x46\x50\x6c\x16\x7e\xc1\x04\x53\x3c\x0b\xd5\x4c\x9b\xe1\x08\x42\x26\x30\xfa\x68\x2e\x05\xcb\x8f\x9a\x4e\x9f\x35\xf8\x36\xc0\x39\xc6\x32\x84\xd0\x19\xb5\x11\x48\x55\xd4\x0b\x8e\x40\x00\x8f\x0c\x63\x9f\xfd\xdf\x3e\x24\xc3\x58\xcb\x61\x53\x6b\x16\x9b\x42\x8d\xa1\x5a\xf8\xa5\x92\x74\xfd\x87\x07\x94\xd7\xbb\x39\xb5\x72\x56\x31\x91\xa3\x33\xac\xa2\xab\x6d\xdd\xe6\x3d\xca\xa9\xf3\xc0\xee\xb4\xbe\xcd\xd9\x9d\x51\x58\x10\x60\x26\xcb\xd2\xba\x09\x01\x71\xce\xe7\x84\x8a\x38\x93\xfe\xfc\x89\x27\xc8\x18\xef\xfd\xa2\xe2\xbd\x07\x6a\xc7\x9a\x80\x08\xef\x1e\x1a\xbc\x38\x4c\xe6\x2e\x1a\xbc\x6e\x19\x37\xfe\xf0\x75\x69\xf0\x9c\x1f\xe7\x95\x69\x1c\xb5\x5c\x49\xd7\xbb\xc9\xe0\xb0\xea\xde\x31\xbe\x71\x4d\x3a\x29\xc4\xf3\x98\xea\xe1\xdd\x54\x72\x40\x0a\x87\x7f\x4d\xbb\x8f\x4a\x0e\xab\x1d\xb6\xf9\x8e\x36\xf6\x68\x6c\xa8\x3b\xf2\xca\xfd\x62\x78\xe5\xe6\x85\xcc\x6e\x30\x21\xd2\x46\x10\x0e\x52\x7a\xef\x81\x88\xaf\x09\x62\x7c\x04\xde\x84\xcc\xfd\xd7\x3c\x84\xe0\xee\xfb\x9f\x27\xd7\xf1\xae\xb0\x2b\x0d\xc5\x9c\xe1\x30\x59\xab\xc6\x94\xb4\x5a\x47\xad\x78\xc6\xc8\x8c\x59\x93\xa1\x6a\x81\x62\xe5\x78\x4c\xf2\x29\x6a\xa8\x66\x06\x8f\xd6\xef\x53\xdd\x76\x8a\xcf\xbc\x64\xac\xd5\x30\x52\xb1\x9c\x50\x4d\x4a\x66\xa8\x95\x45\x26\x7f\xf1\xc5\x6d\x31\x90\x16\x3f\x2b\x88\xbe\xc3\x66\x3a\x50\x1e\x1e\x7a\x93\x49\xa1\x79\xce\xfc\x7c\x73\x7b\x1d\x32\x34\xe1\x72\xa4\xef\xed\xbf\xef\xe3\xc7\x24\xad\xb2\xad\x98\x8d\xfd\x8c\xf2\x56\x00\xf8\xc2\xff\x55\x77\x33\xc1\x78\x6c\x1a\x6d\x76\x30\xe6\xac\x45\x2c\xf8\x22\x63\x97\x56\xa5\x6b\xc3\x84\x39\xe5\xfa\x26\x16\x5b\xfc\xed\xc9\x59\x5f\x60\x6c\x7a\xf3\xdb\x93\x33\xe2\xe5\x3c\x10\xce\xe2\x61\x81\x16\x1d\x17\x01\x63\x01\x10\x00\xd0\x45\xc6\xaa\x66\x0b\x72\xae\x6f\xbe\x30\xf6\x39\x26\xdd\x5a\xe5\x17\x98\x24\xe5\x2f\x0b\x5f\xe2\xd5\x95\x77\x27\xe0\xb8\xaf\x65\x4d\x6e\x29\xba\xc5\x52\x8b\x58\xb9\xe6\xd5\x6b\x72\x26\x74\xad\x58\x83\xe9\xc3\x22\x1f\x36\x72\x9f\x36\xe2\x0a\xe9\x46\xac\x29\xda\x95\xa4\x0c\xe9\x46\xec\x3b\xdb\x1d\x2d\xab\x82\xe9\xd7\xcf\x12\xfb\x12\x09\x06\xdf\xd2\x05\x58\xdb\xd7\x81\xe0\x6c\x83\x69\xb0\xdf\xba\x09\xc1\xd9\x06\xd3\x44\xf8\x49\x8f\x09\xc1\xa9\xa8\x32\x90\xcb\x4c\x02\x83\x07\xd6\x4e\x2f\x90\x44\x35\x01\xde\xa5\x52\xa2\xdf\x2c\xce\xe7\x44\x96\xdc\x98\xc0\xdc\xe2\x13\xf8\xf8\xbc\x58\xd0\x56\x56\x1d\xf8\x19\x5b\xb7\x39\x5e\x01\xbc\x91\x4d\x90\x76\x94\xb3\xd5\x91\xce\xe9\x2b\x6c\x1d\xa4\x5d\x3e\xed\xbb\x70\x99\xde\x0e\xa1\x1b\xd9\xbc\x78\xf5\x62\x4a\xae\x78\xc9\x0b\xaa\x8a\x75\x97\x06\xa7\x95\x8e\xd5\xd5\x52\x35\x9f\x0c\x45\x36\x2f\x5f\x90\x7d\xa9\xec\x57\x60\xf3\x8c\x54\x90\x82\xd1\x95\xcb\x18\x7b\x03\xbc\x76\x69\x3c\x24\xd3\xf9\xe0\x8e\x74\x0f\xe0\xf9\x90\x27\x81\x37\x73\x6e\x50\x0a\xe5\xf1\xd1\x05\x2b\x22\x3a\xef\x75\x79\xda\x7a\xe0\x5c\x58\xb7\x7c\x4a\x3e\x3a\x5f\x17\x7b\xd3\x5d\x00\xe5\xae\x8f\xdd\xad\x46\xee\x3b\x7c\x66\xf5\x89\x1c\x9e\x27\xf1\xf2\x14\x9e\x71\xda\x37\x1e\xbc\xf6\xd8\x78\x19\xea\xbc\xf1\x20\x65\xf6\x5e\x86\xb6\x1b\x27\xfc\x12\x34\x08\xee\xcd\x6a\xc1\xcd\x07\x56\x21\xa2\xc5\x8d\x40\xdc\x89\x89\xcd\x6d\x2e\xb8\xb1\x22\xa4\xe6\x50\xde\x4b\x0d\x74\xba\x57\x86\x67\x75\x41\x15\x51\xcc\x21\x85\x30\xdb\x75\x7a\x76\xf9\xe1\xec\xe4\xf8\xfa\xec\xf4\x35\x09\xb3\xe5\xdd\xec\x13\x46\xe8\xb5\x6c\xe1\x4b\x84\xb6\x65\x55\x8e\x60\x2d\x66\x05\x0e\xbd\x53\x42\x45\x5b\xf1\xc6\x05\x4a\xfb\x51\x41\xce\x05\x37\x6d\x9f\x49\x70\xc8\xb2\x42\x0a\xa6\x91\x2a\xda\xce\xd0\x63\xb4\x16\xdc\x1c\xba\x74\x84\x9b\xb0\xbd\xb7\x61\xc6\x08\xc9\xf6\x1b\x41\xc6\xa5\x2b\xcd\x6e\x96\x14\xf1\xa2\xf4\x68\x79\x85\xf6\x08\x7f\xe9\xec\x74\xa8\x8e\x4e\xa0\xd0\xaf\x01\xdc\xd9\x8a\x8c\x78\x4f\x6b\x99\xd0\x9a\x6e\xce\x52\x39\xf2\x2d\xa4\x54\xb8\x5f\xae\x89\xb3\x8d\x08\xf6\xa6\x7b\x21\x21\x50\x70\x96\x63\xbd\xec\x8e\x0b\xdc\x72\x0c\x78\x2e\xc7\x08\x91\x7d\xad\x36\x25\xe4\xbd\x59\x32\x75\xcb\x35\x9a\x1f\x91\xcf\x77\x13\x58\xc6\x98\xdd\x6e\x9f\xed\x0d\x3d\x1c\x15\x05\xea\x7a\xd6\x5d\x4c\xb3\xf4\xbf\xb0\x42\x97\xda\xe2\xc3\xb3\x68\x77\x29\x2c\x49\x82\xfb\xf5\xa1\x5d\xdf\x8f\x1f\xde\x3e\xce\xe7\x38\xcb\x95\xe0\x63\x4e\x64\x59\x72\x43\x96\x54\x2f\x43\x73\x2b\xec\x43\x56\x53\x39\x1d\x63\xed\xe3\x9e\x29\x5c\x43\xd7\x39\x42\x05\x6f\x78\x45\x41\x50\xf4\xb3\x44\x23\xc8\xd3\x13\x88\x36\x73\x89\x6e\x06\x44\x15\x74\x36\xfb\x19\x0e\x94\x88\x27\x04\xe6\xd3\x20\xd3\x9b\x3f\x82\x23\xec\x5d\xde\xa3\x66\x6d\x8f\x3e\x9c\x1d\x9f\xbe\x3b\x9b\x96\xf9\x33\x32\xec\x4c\xe4\x95\xe4\x98\x5d\x44\x76\x5e\x88\x73\x07\x9a\xe9\xa6\x88\xef\xce\x82\x30\x78\xb4\x46\xe3\xb0\x81\x1e\xcc\x8b\x72\x89\x02\x70\x47\x73\x66\x28\x2f\xb0\x42\xdb\xfb\x61\x64\x25\x0b\xb9\x58\x47\x1e\x63\x82\x3b\xca\xbf\x72\xd4\xaf\x13\x3a\xb1\xb7\xea\x71\x72\xc1\x58\xe6\xde\xfe\x6e\x07\xb6\x5d\xbb\x5d\xcd\xea\x22\x17\xb2\xc9\x2a\x02\xd5\xec\x76\xc8\xfc\xac\x16\xf8\x89\xa7\x4c\xda\x9b\x10\xb2\xef\xd8\x84\xd9\x8c\x39\x63\xc3\x72\xe7\xb5\x35\x1d\x30\x49\xc5\x54\xc9\xb5\x35\xcd\x68\x80\xd7\x76\x06\xe6\x79\xdf\x57\x5c\xf2\xc5\xda\x6f\x5c\xa3\x87\xfe\x39\xfa\x9b\x97\x13\xeb\x66\x54\x8a\x4d\xd8\x1d\xd7\x90\x6b\x03\x12\x77\xa9\xa2\x02\xc0\xae\x9f\x12\x00\x0f\x01\x50\xe1\xe4\xa2\x60\xdf\x1b\xc0\x87\x36\x47\x10\x50\x33\x98\xc4\x0b\x13\x4c\xd1\xa2\x58\x03\x69\xbf\x6b\x91\xe9\x9e\x09\xe9\x02\xb9\xa0\x52\x79\x4c\x64\xa5\xf8\x8a\x17\x6c\x61\xa7\xbc\xe4\x62\x81\x66\xdb\xa7\x8a\x11\x5a\x14\xf2\x96\xf9\xf6\x1b\x6c\x6b\x7d\x31\x37\xf2\x9d\xfd\xef\x3b\x9c\x40\x10\xf2\x5e\xbc\xbf\x26\x82\xb9\x29\xa3\xee\x79\x64\x72\xd4\x7e\x14\xb2\x5b\xd5\x64\x32\x81\x37\xe4\xfd\xff\x91\x82\xe9\xbc\x38\x20\xdf\x33\xff\x2d\x92\x28\x66\x75\x3f\x0a\x5f\x7c\xbb\x94\xf0\x12\x55\x6b\xbf\xe6\x6d\x60\x0b\xaa\x12\x75\xeb\x44\x1e\xe4\x1e\x59\xd9\x42\x1a\xef\xe4\xf7\x7e\x01\x47\xf7\x4a\x35\x69\xab\x37\x9e\x53\x06\xed\x11\x9c\xe5\xa4\x9e\x53\xc0\x00\x46\x26\xcf\x3a\xfa\x33\x54\x15\x38\x06\x7b\xb4\xfb\x4d\x89\x5e\x97\x05\x17\x37\x87\x84\x9b\x50\x89\x63\x35\x4a\x44\xc8\x6e\xc5\x05\x5d\xac\x18\x2d\x3a\x9e\xde\x17\x7f\x57\x0b\x5a\xe3\x51\x7c\x43\x93\x08\xd8\x75\xbd\xae\x5c\xbd\x6b\x30\xec\x51\xaf\x5e\x3d\x67\xeb\xc5\x8b\x74\x8e\xd6\xb3\xd8\x17\xae\x33\xcd\x63\x1d\xac\xf3\xab\x93\xab\xf3\xde\xe3\x16\x26\x77\xe9\xa4\x8c\xf0\xd2\xfb\x1c\x74\xd8\xaa\x67\x99\x17\xe2\xff\x1a\x7e\x1e\x26\xa4\xa8\x31\xff\x95\x23\xdd\xb8\x94\xca\x20\x48\xf3\xe3\x4c\x64\xb6\xa4\xd5\x71\x6d\x96\xa7\x5c\x67\x72\xc5\x92\xa4\xc1\x6f\x97\x0c\x7c\x64\x0f\xe6\x24\xdc\x5e\x12\x6c\x54\x19\xe6\x45\x4e\xfe\x76\x7c\x49\x68\x6d\xcf\xb1\xe1\x19\xbe\x14\x31\xb6\x1c\x34\xac\xd8\x15\xd3\x89\x32\xed\x29\xd7\xcb\xcf\xea\xc9\xac\xd6\x08\x8d\x46\x8d\x11\x1a\xfd\xf4\xa1\xd1\x60\xdb\x90\x53\x19\xe1\xd0\x83\x06\x17\xdc\x70\x6a\x64\x44\x4b\x9d\xfe\xdb\x66\xad\x8d\x2c\x9d\xa2\x05\x24\x0d\x08\x47\x2e\xce\x05\xc0\x21\xce\xe7\xfd\x59\xf6\xea\xc7\x63\x20\x11\x70\xcc\xce\x85\x61\x6a\x4e\x33\xb6\xc1\x9e\x85\x45\x1b\x08\x76\xeb\xbf\x9e\x37\x92\xff\x1c\xc5\x3e\x57\x81\xf7\xf2\x97\xd7\x7f\xee\x00\xae\xff\x12\x89\xb4\xf0\x5d\xf7\xc2\xf3\x33\xc9\xa4\x10\x2c\x33\x8f\xf1\x80\x6c\x07\xff\x57\x0a\x6b\xef\x41\x38\x6e\xf5\xff\xaf\x9a\x16\x31\x27\xe4\xe2\xb1\x70\x13\xfd\x53\x99\x60\x59\xc2\x5d\x0c\xa7\x11\x55\xc6\xe5\x06\xd8\xde\x5a\x33\x1b\xd3\x79\xb9\x46\x51\xa1\xed\x11\x4d\xf1\xba\xb1\xe7\x0b\x14\xf6\xc8\xbe\xc9\x2a\x24\x56\xfd\x49\x70\xb4\xba\xc5\xf1\x27\xf2\x2d\x22\x76\x71\xc3\x71\xb3\xc6\xac\xc3\xa3\x62\xe5\x41\x73\xa5\x78\x50\xef\x2d\x27\x32\x9c\x73\xe3\x2d\xd7\xc6\x75\x5c\x70\xb3\xb3\xd6\x84\x39\xbe\x47\x94\x1b\x6e\xc7\xf9\x25\x91\x8a\xf0\xea\x9f\x34\xcf\xd5\x6b\x17\x69\xf8\xfc\xa3\x44\xa3\xf6\xb8\xf6\x0f\x22\xc0\x48\x12\xa8\xb7\xf6\xcd\xba\xe2\x19\x2d\xd0\x0c\x40\xd7\x27\x97\x30\x2b\x4d\xfe\xf8\xb5\x6b\x13\xfd\xbb\xaf\xbe\x7e\x19\x75\xd5\x9e\x1f\x57\x24\x49\xfb\x36\xfd\x9f\x87\xe6\x7f\x4a\xcc\x4f\x10\x90\x3b\xce\x27\xf0\x67\x62\x82\x7c\xe7\xa8\xc1\xb5\x68\x7c\xce\x74\xc1\xfe\xc8\xd5\xd3\x1b\x23\x57\xcf\x63\x73\xf5\x90\xe6\xc8\x3b\x9b\xfa\x30\x96\x3a\x86\x72\xf2\x72\xdb\x48\x3b\x73\x8b\xb5\xaa\xf7\x18\x69\xfc\x23\xe1\x33\x31\xd2\xa8\xf3\x81\xd3\x19\x7d\x5d\xe1\xec\xcf\xde\x9e\xee\x54\x37\x20\xbe\x03\x98\x57\x4f\x2f\xae\xfe\xf9\xf6\xf8\xaf\x67\x6f\x61\x4d\x3c\xdb\x8b\xbd\xfc\x28\xeb\xb8\xe3\xa1\x26\xb1\xfa\xc1\xbe\xca\xe0\x36\x2b\x1e\x83\x7d\xf1\xe6\xaa\xff\x70\x47\x2e\xde\x5c\x21\x56\x76\x37\xf0\xba\x81\x51\xa3\x42\x89\x1e\xf0\x3a\x36\xc3\x28\xe6\xe8\xbd\x79\x2e\x00\x8f\x09\xf0\x87\x7d\x71\x82\xec\xa4\xc8\x90\xf0\xe0\xcb\xee\x52\x24\xe8\xed\xe9\x76\x6b\x92\x10\x40\xf9\xe0\xa7\x8e\x3c\xa9\x50\xe7\x21\x60\xb8\x76\x5f\xdc\x0e\xfb\xb7\x08\x0f\xa5\x8d\xc9\xed\x3e\x1b\x00\xee\x17\x3c\x3f\x31\xe1\x9a\x4a\xc3\x7a\xbf\x77\x05\x92\x02\x58\xde\x9a\x86\x18\xea\x7b\x65\x7d\x41\xeb\xcf\x31\xad\xc3\x03\x64\xe7\x96\x23\xc5\x3e\x86\x6d\x21\x71\xb7\xbc\xad\x8c\x77\xee\xd6\x49\x41\x39\xa2\x4b\xf1\x86\x0a\xde\x25\xd4\xfd\xeb\x15\x00\x72\x50\xaa\xa8\xd3\xdf\xaf\xc7\xb2\x4c\xc9\xce\xdf\x43\xbd\x69\xb9\x5a\x4a\xea\x1f\x4b\x74\x45\xb3\x54\xa5\x5a\x9f\x73\x10\xda\xcd\x98\x84\x33\xd1\xfe\x95\xfb\x9b\xcc\x7e\xda\x73\x72\x41\x60\xc2\x8f\x40\x00\xd7\xfc\x6e\x0a\xe5\x73\x12\x84\x79\xfd\x13\x91\x49\x81\xe6\xb0\xc9\x4e\x2c\xb9\xef\xd4\x12\x1a\x33\xd1\x4a\x86\xe6\x30\xd0\x0e\x3c\xf4\x43\xfe\xa2\x58\xd3\x07\xbc\x0c\xe4\x49\x79\x46\xdf\x7f\x11\xa2\xfe\xe0\x8b\x60\x9d\xae\xc7\x49\xf9\x56\x4b\x69\xa4\x48\x4a\x67\x7a\xb9\x43\x64\xac\x3d\x72\x32\x4f\x1c\xfd\x72\xc1\x54\xc7\xac\x22\x44\x03\x6f\x52\xc3\x38\x4d\x45\xde\x94\x88\x49\x11\x20\xa8\xb1\xd4\xd3\xcf\xc7\x80\x54\xf9\xf9\xe9\x17\xb6\x1d\x63\x2b\xa1\xa7\xd9\x4a\xe8\xcb\x80\xd0\x1e\xc3\x9c\xd8\x43\x9e\xe0\xbc\x9d\x9f\xfa\xcc\x47\xe0\xb1\xc6\xe6\xa6\x9d\x42\x23\xa9\x34\x1a\xf1\x5a\xed\x8b\x47\x37\x52\x99\x5b\xa9\xd2\xb4\xf7\xbb\xec\x09\x8b\xae\x02\xf5\xd2\xb6\x3a\x0c\x74\xf4\x3d\x42\x70\xc7\x42\x3c\x53\x7d\xef\xd6\xe3\x19\xeb\xfc\x2b\x28\x2c\x8a\x3a\x1e\xc4\x3f\x32\x6c\x62\x8e\x03\xb0\x19\x9b\x9f\xd8\x61\x3e\x36\x0c\x41\x5c\xa2\x34\x31\x92\x79\xc3\x7c\x4c\x3b\x06\x00\x1f\x86\x6c\x9b\x8d\xa7\x60\x00\x12\xc6\x13\x5b\x49\x47\xe4\x5a\xed\x6e\x49\x06\xe9\x5b\x74\x82\x75\x67\xa4\x13\x62\x16\x7c\xfc\xdb\x8b\x74\x1e\x25\xd1\x19\xb4\x56\x82\xfd\xfb\xce\x8b\xf2\xcf\x94\xf8\xb3\xde\x38\x01\x36\x42\xe9\x9b\x9b\x2f\x6e\x88\x95\xb4\x86\x04\x63\x11\xfa\x0e\x8e\x61\xa5\x06\xb0\x0e\x2d\x0a\xbb\xf3\x12\x61\xda\x48\x53\x18\xa8\x43\x83\xae\x43\x92\x49\x31\xe7\x8b\x92\x56\xfa\x10\x59\xce\x97\xcb\x5b\x71\x4b\x55\x4e\x8e\x2f\x87\xa3\x88\x1e\xcd\xdc\xfa\x85\xf8\xc2\xd6\xd6\x03\x1e\xde\xc9\x3c\x85\xc9\xb5\x62\xc8\x8c\x3b\x95\x57\xa3\x15\x9e\x14\x2d\xbc\xdd\xda\x47\x6b\xd5\xfc\x44\xd1\x2f\x02\x8d\xc5\x5d\xd1\xa2\x66\x64\xc6\xcc\x2d\x63\x82\xbc\x44\x9e\x31\x3b\x5e\xfe\xe1\x0f\x7f\x98\x92\xd3\x96\xb2\xc0\x03\x19\x62\xf2\x7d\xd4\x2c\x81\xf6\x42\x48\x43\xe8\x7c\x0e\x57\xd5\x19\x75\x34\xbc\xc5\x2b\x75\xcf\x16\x52\xf2\xc5\x12\x56\x82\x0b\xb8\x6a\x05\x8e\x1b\x82\x84\x67\x3a\x07\x9e\x09\x4d\x4e\x21\xe8\x71\xf3\x8e\xf4\xb6\x48\x29\x73\x76\x48\x0a\x7e\xc3\xc8\x5c\x7f\xab\x64\x5d\x61\x0b\x3a\xac\x23\xef\x8a\xf5\x75\x5d\x18\xa0\xb4\x98\x31\x37\x71\x74\x16\x20\x9c\x73\x74\xcb\xa3\xc7\xc7\x76\x7b\x85\x93\xe0\xda\x17\xdc\x7a\x9b\xf3\x86\xf9\xca\xd9\x18\x7b\x20\x22\x96\xe6\x91\x30\xc9\xfd\x48\xb3\xf9\x12\x2c\x85\x8d\x1b\xbe\x0d\x67\x63\x7c\x09\x2d\xa4\x58\xc0\x05\x42\xcb\x94\xdd\xba\x58\x96\x37\x65\x9b\xeb\x0a\x9d\x6c\x88\xc6\xb8\xa6\x40\xb9\x12\xef\x01\xbc\xa3\x15\x5e\xc4\x26\xa4\x31\xba\x45\xab\x1b\x74\x26\x6b\x13\xca\xad\xdc\x1c\xa1\xb9\x58\x94\x50\x23\xc3\xc1\x88\x10\x93\x60\xeb\x48\xa2\xed\x23\xb1\x57\x30\x8c\xbe\xc3\xd9\x0b\x0d\xb1\xa6\xa0\x1d\x8c\x66\x4b\x72\xc3\xd6\x13\xe7\x0f\x54\x14\xc5\xdf\xdd\x1f\xfe\x01\xf0\x94\x1a\xea\x50\xc6\xd1\x12\x3d\x22\xa2\x79\x66\x8f\x97\x78\xd2\x1c\xdc\xb8\xfa\xc3\x76\xb4\x5a\x2d\xb0\x99\x47\x8b\x0c\xa9\x38\xed\x33\x24\xe4\x76\x29\xd1\xde\x64\x3b\x44\xfb\x70\x6c\xb7\x3e\xc2\xf5\x6b\x47\x26\x85\x61\xc2\x04\xb1\x70\x9a\x62\xb0\xe5\x6e\x9c\x6f\x32\x5e\x47\x4b\xb4\x36\x9a\xe5\xf6\xb3\xf5\x53\xde\xf9\x96\x0f\xd9\xba\xc2\xe8\x10\xb0\x3f\x6a\xb1\xf9\xf5\xf1\x47\x49\x1a\x67\xd1\x21\xb5\x38\x25\xe7\xd8\x2e\x95\xed\xa0\x70\x26\x13\x94\x46\xb7\xe3\x76\xc9\x33\xe0\x35\xb5\xd3\xf5\x73\x4d\xa5\xe5\x1a\x45\x12\xaf\x8b\x3b\xac\x13\x9a\x99\xba\x4a\xb3\x45\xc0\x17\x60\xf7\x9e\x69\x4d\x78\x44\x7d\x40\x3b\x4a\xaa\x6e\x58\xee\xa3\x1d\x5a\x4c\xc9\xa5\x3d\xa4\xf1\x62\x7d\x70\xaa\x58\x41\xa1\xa5\x7c\x8a\x43\x6f\x7d\xce\x6e\x0b\x82\x14\xb7\x73\x6f\x3a\xdd\x73\x31\x6a\x64\x43\x83\x76\xb4\xad\x0d\x22\x45\xc5\x46\x0d\xed\x48\xe2\xbc\x6c\x66\x46\x68\x15\x7f\x4e\x80\xcf\x0e\xb2\x7e\xa0\x2a\xd0\x8f\xd8\x7d\x89\xb0\x9f\x3e\x73\x11\xe7\xc9\xba\xe1\x41\x4a\xf1\x5a\x21\x8d\x4b\xeb\x06\x3e\x33\xb7\x39\x26\x76\xed\x13\x48\x41\x92\x7d\xf6\x47\x2a\x7f\xdd\x8d\x1b\x86\x7c\xf6\xd8\x1c\x7d\x52\x87\x04\x8a\xc7\x0d\x77\xe8\x83\xdb\x11\x7f\xc2\x48\xfc\x73\xd1\xe6\x28\xd1\x89\xd4\xcd\xd1\x07\x3e\xbe\xf7\x26\x27\x8d\xec\x6e\x06\x2b\x89\x16\xb1\xa3\xd6\xcc\x15\x0c\x25\x30\xb4\x6e\x58\xd7\xff\x30\x58\xc7\x44\x32\x37\x12\xc0\x89\xa4\xba\x12\x3f\x48\x08\x27\x92\x78\x3e\x07\xeb\x9d\x30\xe2\x75\xa3\xdb\xf4\xa7\xcd\xfd\x27\x12\xee\x03\x0b\xe0\x94\x4e\xb5\x10\xbd\xac\x75\x22\x99\xf1\xb9\xef\xcd\xb1\x9d\x0b\x4f\xb6\x5f\xb1\x19\xf5\x6d\x89\xdd\x0c\x7b\x22\xa1\x29\xf2\xf4\x9b\xa3\x9f\xb7\x4f\x24\x34\x41\xf6\x7f\x73\xf4\x5f\x03\xf0\x65\xe0\xdd\x11\xff\x3c\xb0\x39\x62\x9f\x0b\x36\x07\xbe\x4c\x70\x73\x3c\x90\xb7\xd0\x44\x53\x49\x3c\x2d\x37\x7c\x3e\xce\x5e\x9f\x54\xb7\x51\x92\x92\x56\x21\x25\x95\x4c\xe8\x94\xbc\x73\xf1\x5f\x22\x89\x33\x1b\x94\x12\x3a\xd3\xb2\xa8\x4d\xaa\x6f\xf7\xc4\xd9\x49\x27\x9a\x32\xdc\x75\x03\xe2\x23\x56\xb0\x32\x45\xf2\xc4\x0d\xd7\xca\x2f\xed\x87\x43\x38\xde\x74\x9c\x4b\x26\x14\xa2\xcd\x14\xf1\xb9\x1b\xc9\xdc\xed\x38\x32\x14\x37\x76\x52\xa2\x24\xc9\x66\xf5\x89\x51\x12\xa4\xdc\x9e\x14\xb1\x8a\x1b\xbb\xe9\x55\xa2\xc5\x7a\x7a\x96\x2e\xc9\x4a\xb4\xcc\x14\x24\x2d\x6e\x24\x3b\xbf\x32\x51\x40\xd7\x3b\xc3\x57\xae\x67\x7e\x82\xbc\x31\xf3\x9c\x28\x9d\x3c\x6f\xfc\x63\x96\x22\xd6\x49\x82\x24\x7c\xaa\xa0\x2e\x67\x73\x2e\xa2\x33\xe5\xb1\xa0\x43\x3f\x17\x8f\x3b\x3b\xbe\x3c\x7f\xc2\x2f\xd7\x9d\x59\x46\x49\xcc\xa9\xa1\xe3\xdb\xf5\x7d\x63\x07\x58\x32\x41\x5a\x84\x36\x50\x9b\xd3\x76\x17\xbf\xc3\x03\x49\xbb\x23\x81\x4f\xfb\xb4\x53\xf0\x5b\x4b\xf6\x26\x8d\x17\xdf\x29\x40\x4c\x75\x5b\xdd\x30\xd2\xc3\x20\x53\xc6\x1c\xde\x3f\x76\x25\xc5\xc0\x9e\x94\x40\x68\x1a\xb0\xc3\x93\x4d\xf8\x3f\xc1\x54\x3d\xac\x38\x9a\x7d\x71\x73\x6c\x12\xc4\xa4\x5a\x3a\x37\xae\x58\x61\xbd\x4f\x92\x0a\x14\xe3\x86\x0c\xd4\x6f\xc9\xe6\x09\x64\x33\x54\x08\x69\xe0\x06\xeb\x64\xb9\x31\x3a\x63\x85\x3e\x24\x11\x3c\x29\x9b\x83\x8a\xbc\xa5\x18\x48\x25\x53\x75\xca\x8f\x92\xa6\xb1\x12\x5d\x69\x92\xf4\x5a\x13\xb8\xda\x70\x22\x23\x7a\x4e\xf5\x47\xda\x3b\x4e\x7a\x54\x93\xa9\x24\x6e\x16\xb9\x38\xe9\xc9\x84\x37\x17\x53\x67\x4b\x56\xa6\x78\x4f\x0e\xc3\x0a\x7d\x93\x74\xbb\xdc\xe0\x9a\xdc\x2a\x6e\x4c\xb2\xc7\x20\xe2\x41\x32\x4c\x95\xa9\x5e\x01\x08\xac\xeb\x61\x78\xb2\x49\x29\xd6\x48\xf2\x62\xf5\x0a\x5d\x0a\xbe\x43\x60\xda\x17\x55\x12\xac\x1d\xae\x75\xec\x7d\xa3\x8f\xf3\x4e\x7b\xa2\x9a\x2c\x71\x3a\x6b\x47\xdc\x4e\x69\x30\xa5\x89\xcf\xa9\xbd\xac\xc9\x20\x67\xed\x38\xbe\x3c\x27\x2b\xa7\x5d\x9e\xec\xe1\x1a\x9f\xeb\xc7\xe7\xfa\x24\x63\x7c\xae\xf7\x63\x7c\xae\x1f\x9f\xeb\xc7\xe7\xfa\xf8\xf1\x4c\x9e\xeb\x93\x27\x0b\x2e\x5d\xbf\x67\x92\xf0\x11\xf3\x21\x80\x00\x22\x49\xff\x84\xee\x80\x3b\xee\xd8\x30\x7c\xf1\x73\x2a\x95\x0c\xb5\xcf\xae\x60\x21\xd5\x55\xf7\x38\x00\x3c\x8b\xff\xe6\x48\xff\x6c\xbf\xb7\x37\x9d\xee\x39\xb4\x7a\xd2\x85\xb4\xf6\xd2\xcc\x27\x7f\x4c\x24\x93\x89\x4c\xe6\x2c\x9f\x26\x04\xbe\xcc\xb9\xd2\x06\x52\xe8\x29\x9e\xb3\xdd\x70\x8a\xdd\xdd\xa3\x94\xb8\x8a\xd2\x9f\xcd\xf4\x20\x08\xb7\xff\xff\x3f\x7b\xef\xfe\x1c\xb9\x6d\xe5\x8b\xff\xee\xbf\x02\xa5\xa4\x4a\x52\xa2\xee\xb1\xb3\xae\xdc\xdc\xb9\x5b\x9b\x92\x25\x8d\x57\xd7\x33\x63\xad\x34\x33\xa9\xfb\x75\x7c\xf7\xa2\x49\x74\x37\x22\x36\x41\x13\x60\x6b\x3a\x9b\xfd\xdf\xbf\x85\x83\x07\x41\x36\x49\x80\x0f\x3d\x26\x6e\xfe\xe2\x71\xab\x79\x1a\x8f\x83\x83\xf3\xfc\x9c\x29\xc5\xfb\x64\x56\x87\x41\xbd\x78\xf3\x88\x4e\x5c\xed\x74\x9d\x4c\x0d\xb7\x2d\xbc\x27\x65\x29\x7d\xec\x87\x22\x53\xef\x3f\xe0\xc3\xb5\xa8\x22\x93\x69\x4b\x1b\x0a\xcd\x14\x62\xf0\x3f\x12\x3e\xd9\xba\x9e\x28\xd2\xf3\x28\x2b\xa6\x53\xed\x80\xe2\x86\x6c\x58\x3e\xb8\x07\x66\xfd\x31\xd3\x96\x03\x9d\x50\x5d\xb4\x64\xd5\x68\x4f\x27\xf4\x64\x47\x45\x9e\x93\x74\x38\x40\x55\xfd\xf9\xd5\x79\xc6\xcd\x21\x7a\xa1\x8e\x71\x2b\x39\x86\x43\x4b\x37\x3d\x35\xb8\x69\xf3\x23\x13\xba\xc5\x20\x71\xcd\xee\xd6\x84\x84\x97\x2c\xd7\xae\x82\xc9\x22\x57\xc8\x49\x54\x9a\x78\xa4\x24\xdd\x4e\x48\x71\x8b\xf3\x81\xf0\xd3\x4d\xcf\x23\x78\xb0\x63\xba\xa5\x9c\x4d\x76\xcd\x35\xe6\x7d\x0d\x47\x19\x6d\x7a\xe4\xf5\xcc\x0a\x91\x15\x53\xba\x9b\x95\x55\x3b\x9d\x0e\x81\xf4\x40\xc9\xe7\x8c\xf1\x49\x4f\x93\xd5\x21\xa6\x3c\x4b\x8f\x14\xbe\xf9\x66\x28\xe0\xee\xfe\x93\x61\x21\x48\x9e\xbe\x46\xff\xf7\xe4\xaf\xbf\xff\xc7\xec\xf4\xcf\x27\x27\x3f\x7d\x3d\xfb\x9f\x3f\xff\xfe\xe4\xaf\x73\xf8\xc7\xef\x4e\xff\x7c\xfa\x0f\xf3\x3f\xbf\x3f\x3d\x3d\x39\xf9\xe9\x87\x77\xdf\x7f\xb8\xb9\xfa\x99\x9e\xfe\xe3\xa7\xb4\xd8\xdc\xab\xff\xfb\xc7\xc9\x4f\xe4\xea\xe7\x40\x22\xa7\xa7\x7f\xfe\xed\x64\x53\xc0\xe9\xee\xc7\x89\x54\x6a\x04\x37\xe1\xf4\xce\x1d\x97\xee\xa4\x62\x06\xa1\xcf\xb3\x32\x3d\x78\x46\x53\x31\x63\xf9\x4c\xfd\xc4\x6b\x24\xf2\x62\x3a\x9f\x8a\x3a\x1e\x8f\x75\xf3\x4e\xed\x56\x42\xce\x98\x1f\x23\x24\xf7\xc2\x2e\x1f\x85\xa6\xf8\x82\xb3\x50\xd5\x00\x0f\xe0\x49\x4d\xcf\x01\x3c\xe9\xa5\x82\x27\xe9\x1e\xc5\x26\x6e\x66\xf1\x6f\x26\x98\xbc\xc2\xcf\x29\x91\x8f\x46\x93\x74\x91\x93\xa6\x49\x3d\xab\x22\x27\x19\xe4\xa3\xa9\xc8\x2a\xe4\xa4\x2a\xf2\xd1\xf8\x94\xd2\x35\xd9\x43\x3e\x1a\x4d\xb4\x82\xe4\x27\x77\x6e\x92\x61\xd6\x91\x8f\xc6\x33\x00\x34\x58\x75\x66\x3f\x9a\x22\xf0\x7d\x0d\xf9\x68\x34\xd1\xeb\xe5\x97\x86\x7c\xa4\xa4\xc0\x34\xb0\x5c\x07\xd8\xa3\x03\xec\xd1\xa8\xe7\x65\xd7\x5c\x1c\x60\x8f\x7a\x3f\x2f\xb6\x0a\xe2\x00\x7b\xe4\x7b\x0e\xb0\x47\xe3\x9f\x43\x1e\xe5\x21\x8f\xf2\x90\x47\x79\xc8\xa3\x3c\xe4\x51\x1e\xf2\x28\xa7\xa0\xf8\x85\xe4\x51\x1e\x60\x8f\x26\x21\x7a\x80\x3d\x3a\xc0\x1e\x4d\x42\xf4\x00\x7b\xd4\xf7\x39\xc0\x1e\x8d\x7a\x0e\xb0\x47\xbd\x9e\x47\x87\x3d\x52\x4e\xde\xf1\x31\x28\x8b\x79\xf4\x4f\x09\x79\xc4\xe5\xb1\x8b\xc8\x79\x14\xb1\x22\x15\x1f\xd8\x3d\x19\x55\xa7\xfe\xe8\x41\xe7\xbd\xd1\x8e\xa2\xfc\xe2\x20\x90\xa6\x70\xf7\x8d\x76\xd1\x4d\xe5\x9c\xc3\x45\x4c\x49\x3a\x3e\xc5\xa4\xc2\x54\xe7\x9a\xe8\x54\x51\x4b\x69\xaa\xa4\x31\x89\xed\x68\xa7\x8a\x5a\x0b\xc9\x9d\x73\x74\x8e\x72\x12\xd1\x8c\x4e\xa1\x84\xb1\x25\xc2\x8a\xae\x92\x45\xba\x2f\xe9\x78\xb9\x49\x05\x27\xc9\x52\x29\x61\x38\x2d\xfb\x9d\x8e\xb7\xe0\xca\xa0\xa8\x8e\xbd\x3d\xca\x32\x4f\xd3\x65\x06\xd4\x81\x07\xca\x09\xe2\x6b\x56\x24\x31\xca\xc9\x24\x3e\x7c\x87\x1b\x3e\x4c\xb9\x02\xb1\xd3\x9e\x18\x58\x79\xba\x6d\xd3\x8b\x8b\x33\x2a\x45\x2e\xc9\xa7\x09\x72\x4d\xa0\x7e\x90\xcf\x19\xcd\xe1\x4a\xb9\x23\x11\x4b\xe3\x69\xd3\x6c\xae\xea\xd4\xa7\x92\x32\xba\x4e\x82\xc4\x28\x2e\xf2\x69\xe0\xc5\xd8\x12\x6d\x71\x42\x63\x2a\x76\x53\xd5\x31\xea\xeb\x15\x61\x75\xbf\x6a\xa6\x1d\x4d\xf6\x9c\x97\x47\x00\xe1\x2c\xcb\x19\x8e\xd6\x13\x28\xf2\x25\x2f\x9c\x29\x3f\x84\x6a\xd7\x3f\x55\x48\x3f\x4b\x8a\x15\x4d\xa7\x89\xe9\xc3\x9c\x05\xdd\x92\x64\x87\x72\x26\xf0\x04\xae\x08\x47\x1f\x32\x1b\x36\x9e\x66\x29\xa5\xa6\x5a\x4c\x70\xad\x2b\x1b\x5f\xe4\xbb\x29\x82\x55\x82\xe9\x25\x2c\xb9\x6a\xfc\x31\x75\x2e\x13\x79\x66\x59\x12\x4f\x20\x45\xc5\x1a\xa7\xe8\x4f\x5f\xa3\x8c\xe4\x11\x49\x27\xc9\x9a\x87\xc8\x17\xdd\x40\xa1\x71\x42\xb7\x93\x14\xf0\x3e\xe2\xe4\xff\xf0\x2d\x5a\xb3\x22\xe7\xf3\xcb\xa9\x12\xe7\x05\x43\xdf\x00\x4d\x70\xb3\x4b\x35\x68\x8a\x74\x30\x2c\x50\x42\x30\x17\xe8\x9b\xaf\xd1\x86\xa6\x85\x20\x03\xbb\xdf\x3b\x03\x9d\xd0\x13\xee\xf8\xc0\xff\xf8\xed\x28\x5a\x53\x78\xbf\xf7\x90\x97\xa6\x48\x51\x02\x28\x40\x49\x6b\xb2\x22\x65\xad\x15\x6d\xe0\x2a\xcb\x18\x9d\x46\x01\xb7\x51\xa8\x49\xcc\x46\x3d\xd2\xf2\xf4\xa5\x82\x3d\xa3\xae\xf5\x4b\xc1\x16\x3b\x31\xc0\x60\xab\xb0\xc4\x7f\x28\x2a\x2e\xae\xea\x90\xfc\x1c\x43\x46\x6d\x20\x53\xe6\xc3\x9a\x71\xa1\x62\x8b\x7c\x8d\xf3\x41\x4a\x04\x46\x19\x8b\x8f\x39\x4a\xe8\x92\x48\x51\xda\x9b\xc4\x28\x5b\x7f\xb8\x85\x3f\x43\x39\x59\x51\x2e\xf2\xfe\xf6\xde\x4c\xeb\x34\xbd\x5f\x1c\xe7\x0a\x58\xe5\xac\x18\xd8\x03\xba\xc2\x50\x10\x9d\x35\x11\xa7\x81\x33\x51\x0f\x8e\x22\xc2\xc1\x60\xd2\x17\x92\xca\x30\x55\x23\x1d\x44\x73\xa4\x65\x93\x13\x1c\xff\x98\x26\x03\xf3\x97\x2a\xab\x74\xab\x49\xa1\x35\xc9\xc9\x18\xb5\x75\xc9\xf2\x48\x29\x57\xe6\x08\x9a\xd6\xe4\x43\x53\x6e\x16\xfa\x14\x93\x58\xf9\x18\xe4\xac\x67\x50\xe9\x9f\x91\x7c\x43\x39\xa7\x2c\x1d\x7c\xe1\x5e\x3a\x66\xf0\x12\x27\x7c\x60\x0a\xdf\x58\x7f\xaa\x39\x9c\x93\xec\xa4\x22\xe5\x48\xd0\xa1\xfc\x8e\x38\x4d\x57\x89\x54\x13\xd1\xa6\x48\x04\xcd\x12\xbb\xab\x03\x49\xda\xc1\x69\xe3\x63\x7c\xd2\x37\x74\x89\xd6\x11\x3b\xcc\x41\xc4\xbf\xce\x58\x2e\xc6\x94\xa5\x9c\xd8\xd9\x92\x54\xe4\x94\x70\x85\x8e\x4b\x32\x9c\xe3\xe1\xf5\x1e\xc0\xbc\x11\xdb\x6c\x30\x3f\xd5\x19\xea\x18\x80\x91\xf9\x08\xfb\x5b\x9a\x06\x39\x4e\x2c\x03\xb9\x75\xe0\xcf\x21\x92\x04\x49\x71\x3a\xb0\xf4\xac\x9a\x12\x01\x84\x10\x7b\x30\x60\xe5\x03\x17\x68\x45\xb7\x24\xad\xcb\xa2\x51\xa1\xf2\xef\x70\x74\x4f\xd2\x18\x7d\xe4\x46\x22\xc5\xbb\x14\x6f\x68\x84\x93\xc1\x78\x13\x59\xce\xb6\x54\x0a\x32\x12\xd7\xc6\x3a\xb8\x14\x44\x65\xfc\x51\xc8\xcf\x41\x8b\x9d\xd2\x91\xc1\x2b\xf1\x1c\x7c\x51\xf0\xa1\x28\x2f\x15\xae\xf8\xc8\x49\xfe\x38\x77\x39\x57\xd5\x9c\x39\xdd\x46\x64\x9c\x47\x44\x4e\xf5\x39\x96\x58\xad\xc7\x04\x8b\xfc\x49\x1f\x92\x52\xb2\x0e\x5c\x09\x50\xb5\x6d\x01\x1e\x87\x64\x9a\x44\x5e\xdf\x3b\x03\x72\x36\x90\x70\xed\x38\x2f\x76\x90\x19\x31\xe6\xea\x1e\x34\xcf\x7c\x31\x40\x13\xaf\x55\x3a\x7f\x77\x59\x31\x75\xd0\x2d\x8e\xd9\x10\xc9\xfd\x5d\xc2\xa2\x7b\x74\x49\xc0\xa5\xd7\x6c\xf5\x0c\xa0\xaa\xec\x24\x6d\xf5\x38\x66\x8f\x4a\xf1\x50\x29\x1a\x03\xc8\x9a\xa4\x0e\xf2\x19\x6f\xb2\x84\xf0\xf9\xfd\x9f\x20\xad\x43\x8b\xbc\x57\xf9\x22\x7e\x75\x7b\x75\x7e\xf9\xee\x6a\xbe\x89\xfb\x67\x2f\x3c\x9b\x8d\x45\x37\x78\xd5\x5f\x22\xcd\xd0\x86\xa5\x54\xb0\xbc\xff\xbe\x8f\x33\xb1\x96\xfc\x83\x5c\xa9\xf1\x12\xe3\xf8\x0d\x4d\x08\xdf\x71\x41\x36\xb0\xf8\x03\x8f\xb5\xf6\x90\x18\x83\x41\x4a\x8f\x1d\x2b\xd0\x03\x1e\x2c\x8b\xe5\x55\x21\xcf\xc2\x1c\x7d\xa0\xd9\x6b\x74\x95\xf2\x22\xd7\x94\x87\x2b\x00\xcb\xea\x64\xe1\x8e\x35\xf8\x50\x43\x6d\x9c\x5d\x79\x54\xe5\x8e\x62\x21\xb5\x1e\xf5\x23\x43\x4d\x9b\x2b\x7d\xb8\x5e\xa3\x23\xf2\x59\x7c\x7b\x74\x86\x8e\x3e\x2f\xb9\xfc\x4f\x2a\x96\x7c\x30\xe4\xfb\xf5\x26\x4b\x68\x44\x45\xb2\x93\xc7\x9f\xe4\x39\x89\x35\x70\xa5\xfa\x99\x81\x64\x69\xa5\x48\xdd\x95\x2f\x41\x29\x60\x5c\xb0\x1c\xaf\x88\x91\x20\xbf\xc9\x17\x43\xb7\x42\x65\x78\xad\xd9\x03\x8a\x19\x7a\x80\x52\xd7\x2d\x49\x85\xaa\xac\x1c\x6a\x4a\xe9\xf8\xb5\xc3\x39\xcb\x9c\x6d\xa4\x35\x90\xe5\x6c\x43\xf9\x98\x3b\x96\xa0\x0d\x8e\xd6\x34\x25\xc3\xd2\xbc\x46\x6a\x1d\x20\xf2\xa6\x10\x21\x1f\xd6\x04\xe5\xf2\xf2\x1b\x28\x45\xd5\x03\x7a\x40\x13\xf3\x04\x5d\x35\xbf\x59\xb3\x87\x99\x60\xb3\x82\x93\x19\x1d\x88\xea\x31\x72\x3d\xef\xc9\x0e\xe0\x5a\x26\x58\xd1\x1f\x14\x29\x13\x46\x1e\x91\xd8\x23\x18\xe4\xb0\x01\x35\x69\x60\xde\x7e\x77\x29\x35\xf1\xb9\x51\x9e\x87\x9e\x0a\x8e\x5e\x11\x11\xbd\x8a\x48\xb6\x7e\xa5\x27\x3e\x52\xb3\x40\x7d\xb5\x8b\x17\xb0\xe5\xe6\xf6\x9f\x62\xcf\xcf\x51\xc4\x92\x84\x44\xf2\x7f\x87\x87\x0c\x2f\x48\xb6\xb6\xc3\x7a\x09\xc7\x69\x78\x85\xf3\xa8\xba\xe6\x91\x1b\x9b\x31\x36\x30\xd5\xb5\x4d\x34\x4a\x8a\x23\x6c\x1d\xe4\x7a\xae\xf3\x45\xf3\x35\xfb\xa5\x1c\x9b\x09\xbd\xdf\xc7\x8f\xe0\xfe\xb6\x24\x39\x11\xa0\xcd\x0d\x74\xbc\x20\x6d\x8f\xbf\x93\x7a\x2c\x9f\x4f\xe5\xb1\x46\x2f\x60\xeb\x87\xfb\xcb\x15\x80\xd4\x60\xf0\xe4\x3a\x58\xb2\x26\x06\xf1\x9c\xe1\x58\x39\x26\xef\xad\x10\x6b\x92\x0a\x1a\x41\x76\x91\x1e\xea\x70\x76\x2a\x2f\xdb\xeb\xa5\xf2\x13\xc6\x24\x46\x6c\x4b\xf2\x9c\xc6\x83\x13\xa1\xec\x6d\xeb\x86\xb2\x68\x32\xaa\x74\xe3\x59\x79\x69\x44\xf6\xf4\xf8\x94\xe5\x71\x75\x39\x8d\x15\x39\x23\x73\xf2\xaa\xb5\x38\x2f\xad\x96\xa6\xb9\x8a\xc6\x54\xc1\x8c\x20\xec\xd4\xcf\x4c\x52\xff\xf2\x32\xbc\xde\x8e\x02\x20\x29\x4e\xa5\x00\xe0\x78\x43\xd3\x5f\x99\xbe\xcd\x23\x9c\x90\xeb\x1f\x47\xba\x6d\xef\x14\x95\xb1\x49\x2a\x86\x4c\x26\x59\x96\x0b\x92\x0a\x8b\x00\x27\x04\x8e\xd6\x83\xdc\x49\x90\xd9\xa6\xe3\xe5\x2c\x45\x3f\xd8\xb3\x8e\x52\x16\x0f\xc9\x4c\x7b\x36\x6f\xea\x0a\x0b\xf2\x30\x40\xed\x9f\x95\xea\xc1\x90\x77\xc1\x3f\xf3\xa5\x7a\x62\x6b\x8e\xd8\xe1\x59\x17\xda\x6d\x6a\x9a\x9e\x60\xc7\x77\x35\xc2\x98\x2a\x1d\xa5\xcd\x2e\xcf\x81\xa4\xb5\xa3\x14\x5d\x7d\x9e\x4f\xeb\xec\x74\xa4\x25\xd0\x7b\xf2\x10\x93\x7c\xf4\x39\x98\x22\xa8\x6e\x16\x1c\xc7\x71\x4e\xf8\xd0\x2b\x5c\x2b\xba\x46\x7c\x9d\xdf\x5c\xa3\xef\xd5\x18\x9f\x65\x7d\xb2\x9c\x09\xe5\xf1\xb8\x64\x1b\x4c\x07\xd6\x20\xee\x2d\x94\xd3\xe4\xc9\x4c\x75\xe0\x7a\xdd\xd8\x01\x22\x35\x42\xd0\xeb\x75\x07\x94\x25\x5d\x15\xc3\x5b\x01\x68\xbf\xf7\xb3\xac\xfb\x84\x06\xf8\x9e\x51\x3b\x34\x73\x47\x8e\xe9\xd5\x43\x4e\x05\x39\x9d\x57\x93\xda\x06\x67\xed\x24\x49\x87\x55\x3f\x3c\x1e\x50\xb1\xea\xbf\x78\x23\xba\xb4\xa1\xcb\x78\xff\x70\x67\xb3\x83\x11\x2d\x4f\x8a\x11\x34\x83\x33\x2b\x94\x56\xa4\x6c\x0d\x4e\x52\x4e\x01\x22\xc5\x29\x31\x1e\x1c\x0c\x5b\x02\xf4\x57\x09\x35\xaa\xcc\xf3\x33\xf4\x96\x0d\x4d\xb4\x41\xe6\x36\x64\xa9\x66\x3e\x4c\x93\x31\x0c\x72\xb0\x8c\x2b\xcf\xc1\x32\x7e\x09\x96\x31\xe7\xc9\x55\x8a\x17\xc9\xd0\x6a\xf5\xaa\xd2\x9b\xe0\x95\x14\x1b\x04\x28\xbe\x8a\x29\x97\xff\x1d\x38\xb5\xbb\xbb\xb7\x90\xa5\x59\xa4\xc6\x83\x07\x39\x7e\x5a\xc1\x19\x9a\x8d\xa7\xcb\x6d\x47\x5c\x6e\xa3\xa5\xbd\xd2\x14\xde\x0d\xc6\x6a\xac\x62\xca\xa7\xb1\x5c\x1e\xc2\x0d\x6c\xc6\x88\xf0\xb5\x1e\x19\x88\x7a\x6c\x31\x91\xa1\x8a\x7a\x68\x3a\x05\x41\x1f\xd6\x34\xba\xbf\x71\xd2\x2a\x59\x2e\x3f\x4b\x9d\x8f\x26\x30\x0a\x26\xa1\x38\xf6\x28\xa9\xe5\xbb\x99\x26\xd8\xf4\xc1\x51\xec\xef\x14\xe5\xa1\x5a\x2f\x63\x09\xc2\x9c\xb3\x88\x62\x9b\xbc\x0f\x81\x68\xab\x0e\x0f\x3d\x4c\xa0\x44\x3f\xcf\x62\x83\xa5\xf9\x08\x16\x06\x1f\xb5\xd6\xda\xe4\xc7\xdc\xb1\x28\xa4\x92\xa9\x77\xf2\x59\x96\x4a\x1d\xe4\xe1\x0d\xda\x5a\x97\x0b\x8f\x4c\xfd\xad\xa6\xa0\x5a\x5c\xf7\x51\x26\x9e\xf1\xb9\xac\xb1\x72\xad\x56\xd9\x7e\xb0\x70\xa4\xdc\xca\x43\x68\x5e\xf3\xe4\x1b\x39\xb4\x95\x4c\x53\x84\x6d\xac\xbb\x54\x5b\x04\xba\x80\x0f\x40\x36\x32\x96\x15\x89\xaa\xe6\x1e\x54\x46\xaa\x61\xbb\xc7\x66\x9b\xa9\x91\x3d\x71\xa2\xea\x38\xe5\xdc\xc1\xc1\x9d\x22\x42\x61\xa1\x9a\x4b\x60\xd0\xe1\xe6\x9f\x06\x55\x36\x07\x14\x3c\x8f\x68\xb1\x33\x63\x1e\x1c\xf0\xb6\xbe\xcc\x0a\x1a\xb2\xc2\x31\x1e\x48\x13\xd0\x8f\x2b\xee\x8b\xaf\xff\xf8\xed\xb7\x73\x74\x49\x73\x12\x09\x96\x0f\xef\xca\xa7\xc1\xe9\x6d\x69\x33\xce\x09\xd8\x98\x0a\x16\x77\x5c\xa6\xa9\xaa\x0a\x11\x10\x00\x2e\xa1\x86\x87\x2b\x5b\x0e\xb4\xf0\x74\xa0\xc0\x0e\x08\x70\x0d\xbe\x17\x80\x77\x87\x46\xd4\x35\x5c\x6f\x0d\x68\x17\x45\x83\x71\xd0\x0c\xb0\xee\x24\x90\xb8\xe3\x0b\xff\xc7\x42\xde\x8e\x48\x98\xea\xea\x3a\x05\x5d\xa3\x86\x27\x2b\x38\xbd\xa6\x26\xeb\x15\xb5\xd7\x21\xca\xed\xf0\x34\x9c\x19\xaa\xdd\x81\x9c\x8c\xf6\xa1\xfa\x0a\xdf\xef\xe6\xa4\x73\x3a\x87\xaf\xa7\xdb\xc3\xa9\xda\x83\x69\xb8\x27\xcc\xd9\xec\x5a\xe7\xa5\x31\xbe\xd7\xe6\x15\x1d\x5b\x36\xaa\xba\x2c\xed\x77\x49\x1a\xb3\xf7\xb5\xde\x48\x6e\x6f\xa3\xa1\x5a\xa5\x05\x40\x9b\xb0\xa3\xd1\x7e\x1f\xa3\x4a\x1f\xa2\x31\x7b\xb5\xdf\x7d\x48\x77\x0f\x1a\xec\x09\xad\xf4\x1c\xda\xeb\x19\x34\xc2\x19\xdc\xd0\x29\x08\x10\x7f\x47\xf0\x93\xed\x0f\x34\xb6\xbf\xcf\xb3\xe6\xbc\xee\x75\xf0\xa9\xf4\xdf\x19\xee\x2f\x64\xf5\xae\x3b\x23\x7b\xe6\x4c\x00\x9a\x39\x16\x30\x73\x4c\x57\x9c\x51\x40\x9b\x53\x80\x6c\x8e\xec\x7b\xb3\x67\x9d\x4f\xd0\x9c\x69\x82\x1e\x37\x93\x60\x05\x8e\xed\x67\xf3\x18\x5d\x6c\xdc\xde\x35\x93\x75\x9d\xa9\xf4\x9a\x31\x76\xd1\x28\x8a\x15\x9b\x4a\x5b\x47\xd7\xe3\x90\xcb\xaa\x1d\x61\xc6\xeb\x53\xea\x71\xec\xdf\x09\x3b\xb8\x54\xfa\xb6\x4c\xd6\x71\x65\xdf\xa4\x1a\x5a\xcf\x5b\x3e\x8d\x86\xd5\x28\x8a\x95\x6e\x28\xc6\xbc\x1a\x45\xb1\x34\xcd\xaa\x46\xd6\x38\x0e\x9d\xa2\x67\xc9\x54\xf8\x6c\xd3\xf4\x27\x19\x8b\xcb\xb6\x27\xcb\x27\x81\x51\x53\x2a\x51\x15\xf4\x6c\x83\x87\xea\x97\xea\x11\xf6\xa2\xb1\x9d\x24\xc6\x82\xaa\x3b\x1d\x3e\xca\xde\x1c\xa3\x05\x96\xab\x56\x4e\xd6\x4b\xa3\xd2\x41\xc3\x51\x35\x47\x2f\xe9\x44\x1d\x2f\x46\x5e\xbe\xe3\xba\x03\x34\xf5\x04\x70\x31\xfd\x87\x86\x83\x95\x4b\xa0\x44\xf2\x2f\xad\x90\x31\x50\xfc\xd3\xe4\xee\x4c\x14\x5c\x71\x33\x2b\xc6\xd5\xab\x18\x8e\x57\x68\x11\x90\x0c\x91\xe1\x88\x68\x9d\x65\xc2\x4a\xa5\xa7\xf0\xce\xa3\x91\xa1\x13\x35\x0c\x36\x40\x47\xaf\xf2\xb2\xa2\xf3\xe3\xdd\x38\x44\x2f\xec\x10\xaa\x65\x99\x0f\xf4\x7f\xbf\x9c\x2c\xf3\x43\xf2\xb5\xef\xf9\x12\x93\xaf\x9f\x06\x69\xe2\x39\x42\xe3\x87\xcc\xd9\x43\xe6\xec\x7e\xe6\xac\xe1\xc9\xe1\x01\x33\x9b\x35\xab\x7d\x04\x4b\x96\x23\xb6\x90\x8a\xe8\x38\x80\x91\xf2\xe6\x38\xbf\xb9\x46\x51\x4e\xa0\x59\x04\x4e\xf8\x1c\x0d\xb7\xee\x6b\x76\xbd\xc9\x90\x03\x1f\xc4\xd8\x88\x01\x16\x82\x6c\x32\x31\xee\x78\x1f\x12\x67\x2b\xcf\x21\x71\xf6\x25\x24\xce\x4e\x9a\x55\xf5\xc9\x12\x1b\x17\x50\x5c\x17\x1b\x9c\xce\xe4\x0d\x82\x17\x49\xad\x72\xc6\x88\x8e\x81\xa4\x4d\x86\x8e\x41\x25\x04\x3e\x81\x64\x08\x96\x0e\x86\xdb\x2c\x52\xfa\x4b\x41\xca\x48\x84\x35\x54\x9e\x39\x51\x0e\xc6\x30\xe9\xbe\x2a\xf3\x6b\x92\x9b\x25\x62\x19\xa9\x41\xb4\xa9\x05\x1c\x6a\x59\x1b\xce\x98\xeb\xc6\xdf\xe5\x36\x0c\xd5\x0d\x1c\x38\x61\x39\x4c\x65\x8c\xde\xb0\xf8\x78\xe8\xc4\x4b\x0b\xb6\xe2\x23\x56\x8e\xde\xa1\xd1\xc7\x24\x61\x0f\x2a\xe2\xee\x9a\x4d\xf2\xcc\xc8\x35\x1e\x71\x53\x83\x6e\xbc\xa1\x79\xce\x72\x9d\x78\x48\xd3\xd1\x07\x10\x4a\xd5\xe8\x6a\x2d\x48\xae\x1c\x9e\xaa\x36\x65\x8e\xee\x06\x7b\x09\x1c\xb1\x23\x18\xc2\xa9\x82\xef\x94\xff\x36\xb0\x16\x23\xf8\xd4\xe8\x11\x0b\xb2\xc6\x5b\xca\x8a\x1c\x46\x3a\xdc\x16\x3b\xd2\x04\x8f\xa4\xe1\xb0\x63\x85\x4d\xc4\x2a\x46\xa0\xb6\x59\xbe\xe2\x7b\xdb\x34\xf4\xae\x7a\x5f\x92\x84\xcc\xa9\x98\x99\x5c\x81\x19\xf9\x4c\x07\x77\x3a\xa9\x0f\xcf\x1e\x04\x9d\x9d\xf7\xe4\x12\x73\xcb\x33\x69\x94\x7c\x1a\x88\x76\x5b\x95\x93\x2e\xad\xb1\xee\x95\xed\x1d\x10\x6b\x72\xae\x18\x57\xc9\x10\xa7\x68\x6a\xba\x29\x29\x70\x73\x03\xf6\xf7\xb4\x0e\x96\x31\x65\xfc\x6a\x3d\x6e\x86\x44\xbb\x0f\x7e\x1d\xdf\x73\xf0\xeb\xd8\xe7\x05\xf8\x75\x6c\x29\x4e\x42\xa3\xdd\xf5\xe5\x14\xde\x01\x5d\x1b\xa5\x48\xa2\xef\x30\x1f\x9c\x4c\xf5\x0e\xa7\x78\x05\x41\x28\x74\x72\x77\xf3\xdd\xbb\x53\x79\xbc\x20\x30\x77\x7d\x39\x54\x95\x69\xa8\xee\xb9\x73\xd7\xe0\xfd\x73\xc0\x72\xa3\xfa\x4e\x4c\x64\x2d\x3d\xc9\x5e\x3c\x0b\x90\x39\xb2\x56\xc8\xcd\xe0\x50\xf2\x7e\x63\x2f\x55\x0c\x63\xfa\x8a\x0e\x55\x97\x6b\xd7\xea\x76\x13\xdf\x3f\xd6\xf2\x38\xfd\x64\xda\xd7\x20\x24\x39\xcf\x9b\x80\x57\xe3\xab\x1c\x0b\xb2\xda\x5d\x92\x2c\x61\x3b\xc9\x14\x37\xe5\x40\xf4\x57\x17\xc4\x6b\x9e\xe7\x0b\x1c\xa1\xbc\x48\x00\x68\x3f\xde\xeb\xc7\x99\x12\x12\x97\x37\x04\x4d\xb9\xc0\xd0\x5c\x51\xfd\x76\x07\xe5\x40\xc5\x21\x44\x45\x98\xa9\xf1\x75\x7e\xa3\xda\xa6\xfb\x7d\x37\x1c\x5f\xa8\x82\x00\x3f\xeb\xe3\xeb\xf0\xb4\xcb\xc0\x04\xcb\xea\x91\x00\xa9\x71\x5b\x24\xf2\x7a\x4e\x62\xee\xc2\x0f\x68\x8d\x5d\xef\x74\xc8\x49\xc1\x28\x53\x52\x48\xce\xec\x0c\x2d\x0a\xa9\xf0\x13\x5e\xc9\x3d\xe8\xd7\x42\x5d\x35\x4a\x7f\x58\xab\xfc\x6a\x49\x16\xe1\x2c\x4b\x28\x81\xd0\x02\xcb\x75\x0a\x72\x1f\x1b\xbd\x81\x90\x5f\xb4\xf5\xd2\x53\xc3\xf5\xd2\x19\xda\x92\x7c\xe1\x5f\xda\x7e\x2a\x27\xce\x28\xe4\x3b\x05\xea\xa7\xd5\x66\xe4\x37\xd7\xea\x5d\x93\x7f\xef\xba\xcd\xcc\x1f\x03\x45\x1d\xf0\x8f\xde\x77\xd3\x34\x58\x55\x0c\x2a\x17\x7d\xd9\xbf\xe9\xfc\xe6\x3a\x90\xe6\x4a\x0d\x0e\x5a\x1f\x95\x6e\x7a\x69\xad\x63\x85\x65\x53\xf6\x25\xc6\x2b\xf9\xbb\xa1\x66\x05\x4b\xed\x34\x49\x5a\x6c\x08\x34\x55\x2a\x07\x8c\x68\x0a\xbf\x72\x7e\x73\xdd\xab\xb5\x9a\xf5\xfd\x27\x09\x7b\x08\x55\x00\xfb\xa6\x5a\xf7\x4a\xad\xee\x79\x23\xa7\x2c\xbd\xd5\x8b\xf0\xf1\xf6\xed\x10\x96\x7a\x5f\xa5\xa0\x5b\xb8\x10\x21\x97\x3b\xc3\xb9\xa0\x38\xb4\xb6\xa1\xc8\x13\xed\x47\xc0\x0a\x73\x50\x17\x5c\xae\xf1\x96\x94\xcd\x73\xe6\x08\xfd\x2e\xf4\x5e\x97\x7c\xa4\xb7\x46\xc9\x2b\x68\xe1\xa6\x9a\x5f\xa1\x65\x91\x24\x67\x68\x49\x53\x2c\xaf\x24\x12\xba\xe5\x6e\x82\xd5\x1d\x4d\x23\x22\xd7\x70\x66\x38\x09\xc1\x1a\x68\x77\x4d\x20\x45\x2b\xde\x20\xd3\x94\x72\x15\x40\x80\xc6\xb6\x30\x5c\x29\xc8\x22\x70\x72\x2f\x83\x9b\xe7\x5e\x24\x05\x17\x24\xbf\x65\xf2\x6a\x76\xaa\x8d\xa0\x05\x00\x76\xff\xfc\x1d\x4d\x63\x9a\xae\x42\xf5\xbf\x5b\xb8\xec\x23\x9c\x22\x42\x21\xe8\x21\x87\xb7\x93\xe2\x5a\x9e\x9d\xf2\x40\x9d\xf0\x22\xb8\xf6\x0a\x73\x74\x94\xb1\x98\x1f\x49\x91\x7f\xa4\xc2\x89\xfc\xe8\x54\xfe\x5f\x7d\x6d\x03\x29\x42\xa9\x8d\x1a\x03\x50\x7f\x85\x33\x7a\x74\x7a\x86\x80\x09\x20\x81\x8f\x89\xf5\x97\x77\x5a\xcd\x4a\x80\xdf\x6d\xc0\x59\xbd\x75\xdf\x87\x93\x9a\xda\x0c\x38\x79\xd7\x06\xf7\xd8\x4b\x28\x87\x03\xae\x22\x23\xa6\xb7\xc9\xde\xc5\x8b\xd0\x79\xa8\xa7\x9e\x6c\x32\x01\x71\x7a\xb4\x21\x58\x27\x1b\x23\xb2\x25\xf9\x4e\xac\x75\x43\x81\x2f\x56\xc8\xda\x53\x31\x62\xcb\xb4\x60\x35\x0b\x6f\x49\x06\x5f\xd6\x94\x37\x6c\x8f\xa1\x7e\x9e\x24\xfd\x5d\x91\x18\x5e\x32\x57\xfe\x17\xb7\x2b\xa0\x9b\x0d\xd8\x91\x4f\xf2\xbd\xea\x6e\xa8\x8f\xd4\xd5\x25\xc5\x61\xe8\x80\x19\x3a\x7f\xfb\x56\x67\xaa\xa8\x75\xfc\x81\xa6\xb1\xb2\xa5\xce\x85\xc8\xe9\xa2\x10\xe4\x96\xc8\x29\x45\x7d\xca\x9a\xb5\x56\x66\x80\x26\xf4\xd6\xcf\x11\x0c\x74\xf0\x5e\xdf\xcb\xb1\x7d\x49\xfb\xbc\x6f\xd6\x85\x99\x63\xad\xa4\x8d\xe5\xda\x4c\xa6\xe3\x65\x6d\xfa\xbe\x63\x71\x93\x10\xa8\xa1\x1c\x95\x5f\xd5\x4a\xf0\xce\xf1\xb6\x6a\x4a\xda\x84\xdb\x65\x0d\x12\xa0\x6b\xf1\x5b\x17\xba\x6d\x0c\xa5\xbf\x0d\x6e\x0b\xe7\x2f\x1f\x76\x99\x8a\xc6\x22\x8c\x96\x09\x6e\xde\x0a\xcb\x68\x20\xc3\x95\x02\x7e\x71\xf7\xc9\x4c\x88\x23\xda\xa4\x25\x79\xec\xb1\x2e\x0b\x6c\xd6\xd9\x17\x6b\xd6\xd6\x2a\xcc\x67\x82\x59\xa2\x6d\x1c\xe4\x4f\xef\x12\x1d\x81\x81\xb6\xd5\xff\xa0\x7b\x7d\x61\x87\x03\xc0\xfd\xce\x96\x86\x13\x5a\x39\x1a\xaa\xb7\x96\x2c\x87\xf5\x76\xd9\xa6\x73\x06\x8d\xec\x7b\x4f\x76\x0f\x2c\x8f\x1b\xd6\x66\x10\xaf\x75\xfc\x52\x82\x17\x24\xf1\x1d\x91\x77\x38\x93\x0b\x50\x56\x88\x2a\x89\xa9\xb2\xb8\xb4\x5d\xaa\xea\x77\x0a\xae\xfc\xfc\x2c\x5f\xe1\x94\xfe\xbd\x69\xe7\xa1\x28\x5d\x9e\x6a\x96\xd3\xbf\x13\x74\xa2\x72\x0e\x94\x37\x2b\x21\x91\x38\xd5\x7c\xd8\x20\xf9\x3a\xd9\x14\xc7\x31\x55\x9a\xd5\x4d\x27\x6f\x75\x2d\x06\x4d\xef\xa7\x5d\xf3\xd6\x23\xe5\xe3\xff\xae\xd4\x30\xaf\x3c\x2e\xf2\xd6\xfa\x8a\x8e\x77\x37\x98\xaa\x5b\xac\xa9\x4b\xd1\x73\xac\x01\xd9\x60\x3a\x64\x22\xea\x19\xb8\x82\x1b\x2c\x8a\x9c\x8a\x86\x2b\xa7\xeb\x25\x9a\xfe\x50\x2c\x88\xce\x21\xeb\xf5\x6a\x0a\x45\x58\xe7\x37\xd7\x53\x2d\xfa\x7e\x63\x7c\x3d\x2c\xa9\xea\xa0\x22\xc5\x9b\x05\x5d\x15\xac\xe0\xc9\xce\x71\xdc\x23\x0c\xea\xc6\x1c\xa1\xeb\x66\x33\x3a\x66\x84\xa7\xc7\x02\xe1\x94\xa5\xbb\x8d\x7e\x3d\x8d\x92\x22\x26\x95\x5f\x81\x6c\x8f\x2d\xa3\x31\xc2\x85\x60\x1b\x2c\x68\x84\x22\xa6\xfe\xe6\xa7\x5e\x70\x82\x70\x0b\xbd\xa8\xe0\x82\x6d\xd0\x06\xe7\x7c\x8d\x93\xa4\x79\xdf\x47\xdd\x64\x6d\x9e\xa8\x19\xac\x4d\xe3\x1f\xb6\x6a\x94\x03\xb8\x1b\x7e\x6c\x30\x77\xcb\x01\x0d\x7e\x79\xdb\xc6\xa7\xde\xf7\x35\xf8\x6d\x43\xc3\x8b\xce\x85\xef\x5e\x8b\xf6\x93\xea\x99\x49\xab\x9c\xeb\x78\x2f\x27\x59\x82\x1b\x4d\xc3\x0e\x2c\x3a\x79\xa3\x83\x5a\xcf\x52\x62\x29\xcc\xd1\x9d\xf2\x97\x6d\xb0\x88\xd6\x2d\xa1\x9b\xff\xb7\x21\x02\xc7\x58\xe0\xb9\x54\x87\xff\x9f\x76\x35\x69\xcf\x28\x4b\x62\x49\xba\xed\xa2\x6b\x1c\xbf\xba\x24\x59\xc3\x0e\x54\xc6\xff\x56\xde\xeb\xf6\xcb\xa0\x96\x40\xc1\xa7\xeb\x84\xed\x79\xc1\x76\x6f\x22\x2c\xc2\xd5\x67\xa9\x7d\x76\x04\xd7\x2a\x63\xac\xbf\x52\xb5\xf1\x92\xea\x0c\xf4\xc9\xdd\x90\x8e\x82\x00\x55\xd6\x5a\x7e\x0f\xfc\x82\xe7\xef\x2f\xdb\x7c\x18\x3e\xab\xa9\xd3\x4a\xaa\xfa\xf9\x3b\x86\x6b\x3c\xb4\xfa\x2f\x9d\x55\xdd\xd6\xbd\xaf\x74\xab\x33\x05\x2e\xa3\x2a\xad\xc1\x77\x44\x72\x6c\x88\xe8\x0d\xe5\xa6\x60\xb6\x95\x68\xa9\xab\xb5\x2d\x5c\x40\x3c\xc6\x17\x85\xe9\xc2\xc9\x98\xd9\x81\xb7\x7c\x21\x24\x20\xe3\xc1\xb2\xa8\x6c\x87\x02\xe4\x51\x08\x45\xb0\x2f\x50\x4f\x6c\xbc\x66\x76\x2b\xb4\x6b\xa6\xd3\x46\xed\x0e\x67\x05\x99\xc6\x66\xf2\xc1\xc3\xb7\xdb\x5c\xe9\x1a\x7e\x4f\x76\xc7\x5c\x97\x6d\xb3\x94\xaf\x69\xe6\x4b\x52\xb2\x71\x01\xbd\xfb\xe8\x13\x4e\x68\x6c\xc9\xab\xf3\x71\x9d\x9e\xa1\xf7\x4c\xc8\xff\x5c\x7d\xa6\xdc\xe3\xa1\x90\xbc\x74\xc9\x08\x7f\xcf\x04\x7c\x7b\xf4\xe2\xa8\xa1\x05\x2f\x8d\xb6\x39\x94\x2b\x15\x4e\xae\x63\x99\x98\x69\x5e\xfb\xcb\x20\xec\x12\x53\x8e\xae\x53\xc4\x72\xb3\x06\x16\x24\x8b\x6b\xf2\xa6\x12\x38\x65\xe9\x0c\x9c\xa6\xdd\x1e\x99\x6b\x2d\xda\x1d\xfa\x6a\x59\xe5\x6f\xb8\x2b\xe7\xfe\x54\xf7\x92\x57\x86\xa1\x86\xa0\x40\x28\xd4\x5f\x28\x37\x57\x52\x8c\xe2\x02\x16\x02\x1b\xcf\x09\x8d\x3a\x49\x6f\x48\xbe\x82\xd0\x4a\xd4\xe9\x9c\x0f\xf3\x2e\x05\xf8\x94\x3c\x1c\x01\x17\xc2\xdb\x16\x8b\x14\x35\x5e\x1f\xea\xdb\x4a\xc4\x6e\x94\x99\xfa\x5f\x52\x62\xc2\xba\xfe\x37\x60\xc9\xf1\x39\x3a\x47\x9c\xa6\xab\x56\xb8\x70\xf7\x0d\x1d\x6e\x72\x89\x4b\xba\x94\x23\x29\x00\xb7\x38\x91\x12\x1d\x32\x9a\x3d\xe5\xfe\x6c\xb9\x77\xc1\x9d\x69\x74\x37\x29\x8d\x6c\xcc\xe9\xe8\x9e\xec\x8e\xce\x2a\x4c\xd3\x42\x51\x7e\xf9\x3a\x3d\x2a\x61\x0d\x2b\x7c\x6a\xaf\x0e\x08\x62\x1d\xc1\xdf\x8e\xe6\x7b\x77\x62\x0b\xed\xa0\x9b\xb2\xe3\x82\x08\xb5\xbe\x51\x37\x17\xb4\x6a\xa6\x95\x9d\xff\x51\xaf\x93\x31\x11\x60\xf7\x1f\x72\x9c\x65\x24\x47\x38\x67\x05\x38\x13\x36\x5b\x92\xcf\xcd\x57\x20\xb1\xa1\xc9\xc3\x68\xfc\x62\x11\xcb\x73\x12\x09\x63\x5e\xc8\x53\x24\x18\xfa\x3f\xe7\xef\xde\xc2\x72\xff\xef\xbb\x1f\xdf\xf7\xd2\xd3\x1e\xc8\x62\xcd\xd8\x3d\xe0\x07\xc0\xca\x3c\x8a\x7d\xf7\x17\xf5\x2b\x97\xe5\x67\x46\x45\xe7\x28\x26\x02\xd3\x04\x32\x3b\x7e\x7c\xfb\x4e\xe7\x7e\x98\x6b\xbc\x71\x6b\xf4\x98\x9b\x78\x64\x94\x5d\x85\x63\x9d\xe9\x74\x4b\xb6\x94\x3c\xe8\x3d\x69\xfa\x99\x19\x5a\x91\x14\x92\x05\x5a\x92\x82\x66\x88\xd3\x98\x5c\x01\xb0\x4d\x33\x81\x81\x0e\xc7\x96\x31\x76\xf3\x70\x97\x48\xf4\x88\x43\xef\xe5\x68\x62\x0a\xf9\x0d\xcb\x5b\xc1\x99\x43\x30\x6a\xfc\xf8\x33\x11\x4b\xf5\xc1\xbb\xb8\xbd\x7c\xc6\x29\xc7\x36\x39\xae\x2b\x76\xe0\x25\xb3\xc4\x34\x29\x72\x9d\x17\x3a\x98\x8a\xcb\x88\x83\x89\xc0\x0d\xd0\x3d\x90\x9a\xa7\xd5\x7e\x1f\x5c\xd1\xb6\xa8\x0b\xe4\xbd\xf1\x44\x2b\x83\x53\x25\x87\x0d\x1d\x99\x3a\xca\x77\xad\xd6\x64\xc3\xe0\xf6\x8c\x1c\x65\xaf\xc1\x67\xbf\x14\x24\xdf\x41\x69\x8f\xd5\x3a\x5b\xf9\xc0\x49\x5b\xfa\x50\x82\xf3\x9a\x79\xe9\x4b\x57\xe1\x37\x56\xef\xcf\x76\x0b\xc7\xde\x5e\xe8\x3c\xd5\xa1\xed\xda\x58\x81\x16\x81\xa0\xb6\x75\x30\xa3\xf3\x56\x8a\x69\x91\x24\x6d\x24\x52\xd6\xee\xa2\x76\x57\xbf\xd3\x9e\x0a\x31\x79\xc2\x6c\x6a\xf5\x0c\xb6\xac\x3b\x15\xb6\x8a\xd5\xdd\xdb\xbe\x76\x17\x63\x02\xed\x71\xa0\xc5\xdd\x49\xb3\x9e\x56\xd7\xc3\xee\xf6\xd2\x25\x16\x84\xb7\xdb\xfa\x76\x97\x29\x20\x27\x32\x2c\x1f\xd2\x8f\x5b\xe9\xb5\xca\xd5\x13\x9e\x2c\x19\x84\x36\x39\xc0\x4e\xf7\xd2\x44\x03\x92\x4f\x83\xd2\x16\x42\x2c\xf7\x86\x69\x85\xda\xef\x01\x13\x03\x48\xd5\x5e\x56\x7c\x00\x51\x6d\x90\xf6\xb1\xe5\xf5\x68\xc2\x97\xce\x6f\xd7\xab\xa7\xb7\x75\x1f\x30\xbf\x06\x1b\xbc\xd3\xc6\x0f\x20\xb9\xef\x05\xe8\xb4\xf4\x03\x28\xb6\xf9\x02\xda\xed\xfd\x90\x73\x10\xe0\x11\x08\xb5\xfa\xd5\xd3\x27\xb3\x24\x38\xab\x24\x88\x8f\xbc\xde\x00\xf5\x0c\xf4\x09\x74\x8e\xd2\xf8\x0b\x7a\x7b\x06\x3c\xae\x44\xc7\x6b\x10\xea\x1f\xe8\xa4\xd8\xe0\x3b\x08\xf4\x12\x74\x3b\xc7\x3a\x3d\x08\x7d\x6e\x7d\xef\x75\xd6\xc7\x6f\xe0\x12\xee\xe0\x9d\x9c\xd0\x74\xcb\x54\x5f\xb7\x1e\xaa\xf7\xed\xde\x6b\x35\x0d\xfc\x01\xee\x25\xad\x82\x77\x2a\xdf\xea\xf2\xb7\x16\x25\x92\x46\x35\x2a\xb8\xcf\xff\xde\x35\xa7\xae\xda\x96\xd1\x86\x59\x75\x1d\x8a\x84\xfc\x85\x8a\xf5\x8f\xa6\x43\xa5\x3e\x49\xa2\xc8\x12\x98\xba\xf3\x87\x6e\x4c\xb9\xdb\x52\xcf\xbf\x16\x4a\x28\x45\x6c\xb3\x21\x69\xac\x92\x44\x36\xf8\x9e\x20\x5e\xe4\x44\x67\xf2\x25\x89\xb2\x72\xe4\x0f\x75\x90\x25\x9f\x33\x9c\x2a\xb5\x56\x72\xe2\x56\xde\x86\xed\x9c\x18\xc4\x87\x61\x3a\x4e\x60\x21\x48\x77\x01\x88\xad\x78\xa8\x95\x70\x78\xa4\xe6\x82\x24\x0c\x5c\x52\x73\x74\xfc\xbb\x63\x9d\x9d\xab\x09\xc1\x55\xa4\x3f\xd5\xfa\xc6\x59\x00\xd0\x4b\x42\xd2\x55\x89\xde\xca\x13\x1a\x11\x7b\xeb\xb0\x94\xcc\xd1\xad\x56\x34\x43\xf4\x56\xff\x05\x11\x74\x39\x04\x2a\x18\x25\x5e\x4f\xcf\xbd\x30\x6f\xb9\xbb\xb1\x35\x9f\x8d\xdf\x0f\x43\xea\xd7\xb7\x23\xb6\x9f\x6d\x9f\x0d\xa9\x8a\x98\xf2\x16\xb3\xbb\x61\x45\xa8\x67\x90\x20\x60\x23\x9c\xcb\x6b\x0e\xdc\x9c\x33\x74\x71\x7b\x75\xfe\xe1\xea\x0c\x7d\xbc\xb9\x84\xff\xb2\x1c\xfd\x4e\x75\x9f\x4c\x12\xe7\x67\x7c\x0a\x50\xf3\x3e\x7a\x77\xca\x43\xf5\xe5\xee\x63\x60\xea\x7c\x65\x1b\x8f\x7c\x39\xf3\x65\x4a\xb4\x67\x90\x6e\xae\xfc\x5f\x53\xf4\x86\xe5\x88\x7c\xc6\x9b\x2c\x21\xaf\xd1\x71\xc6\x62\x7e\xac\xab\x15\xe4\xbf\xe7\xea\xa3\x57\x09\x5b\xf9\x90\xba\x4c\x89\x03\x41\x09\x5b\x21\x5e\x2c\x6c\x89\x0b\x5c\xe5\x40\xeb\x77\x86\x76\x25\xcd\xde\x67\x4e\x99\xfa\x16\x87\xa6\x1d\x58\x85\xa2\xfb\x05\x9f\xd5\x59\x8e\xe9\x15\x8f\x70\x42\x2a\x74\xe4\x07\xf5\x9f\xfb\xdd\xab\xdf\x85\x2d\x41\x65\x6e\x46\x43\xa4\x79\x8d\xde\x5f\x53\xc9\xf7\x0f\x34\x89\x23\x9c\xfb\xca\xdf\xeb\x47\x03\xee\x63\x95\x2e\x0d\xf5\x0f\xaa\x69\x4c\x0a\xf7\x7c\xe8\x0a\x68\x5c\x1b\xb6\x25\x79\x82\x33\x95\xf4\x4c\x70\xa4\x01\xf2\x61\x80\x97\x24\x23\x50\x48\xa5\x9a\x24\xf8\x38\x8b\xa4\x51\xc2\x38\x7c\x1d\x54\x81\xb3\xca\x94\x35\x9c\xbf\x6e\xee\x13\x58\xf7\x62\x0f\x71\x37\x98\xc5\x73\x9c\x62\xc8\xa9\xed\x71\x82\x55\x0e\x6e\xd5\xd9\xec\x60\x81\xd9\x7a\x06\xf0\x3c\x04\x19\xfe\xa0\x9a\x1d\xe9\xb2\xb7\xa3\x33\x74\x64\xa1\x8b\x62\x6d\x9a\x1c\xfd\xee\xa8\xfc\x42\xe0\xf9\xc5\xba\xa2\x30\x52\xaf\xcd\x60\x8c\x6e\x59\x29\x30\x1b\x98\x55\x5e\xef\x9c\x9d\x54\x09\xa1\x26\xb5\x01\xed\xd9\x85\xf1\x57\x7f\xc6\xc7\x0f\xee\x14\xf7\x46\x5c\xd6\x1c\xd6\x46\xeb\x9b\xb9\xce\x2d\xb3\xa3\x95\xcb\xe6\x10\x17\x80\x9b\xa0\xea\x1f\xf5\x96\xe5\x4e\xfd\x8a\x6f\xcc\x77\x95\x43\x60\xf2\xd8\x2a\x38\x70\x34\x47\x19\xce\xa5\xc5\x6a\xbe\xe9\x23\xea\xf4\x4e\x3e\xfa\x9d\x07\x41\xc6\xcb\xd0\x4e\xb8\x6f\x70\x14\x46\xd0\x0d\x61\x85\xb8\x23\x11\x4b\x9b\x92\xea\x5d\x32\x63\x63\x69\xc1\x55\x07\x3a\x74\x7b\x6e\x54\x1c\x53\x7a\xe0\x06\x7a\x4a\x13\xb2\x23\x34\xab\x9e\x0a\x3e\xd0\x8f\x6f\xdf\x0d\x5d\x2b\x04\xf5\xda\xed\x59\x5e\x9f\xb4\x78\x4f\x57\x76\xe4\x7a\x26\xad\xaf\xbc\x2b\x44\xf8\x0b\x7a\xa2\x5d\x18\x25\x2d\x73\xe0\x02\x8b\xa2\xb6\xbb\x95\x15\xd7\xc2\xe6\x4e\x55\x29\x69\x53\xe0\x0e\xde\x72\x3d\xb5\x2e\x66\x03\x68\x93\xb5\x61\xa8\x66\x0a\xf0\x16\x24\x87\x66\x2c\x9e\x23\x4d\x66\x83\x77\x48\xe4\x98\x2a\x4b\x16\x47\xa2\x80\x62\x67\x2c\x74\x22\xa9\xc6\x5b\xfa\x6a\x7f\x3a\x0d\x16\x6a\xbb\x55\x1a\x91\x5c\xf0\xb7\x98\x8b\x8f\x59\x8c\x1b\x8b\x64\x6a\xc9\xa0\x5c\xc0\x21\x50\x3a\xf6\x43\x4a\x62\x29\xeb\xf4\x42\x28\x6a\xe8\x41\x0a\x92\x42\xd1\xdb\x23\xd7\xc9\x36\xe6\x50\xc8\x57\x67\xf2\x67\x9a\x46\x7b\xcb\xe4\x2a\x9c\x37\x44\xb2\xab\x79\xb7\xbe\x51\x4a\x01\x9f\x03\x2d\x94\x92\xcf\xfb\x26\xfd\xb8\x91\xb2\x34\x6e\x4b\xd6\xa8\xae\xa8\x56\x71\xcb\x17\xce\x10\x46\x6b\xca\x05\xcb\xb5\xcf\x1a\x3a\x16\xe7\x38\xe5\xb4\xb9\x92\x70\x7c\xf2\xc7\x85\xfd\x71\xa9\x38\x13\x6c\xbb\x66\x6a\xee\x84\xa6\x92\x39\x89\x58\x1e\xdb\x21\x35\xcb\xac\x72\x98\x5a\x9b\x6a\x3e\x2b\x0d\x2f\x8f\x2c\xf1\x48\x30\x17\x1f\xec\xaf\xcb\xcd\x0f\x92\x9d\x55\x86\xd6\xd3\x2d\x67\x61\xea\xee\x59\x6a\xfe\xd8\xee\x1e\x62\x08\xa7\x4a\xab\x1c\x2e\x31\x7d\x6c\x55\xce\x55\x9d\xd7\x01\xf3\x7c\xb0\x67\xd3\x99\xf2\x63\x8f\x78\x43\x38\xc7\xab\xb0\xa1\x9e\x2b\x80\x60\x64\x01\x82\xf5\xcb\x88\xa6\x31\x8d\x40\xfe\xdb\x8c\xa4\x26\xa9\x5a\x3e\x0f\xeb\x5d\x3b\x0b\xca\x1b\xd2\xd4\xd8\xda\xc3\x37\x78\xeb\xb2\x35\xe6\x61\xd3\xb3\x67\xcd\xd8\xfc\xa1\x07\x24\x68\x1c\x39\xc1\xbc\xbd\x1e\xa3\xb6\xce\x8b\x9c\x92\x25\xba\xc0\x1b\x92\x5c\x60\xfe\x14\x0b\x0d\x92\x63\x8e\xc8\x7c\x35\x47\xc7\xb7\x4e\x28\xe0\x3d\x13\xef\xda\xbb\xae\x74\x96\x1d\xfa\xcf\xfd\xb8\x13\xdf\x9c\x1b\xdd\x7a\xd6\x47\x5d\x1b\xbe\x93\x3d\xea\x4c\x8f\x1a\x59\xeb\x09\x1e\x77\x76\x25\xeb\x34\x5d\x06\x23\x4f\x6d\x57\xe1\x51\xf3\x49\xad\x9e\xd1\x22\x07\x3b\x25\x1a\x76\x56\x3b\x8b\x86\x9a\xcf\xe7\xc8\x93\x39\x66\x19\x7b\x9f\xc9\xce\xe9\xd9\xd7\xef\x1a\x94\xe8\xbd\x99\x7e\xa8\x68\xc0\xe0\x98\x71\xb3\x6f\x00\x4d\x5a\x8e\xf1\xe2\xee\xd3\x34\x6a\xcf\x53\x57\xf5\xe9\x8d\x6b\xfc\x5b\xda\x9a\x98\xda\x76\x27\x8f\xa9\x12\x8c\xc1\xcd\x25\xf7\xf5\x69\xa2\x7f\x97\xe6\xf7\xb4\x41\xa3\x0d\x52\xbd\xdb\xe0\x3f\x2f\xc7\xd4\xe9\x47\x2e\xf9\xe1\x44\x30\x94\xe5\x64\x0b\x99\x59\x29\xe4\x43\x4b\xe5\x9d\xcb\x03\x71\xda\xae\x99\x85\x04\xee\xfc\xb9\x50\xed\xfb\x6f\xfe\xde\xc2\x05\xe6\xcf\x1e\x05\xb2\x6b\x73\xd5\x13\x16\x5c\xec\x2c\x07\x55\x4f\xa0\xf3\xaf\xab\x34\xb4\x17\x21\x8f\xfa\xd7\x8b\x56\x93\x71\x5e\x7f\x6a\x80\x99\xf2\x85\x5b\x10\xbc\x2a\xac\x10\x49\xb9\x1a\x61\x0e\x2e\x34\xf8\x58\x09\x1a\x9f\xeb\xd7\xb5\xd5\x6f\xeb\x92\x0e\xaa\x72\xaa\x3c\x3f\xc5\x74\x8b\x82\x4e\xb3\x07\x9e\x52\xdd\x40\x5a\xcf\x58\x6b\xec\x61\xa2\xc7\x2a\xe3\x57\x4f\x37\xd7\x0d\xe5\x37\x9f\x48\x18\xcb\x69\x7e\x7c\x87\x0e\xee\x9a\xbc\xf8\x9b\x93\x7c\x4b\xe2\xd7\x48\xe4\xba\x6d\xb4\x86\x5d\x76\x3f\x71\xbc\xc8\x86\xae\x5e\x7a\xf4\x5f\xff\xfd\xd5\x57\xb3\xd9\xec\xab\x32\x64\xff\x1a\xe1\x8c\x92\xcf\x82\xa8\x24\x8e\xf9\xfd\x9f\xa0\x9f\xd0\xf6\x9b\xaf\x80\xd1\xd0\x05\xd4\xf9\x9b\x98\xe2\xa5\x2d\xa0\xf9\xca\x94\x52\xcb\x9f\xc0\x69\xca\x84\x1b\x70\x8e\x58\x2a\x72\x96\x24\x24\x9f\xad\x48\x3a\xbf\x2f\x16\x64\x51\xd0\x24\x26\x39\x10\x37\x3f\xbd\xfd\x7a\xfe\x2f\xf3\xaf\xbf\x42\xaa\xb5\x81\xb6\x3d\xb8\xc0\x9b\xec\x35\xe4\x7c\x7f\xa5\x39\xce\x00\xb8\x64\x09\x4e\xf9\xdc\xe6\x5a\xce\x23\x96\x13\x26\xff\xb3\xf9\x8a\x67\x24\x92\xbf\xad\x0e\x17\x6a\xfc\x8e\x06\x1b\xd4\x43\xd4\xa8\x27\xe6\xff\x67\x88\x25\x0a\x13\x5e\x4d\x5c\xe3\xd0\xdc\x24\x1a\xd0\x26\xa1\x5c\xfc\x50\xff\xcb\x5b\xd3\xe6\x21\x4b\x8a\x1c\x27\xd5\x81\xaa\xdd\x58\xb3\x5c\x38\x88\x75\x33\xa4\x33\x4d\x39\x4d\x57\x45\x82\xf3\xca\x3b\x5f\x99\x68\x51\x19\x07\x91\xb7\xe1\xd6\x49\xaf\x98\x55\xb2\xb4\x68\x2a\x48\x7e\xc1\x92\x62\x93\xda\x1f\xd8\xd3\x0e\x97\x34\xe7\x42\x03\xe1\xa8\xb8\xab\x71\x98\x35\xe9\xb5\xef\x9d\xbe\x50\x7f\xe3\x2c\x05\xe7\x2f\x9a\xcb\x05\x9e\xb7\xbf\xf0\xd3\xd7\x3f\xeb\x77\xd4\x8e\x95\xda\xe6\x1e\x0f\x37\x8c\x10\x67\x59\xce\xb6\x38\x71\x9b\x4d\xd7\x7f\xdb\x7c\xa7\xf2\x33\xe7\xd5\x0f\x1b\x7e\xab\x99\x8c\xf5\xaa\xba\x64\xec\x87\xfb\x70\x46\xea\x6b\xdb\x6f\x70\x92\xad\xf1\x37\x6a\x03\xa3\x35\xd9\x60\x73\xc2\x58\x46\xd2\xf3\x9b\xeb\x4f\xff\x72\x57\xf9\xb8\x19\xdc\x48\xb2\x8e\x6e\x66\xcb\x5d\x70\x68\x6c\xec\x24\x9b\x65\x5c\xf2\xf1\x57\x55\x99\x50\x53\xc5\xf6\x55\x2f\xa9\x37\xab\x13\xea\x7c\x24\x57\xc0\xfe\x6f\xb3\x2a\xe4\x88\x86\x8a\x50\xaa\x36\x38\x2b\xb3\x77\x2a\xf3\xd0\x8c\x4a\x62\xbd\x3a\x65\xc4\xd2\x78\xf4\x9b\x30\x98\xe4\x84\x53\x3d\xa3\x39\x92\xcc\x45\x72\x6e\xf0\x4f\x55\x39\x94\x00\xd7\xe9\x2a\xa5\x7f\xb7\xb4\xa1\x96\x4e\x25\xab\x0b\xb2\x07\x85\x0b\x07\x23\xc5\x89\x8a\x80\x9e\xe9\x0a\x96\x1d\xca\x89\xfc\x15\x54\xa4\x0e\x3d\x93\xca\xdd\xd0\x65\x6d\x45\x85\x11\x89\x11\xdb\x6c\x8a\x94\x8a\xdd\x2b\x90\x6e\x74\x51\xc8\x7d\x79\x15\x93\x2d\x49\x5e\x71\xba\x9a\xe1\x3c\x5a\x53\x41\x22\x51\xe4\xe4\x15\xce\xe8\x0c\x86\x9e\xaa\xd0\xdf\x26\xfe\x8d\x95\xca\x55\x73\xb0\xe5\x8e\xd8\xbf\xe7\xab\x3b\x00\x00\x32\xaa\xb4\xc2\xc9\xc8\xae\x42\x8e\x01\xb6\xde\xd5\xdd\x07\x1b\x2c\x84\xcd\xa8\xaf\x3e\xac\xbb\x13\x73\x29\xb7\x40\x2e\x18\x34\x8c\xd0\xc8\xac\x39\xdb\x68\x10\xe1\x38\x63\x34\x55\x85\x01\x51\x42\xf7\xad\x0f\x5e\x2c\x36\x54\x70\x83\x58\xac\x92\x48\x2e\xe0\x9e\x00\x64\x2a\xe5\x69\x99\xa3\xeb\xb4\xb4\xd0\x1f\x7d\x03\x00\x30\x6e\x06\x40\x7e\x41\x5b\xe0\x5e\x71\xf5\x2f\xef\x99\x42\xe6\x02\x6a\xd9\x2f\xe7\xe4\xdf\x65\x24\xb2\xa7\xc6\x9e\xf4\x73\x05\x74\xab\x71\x9e\x6d\xae\x4e\xdd\x6f\xb6\xb0\xc2\xa2\x16\x18\x6a\xb5\xd0\x9a\xad\xb2\x19\xaa\xc9\xd3\xea\xc7\x35\xe2\x33\xff\x55\xa1\x9e\x76\xf3\xca\xfc\x9c\xcf\x6f\x63\x6e\x02\x6d\xeb\x02\x14\xb2\xbd\x1e\x34\x04\x3b\x58\xbe\xa9\xbb\xa6\x4d\x4e\xe7\x6b\xe1\x66\x81\xc9\x35\x3e\x3a\x37\x28\x48\x0a\x6c\xf7\x1d\x4e\x0b\x9c\x34\x04\xc5\x3b\xf4\x36\xb3\x3e\x6d\x05\xc4\xcd\x20\x78\xed\xcb\x37\x51\x21\x72\xc7\x88\x75\xed\x64\x07\x16\x56\x73\x98\x5d\xf1\x60\xdb\x3b\xcd\x78\x38\x25\xc0\x6e\x73\x63\xbd\xa1\xd1\xe2\x23\xf7\xfc\xec\x05\x89\xd5\x15\x5a\x0b\x14\xb7\x1b\x07\x10\x7e\x23\x19\xb7\x47\x43\xde\x24\x11\xdb\x64\x09\x11\xd5\xbb\x18\x92\x9b\x9a\xa2\xc9\x75\xa6\x68\x8b\x2d\x1f\x8d\x3b\xa3\x11\x16\x38\x61\xab\xbb\x86\x3c\xad\x99\xf2\xc2\x86\x9e\x3e\x21\x48\x5a\x48\x99\x7b\x57\x81\x05\x6d\xec\xa8\x5b\x3d\x90\xed\x6f\x96\xd0\xda\xda\x2f\x55\x6d\x80\xd1\xc4\xa5\xd0\xa0\x84\x5b\x64\xc2\x58\xa7\xc9\xc4\x4e\xc5\x84\x5a\xfe\x49\xe1\x90\xda\x74\x9a\xe6\x09\x97\x59\xc8\xc6\x65\x6d\x1b\xb1\x36\xbe\xed\x31\xf2\xa0\x76\xa4\x3d\x83\xa2\x7a\xab\x5f\xeb\x45\xcd\x35\xe4\x01\x46\x19\x25\x2a\x33\xd2\xaa\x48\xb0\x44\x04\xc7\xed\x55\xbd\x38\x45\xf2\xda\xcb\x89\xcd\xaf\xd3\x5e\x6a\x20\x5b\x2a\x56\xd0\xb4\x02\xab\x24\x41\x00\x55\x78\xf5\x7d\x1b\x86\x8d\xaa\x80\xd1\x38\xf4\xc0\xe7\x1b\x48\x32\x34\x20\xe3\x31\xe1\x92\x81\xef\xc0\x11\xbe\xc1\x29\x5d\x12\x2e\xe6\xb6\x6c\x9e\xff\xf4\x87\x9f\xdb\x02\x83\x4e\x62\xe9\x99\x41\x49\xb5\x4a\x89\x66\x30\xb8\x0e\xe4\x72\x58\x8a\xdd\xad\x30\x21\x11\x44\x4f\xfb\x01\xa6\x2b\xf0\xbd\xbc\x07\xd4\x74\x0b\x69\x03\xdd\x93\xd7\xe8\x48\x99\x35\x76\x98\xff\x25\x15\xfd\xff\x6e\xcb\x80\x3b\x79\x80\x04\xaf\x23\xf9\xa5\x23\x35\x38\xab\x85\xba\xbd\x24\xca\x41\xaa\xb4\xb0\x9c\xae\x56\xa4\x0d\xe7\x41\x85\x18\xc0\x21\x0b\xa0\xef\x14\x3a\x73\x96\x24\x52\xdd\x2c\xb6\x6c\xb4\x59\x1f\xf4\x4f\x7f\xf8\xb9\x75\xc4\xd5\xf5\x42\x34\x8d\xc9\x67\xf4\x07\x1b\xb8\xc8\x58\x7c\xaa\xf1\x6b\xf8\x2e\x15\xf8\xb3\xfc\xa5\x68\xcd\x38\x69\x5b\x59\x48\xa0\x13\x4c\xf5\x25\xe0\x0c\x22\x67\x49\x32\x53\xfa\x4c\x8c\x1e\x54\x95\xa0\xd9\x38\x55\xed\x96\xe1\xbc\xa3\x06\xdd\xd1\xfd\x55\x4f\x61\x18\x99\x64\xa8\x15\x38\x7f\xa4\xce\xa8\x1a\x15\xa8\x14\x59\xa7\x47\x40\x0b\x45\x5e\x28\xf6\x91\x62\x7d\x8d\x53\x08\xfa\xe8\xae\x07\x52\x37\x9c\x37\xc7\x48\x3d\xe7\xb8\xdd\xf1\xd6\xa0\x98\xd7\x05\xc7\xb3\xa9\xb6\x81\x93\x6b\x77\xec\xb5\x36\xb6\x7e\x8a\xf6\xd4\x83\xe7\xd2\xd1\xd7\x77\x7f\x42\x2a\xdf\xf4\x09\x66\x05\xcd\x42\x5f\x0d\x9a\x94\x31\x09\xc2\xef\xb1\xe3\x3b\x25\x30\xa2\xfa\xbb\xf2\x58\xa8\xd6\x42\xda\x34\xd7\x32\xb6\xe5\x30\x51\xa9\xfa\xc4\x4a\x34\xe3\x74\xf7\xe8\xac\x2c\x17\x14\x62\xc7\xd1\x6e\xa6\xfd\x88\x33\x9c\xc6\xf2\xdf\x9c\x72\x21\x3f\x1f\xb4\x82\xad\x6e\xda\xea\xaa\x7d\xbc\xbe\x7c\x1a\x06\x2f\xe8\x80\xb3\xba\x28\xd2\x38\x21\x6f\x19\xbb\x6f\xac\x7c\xab\x4c\xe5\x3b\xf7\xbb\x36\x76\xa8\xac\x4d\x9a\xce\xb2\x9c\xad\x72\x79\x9b\x3b\x36\x3a\xca\x8a\xc6\x24\x68\x0c\x60\xb5\x19\x8e\xee\xf1\x8a\xe8\x41\xc0\x15\xa5\xf1\xb7\x94\x1f\x00\x4c\x9c\x36\xc5\x6d\x4c\x6e\x9d\x3b\x13\xe5\xf3\xd0\x63\x36\x43\xae\x0d\xb0\x2d\x0c\x65\x46\x0c\x1a\xba\x9e\x85\x6f\xf4\x23\xe3\xdd\x15\x0d\xfe\x96\x34\xdd\x81\xb3\x12\xf9\xb7\x29\xd3\x79\x06\xfd\x5c\x1a\xff\x60\xc0\x4f\x1b\xfe\xe8\x8b\x73\xd6\xc7\x15\x96\x77\x55\x7b\xc9\xec\x85\x51\xd2\xf4\x5a\x56\xbe\xd6\x42\x57\x69\x3d\x7a\x0f\xa0\x9d\xd0\x03\xe6\x20\xa9\x92\xad\xce\x1f\x7a\x64\x3c\x17\x9f\x51\xd0\x30\xff\xde\xa6\x81\x3b\x60\x4f\x74\xd1\x63\x26\x34\x8c\xa6\x97\xb1\xd0\x41\xd4\x38\x60\x7b\x9b\x0c\x9d\x34\xb5\x39\xf1\x98\x86\x83\x7a\x86\x99\x0f\x9d\x24\x75\x0b\xee\xc7\x31\x22\xd4\x33\xcc\x94\xe8\x24\x69\xcd\x8c\xbe\x06\x45\x27\xd5\x26\x63\x23\xcc\xac\xe8\x24\xdb\x68\x72\x04\x18\x17\x3e\x3e\x6e\x34\x3c\x3a\x4d\x8c\x4e\x8a\xdd\xe6\x47\xab\xa1\xd1\x49\xb3\xd3\x08\x51\x4f\x90\xc4\xf0\xa5\x96\x7c\x09\x66\x49\x8f\xe9\x76\xe5\x1e\xec\x4f\xf7\x45\x18\x2a\x3d\x67\xd7\x61\xb4\xb4\x4d\xf1\x45\x98\x2e\x3d\xa6\x19\x64\xc6\x34\x4d\x76\x22\x63\x46\x3d\x5f\x8c\x49\xd3\x63\x65\x3d\x39\x4e\x2f\xce\xc8\x09\x9c\x5a\x57\x11\x50\xc3\xcc\x9c\x2a\x9c\x5a\x7c\x40\x0e\x57\xf5\x5f\xb6\x3e\x7a\xd7\xac\xe8\x56\x36\x47\xe3\x6c\x4e\x90\x39\xe9\x4d\x7d\x6c\xc1\x5a\x55\x4f\x58\xde\x63\x78\x05\x90\x7a\x3a\xaa\x02\xca\xbc\xef\xbd\xc2\x80\x4e\x92\xa8\x5a\x36\xe0\x2b\x08\x52\x4f\x30\x14\x5a\x58\xa9\x4d\xb9\x18\xfe\x12\xa1\x1e\x0b\x21\x2d\x9c\x2c\x67\x8b\x30\xa8\x89\x89\x67\x13\x94\x3f\x3a\xb4\x10\xc1\xb3\xa3\x65\x3c\xae\xe4\x85\x49\x96\xa0\xbb\x54\xa7\x61\x4e\x0a\x3e\xab\x92\x3f\x68\xf7\xe7\x98\xc3\x96\x4f\x3d\xc6\x81\xc9\xb6\x8e\x01\xa0\x86\x77\x66\xa2\xd8\x1f\xf2\x82\x9c\xa1\x37\x38\xe1\xc4\x07\x88\xf1\x31\xbd\x4f\xd9\xc3\x34\xf3\xe8\xaa\xa5\x6e\x98\xc5\x07\x5d\x35\xed\xad\x0b\x0b\x1c\x44\xe9\x23\x09\xba\x08\xae\xed\xd7\x8d\xe7\x4b\x7b\x3c\x66\x45\x4a\x7f\x29\xaa\x46\x96\x17\x7a\xf3\xa4\x6e\x96\x5d\xdc\x7d\x02\x06\x52\x0e\x0c\x5e\xc1\x2d\x95\x7f\xe4\x6d\xa9\xf4\xfe\x2a\xb8\x0e\x17\x40\xb5\xbd\x3d\x16\xeb\x9a\xe1\x98\x68\xc4\xb4\xba\x83\x2b\x2b\x9a\x02\xaa\xe6\xb9\x16\xc7\x5c\x8e\x8b\x46\x38\x49\x76\xd2\x56\xa2\x1b\x79\xcc\xad\x2e\x35\x1c\x28\xad\xb5\xbd\x4f\xc3\x7c\x6e\xf5\x97\x9b\x9a\xb3\x97\x53\xd1\x24\xc1\xec\xec\x74\x2d\xc9\xc3\xb2\x04\xf0\x79\x2c\x60\xad\x06\xcc\xa2\x1a\x7e\x7f\xfc\x4c\x8d\x2e\x65\x67\xbc\x17\xd5\x49\xa1\x28\x0b\x28\x3b\xb4\xa4\x16\x65\xc3\x34\x92\xff\x4c\xa2\xc2\x32\x9b\x37\x19\xe7\xc9\x4a\x93\x9f\xb8\x42\xf8\xa9\xca\x7b\xa7\xac\x5a\xb5\xbb\x3f\xae\xa0\xa3\x5e\x55\x3f\x58\x4c\x74\xdf\x90\x7e\x40\x91\x50\x90\x8f\xa6\x03\x00\xd7\x94\xfa\xd6\x82\x94\xe5\x55\xa4\x0b\x32\xbd\xca\xed\x08\x5a\xf6\x47\x24\x07\xd9\xaf\xf2\x22\xa1\xd8\xff\x61\xcd\x92\x21\xb2\x33\xa4\xba\xd2\xf9\xfd\x1b\xf9\x75\x7b\xc9\xe9\xaa\x4b\xb7\xcc\xa6\x9e\xc9\x5e\x9b\x4c\xc7\x50\xbb\x06\x99\xe0\xd6\x74\xb2\x31\x42\xea\x4e\x90\xac\x2e\x94\x9c\xc9\xa4\xa0\x7c\x6e\x69\xac\xd2\xad\x48\x86\x5a\x52\x40\x46\x4b\xa4\xee\xb0\x8e\x0a\x54\x34\x73\xe4\xcc\xfa\x28\x1a\xff\xd8\x2a\x5a\x7d\x32\xd0\xfe\xe6\x08\x19\xd1\x96\xd3\xa7\x9e\xbd\x9d\x30\x75\x1f\x1d\x3b\xd2\x35\x59\x3d\x2c\x86\x16\x20\x27\xa2\x7b\x05\x88\xe3\xdf\x1b\x14\x66\x38\xfb\xdb\xa0\x75\x95\x1b\x76\x16\x1b\xb6\x96\x96\xaa\x3f\x96\x89\x8e\x01\x5f\x01\xe7\x59\xeb\xf7\xba\x2b\x16\x43\xec\x76\x6f\xb5\xe2\x24\xee\xe4\x40\x98\x68\x15\xc0\x19\x4d\xc8\xe7\xed\x0d\x22\x52\x6e\xc1\x84\xa4\xbc\x5e\xda\x20\x7a\x01\xa5\x84\xd3\x16\xd4\x91\xac\x5a\x44\xdc\x74\x53\x64\x38\x17\x34\x2a\x12\xdc\x6e\x09\xd9\x4a\x02\x10\xc5\x9e\xbb\xa5\x71\x16\xbf\xd2\x12\x36\x63\x63\x6a\x94\xe0\xa7\x29\x62\x33\xbd\xb9\xbe\xb7\x62\xb0\x2c\x63\xab\xfc\x6d\xaf\x90\xad\x3a\x5c\xb5\x2b\x7b\xa5\x6c\x4c\xef\xa8\x2d\x65\xab\xbc\x15\x54\xcc\x66\x0a\xab\x14\xa1\x01\x25\x55\x95\x69\xd8\xaa\x81\x94\x2a\x4c\xf7\x22\x11\x54\x90\x14\xa7\xba\x6a\xe0\xc7\xb7\xef\xa4\x8c\xc2\x2b\x27\xe5\xb8\x82\xcb\x77\x0d\x66\x3c\x17\x39\x34\x20\x69\xaa\xcd\x2a\x5b\x3d\xd0\x14\x51\xc1\xcb\xd0\x8d\xee\x0f\xd1\x10\x56\xd5\x59\x37\x02\xe7\x2b\x22\xca\x17\x26\xa9\xea\x3a\x94\x71\x1d\xca\xb8\x0e\x65\x5c\x1d\x5b\x30\x65\x19\x57\x45\xda\x40\x21\x97\xc9\xab\x93\xff\xd6\x75\x49\x55\x91\xd4\x0c\xd4\x39\x00\x67\x30\xb0\xd9\xb4\xe9\x22\xa6\xbf\xaf\x86\x57\x19\xd2\x31\xef\x92\x44\xde\x11\x76\x8f\x12\x1d\xda\x4f\x1f\xda\x4f\x1f\xda\x4f\xb7\x7d\xe9\xd0\x7e\xfa\xd0\x7e\xfa\xd0\x7e\x1a\xf9\x39\xe2\xd0\x7e\xfa\xd7\xde\x7e\x9a\x57\xea\x4d\x9b\xbd\x38\x35\xcd\xa7\xfe\x82\x11\xfc\x38\xde\xd0\xd4\xa9\xa0\xf3\x57\xaa\xaa\x9c\x32\x00\x38\x5e\x90\xb2\x5e\x15\x7a\xe2\xda\xbd\x39\xe1\xa7\x36\xe5\xd5\x1e\x72\xb0\x7d\x7b\xf9\xd2\xb9\x34\xa7\xa2\x1b\xd5\x2a\x3a\x3e\xbf\xb9\xf6\x55\x76\xdc\xc1\x0b\x48\x90\x24\xe1\x60\xd2\x4a\x7d\x5c\x30\xad\x8f\x37\x2a\x7c\x99\x43\xbd\x61\xba\xa5\xfb\xa3\x65\xe0\xcd\x65\xed\x4a\x8d\xb4\xe6\xbd\x17\xaa\xb0\xf6\x75\x2d\xba\xc9\xe7\x2c\xa1\x11\x15\xe6\x86\x2a\xb5\xd2\xe6\x4b\x4d\xfd\x2a\x88\x76\x0a\x1a\x15\x27\xe2\xac\xd4\x7b\x29\x47\x74\x95\xb2\xc6\x8e\x2e\x53\x47\x6c\x11\xfa\x3c\x2b\x93\xe4\x66\x52\x5f\x9d\xe9\xaf\x93\x8a\x59\xe1\x2b\x70\xaf\x1a\x16\xad\x70\x7f\x35\xe3\xe2\xb6\x9f\x6d\xd1\x56\x66\x5e\x86\x3a\xe3\x40\x5b\x24\xe9\x05\x77\xae\xbf\xa9\x5b\x97\x19\x07\x99\x89\x24\x27\x95\x74\xa9\x1a\xe3\x36\x6c\x87\x5e\x8f\x07\xcc\x91\x26\x3c\x31\x82\x6c\x1a\xca\xcf\x55\x4e\x76\xca\xab\xf6\xcc\x2b\x9b\x6d\x54\x99\xde\xcb\xe1\x4f\xb4\x27\x6f\xfd\xc8\x00\x7d\xf1\x00\xda\xaf\x0c\x2b\x98\x0f\x55\xff\x87\xaa\xff\x43\xd5\xff\xa1\xea\xff\x50\xf5\x7f\xa8\xfa\x1f\x30\x97\x43\xd5\xff\xa1\xea\xbf\xf6\x7c\xc1\x55\xff\xe3\x03\xe5\x6e\x80\x15\x90\x2b\x55\x97\xac\x43\x98\xf5\x10\x66\xad\xd2\x3c\x84\x59\x0f\x61\xd6\x43\x98\x55\x0f\xed\x10\x66\x3d\x84\x59\x0f\x61\x56\x74\x08\xb3\x1e\xc2\xac\x87\x30\xeb\x21\xcc\x7a\x08\xb3\x1e\xc2\xac\x87\x30\xeb\x21\xcc\xfa\x5c\x61\xd6\x43\xe8\xf4\x10\x3a\x7d\x8e\xd0\xe9\x21\x1c\x7a\x08\x87\x36\xcd\xe2\x10\x0e\x3d\x84\x43\x0f\xe1\xd0\xbd\xe7\x10\x0e\x3d\x84\x43\x0f\xe1\xd0\x43\x38\xf4\x19\xc2\xa1\x4b\x9c\xf0\x7f\xfe\xc2\xe1\xa7\xae\x19\x86\x8f\xf6\xcb\x85\x5b\x2b\x85\x75\x91\xf0\x5e\x2d\x70\x59\x06\xac\xdb\xa8\x3f\x5e\x0d\x70\xd5\x79\xab\x21\xdd\xed\x40\x3c\x51\xe0\x43\x80\xf7\x10\xe0\x3d\x04\x78\x3b\xb6\xe0\x31\x02\xbc\x95\x5e\x88\x72\xf9\xb4\x09\x55\xc2\xb4\xfe\xd8\xe4\xa0\x6d\xfb\xd1\x50\x57\x91\xf6\x12\xb9\x3f\xcc\x16\xea\x82\x71\x00\x62\xd3\xe6\x1f\x57\x11\x19\xb9\x9d\x11\xdb\x64\x2c\xdd\x73\xf1\x0e\x08\x3a\x97\x94\x3c\x5e\x86\x0b\xfb\x45\x07\xb5\xca\xe9\x17\xa9\x70\x08\x37\x19\xe3\xa4\xe2\xdf\xee\xe9\x4a\x68\x0f\x3d\xce\x54\x78\xcf\xb8\x01\x7b\x3a\x21\x2a\xef\x06\x68\x22\x6f\xdd\xef\xeb\x60\x35\x44\x17\x7f\x29\x48\xbe\x03\xb8\xba\x32\xe4\x66\x97\xa1\x45\x89\x33\xee\x65\x15\x8c\xac\x2c\xcf\x71\xeb\x66\x06\x2d\x97\x7f\xe2\x28\x38\x5e\xbf\xb7\x06\x7d\x62\xf6\x1d\xa1\xa0\x4a\x34\xbf\x77\xdc\x1e\x05\xc6\xa4\xbc\x11\xa9\x81\x31\xfc\x0e\x8a\xa8\x82\xbe\xd9\x2b\x8e\xef\xa1\xaa\xc2\x46\xfe\x58\x3e\x0a\xc5\x79\x0e\x41\x7a\xee\x8e\xeb\xa3\x90\xd8\x3e\x0a\x06\x7c\xf6\xc6\xf8\xd1\xb0\x38\xbf\x87\x22\x32\x79\x00\x9e\x58\x3f\xea\x83\x86\x1c\x12\xf3\xdf\x9b\x4e\x68\xdc\xdf\x3b\x21\x95\x94\xd8\x27\xf6\xef\x25\xa9\x83\xd8\x7d\xe2\xff\xa8\xcf\x82\xf9\xf3\x00\xd0\xc0\x5c\x00\xff\x6a\xd5\xe2\xf5\xfe\x7c\x00\x2f\xc9\x4a\xbe\x40\x8f\x9c\x80\xa0\xb1\x36\xa6\x27\x74\xe6\x05\x78\xc9\xee\xe7\x0d\x84\xe6\x06\xa0\xe0\xfc\x00\x14\x96\x23\x80\xc2\xb8\xc6\x9b\x2b\x80\xc6\xe4\x0b\x74\x8c\x50\x65\x12\xf4\xce\x19\xe8\x92\xd6\x6e\x36\x41\xcf\xbc\x81\x2e\xb2\x35\x96\x0b\xcd\x1d\xe8\x20\xd9\x9a\x55\x10\x7e\x63\x7b\x2e\xa5\x3e\x79\x04\x28\xc4\x49\xb7\x0c\x49\x25\xb9\x25\x4b\x35\x05\x47\x7d\x2b\xc3\x65\xac\x55\x3b\x6b\x19\x98\xd5\xfd\xce\xf4\x1d\x44\x62\xe5\xec\xaf\x68\x90\x8f\x9d\x93\x78\x4b\xa3\xf5\xad\x1b\xae\xa9\x75\x47\x2b\xd1\x32\xcf\x10\x49\x73\x1a\xad\x3b\x04\x85\x8a\x55\x08\x6e\xa2\xb6\x25\x3a\xf4\xaf\xab\x33\x9a\xbf\x05\xc8\xde\x70\xda\xdb\x80\x28\xef\x48\x69\xe4\xf9\x92\xd6\x2c\xdf\x3d\x49\xb2\x56\xf3\x24\xca\x39\xb8\x53\xc0\x5b\x4c\x13\xbc\x68\xcd\xb0\x32\x8f\x32\x6c\x95\x22\xa3\xcd\x5a\x3b\xa9\x63\x1d\xc6\x0c\xc1\xe6\xf7\xaa\xb6\x61\xca\x6d\x40\x2b\x13\xe4\x6f\x67\x82\x7a\x68\xb8\xfd\xdb\x9a\xa0\x21\xad\x4d\xbc\x14\x91\xf2\x18\x0d\x68\x6f\x82\xfa\x68\x75\xa8\x67\x63\x10\xd4\xb3\xd5\x09\xea\xdf\xee\xe4\x79\x27\x17\xd4\xf9\x64\x6f\x56\xd3\x75\x3f\x41\x83\x3a\xa0\xa0\x7e\xcb\x12\xd2\x09\x65\x6f\x8e\x53\x76\x43\xe9\x39\xde\x90\xae\x28\x7b\xe3\x0d\xea\x8c\x12\xb0\x1b\xaa\x77\x4a\x58\x77\x94\x9e\xf3\xf2\x77\x49\xd9\x9b\x55\xcf\x4e\x29\xc1\x03\x3a\x74\x14\x3d\x74\x14\x3d\x74\x14\x3d\x74\x14\x85\x67\x12\x08\xf8\x2f\x21\xc7\xa7\xc7\x74\x0f\x1d\x45\x5f\x6a\x1e\x50\x8f\x69\x1e\x3a\x8a\x1e\x3a\x8a\x76\x4e\xed\x57\xda\x6f\x80\x17\x0b\xbb\x3f\x4f\x95\x3a\x74\xe7\xfc\x26\x7c\x5c\xa6\x0f\xb9\x7f\xda\x4b\x21\xaa\x8c\x55\xed\xc8\x5e\xaf\x01\x5e\x2c\xca\x7f\xd5\x73\x8d\x78\xf5\x87\xfd\x6d\x07\x5c\x9f\x27\xe4\xc6\x5c\xb0\xa4\xd8\xa4\xf6\xd7\xf6\xcc\xa4\x0c\x47\xf7\xd2\xfa\xd3\xbf\xb4\x80\x48\xb2\x66\x95\xbf\x71\x96\x82\x9e\x8d\xe6\xa0\xda\x38\x9d\x63\xd4\x5e\xdc\xa8\x97\xbf\x6a\xe1\xd0\x86\x9f\xd3\x9d\xe7\x74\xdb\x11\x6b\x9d\x95\xe9\xcf\x59\x85\x64\x7d\x04\x95\x8e\x3c\x6a\x0c\x77\xee\x47\x41\x43\x58\xe3\x34\x25\x89\x3c\xd5\x2a\x3f\x05\xb4\x49\x3b\xff\xf6\xe9\xeb\x17\x2b\xbf\x7e\x51\xf9\x6c\xef\xe7\x2b\x20\x25\xc3\xf3\xc0\x5c\x26\x43\xf7\x84\x64\xdc\x09\xbe\x15\x19\x94\x96\x61\x41\xd0\x62\xa7\xda\x11\x49\x95\x4e\x69\x59\xb5\x12\xa8\x0b\xb5\xfc\x93\x00\x87\xcc\x60\xd7\xec\xff\x1e\xd2\xcc\x0e\x69\x66\x87\x34\xb3\x8e\x2d\x98\x32\xcd\xcc\x15\x08\x95\x54\x33\x9c\xa2\xf3\x2c\x4b\xa8\xee\x97\xaa\x12\x48\x70\x2a\x57\x49\x03\x11\xd5\x8c\xd8\xde\x85\x81\x7b\xed\xc3\x4c\x47\xb0\xc6\x0f\x9b\xdb\x84\x75\xe4\x8b\x29\x79\xba\xaf\x9f\x75\x68\x76\x11\x4b\x97\xb4\xa1\x79\x5c\xeb\x8a\x5d\xc0\x0b\x65\xa4\x52\x11\x28\x72\xb5\x66\xe5\x5d\xb4\x6c\xcc\xf7\xc0\x95\x5b\x79\xd2\x52\x36\x92\x6e\x03\x22\x8c\x57\xe9\xb6\x9a\x2a\x45\xd2\x2d\xcd\x59\x0a\x21\xdf\x2d\xce\x29\x5e\x24\xfa\x52\x23\xa2\xad\x8f\x20\xaa\xfa\x4c\x9a\x8e\x53\xe3\x7b\xd3\xc5\x14\xaf\xd2\xed\x27\x5c\xcd\x4f\x49\x1b\xa7\x82\xf4\x17\x5a\x95\x63\x70\x40\x5d\xd8\xa9\xb4\xcd\x77\x0a\x60\x92\x8e\xe6\x79\x21\x61\x9b\x5e\x96\xb9\x6b\x98\x37\xad\xcb\x1c\xbd\xd3\x09\x1b\xb8\xd3\x86\xbb\xf8\xcf\xeb\xcb\xab\xf7\x1f\xae\xdf\x5c\x5f\xdd\x4e\x83\xb1\x11\x6e\x3e\x7d\x32\x7b\xe8\x04\xc1\x7f\x7b\xf2\xe9\xfc\xf6\x3f\xdf\x9f\xbf\xbb\x3a\x85\x40\x39\xf9\x9c\xe1\x34\xf6\x38\xd7\x0a\x6e\xae\xa0\x2c\x27\x5b\xca\x6c\x96\x6b\xdc\xc2\xfe\x01\xee\xa5\xd2\x35\xa7\x72\xe9\x76\xb6\x94\xb5\x91\x24\x24\xdf\x74\x2f\xb5\x65\xd9\xc8\x9e\x26\xd5\xdd\x92\xc4\x67\xae\x0d\x19\xd9\xa2\x35\x9a\x66\x45\xb7\xb3\x52\x5f\xc8\x16\x4b\x20\x55\x9a\x5d\xac\x32\x27\xdc\xc5\xd4\x4e\x42\x25\xef\x3b\x69\x12\x1e\xe1\xcc\x64\x12\x60\x14\xb3\x42\x0e\xfa\xb7\xbf\x3d\x43\x94\xbc\x46\xbf\x75\x88\xce\xd1\x95\xfe\x6e\xb9\x83\x1e\x8f\x70\x92\xa0\x94\x6c\x49\x0e\xa9\x44\x7a\x6f\xcf\x50\x4e\x56\x38\x8f\x13\xc2\x21\xce\xf1\xb0\x26\x62\x4d\x72\x9d\x3e\xa2\x16\xad\x7b\xc4\x36\xc9\x29\x65\x62\x8e\x2e\xc9\x12\x17\x09\x68\x02\xe8\xe8\x68\xbc\x87\x10\xd8\xfa\x4d\xce\x36\xc1\xac\x7d\x57\xb5\x60\x9a\x38\xe6\x58\xe7\x6c\x76\xfb\x77\x1d\xc1\xcb\x49\x8c\xa8\x4e\xb3\x33\x0e\x55\x2f\x4e\x4c\x60\x14\x3b\x34\xaa\xac\x2e\xc3\x77\x38\xfb\x81\xec\x1a\x8b\xc3\xbb\xd6\x44\x43\x86\x41\xa2\xa1\x6a\xbd\x78\x61\xc8\x85\x25\x7e\x05\x04\xe3\x43\xc3\xf1\xfe\x7c\x53\xd4\x2b\xd8\x1e\x94\x52\x8a\x9a\x42\x91\x90\x49\x6a\xd2\xb3\xfd\x41\xb0\x9e\x61\x63\xdf\x9d\xd2\x38\xac\xa7\xf6\xfa\x06\x8c\x0f\xe9\x80\xc3\x79\x1c\x23\xc8\x1d\x90\xe7\x61\x59\x24\x2a\x86\xc0\xe7\x8e\x2d\x79\x06\xf6\x4c\x48\x44\x14\xbc\x7d\x7f\xee\x12\x0f\xe6\xe9\xb5\xe6\x2c\x53\x4e\x96\xde\xeb\xae\x9c\xb3\xbb\x8a\xfc\xb3\x47\x04\x42\x50\x1e\xd0\x2c\xf3\x48\x9e\x32\xf9\x9a\xfa\x22\x0c\x9e\x64\x33\x18\x4b\xf5\x81\x45\xef\x7b\xfe\x8f\x4b\x01\xa0\x02\x3f\x9a\xc1\x32\x16\xbf\x46\xbc\xc8\x32\x96\x0b\x6e\x0d\x21\xf0\x27\xf9\x37\xb1\xf2\x75\xb0\x25\xce\xca\xcf\x20\x55\x9b\x3b\x1f\x38\xfe\x47\x3f\x69\xe5\xd5\x62\x31\x98\x29\x67\xea\x7f\xf7\x61\x83\xce\xb4\xcf\x74\xbe\x66\x5c\x5c\xdf\x04\x90\x55\x5f\xcf\x58\x7c\x7d\x73\x56\xf9\x3f\xde\x79\x53\xa1\xc7\x12\x83\x36\x62\x3e\xa1\x30\x0c\x4b\xa6\x33\x4f\x85\x4d\x3e\x55\x13\xea\xb4\x73\x47\xfe\xf3\x4d\xe0\x40\xd5\x43\x39\x7a\xc8\xa9\x10\x04\x5a\xf6\x0a\x92\x6f\xa4\x6e\x71\x26\xcf\x43\xa9\x1c\x6c\xbf\x39\x9a\x5c\xe4\x06\x65\x20\x34\x4e\x5d\xbe\x64\xe6\xad\x8e\x48\x59\xb7\x13\xa0\xb1\x9a\xa7\xb4\x51\x9d\x04\xc5\x49\xa7\x69\x7c\x3c\x6f\x46\xca\x01\xeb\x2b\xaa\x47\xe9\x5f\xfb\x12\x84\xab\xe3\xe0\x28\xa1\xe0\x03\x92\xaa\xba\xf5\x03\x9d\xa8\x0f\xe7\x51\x56\x9c\xe9\x2f\xcc\x37\x64\xc3\xf2\x9d\xff\x94\xea\xaf\x93\x6c\x4d\x36\x24\xc7\xc9\x4c\xc7\x4f\xce\x2c\x79\x45\xd6\xfe\x9f\x22\xec\x3f\x18\xce\x00\xf7\xa9\x2b\x93\x47\x37\xa9\x4e\x76\x46\x2a\x92\xf8\x79\x24\x83\xb7\xc9\xbd\x7a\xfa\x08\x06\xbb\xc3\xbe\xfe\xe4\xe6\xa9\xb2\xce\x45\x25\xfb\xe2\xb5\x9d\x0b\x68\xda\x5b\x96\x14\x1b\x12\x20\xd9\x91\x73\x49\xc3\x9b\x24\xdd\x4a\xbd\xbc\x33\xc4\x66\x9e\x5e\xb2\x20\xa6\x5b\xca\xfd\xc5\x39\x7b\x13\xd5\x61\x5a\x53\xa5\x59\x88\xac\x10\x3a\x05\x30\x24\x7f\xd7\x3c\xe4\x73\xc6\x38\x58\x67\x36\x4f\xbc\x22\xfe\xbe\xe9\x4e\xae\x51\x4f\x86\x85\x20\x79\xfa\x1a\xfd\xdf\x93\xbf\xfe\xfe\x1f\xb3\xd3\x3f\x9f\x9c\xfc\xf4\xf5\xec\x7f\xfe\xfc\xfb\x93\xbf\xce\xe1\x1f\xbf\x3b\xfd\xf3\xe9\x3f\xcc\xff\xfc\xfe\xf4\xf4\xe4\xe4\xa7\x1f\xde\x7d\xff\xe1\xe6\xea\x67\x7a\xfa\x8f\x9f\xd2\x62\x73\xaf\xfe\xef\x1f\x27\x3f\x91\xab\x9f\x03\x89\x9c\x9e\xfe\xf9\xb7\x01\x83\xc3\xe9\xee\x47\xaf\xf8\x41\x36\xb5\xf6\x35\x38\xeb\x57\x9e\xbc\xa5\xea\x1b\x81\x5b\x5d\x6b\x3a\x44\x53\x31\x63\xf9\x4c\xbd\xec\x44\x5d\xbb\x1e\xb3\x4d\xfd\xcf\xc5\xad\x39\xd3\x8e\xfb\xdd\x5c\x1d\x93\x32\x35\x27\x51\x4e\xc4\x34\xd6\x9f\xa2\x65\x7c\x1d\x19\x8b\x1b\xd1\xdb\xaa\x4f\xda\xe8\x32\x6e\x9b\xd0\x3f\xad\xc1\x68\x94\x23\xb5\x82\xa5\x96\xb0\xcc\xd9\x66\x8e\xc0\xf5\x17\x24\x20\x16\xc4\x82\x80\x69\x5a\xf7\xc4\x83\x3b\xab\x9e\x83\x11\xfa\x6b\x32\x42\xef\x14\x6f\x28\x0b\x34\xe0\x18\xa8\x67\x7a\x0b\x94\xa4\xdb\x76\x37\x5c\x3d\x7e\x20\xbf\x59\x0d\x85\x58\xbc\x00\x86\x32\x96\x15\x09\x16\x15\xd7\x5c\xcb\x00\xeb\x5e\x63\x37\x2e\xa2\xcf\x63\xe9\x6e\xb6\x29\xaf\x9d\x9a\x93\x59\x19\x5c\x75\xbf\xa3\xf3\x24\x41\x34\x55\xe7\x11\xc8\x1a\xbf\x6e\x4e\x94\x1e\x88\x70\x2b\xae\x6e\xaa\x52\x55\xe5\xbe\xd5\x86\x09\x19\x96\x02\xe7\x82\xa6\xab\x39\xfa\x8b\xfc\xbb\x92\xc2\xda\x6d\xda\x1a\x04\x82\x0e\x27\x59\x42\x90\xd5\x1e\x6c\x41\x1f\xc2\x9c\xb3\x88\x62\x5b\x71\x66\x81\x39\x3b\x27\x0e\xf3\x81\xec\xdf\x2c\x27\x11\x89\x49\x1a\x11\xa8\x18\x2e\x48\xb9\x86\x8b\x9d\x9c\xcd\x55\xba\xb5\x1e\xe8\x42\x05\x2d\xdb\xa8\xca\xb9\x34\x53\xbe\xde\x6c\x0a\x01\xe1\x90\xc7\x8f\x57\x49\x7e\xd3\x7e\xdf\x5a\xf9\x55\x69\xe4\x98\xb2\xbf\xd6\xb3\x60\xdd\x3d\x6d\xfb\x3c\x51\xb5\x9b\x75\xe4\x7a\xee\xf1\xbd\xdb\xa7\xf4\x47\x55\x6f\x9d\xa7\xf3\x41\x87\xdc\x26\x2f\xfb\x26\xe9\x7b\x8b\x04\xdd\x10\x3d\x10\x03\xc2\x6e\x86\x1e\xae\xc9\x7e\x92\x3e\xcc\xcf\x98\xe5\x64\x49\x3f\x87\xd7\x62\xa6\xa5\x49\x47\x63\x92\x0a\x69\x3e\xe5\x20\xea\x73\x92\x91\x14\x7c\x29\x04\x47\x6b\xef\xf5\xa5\xa5\x7c\x19\x9b\x28\x23\xa9\xd3\x46\x4b\x95\xc6\xd5\xf7\x00\xde\x35\xe9\x7c\x87\xd3\xf7\xab\x3b\x7d\x9a\x0f\xa6\x3d\x7a\x29\x8b\x49\x0f\xa0\xa2\xe3\xf7\xce\xf7\x6b\xed\x67\x54\x36\xb9\x19\x9e\xb4\x7f\x5b\x52\x66\x90\x4e\x37\xc9\x18\x9c\xd1\x25\x15\xaa\x34\x48\x8e\x65\x5e\x22\xaf\x3b\xf4\x00\xb6\x40\x7f\xe3\xb8\xd5\x68\x54\xde\x7f\x1b\x83\xd5\xe4\x17\xca\xa5\x1c\x17\x09\x89\x91\x49\x82\x52\x3f\x55\xb2\x64\x0b\xc5\x10\x46\xad\xa4\x0b\xbd\xc2\x9c\xd3\x55\x3a\xcb\x58\x3c\x93\xbf\xd1\x09\x00\xfa\xf8\x4d\x0f\x90\xeb\x32\x0d\xd9\xde\x5b\xeb\x5f\x75\x34\x9a\x88\x6d\xb2\x42\x10\xc7\xf9\x6a\x2c\xe8\x96\x11\x2d\x76\x2a\xa7\xcf\xd1\x9b\x4b\xbd\xac\xaf\x20\xa8\xae\xaf\x6a\xb7\x37\xd3\x43\x9a\xd9\x21\xcd\xec\x6f\x0d\x5d\x72\xbf\x3c\x54\x2e\xe2\x40\x4c\x90\xe3\xb7\xca\x41\x5d\xc2\x97\x29\x20\x8f\xcf\x74\x53\x6c\x10\xde\x28\x6c\xf4\xa5\x59\xdc\x8e\x63\x5c\x2e\x3b\x4e\x12\xf6\x40\xe2\xe7\x5a\xc2\xa0\x65\x44\x03\xa0\x36\x5e\xa4\xc3\xd1\xeb\x68\x0c\x77\x30\x06\x3b\x16\x07\x3a\x14\x4d\x7c\x21\x94\x35\x6f\x4d\xc0\xa4\xc6\x9c\x34\x1d\xc1\x9c\x46\x26\x40\x5e\x94\xfd\x05\xca\x11\xdb\x50\x21\xb4\xc7\xde\x29\x24\xed\x72\x95\x50\x51\x71\x5b\xeb\xa3\x04\x35\xaa\x18\x10\xd3\x4c\x93\x8f\x64\x57\x06\xbf\xce\xd4\xf5\xfe\x40\x79\xd7\x80\x15\x24\x0e\xdd\x64\x0a\x14\x07\x8e\x84\xad\x93\x54\xf9\x39\x87\xe3\x75\x38\x5e\xe6\x69\x6f\x93\x88\x5a\x5b\x25\x56\x70\xe3\xac\x7a\x24\xd9\x3f\x63\x31\xd7\x3a\x89\x61\x9a\x76\x5c\x23\xc0\xed\xa2\xe9\x0a\xdd\x12\xf0\x86\xdc\x11\xc1\x35\x5c\x13\xd0\xc1\x39\x29\x41\x80\xcc\x95\xab\xfd\x47\x1d\x5a\x17\x83\xc4\xf0\xe5\xb2\xfa\x9e\xea\x45\xb4\x01\x4d\xfd\x5a\xb8\x5a\x97\x56\xa5\xda\x28\x92\x4d\x96\x60\x41\x00\x47\x41\xaa\x5f\x03\xbb\x3c\x1d\x60\x25\xd1\x01\x56\xf2\x00\x2b\x79\x80\x95\x3c\xc0\x4a\x1e\x60\x25\x0f\xb0\x92\x07\x58\xc9\x5f\x29\xac\xa4\x60\x09\xc9\x71\x07\x0c\x60\xd5\x3d\x5c\x7e\x1b\x26\x64\xd3\x2a\x5c\x3a\x8f\x1d\x09\xfb\x60\x7c\x6d\xf2\x24\x97\x23\x02\x96\x15\x02\x47\x6b\x05\x47\xae\x47\xd4\xa1\x36\xe0\x74\x87\xe4\xae\x0a\x75\x23\x02\x53\x69\xd3\x54\xe4\x10\x96\xfc\x57\xcb\xc3\x67\x04\x34\xd8\x7f\x53\x95\x40\xed\x5b\x68\xb8\x5c\x0a\x0b\xcb\x5b\xff\x6a\xfe\xf5\x6f\x8f\x0c\x31\xa9\x06\x19\xac\xd0\x5d\xc1\xd7\x0d\xf4\x9a\x99\x3a\xac\x88\xa2\x24\xd7\x71\xe3\x17\x70\x57\x52\xb4\xa2\x0d\xc1\x29\x37\xae\x53\x88\x95\x96\x84\xb8\x0e\x0b\x3b\xc6\xb3\x76\x2e\x05\xdc\x79\xc0\x6a\xef\xd9\x9d\xf6\xaa\x9e\xa1\x1b\xf0\xf2\x97\x9f\xc0\x99\x7d\xcf\xae\x3e\x93\xa8\xe8\x46\x5d\x0c\xc3\xeb\xe9\xd1\x9f\xfb\x87\x52\xc1\x52\xf3\xad\x28\x58\xe5\xa9\x08\xed\xd0\xdd\xb9\x96\xf7\x64\x67\x7b\x42\x1b\xd5\x0e\xae\xb5\xee\x6b\xd1\xf2\xa1\xb9\x0a\xd5\xdd\xfa\xbf\x8c\xd3\x74\xb3\xa0\xa9\x1a\xa4\xfa\x59\xb3\xe9\x9d\x44\xe5\xa8\xcc\xf6\x48\x9d\x3d\x49\xd4\xf0\xc6\x2e\x7e\xef\x16\xe3\xcd\x5d\x6a\xfa\xb7\x18\xb7\x32\xbf\x59\x13\x74\xd4\xbb\xab\x5f\x0a\x9c\x94\x45\x60\x9e\x2d\x35\x5f\xd7\x04\xf6\xda\x2f\x3f\xd0\x24\x8e\x70\xae\x33\x4c\x41\xd6\x74\x52\xe4\x4c\xf1\x17\x80\x9e\x41\xb5\x9d\x91\x74\x25\xa7\x28\x44\x52\x40\xd5\xa2\x51\x91\xe0\x6e\x0d\x5f\xe3\x8f\x04\x94\x79\x79\xf6\xae\x64\xf7\x3b\x12\xb1\x34\x0e\x37\x2d\x3f\xd4\xdf\xac\x67\x38\x64\x24\xa7\xac\xa3\x2d\xa5\x1e\x80\x81\xcb\x74\x0e\xde\x49\x35\x4e\xc4\x96\x46\xb6\x59\x81\xe1\x39\x3d\xc6\xc9\x57\x83\x14\xd3\x5d\x7a\x4f\xcb\x8b\xa6\x94\x02\xdd\xe2\xf2\xbb\x9d\xf1\x36\x9e\xe9\x16\xc0\x29\x13\xaa\x0d\xb0\x1e\xab\x3e\x86\x7a\x5b\x2d\xd9\x4e\xaa\x4b\x96\x43\xd9\xe3\x49\xcc\x54\xe5\xde\x96\x46\xe2\x74\x8e\xfe\x3f\x92\x33\x60\xdb\x94\xac\xb0\xa0\x5b\xab\xd9\x3c\xd0\x24\xe9\xa4\x08\x51\x35\x82\x55\x56\x10\xfa\x1a\x9d\x00\x49\x44\x37\x1b\x12\x53\x2c\x48\xb2\x3b\x55\xfe\x1c\x82\xf8\x8e\x0b\xb2\xf1\x33\x90\xdf\xb9\x66\x60\x48\x69\x2a\xfe\xf8\x6d\xeb\xf7\xfa\xd5\x01\x7f\x32\x15\x8d\xa5\x98\x56\x39\x46\x35\x56\xd1\x1a\x80\x57\x46\xb7\x9a\x2b\x6e\xfe\x92\x86\xfc\x30\x96\x47\x28\x93\xfd\x4d\xf2\x29\x46\x39\x01\x0c\x1e\x7d\xe2\x46\x9c\x4c\x95\xb3\xfe\x8e\x15\x8d\x4d\x70\xf6\x96\xea\xad\x76\x54\x7d\x72\x5e\x2b\x6b\xf9\x6b\xd9\x69\x8f\xac\xe8\x39\x63\x70\x22\x07\x18\x41\xb8\x00\x14\x2c\x29\xe4\xd4\xb7\xba\x5b\xb6\x22\x37\x10\xf0\xa8\x15\xfa\x30\xb6\x8e\x12\xa2\xd1\x35\xfc\xf6\x07\x82\xb9\x1f\x8a\x7e\x74\xda\x60\x35\x6d\x0f\x0b\x0b\xc9\x46\x34\xa3\x74\x5f\x3d\x96\xa5\x61\x14\x24\xd6\x99\xc0\x20\x6f\x0c\xe6\xe8\xf1\xeb\xe3\xd1\x17\x89\x9a\x64\xce\x32\xbc\x82\x93\x19\x3c\xd7\xfa\x8b\x28\x26\x82\xe4\x1b\x00\x27\x59\xb3\x07\xf5\x77\xb8\xd0\x3b\x27\x9a\x69\x0a\x24\x2e\x71\x62\xd6\x8c\x2b\xfc\xc8\x4a\xd9\x3e\xc8\x01\x48\x99\xf0\x61\x5e\xe2\x9c\x15\x69\xac\xf5\x60\x2b\xf0\xdf\xd5\x06\xfc\x9e\xa5\x20\xa9\x0a\xae\x4a\xec\x5b\xfb\xd0\xaa\xc7\xde\x46\x0b\x22\xb0\x3c\xa0\xdf\xcc\xbf\xf9\x7a\xf4\xf2\xf7\xc2\x89\x00\x87\x4a\xcd\x7f\x6f\x32\x72\xcc\xe9\x1c\x3d\xa2\x9c\xe0\xf8\xc7\x34\x09\xd7\xcb\xdf\x29\x06\x85\x17\x67\x80\x56\x4a\x97\x10\x73\x39\x53\x1f\x3d\xe4\x54\x90\xa0\x00\x1e\x42\x27\xd0\x09\x13\xb1\x1c\x15\xa9\x35\x60\x4e\xab\x28\x00\xf0\x15\xff\x34\x7d\x39\x69\xbc\x58\x8c\x3a\xdb\xea\x10\x2b\xa6\x2d\x8f\xb6\x65\x59\x4f\xfd\x83\x7e\xbb\xe1\x98\x57\x01\x0f\xd0\x89\xfa\xa6\xd4\xb0\x19\x13\x9d\x08\xb2\x61\x89\x6a\x6a\xda\x57\x9f\xb3\x70\xbd\xff\x4a\x63\x3b\xa0\xcc\xb7\x06\x5e\xb5\xdf\x59\x9f\x8e\x35\xf8\x8e\xac\xf1\x96\x70\xc4\xe9\x86\x26\x38\xf7\x54\x0f\x0a\x86\xee\xd4\xac\xd0\xa2\x10\xcd\xc8\x32\xcd\xa8\x24\x1e\x29\x52\xa2\x5a\x38\xa8\x24\xee\x0c\x9c\x9f\x0a\x37\x52\x1a\x36\xd5\x8c\x5f\xee\x0a\xc8\x3a\x33\x1f\x39\x86\x4d\x21\x0a\x9c\x78\xd6\x80\x7c\x8e\x92\x82\xd3\xed\x98\xf3\xaf\x6b\xee\x7a\xab\x2e\x75\xad\x25\x63\xf1\x5d\x46\xa2\xa7\xd1\x59\xaa\xb6\xa8\x14\xa7\xb1\x61\x2c\x03\x57\xdd\x0d\x13\xbd\xc1\x3b\xc8\x07\x05\x34\x6e\x93\xb1\xbe\x73\x33\xee\xed\xac\x5e\x32\xe0\x10\x7e\xe0\x57\x09\xe6\x82\x46\xdf\x25\x2c\xba\xbf\x13\x2c\xef\x81\xde\x73\xfe\x97\xbb\xbd\xb7\x6b\x80\x4d\xe7\x7f\xb9\x43\x97\x94\xdf\x77\xb2\xa1\x03\x18\xa7\xb2\x39\x5c\x37\x21\x46\xf7\xc5\x82\x24\x44\x1c\x1f\x73\x75\xc7\x6f\x70\xb4\xa6\x69\xf7\x95\xa0\xaf\xfe\xd4\x16\x40\x6a\xf8\x3e\xb9\x1f\x7d\xd3\x39\x74\x69\xee\x2b\xcd\xe9\xbf\xc1\x0f\x9c\xa8\x69\x2f\xe4\xb4\xe5\x9f\x89\x1f\x61\x66\xa2\x58\xa6\x1a\xc4\xf5\xe5\x04\xb1\xca\x25\xff\x10\x80\xda\x5f\xdd\xf2\x37\x34\x21\xca\x96\x84\x69\x99\xac\x5e\x7d\x76\x60\xff\x76\xac\xf0\x86\x47\x1e\xb0\xf2\xad\x80\xec\x9e\xa3\x0f\x34\x7b\x8d\xae\x52\x5e\xe4\xa4\xf4\xcd\x2d\xab\x3f\xe5\xa5\x09\x28\xe2\xba\x5a\xda\x98\xbd\xc0\x2f\xca\x0c\x04\xf4\x7d\x65\x05\xa3\x2b\x85\x72\x1f\x10\xc7\x39\x22\x9f\xc5\xb7\x47\x67\xe8\xe8\xf3\x92\xcb\xff\xa4\x62\xc9\x8f\xe6\xe8\x7a\x63\xd3\x8d\x00\xb2\x30\x27\x26\xb5\x54\xbd\xe0\x1f\xec\xd2\xd5\x55\x1e\x85\x25\xbd\x63\x50\x69\xd0\x52\xeb\x8e\x19\x7a\x50\xc8\x59\xf2\xfa\x23\x79\xce\x72\x5b\xeb\xe4\x6c\x83\x27\xcf\x5c\x3d\x11\xdb\x64\x39\xdb\x50\x7b\xf5\xe9\xe3\x3a\x59\xfe\x34\x38\xcd\x7c\x46\x07\xda\xe3\x5c\x85\x66\xab\x5f\x45\x55\x55\xc4\xf0\x2d\xf0\xa5\x3f\xb6\x67\xf9\xf6\x7a\x69\x92\xd9\xce\x74\x17\x5f\xb8\xcc\x75\x93\x04\x95\x35\xb7\xd8\x85\x58\x6e\x48\x6b\xf5\x0e\x6f\x42\x3f\x06\x3d\xc0\x57\x31\xd9\xbe\xe2\x31\xfe\xe6\x0c\x86\xa9\x18\xc7\x5f\x83\x27\x2a\x73\xc6\x1c\x1d\x7d\x73\x34\x47\x77\x46\x3f\x3a\x73\xd7\xc0\x7e\xcf\x4b\x75\xc9\x72\x3b\x20\x08\xcb\x7d\x7d\x84\x4e\x58\x0e\x23\x8b\x70\x8a\x12\x82\xb7\x3a\xf4\xa4\x24\x91\x7f\xa0\xe0\x81\x39\x0d\xc4\x38\x08\x2b\xe0\x76\xfc\x54\xff\xf2\x07\xcf\xf5\xe3\xb7\x5d\x50\x0b\x8e\xfa\x0e\x1d\x49\xa3\xe5\x08\x4c\x0c\x26\xef\x30\x79\xf3\x48\xb5\x06\xe0\x50\x35\x65\xef\xfc\xcd\x42\x49\xbe\xac\x7b\x76\xd4\x0f\xec\x31\x9b\x97\xa6\xc3\x8c\x47\x60\xfd\x1c\x3d\xf9\xcd\x87\x7a\x61\x0a\x99\xab\xad\xdf\x3e\x7c\x4c\xe9\x2f\x05\x41\x25\x0e\x7b\x46\x72\x85\x05\x2f\x50\x4c\xf9\x7d\x28\x86\x05\x94\xfd\x48\x75\xe5\xe4\x7c\x83\xff\xce\x52\x74\xf5\xdd\x9d\x1e\xd2\xe9\x33\x2e\x9c\x47\x20\xe2\xbf\x17\x39\x91\x0a\x56\x78\x92\x98\x79\xa3\xae\xa9\xc9\xcf\xd1\x25\x16\x18\x14\x36\x25\xbd\xba\x7d\xa2\x69\x79\xc7\x4a\xae\x5f\xd0\x34\xd6\x42\xcf\xd1\xb6\x9e\x4a\x31\x92\x7b\xfd\xbe\x5d\x1b\x2e\xbf\xf4\xf1\xf6\x7a\x02\xe5\x29\x82\x5b\x6d\xf5\x8e\xc5\x3d\x35\xa8\x7f\x97\xcb\x75\xa1\xde\x46\x1b\xf9\x3a\x7a\xcf\x52\x72\x06\xc2\x02\x49\x69\xa1\xfe\xe9\x65\xd7\xbf\xe4\x54\x74\x37\x3f\x41\x7d\xae\x55\xb3\x7e\xbd\x66\xf3\xc1\xf1\x25\xc1\x05\x28\xd9\x07\x4e\x9d\xbe\x60\x17\x09\x5b\x98\xce\x03\x53\x8e\xf4\xe3\xed\x75\xef\x81\x7e\xbc\xbd\x7e\xba\x41\x0e\x50\xae\xeb\xba\x75\xa9\x67\x94\xe5\x87\xa5\x36\xe6\xbf\xfc\x25\x8d\x70\x8d\x78\x6e\x74\x5d\xbf\x4e\xdc\x4f\x17\x46\xd4\x9f\xc0\xe6\xea\xc2\x53\xed\x80\xaf\xab\x0f\xda\x3b\x9a\x57\x9f\x33\x95\x04\xad\x03\x70\x77\x6b\x0c\x88\x2a\xb6\x0a\x5e\x32\x8a\xff\xde\xa5\xfc\x9e\xcb\x5b\xc8\xb0\x14\xc2\x0a\x2c\x0e\xa1\x4b\xa2\x12\x39\xe2\xd7\x26\x09\x2b\x98\x62\x33\xc1\x77\x50\x5b\x10\xbf\x56\xf7\x00\x52\xa5\x06\x31\xaa\x00\xf1\x77\x52\x3d\x51\xae\xd7\xd4\xbe\xaa\xdb\x6b\xd2\x84\x8a\x9d\xd4\x63\x4e\xe7\xb6\xf2\x22\x44\x31\xe6\xb0\x64\x93\x09\xa5\x41\xaa\xd9\x9e\xdb\x17\x9d\x48\x3a\xaf\xc0\xa5\x7c\x3a\x0f\xd7\xca\xa0\xb1\x18\x24\xd0\x2b\xd5\xce\x55\xe9\xe4\xda\xc0\x09\xaa\x69\x6c\x61\xec\xeb\x53\x87\x60\x3b\xa5\x3c\xe8\x77\xad\xcb\x37\x1a\xaf\x75\xf8\xc3\x9d\x82\x2e\xec\x1c\xa0\xae\xf4\x79\x51\x37\xbb\xaa\x92\xf6\xde\xed\xc0\x7a\x9e\x6f\x85\xde\xee\xbf\x56\xbe\x43\xb6\x28\xbd\xb7\x2a\xe0\xf6\xdb\x33\xa8\x44\x95\x42\x02\xe0\x44\xef\xdc\xef\xb4\x88\xd3\x00\x9b\x4a\xbb\x90\x3c\xf8\x83\x17\x73\x26\x1c\xc2\xca\x70\x4a\xbf\x12\xec\x35\xa4\xb9\x75\x33\x58\xf0\x38\x22\x92\xad\xdb\x1a\x86\x37\xfc\xf8\x05\xc9\xd6\x6f\xee\xaa\x6e\x6b\xf9\x19\x7a\x73\xb7\x7f\x66\x3d\xf1\x14\x2c\xd4\x0a\x70\xe5\xe8\x3e\xe6\x28\xa1\x4b\xe2\xe9\x28\x3b\xe9\x89\xde\xb0\x94\x0a\x96\x77\xdd\x28\xa1\x27\xd5\x90\xea\x77\xd3\x97\x68\x69\xef\xf4\xfb\x2a\xa1\x3a\x62\x49\x42\x22\xa1\xd0\x47\xbd\xbc\x0a\x1b\x60\x06\xd0\x64\x22\xea\x6e\x9a\x65\xaf\x2c\x65\x0e\xbe\x52\x9b\xff\xea\xf6\xea\xfc\xf2\xdd\xd5\x7c\x13\xff\x66\xcd\x1e\x66\x82\xcd\x0a\x4e\x66\xd4\x0b\xd7\xf6\x1c\xc9\xea\xea\xc9\x02\x30\x4d\xab\x0b\xfd\xa3\x01\x3b\x40\x1f\xb9\x4a\x53\x02\x97\xa0\x09\xfe\x32\x26\xce\x50\x8e\xc5\x3a\x00\x8f\x4f\xac\xb1\xf6\x48\x16\x49\xa2\xd6\x5e\xe4\x84\x9c\xb9\x8e\x8e\xce\xbe\x7a\xbd\xa6\x3a\xcc\x29\x54\x4e\xd7\x73\x19\x78\x67\x6b\xe5\xfd\x63\x5c\x06\xe8\xa9\x99\x35\xfc\xde\xf1\x29\x3d\xa8\x63\xcd\xef\x2c\x05\x93\x4b\x06\xa1\x67\xc1\x82\x00\xcb\xa0\x7e\x64\xc9\x72\xc9\xa9\x79\x95\xab\x88\x88\x60\x19\x5e\x15\x9c\xe4\x73\x7d\xbb\xbd\x0b\xf1\xb1\x3f\xdd\x12\x07\x43\x37\xf6\x46\xeb\xad\x2f\xf0\x2d\x59\x22\xb7\x43\xa4\xd6\x09\xbd\x6b\x81\x0b\xb1\x26\xa9\x30\xcd\x87\xf4\x32\x36\xae\xb8\xb7\xab\x81\x7a\x9e\x98\x8b\x83\xc0\x24\xfb\x00\x40\x1e\x60\x11\x3b\x9f\xc9\x61\x11\xe5\xf1\x1d\x71\x7f\xd9\x4a\xee\x1c\xc7\x0c\x52\xc0\x14\x0a\xb1\x7f\x36\x0e\x6b\xe3\x78\x43\xd3\xa7\xe6\x5c\x9f\x32\x4a\xd3\xb8\x7b\x65\x6a\x20\xcc\xf0\xfd\xaa\x36\xaa\x68\x98\x68\x92\x89\xe0\x77\x8e\x0e\x1b\xab\x52\x01\xf1\xe8\x38\x7f\x35\xca\xdf\xc8\xd8\xf5\xa5\xda\xec\xf8\x2f\xc9\x4c\x8d\x60\x96\xc5\xe5\x5a\xfd\x5a\xc3\xf2\x4f\xeb\x3a\xfc\x02\x82\xe9\x93\x70\x0c\x3a\x28\x90\xf6\x79\xfc\x35\x0e\xd7\x19\x47\x68\x34\xd0\x59\x92\x9b\x72\x73\x85\x71\xab\x5a\x54\x6a\xbf\x45\x08\xd2\x6e\x86\x73\xbc\x21\x82\xe4\x2a\x2d\x58\x27\x21\xa7\xba\x3e\xef\xc7\x8c\xa4\x77\x02\x47\xf7\x53\x42\xf8\x1f\xb4\x8c\x97\xab\x65\x0c\x8b\x63\x9b\xf4\xc3\xd8\xf2\x90\x06\xb1\xdc\x85\x66\xff\x23\x15\xc3\x56\x07\xee\x05\x48\x41\x8b\x30\x1b\xee\xe5\xb2\x78\xa2\x55\xd5\xa2\x44\x9c\x55\xce\x2b\x56\x24\xdd\x9a\x85\x05\x77\x86\x92\x30\xef\xda\x4d\x8c\x90\xa9\xb5\xbd\xfe\xb1\xe1\x52\x2e\x6d\x58\x4c\xd0\x82\x2a\xd1\x54\x70\x22\xf5\xa3\x48\xd5\x7a\x79\x79\x00\x2e\x7a\x79\x69\xeb\x71\xb8\x4a\x80\x2a\x7d\x5a\x10\xf1\x40\x48\x8a\xbe\x06\x15\xec\xeb\xff\xf1\x3f\xfe\x87\x5f\xe0\xbb\xf7\xd1\xd7\x7f\xfc\xf6\xdb\x39\xba\xa4\x39\xa0\x93\x50\xa8\x55\xb3\xe9\xdd\x99\x4e\x41\xf6\xcb\x25\x26\xf6\x71\x87\xf4\x85\xa4\x71\x20\x36\x74\xb5\x16\xaa\x3b\x2d\x70\x41\x42\xbd\x92\x11\x29\xcc\x68\x25\x20\x14\xd6\x26\xd7\x05\x99\xba\x64\x5a\x27\xb5\xc1\x1a\x9f\xa1\x84\xde\xfb\x87\xba\xe4\xdf\xe7\xac\xc8\x4a\xf0\x81\x9c\x70\xa9\xcf\xeb\xde\xb9\xea\xc7\xca\x3d\xe3\x44\x3c\x53\x2e\x53\x90\xc7\xaf\xc2\x74\xd7\x15\xe5\xe9\xcc\x22\xe4\xce\x14\xab\x64\x98\xe6\xed\xf8\xe0\xce\x74\xd6\x3a\x79\xa4\xd2\xd9\xcb\xfa\x08\x62\xe7\x6c\x77\x43\x52\x95\x4f\x96\xb3\xbf\x29\xe6\xa0\xa9\x0e\x3b\x19\xeb\x82\x6b\x7d\x56\xc3\x4a\x40\xdc\xc1\x53\x89\x83\x6a\x18\x44\xf2\x7e\xd7\xb8\x48\x4e\x65\xf1\xf5\xd2\x2d\x81\x0f\xf1\x6a\x24\x94\xcb\x21\x56\xc0\xda\x1b\x46\xee\xb6\xb0\x17\xeb\x80\x16\x35\x72\x8c\x45\xba\x47\x5d\xf7\x82\xd4\xd2\x51\xf5\x1c\xd5\xa5\xe6\x5e\x92\xe5\x18\x54\xe9\x89\x2e\x6c\xd5\xb4\xf6\x60\x8f\xc3\xe6\x6f\xea\x31\x88\x28\xf4\xd6\x42\xfe\xa8\x1c\x3b\xe1\x5c\xd7\xcf\x6e\x70\x7e\x2f\x8d\x3c\x2d\xdf\xfc\xd2\xe6\x46\x2e\x92\xad\x09\x56\x65\xe2\x5b\x62\x1b\xab\xbb\xf5\x6c\x72\xcc\xc7\x73\xef\x79\x53\xde\x6b\xc4\x72\x85\x84\xaf\xa4\x84\x7c\xef\xc9\xb1\x61\xaa\x75\x50\x38\x73\xda\xaa\xeb\x56\x90\xb8\x52\x33\xe3\x0f\xe5\x9b\x5d\xf0\xaf\x6b\x0f\x15\x33\xbc\x2f\x4a\x58\x67\x14\xf9\xad\x2c\xa4\x77\x5b\x1f\xdd\x36\xb8\x89\x4a\x7b\xdf\x4d\x7d\x58\x43\x7a\x9e\xf4\xec\xc0\x81\x54\x7e\x57\xff\xd1\x79\x14\x81\x86\xbe\xfa\x6d\x8f\x14\x92\x67\x4e\xb7\x89\xd6\xfb\x3f\x04\x66\x4a\x3d\x50\x1a\x59\x91\x91\x46\x06\x38\x7a\x4f\xb0\x90\x57\x4f\x59\x4d\xd9\x78\xe5\x37\x5c\xe9\x81\x84\x3d\x17\x7f\xe5\x62\x0f\x26\x39\xc5\xf5\xaf\x69\xf5\xec\x48\xd5\x47\x15\x50\x4f\x48\xc8\x4e\x3d\x7b\xe7\xc3\x4a\xdd\xac\xd2\x95\x30\x21\x3e\xa4\x8e\xf2\xd9\x80\xce\x6e\x8e\xda\x1c\xbd\xd3\xb2\x5b\xf2\x62\x8a\xf0\x82\xb3\xa4\x10\xea\x07\xc2\xce\x1f\xb2\x24\x5c\xf1\x0f\x03\x34\xf0\x53\x20\xd3\xcd\xd7\x02\x89\x3a\x57\x02\x5c\xd6\x4a\x1a\x87\xdc\x0e\xea\x09\x16\x0b\x07\xf0\xfc\x71\xeb\xf7\x08\xad\x2b\xca\x9e\x46\xfe\xc9\x3f\x46\x9b\x8b\x88\xd3\x70\x03\xf9\xee\x1a\x9d\x94\x2d\x10\x4d\xb2\xcc\x75\x2a\x48\xbe\xc4\x11\x39\x75\x0c\xe7\x6e\xc7\x99\x7e\xd3\x54\xdc\xad\x71\x1a\x27\xb6\xf3\x0e\xf9\x2c\x48\x9e\xe2\x04\x7e\x2f\xce\x29\xc0\x96\x9c\x27\xd9\xba\x5b\x15\x59\x12\x2c\x8a\xbc\xdb\x39\x39\x6d\xce\x37\x0c\x6d\x0a\x8b\x1d\x08\xf5\xcb\xf6\x52\xcb\xa2\xcd\x87\xd4\x39\xa5\xce\xa2\x75\xd6\x90\x9a\x47\xad\x3d\x77\x7d\x15\x73\xc9\x9f\x70\xc5\x80\x4c\xda\xb1\x22\xd7\x81\x23\xdd\xcc\xc0\x4b\x34\x62\xb9\xb4\xce\xd5\xc0\x30\x47\x39\x59\x49\x53\x22\x07\x9b\x44\x95\x24\x27\x85\xfc\x60\xb2\x7c\xdb\x49\x33\x9e\x9d\x7c\x64\x1d\x2e\xf0\x47\x17\x4c\x38\x61\xa9\xad\x1a\xb6\xa5\xb1\xd1\x50\x20\xa0\x5c\x76\xce\xcf\x30\xe7\x01\x9e\x14\x6d\xbb\x39\x9d\xae\x9c\xbd\x55\x36\x14\xe8\x39\x16\xc4\x22\xc8\x02\x35\xc1\x40\xb7\xc0\x91\x01\xfe\x98\x37\xe4\x1d\x7e\xcf\xb0\x98\xdc\x14\x8b\x84\xf2\xf5\xdd\x20\x1f\xf9\xfb\x06\x02\x2a\x47\xca\x8d\xfb\x07\xcd\xb7\xcd\xaf\x8e\x38\x49\x39\x05\x0d\x43\xde\x64\x52\xaf\x09\x29\x3f\x93\x2a\x3b\xe6\xdc\x6c\x8e\x7b\xda\x18\x54\x1f\x26\x44\x63\x32\xc9\x3f\x39\xf3\xf8\x14\xe6\x42\x55\x58\x75\x31\xf9\x98\x66\xee\x7b\x28\xc2\x49\xc2\xb5\x92\x6a\x61\x3d\xcc\x7d\x14\x66\xcf\x9b\xb2\x71\xc5\x8d\x54\x32\xaa\xed\x81\x59\x03\xcc\x0f\x39\xe3\x8d\x0b\xcb\xd1\x86\xa9\x32\xda\x14\xb1\xd4\xac\x3e\xc0\xf9\xe9\x7f\x07\xd8\x7d\x16\xf6\x00\xe7\x44\x1f\x96\x30\xd6\x3c\x04\x2f\x5a\x9f\x2f\x23\x78\x31\x28\x6c\x59\x36\x2b\xc6\x0e\xa0\x4b\xa5\x0d\x42\x47\xeb\x1f\x67\x94\xd6\x96\x6c\x00\x6f\xe9\x15\xff\xec\x5b\x75\x78\x2e\x44\x4e\x17\x85\xe8\x09\xe0\xfc\xa9\xf6\x32\xe8\x55\x84\x6b\x81\x34\xd3\x66\x72\xd4\xc3\xe5\xa1\x2d\x56\x7b\xec\xf6\xc5\x9c\xd5\x0d\xbc\x54\x41\x6d\x50\x2f\x1d\x73\x14\xb3\xa8\xb0\x1d\x2e\x40\x8f\x28\x23\xfc\x7e\x40\x76\xd4\xef\x88\xf7\x45\xc1\x75\x7f\xc0\xc3\xa5\x31\x7b\x48\x1f\x70\x1e\x9f\xdf\x74\x96\x80\x55\x95\xb5\xf2\x1d\x37\xb4\x64\x48\x41\x9b\x7c\xbc\x60\x85\xf0\xca\x5d\x83\x0c\x62\x00\x68\x0e\x91\xa6\x43\xa4\xe9\x10\x69\x6a\x7b\xaa\x91\x26\xf9\x46\xb5\xdd\x46\xe5\x00\x06\x86\xb8\xe5\x8a\x3e\xab\xcb\xde\x11\x26\x4a\xfe\xd7\xcb\xae\xfa\x68\xb3\xa0\xcf\xaa\xf3\x56\xf2\x8b\xa3\x23\x9b\xc6\x75\xa0\x26\x3c\x9f\x7b\xff\x11\x1c\xf7\x30\xa3\x00\xb3\x44\x3d\x6d\xf5\x1b\x65\x57\x79\x37\xf0\x18\xe8\xf6\xcb\x58\xfc\x1a\x10\xe3\x11\x4e\x53\xa6\x6e\x46\x7e\xa6\x1b\xd7\x9c\x69\xdb\x39\x8d\x83\x7b\xce\x9b\x07\x3a\xf1\x98\xcb\xb5\x97\x2b\x38\x70\xeb\x50\xaf\xed\x43\xb0\x85\xb0\x3e\x1d\xc8\x97\xd5\xa7\xdf\x5e\x22\xe8\x41\x62\x14\xd8\xd0\x37\xea\xca\x94\x7a\xdb\xb6\xb6\x8f\xd6\x64\x83\xe1\x9f\x6f\x7a\x0d\x5d\x3d\x94\x23\xa9\x2a\x0a\xa2\xc0\x5e\x48\xbe\xe1\x88\x2d\xcf\x2a\x7d\xc4\x8e\xb6\xdf\x1c\x85\xfa\x9d\x7b\xc7\x7e\x90\xe1\x71\x1f\x60\x60\xf5\xd9\x87\x0f\xb4\x9e\x77\xc9\xdf\x65\xd7\xd7\x80\xa0\xbc\x33\xf6\x4a\x08\x1a\xa4\xad\x5a\xed\x47\x9b\xfe\x21\xf4\x15\x46\xf3\x10\xfa\x7a\x61\xa1\x2f\xe7\x72\x81\xe3\x47\xb9\x99\xb8\x0a\x87\x85\xde\x2d\xf2\x5d\xd7\x2d\xac\x23\x67\xd0\xeb\x4d\xe9\xd7\x73\x0b\xce\x1b\x48\x53\xf2\xb1\x89\x99\xb1\xbc\x9a\x01\x71\x3c\x9f\x1f\x1f\xab\x48\x1a\x90\x0d\x27\x59\x88\xe5\xec\x4f\x88\xa4\x11\x8b\x15\x2b\xca\xb1\xe6\x5c\x80\x72\x54\x7a\x51\xfa\xcf\x7e\x63\xa0\x87\xdd\x8c\x0b\x18\x67\x1f\x16\x09\x96\x38\x06\xe8\xe7\xcd\x08\xc5\xa2\x54\x27\x2c\x28\xa1\x5e\x00\x0b\xed\x18\x2a\xca\x41\xaf\x28\xdb\x61\xaa\x66\xb1\x20\x75\x4c\x7b\x4e\x74\xa2\x3e\x9c\x47\x59\x11\xe6\xee\x31\x3d\x67\xe7\x1b\xb2\x61\xf9\xee\xcc\x92\x92\x24\x2a\xb4\xf5\x37\xba\xc1\x4a\xcb\x47\x6a\x2c\x51\x91\xe7\x24\x85\x16\x9a\x2f\x4d\x77\x09\xc6\x70\x42\x83\x54\x17\xbb\xb7\x21\x45\xe1\xe5\x53\x2b\x8a\xb1\x61\x39\xf0\x59\xda\x39\x06\x79\xbe\xca\x47\x97\xfd\x9c\x95\xcd\xec\x97\x2c\x47\x24\xdd\xa2\x2d\xce\x79\xd8\x7e\xa0\x61\xda\x4a\x4c\xb7\x94\xfb\x3b\xbe\x39\x2f\x34\x3b\x01\x01\x73\xbb\x10\x59\x21\xb4\xcc\x0e\x29\xa6\x76\x46\xbe\x26\x16\xb6\xd3\x9e\x9f\x9a\xe2\xf6\x8d\xbf\x2a\xc4\x3c\x2f\xb2\xdb\x69\xf5\xf1\xf6\x3e\xad\x3e\xe1\x9d\x50\x9b\xdf\xeb\xc5\x14\x83\x9b\x10\xd7\x1f\xb3\x95\x43\xcf\x57\x79\x2d\x97\x78\xb1\x46\x19\x9e\xf8\x58\x40\x7c\xe6\x92\xf6\xa8\x88\xbb\xd2\x6f\x54\x13\xd7\x05\xd9\x64\x2c\xc7\xf9\x0e\xc5\xda\x83\xe5\xc1\xa4\xde\xc3\x66\x70\xc0\x19\x46\x83\xd0\xc1\xac\x62\x9a\x4f\x50\x14\x17\x8c\xce\x40\x62\x5a\x6c\xfa\xb9\x26\xff\x02\x00\xb0\x1a\x5c\xd6\xe4\x29\x28\x42\x16\xf5\x1b\x47\xdd\x88\xc2\x6a\x31\x29\x2f\xd7\x5d\xe9\x35\x2e\x26\xe2\x51\xad\x99\x8b\xd4\xc4\x83\x22\x14\x29\x8b\x89\xdc\x18\x43\x4c\x8d\xcd\xf1\x7d\xa6\x3a\xc0\x17\x78\xce\x4e\x34\xa1\x53\xa9\xd3\xbd\x83\x6b\xfb\x49\xf6\x1a\xf5\xaa\x1d\xa7\x7f\x27\xd0\x76\xbb\x27\xea\x2a\x13\x38\x71\x1a\x88\x27\x2c\xc2\x89\xdd\x55\x73\x45\xfa\x7d\x7e\x90\xf5\x40\x39\xb2\xe7\xcc\x84\x89\xe4\xae\xca\xb1\x29\xc5\x08\xbc\x8b\x09\x57\xd1\x74\x1a\xe1\x85\xd7\x55\xa8\x68\x2b\x65\xc9\xee\xe4\x07\xa7\x33\x7f\xc1\xe5\x48\xa1\xf7\x96\xf3\x1d\x2f\x55\x3b\xd0\x07\x83\x53\x2f\x9c\x8e\xea\x55\x5b\x54\xfe\xe5\xce\xac\xaf\x3f\xea\x6b\xcd\x78\xa8\xec\x33\x7e\x62\x5e\x80\xae\xae\x47\xa9\xb5\x4d\xb6\x44\xd8\xd3\x44\x08\xb9\xfa\x0f\xb7\xf0\xe7\x7b\xe7\x25\xa5\x89\x7b\x60\x02\x4e\x8a\xc6\x71\xb6\x1b\x53\xa4\x3a\x6d\x6a\x8f\xbb\x9b\x99\xbb\xe0\x24\x9f\xad\x0a\x1a\xf7\x67\xeb\x17\x7b\xe7\x07\xdd\xf4\xfd\xee\xf7\x5e\xb7\xfa\xe0\xbb\x7c\x19\x05\x5f\x86\x6f\x2e\xaa\xb7\xe0\x1b\xba\xc8\x09\xba\x58\xe3\x34\x25\x49\x15\xec\xbd\x3b\xc2\xd0\x06\x04\x5f\xad\x10\xdf\xc3\x7a\xef\xbe\x62\xa7\xc4\x2f\xfb\xe7\x2d\xe9\x7e\x31\x68\x90\x61\x28\xe5\x61\x91\xca\x12\xc5\xfc\xf1\x51\xca\x93\xa2\x27\x3e\x79\xe9\xf7\x7c\x73\x81\x04\xce\x57\x44\x48\x22\x28\x2d\x36\x0b\x12\x78\x8f\xbf\x0c\x64\xec\x97\x52\xc3\x3e\x5d\x99\xb9\xda\x8e\xbf\xfc\xe5\x7d\x4f\x98\xb1\xa6\x3d\x7d\x60\x79\x12\x3f\xd0\x58\xe5\x8c\x72\x74\x22\xc9\x9e\xbe\x5c\xcc\xaf\x87\x07\xda\xdd\x27\x12\x75\x4f\x5b\x3b\xc8\x61\xda\x08\xe6\xad\xeb\x9a\x29\xe9\x04\x80\x53\xcf\x09\xfc\xfc\x29\xba\xa2\xaa\x87\x97\xfc\x3f\xe5\xfa\x2c\x9b\xa2\xb2\xa5\xb3\x41\x5e\x8a\xf2\xb6\x90\xe7\xca\x04\x06\xa0\xcb\xd7\xa2\x50\x8e\xca\x05\x13\x6b\xc4\xe9\xa6\x48\x04\x4e\x09\x2b\x78\xb2\x0b\x64\xa3\xa7\xde\x9a\x65\x42\x3e\x2b\x6e\x0f\xbf\x97\xed\x2b\xd5\xfb\x79\x45\x52\x92\xd3\xc8\xec\x54\x90\xaf\xcd\xe4\x8d\x43\x96\x2d\xa7\x2c\x25\xf1\x2b\x7b\x59\xab\xb6\x47\x90\x47\x4e\x22\xb4\xc0\x9c\xc4\x28\x4b\x8a\x15\xed\x8c\x36\xfd\x0a\x32\xc3\xcb\x3c\xd5\x10\x5b\xd3\x1a\x3d\x61\xc5\x7d\x07\x68\xea\x3d\x65\xe4\x43\x73\xb6\x75\x4c\x32\x92\x4a\x39\x92\x3a\x67\xc2\x6f\x77\xc1\x72\x4c\xb6\x0b\x3a\x98\x37\x54\xb2\x5e\x7d\x16\x39\x96\x62\x70\x23\x05\x9a\xc9\x3e\xa2\x4b\x69\x61\x4c\x09\x34\xf2\x88\x89\x7c\xe8\xa0\x61\xd8\xe7\x99\xa1\xf9\xfa\xa5\xe8\x87\x24\xfe\xbb\x29\xfa\x4a\xf6\xeb\x03\x64\x52\xe8\xf7\x53\xe1\x7b\x8e\x92\x72\xe4\x98\x09\xba\xe5\x6f\x73\x4a\xbc\x97\xb2\x2f\x65\x9e\xef\x67\xe4\xfa\x57\xa0\x3a\xeb\x03\xf8\xcf\x3f\x7d\xfe\xfc\x32\x61\xd1\x7d\x0f\x1c\xbd\x37\xea\xfb\x35\x6f\x89\xfe\xb0\x0f\x90\x5e\x87\x77\x44\x9f\x36\xe7\xca\x83\x84\x2a\xf5\x23\x9d\x44\xe5\xe1\xc9\x99\x3c\x01\x00\x1b\x8f\x16\x44\x0a\x84\xbc\x48\x3d\x98\x58\x53\xa7\x38\x63\x81\xf9\x00\x3c\xf2\x7a\x5b\x12\x4e\x84\xca\xce\x07\x14\xe2\x0d\x11\x38\xa8\x4b\xc2\xec\xdf\xb4\x06\x97\x56\x28\x49\xdd\xcc\xec\x54\xd9\x8a\x34\x62\x29\xa7\x31\x09\xf1\x68\x63\xd8\x93\x9c\x44\x01\x89\xd6\xe1\x9d\x51\xd4\xe8\x3e\x7e\xec\x09\x3e\x25\x5f\xa8\xad\x95\xe6\x1b\x70\xdb\x42\x83\xa5\xd2\x6a\xf3\xce\x0d\x1a\x0b\x9b\xd5\xd1\xf4\xa6\x98\xe2\x2a\x22\x37\xb6\xb9\x53\xaf\xa6\x47\xc7\xdf\x5f\x5c\x55\x5f\xad\x1e\xba\xef\x2f\xae\xd0\x65\x70\xb3\xa8\x5e\x6d\x2a\xad\x7b\xb2\x93\xe4\x23\xb4\xa9\x5c\x45\xa4\x6c\x85\x15\x53\x7e\xff\x64\x60\x98\x59\x3c\x51\x1b\x86\x43\x87\xca\x17\x0d\xaa\x39\x8a\x1b\xbd\x03\x38\xb4\xa7\x3c\xb4\xa7\x7c\x59\xed\x29\x9f\x54\x22\xa3\x47\xf3\xea\x2b\xf1\x3c\xa8\xcb\xa2\xeb\xcc\xba\xb9\x2c\x63\x79\x34\x95\x57\xa8\xdf\xdc\xfe\xd8\x04\x6d\x69\x5a\xb1\x49\x0a\xcf\xb4\xc4\x8f\xe6\xa9\x08\xf2\x2f\x04\x18\xbe\xcd\xfe\x87\x7d\xf7\x87\xbb\x80\x5e\xb2\x4f\xb8\xc0\x3e\x1f\xc8\x8a\x8a\x5b\x92\x75\x8e\xb9\xa6\xd0\xa9\x17\x6a\x9e\x6c\x2a\xe4\x07\x8c\x53\xc1\xf2\x1d\xc2\x02\x90\xd4\x72\x41\xa3\x22\xc1\xdd\x07\x28\x27\xca\x8f\x3d\x47\x97\x57\x37\xb7\x57\x17\xe7\x1f\xae\x2e\x5f\x23\xf3\x2b\xd4\xd5\xd6\xe7\xe8\x03\x2b\x1d\xdf\x9d\x54\xb1\xd3\x11\x1e\xd2\x9f\xcb\x31\x9e\x69\x01\x8c\xd3\x32\x57\x04\xd0\x02\x3d\x9e\xa2\xeb\x94\x8a\x32\xd5\x54\xb5\x58\x4a\x58\xaa\xd3\x2e\x25\x65\xed\x7f\x5f\x51\x71\xa6\xe2\xe2\xfe\x56\x9e\xf2\xd5\xea\x28\xe0\x84\xab\x04\x34\x3b\x85\x4e\x1f\xc6\xa4\x1a\x64\xb9\x89\x53\x58\x90\x26\x07\xac\x5f\xc7\x48\x15\xae\xb3\x2f\xeb\xfb\xcf\x64\xec\x9b\x55\xf1\x1b\x43\xfb\x80\x83\x48\xde\xcc\xc7\xf3\x63\xa3\x10\x26\xb5\x6a\x12\x2f\xcd\x72\x50\x06\x71\x52\xbe\x5c\xe5\xfe\x39\x42\x3f\x8a\x35\xc9\x1f\x28\x0f\x68\x50\x40\xeb\xb8\x97\x36\x6e\x27\x7f\xc0\x2d\x34\xa8\xfe\x8a\x9f\x70\xaa\xb3\x93\x16\xee\xa0\x35\xce\xd6\x8a\x6e\x49\xaa\x16\x76\x3a\x31\x6d\x86\xd6\x6b\xb7\x6f\x4b\xa9\xf1\xf1\xf6\xed\x74\x83\x51\x32\xa2\xd7\x50\x2e\xd8\x66\x43\x05\x5a\x63\xbe\x36\x68\x3f\x4e\xce\x97\x95\x53\x93\x18\xd4\x0a\x02\xa8\x47\x1f\xb2\xe3\xef\xcd\x2b\x35\x03\xda\x7e\x6c\xba\x91\x79\xe5\x0d\x58\x3e\xfd\x33\x5e\xdb\xda\x64\xd8\xb9\x3c\x43\xf7\x07\x92\xc6\x0a\x48\xbe\xdb\x2c\xee\x2e\x60\x0c\x15\x67\xf6\xc7\x7a\x36\x37\x35\xaf\xbd\x57\x60\xb9\x2a\xcd\x5e\x7f\xa8\x14\xbb\x20\xb4\xaa\x98\x08\x4c\x13\xee\xec\xb8\x60\x19\x4b\xd8\xaa\x39\x69\xb5\xc7\x76\xfd\x46\x95\x45\xcd\xf0\x4c\xf2\xc1\x74\xf6\x58\xdf\x9e\x65\xa6\xea\x4b\x2e\x50\x39\x4b\x6b\x87\x40\x81\xd5\x74\xbd\x9f\x9e\x6c\x21\x1e\x41\x81\xb5\xab\xe3\x5d\x0b\x63\xc9\x82\x07\xc2\xf4\x7c\x81\x7b\xa0\xc4\x8b\xc9\x48\xbe\xa1\x5c\x0a\x37\x47\xb3\x0d\x31\x77\xf7\x34\xdf\x27\x5a\x74\x9f\x52\x2b\x25\x9c\xaf\xf8\x77\xbf\x39\x38\xb0\x5f\x45\xb8\x66\x39\x99\x91\xcf\x94\x83\x0d\x00\x65\x84\x9e\x8a\xa2\xf2\xaa\x75\x3b\xb9\x1a\x87\xa4\x71\x5f\xaa\x6f\x25\xbb\x3e\x79\x93\xa5\x2e\x68\xfd\xc3\x90\x3e\x82\x93\x64\xa7\x1a\x17\x00\xb0\x8c\x72\xc8\xe0\x95\x17\x87\x90\xe5\x3a\x9a\x93\xe5\x74\x4b\x13\xb2\x92\xf6\xe1\x9a\xa6\x2b\x07\x08\x07\x27\x09\x7b\x20\xba\xf4\x99\x78\x63\x6f\xf5\xee\x41\x5c\xb8\xf9\xcd\xc0\xc1\xef\x7f\xfc\x80\x52\xa2\x7e\x8a\x07\x9c\xe6\xe1\xf6\xa8\x1c\x8c\x17\x3b\x61\x36\x9b\x81\xb7\xeb\xe4\x6f\x52\x8f\x8f\x93\x53\xf4\x17\xa2\xc7\x27\x0d\x1c\x79\xb6\x23\x81\x1e\xd6\x0c\xfc\x17\x05\x0f\xe8\xf2\x59\x72\x00\x1c\x36\x55\x77\xa8\x29\xbc\x92\x54\xa4\x0a\xab\xae\x6a\x58\xaf\xb8\x44\x58\xe9\x36\x68\x38\x2a\xe3\xeb\x4f\x67\x0f\x4c\x74\x75\x0e\xbc\x0b\x4c\x64\xa4\xe9\x54\x05\x55\x8f\x5b\xb0\x1a\x00\x3f\xe1\xbb\x4d\x42\xd3\xfb\x33\x44\x85\x11\xa8\x92\xc3\x75\xb2\x7c\x7a\x1f\x8a\xab\x97\x13\x9c\x38\xf7\xd1\x04\x5c\x3a\xd9\x5d\x23\x7a\xbb\xed\x3f\xec\x32\x02\xb2\xc3\x8a\x40\x9d\xaa\xe6\xba\x38\x8e\xfc\x6e\xeb\x97\xb4\x12\x94\xf7\xc1\x76\x3d\xbe\xbe\xbb\xb8\xbb\xae\xb5\xef\x56\x9f\x55\x42\x53\x23\x12\xe7\xa7\xca\x9c\xef\x73\xd5\xc2\x22\x3c\x83\x4e\x4e\x7f\xe9\x32\x41\x66\x28\x29\xba\xff\xae\x52\x4a\x6f\x58\x2e\x70\x57\x01\x4d\xa8\xe8\x89\xd6\x38\x3b\x2f\xc4\xfa\x92\xf2\x88\x6d\x49\x4f\xf3\xd4\x20\x17\xeb\xf0\x11\xa2\x86\x2d\x14\x2d\x74\xf1\xef\xe7\x37\xb5\xfe\x9a\x93\x68\x30\xee\xc8\xef\x08\xef\x6d\xcb\x36\x8f\x5b\x53\x7a\xd4\x51\x1f\x42\x87\xff\x34\xa1\x43\x90\x20\xff\xac\xe1\x42\x9a\x52\x41\xb1\x60\x41\xd0\x03\x55\x3f\x51\xc1\x05\xdb\xe8\x23\x75\x6d\xc8\x40\xde\x0b\x84\xfe\x2a\x94\x83\x18\xac\x6c\x0f\x43\x41\x57\x89\x38\xb5\xc8\xe2\xb5\xac\xf8\x33\x94\x92\x07\x3f\x51\x18\x1b\xb5\x34\xfe\x55\xd7\x40\x64\x20\x55\xff\xed\xf5\xbf\xea\xa3\x95\xe2\x0d\xf9\x37\xd0\x85\xbc\x24\x4b\xf4\x14\xeb\x1c\xd3\xbd\xf6\xa6\x72\x8a\xc1\xc0\x7f\xe9\x27\xe7\xb4\xb3\x58\xcd\xf7\x3f\x0a\x9c\xa8\x75\x7c\x3f\xa5\x67\xb3\xba\x1f\xbd\x86\x67\x78\xc4\xec\xc3\x7b\xe3\xed\x91\xc6\x04\xe8\x19\xf0\x0d\xbf\xd6\x99\xe3\x94\xcb\xcd\xab\x46\x9e\x8e\x75\x60\xf9\x18\x9d\x88\x28\x0b\xc4\x66\x7d\x84\x1a\x2a\x35\x4d\xbd\x17\x6f\x6d\xed\x54\xd8\x78\x26\x8f\xb2\x02\x8f\xf7\x73\xd2\x55\x26\xa0\x54\x0f\xf4\x96\x72\xa1\x32\xd9\x15\xc5\x90\x46\x4f\x44\x55\xcb\x48\xfd\xf1\x06\xfa\x1b\x64\xff\x89\xe3\x38\x7f\xad\xee\xe0\xa5\xd6\xe3\x72\xf0\x02\xb0\xf0\xe6\xfb\x26\x7f\xe0\x44\xec\x32\x1a\x81\xc9\xff\xe1\xe2\x06\x28\x71\xf4\xa7\x3f\x2a\x48\xad\x7f\xf9\xc3\x1f\xbf\x0e\x64\x81\xe7\x28\x67\x1a\xe4\x05\xeb\x95\x25\x1e\x12\x12\xf1\x45\x71\x27\x53\x83\x86\xe5\x95\x83\x62\x76\x57\xf6\x67\x57\x7c\xa9\x85\xb7\xdc\x64\x7b\xb7\x78\x27\x3b\x40\xbd\x3b\xe4\x40\xb7\x3e\x2f\x3f\x07\x1a\xd9\x72\x49\x25\xbf\xc6\xca\x3f\x25\xfa\x6e\x8c\xe8\xd3\xa2\xcd\xcf\x76\xc1\xa2\xaf\x22\xda\xbc\x74\xa7\x12\x7d\x9e\x55\xf4\x71\x6c\x95\x53\x95\x34\x91\xd6\xbd\x13\xa3\x86\x9a\xac\xcb\xf7\x77\xff\xf9\xf6\xfc\xbb\xab\xb7\xba\x9d\x20\xfd\xc5\x03\xd7\xe3\xa2\x2b\x0f\xc8\x41\x0d\x67\x77\xbf\x1f\xc0\xb7\x44\x7d\xa2\x96\xef\xdf\xdc\xd5\x1c\x2b\xf2\x13\x13\xaa\xac\x86\x23\xbb\xe5\x69\x4b\xa8\x72\xac\x8d\x93\x2e\x03\x56\xe4\x69\x9c\xa9\x33\xc8\xf8\x9f\xa4\x78\x72\xa0\xbf\xd5\x04\x28\xc8\xe7\xaa\xc1\x2b\xf7\x4c\x8d\x6d\x50\x7f\xf2\x09\xf7\x03\x3d\x73\xe0\x4d\xae\x84\x5a\x9d\x90\xf8\xd8\x93\x86\xdc\x1e\x65\x95\xc3\x54\x9d\xbc\x6f\xa5\xee\xf1\x1d\xbc\x63\x82\xbd\x52\x04\xa8\x0c\xc7\x5c\xde\x1e\xf2\xde\x20\x9c\x87\x80\xd7\xd5\xb8\xf3\xa5\x70\x5f\x99\xa9\xa7\xae\x88\x8b\x04\xd3\x4e\x34\xae\xda\x61\x6c\x7a\x5d\xfd\xf3\x4e\xb9\xa2\x03\xbb\x8d\x55\x9b\x06\x21\x8c\x1a\x29\xdb\x5c\x21\xac\x5d\x02\x00\xb9\xdd\x7d\xd4\x07\x2e\x74\xb9\x30\x33\xb3\xe6\xe5\x47\xea\x93\x48\x0e\xe9\xe9\x84\x32\xfc\xdc\x44\x65\x13\x96\x56\xbf\xc3\x70\x61\x5e\xab\x97\xae\xb7\xec\x57\x88\xa1\xb3\xbf\x9f\x08\x73\x0b\x6a\x5f\x68\xb7\x5a\x70\x8d\xfb\xf3\x6e\x38\x7a\x74\xa9\xff\x97\x9e\x05\xc8\xde\xe5\xba\x34\xd5\xef\xd3\x99\x95\xd9\x9a\x09\x96\x0e\x2c\xc4\xba\x69\x78\xb9\x9a\xec\xa0\xbe\x71\xa1\x8a\x0f\x13\x8f\xaa\x5f\xee\xa1\xca\x22\xb7\x61\x2f\x68\x14\xad\xef\x3c\x96\x9a\x00\x18\xf7\x07\xce\xb5\x7f\xf7\xc9\x74\xb1\xf8\xfa\x72\x82\x13\xff\xeb\x81\x74\x98\x1a\x5f\x6a\xaa\xe3\x2e\x37\xb2\x5f\x37\x94\x4b\xad\xe7\x9a\xba\x4a\xae\x59\x1f\x95\xbc\xef\xf0\xb7\x77\x52\x01\x35\x55\x61\x3a\x03\xcb\xc5\x03\xcb\xfb\x82\xcb\xdc\x54\x5e\xab\xe5\x2f\xe9\xbf\x85\xa4\x37\x07\x9d\xe0\xa7\x3e\xa5\x6a\xdc\xcf\x76\x52\xef\x20\x39\xc2\x59\xd2\x86\x08\x62\x48\xd2\x88\xb2\x77\x9b\x8e\x77\xc7\xf1\xf5\x52\xed\x3c\xde\xea\xf8\x36\x1e\xdb\x40\xcb\xc5\x1e\xeb\x47\x39\xb6\x83\x6e\x69\x0f\xe8\x48\x78\x5d\xcf\x20\xd0\x91\xc9\x0c\x26\xc3\xd5\x03\x3a\xde\x5d\x5f\x6a\x67\x92\xdc\xcf\x52\x80\x61\x2b\x06\xbc\x53\x0f\xaa\x74\x08\x13\x58\xaa\x7f\x7f\xf7\x19\x6e\x68\x44\xb5\x64\x39\x20\x7c\x50\x05\xfa\x51\x22\xf5\x6b\xc8\x8f\x33\xdd\xc0\x70\x83\x33\xde\x7d\x4d\x49\x51\xe5\x76\xb2\x7a\x2a\xb1\xa4\x07\x3c\x81\x54\x1a\xda\x47\xee\x5d\x7b\xf3\xb8\xfd\xe6\x70\x7e\xdd\x3e\xa0\x57\xcb\x7e\x2b\xb8\x20\xe3\xdc\xb4\x8a\x0b\x6e\x05\xe7\xa5\xea\x6d\xd3\x52\x6f\xc0\xe2\xa5\xd8\xd5\xa0\xa5\xad\xf5\x4a\x80\xcc\x77\x5b\xb3\x3c\x4b\x24\x54\xb3\x69\x2f\xc6\x32\x0d\xe2\x4c\xd6\xbd\x3a\xe3\x01\xdd\x6f\x1e\xb7\xf5\xdb\x8d\x1d\x87\xda\x5d\x0d\x62\x64\x45\x10\xc2\x09\x0b\x42\xd6\x77\xd8\xc5\xe9\xc2\xa9\x13\x8d\x76\x59\x40\x38\xa8\x57\xcf\x8d\x7e\x2d\x31\x22\xd3\x1b\x7f\x40\x07\x15\x17\x26\xca\x76\xd4\x2c\x29\xa2\x20\xd0\x15\x3d\x43\x66\x16\x36\xe8\x85\xde\x4d\x48\xfa\xf7\x09\x09\x64\x19\xf3\x54\x2f\x9d\x8a\x02\x73\x86\x08\x8e\xd6\xe8\x9e\xec\x66\x20\xeb\x82\x69\x22\x94\x61\xa8\xd1\x84\x75\xbd\xc4\xa2\xda\xf8\xae\x74\xb4\x85\xf6\x74\x92\xcf\x85\xdd\x1e\x53\x4f\x58\x72\xb4\xad\x06\x0d\xac\x4d\x2c\x1f\xcc\xb5\x8e\x89\x1e\xd6\x8c\x6b\x77\x92\x76\x2d\xdd\x93\x1d\x88\xb5\x88\xa5\x41\xd6\x4d\xf9\x68\x02\xb0\x6a\x90\xe7\x54\xab\x5b\x94\x92\x83\xc4\xf2\x07\x42\x1b\x65\x21\x38\x8f\xad\xf3\x2e\xd3\xa2\xe4\x25\xe2\x51\x05\x6a\x2b\x00\x41\x37\x67\x44\xea\x77\x00\x69\x14\x32\xd4\x38\x49\xc3\x32\xc8\x1d\x9a\xb0\x76\xd5\x74\x2d\x80\x65\xa7\x5c\xf7\xbd\x07\xaa\x7d\x56\x54\xf1\x92\x65\x82\x4a\xfd\x27\x27\xa2\xc8\xc2\x52\xb3\xca\x07\x72\xee\xe4\xcc\x09\xe7\x48\x81\xbf\x6f\x70\x7e\x4f\x62\xdb\xd4\x66\x0e\xbd\xb5\xfa\xec\x90\xc1\x6b\x35\x8d\xa8\x94\x81\x88\x77\x6e\x31\x6e\x8f\xd6\x8f\xf2\x39\x9e\xcf\x55\xc7\xac\xa6\x22\xdd\x60\x3a\xe1\x37\x4e\xf9\xf4\x14\x24\x75\xad\x0b\x67\x50\x47\x00\x7a\x31\xb0\x03\x38\xd5\x83\x7a\x74\xba\x8f\x0e\xf6\xe2\x60\xe7\x6b\xf9\xf4\x16\xb6\xea\xe9\xd7\xf7\x49\x3d\x33\x39\xc3\x5e\xdf\xef\xb9\x10\xfd\xef\x01\xf5\xdc\x13\xaf\xd9\x58\x7f\xaa\x49\x83\x5a\x0e\x96\xf7\x5c\x9f\x1d\x40\xc3\x7a\x3c\xa9\x27\xbc\x39\x63\xcb\xd8\x5b\xda\x34\xf6\x24\x89\xdc\xb6\x8e\xcd\x0d\x1b\x7b\x53\x6c\x6e\xf0\x58\x6b\xdd\xd8\x9b\x6a\x77\xab\x47\xd5\xc4\xb1\x37\xd1\x90\xa6\x8f\xbd\x89\xfa\x1b\x51\xf7\x26\x19\x60\x8d\xf4\x1f\xe6\xe0\xc6\x91\xe5\x33\xac\x0b\x96\x7a\xfa\x36\x93\x2c\x9f\xf0\xb6\x92\xe5\xb3\x77\xee\xed\x2d\x96\x95\x05\x66\xbd\xd7\xd0\x74\x94\xdc\xe0\xcc\x2a\x55\x82\xcd\xd1\x3b\x7d\x2b\x0e\xd8\x16\x9c\x96\x1d\x26\x75\x69\x59\xf5\x8a\x1d\x74\x72\x60\x92\x24\x21\x1b\x92\x0a\x0d\x81\x61\xc8\xc2\xb5\xdb\x9b\xa8\x45\x90\xd0\x77\x60\xbf\x1b\x5b\x0f\xac\xbf\xf0\x0c\x4d\x24\x54\x4f\xbf\x74\xc2\x1e\xa3\x7f\x86\xc4\x43\xf5\x84\xa7\x1f\xf6\x20\x0a\x89\x8a\xc1\x49\x88\xea\x19\xb0\x77\x46\xf3\x1c\xd5\xdd\x70\x67\x2b\x9a\x2a\x1a\x73\x8f\xd9\xb2\x1c\x49\x71\x07\xc6\x80\xb9\xea\x74\x5b\xa4\x9e\xb3\x0f\x71\xf1\xea\x89\x94\x0d\xeb\x27\xb3\xe8\x1d\x9a\x81\xe3\x96\x96\xff\x3f\x9b\x4d\x0f\x8e\x64\x28\xea\x35\x0e\xab\xcb\x72\x5d\x02\x71\xe5\xcb\x47\xca\xf3\x17\x6c\x76\xec\x4d\xed\x8d\xbc\x7f\x02\x53\x80\xf6\x86\x52\x81\x13\xd7\x4e\xe3\x52\x51\x29\x21\xc8\x7b\x51\x35\x89\x25\x20\x91\x5e\xaa\x39\xf3\x44\xe6\xc9\xb2\x57\x1b\xe4\xf2\x69\xeb\xba\x59\xb6\x46\xee\xbb\xba\xea\x61\x26\xf9\x3a\x7e\xad\x7a\x23\xe3\x34\x65\x02\x38\x80\x9f\xa1\x04\x2f\x48\xd2\xcb\xb9\xa2\x1e\x70\x2a\x49\x95\xd4\x49\x30\xca\x49\xef\x0e\xc6\xe5\x33\x90\x15\xd0\x40\x76\x40\xc0\x12\xb0\xa2\x37\x7d\xed\xf7\xe1\xbc\x21\x9f\xf2\xb6\xee\xff\x6e\x3d\x28\xa8\xe8\x98\x2d\xe6\xd1\x9a\x6c\x42\xbd\xbc\xd5\x07\xc0\xc9\xcd\x62\x48\xc9\xfa\x90\x53\x21\x88\x42\x44\x25\xf9\xa6\x9f\x90\x31\x0f\x5b\xd6\xda\x07\x6f\xbf\x39\xea\x6f\xae\x8d\xb0\xb7\x91\x39\x8f\x3e\x38\x98\xb6\xa7\x1a\x85\x70\x40\x29\x94\xf3\x77\x80\xe5\x8d\x20\x65\x36\x81\x4e\x0a\x69\xcd\xd1\x79\x7e\x73\x8d\xb6\x6a\x4f\x9f\x74\x99\x0e\x6e\x89\x9e\xcf\xc1\x2d\x71\x70\x4b\xe8\x67\xb4\x5b\xc2\xb9\xea\x8d\xf0\x1d\xe4\x95\xa8\xba\x36\x5c\xc4\x60\xed\xaf\x18\x70\x76\x4c\x52\x81\x83\xbf\x29\xcf\xa2\xf1\x54\xf4\x6a\xb0\xaf\x1e\x17\xd2\xf2\xf8\x78\x3e\x3f\x3e\x36\xfe\x0e\x7d\xd0\x0b\xb1\x9c\xfd\xa9\x37\x59\x92\x46\x2c\x26\xba\x7b\xee\x92\xe6\x5c\x80\xd2\x5d\x1a\xfe\x6a\x6d\x7a\xd3\x85\xb5\xdc\x98\xb9\xbb\xb1\x0a\x18\xfb\x30\x16\x1d\x20\xa1\x4d\x96\xcc\x9b\x49\x94\xcb\x52\xa5\xb4\xe0\x36\x01\xc5\x16\xf5\xa7\x82\x4b\xa6\x75\xcb\x32\x9b\x47\x75\x42\x1e\xe0\x08\x8b\x41\x9f\x23\x5c\x70\x74\xa2\x88\xcc\xa3\xac\x38\xd3\x04\xe7\xaa\xd1\x72\x7f\xa9\x65\x88\x4a\x62\x95\x5f\xd1\x14\x4f\xfb\x0f\x35\x27\x28\x2a\xf2\x9c\xa4\x22\xd9\x7d\x69\x9a\x6f\x50\xc3\x8d\xfd\x67\x8c\xe2\x6b\x79\x25\xa4\x44\xa2\xe9\xa9\x95\x4d\x58\x30\x66\x70\x0f\x86\x37\x35\x6f\x7a\x96\x16\x54\x9f\x9f\x59\x97\x15\x7c\x4a\xd2\xed\x20\x8a\x5b\x9c\x7b\x8b\x1a\x9a\x9e\x51\xba\x6e\x4c\xb7\x94\x33\x6f\x31\x56\xe3\xab\xfb\x5e\x37\xaa\xc1\xad\x59\x21\xb2\xa2\xbf\xb3\x18\xd9\x7b\xd5\x88\x61\xd3\x6d\xc5\x4a\x89\xfe\xc7\x18\x95\x59\x73\xca\xa4\xf8\xc6\x8f\x8b\xb3\xff\xbc\xd8\x3e\xe5\x4d\x4f\x50\xef\xf2\xa6\xa7\x5f\x3f\xf3\x2e\x0a\x03\xd9\x71\x44\xdf\xf3\xb6\xc7\xb0\xce\x78\xf9\x51\xaa\x5d\x03\x65\xa1\x7a\x00\x1d\x53\x5e\xa7\x4f\x70\xd8\x55\x86\xec\x64\xbe\x64\xdd\xb4\xef\x90\x1a\xf6\x02\x53\xc3\x34\x0a\xc8\x21\x2f\xec\x57\x9b\x17\x76\xa7\xbb\x61\x36\x26\x85\xa9\x54\xaf\x1e\x44\x03\x92\xc2\xc0\xce\xe9\x41\x32\x20\x29\x0c\x02\xc4\xbd\x0e\xd2\x21\x29\xec\x90\x14\x76\x48\x0a\xeb\x37\xf6\x83\xf7\xf5\xe0\x7d\x3d\x78\x5f\x83\x9f\x43\x52\xd8\x21\x29\xec\x90\x14\xd6\xfc\x7c\xb9\x49\x61\xda\x60\xea\xa5\x14\xeb\x8c\xb0\x27\x4b\x08\xd3\x2d\xbd\xcf\xa3\x88\x15\xa9\xf8\xc0\xee\x49\x60\x0e\x40\x90\x31\xbf\x47\x3b\x70\x1e\x4f\x92\x20\xd6\x4f\xd9\xec\xa1\x36\xf6\x57\x18\x71\x11\x53\x69\x8e\x0f\x64\xbe\x73\xfd\xba\xb1\x7c\xe5\x95\x97\xc6\x24\xb6\x74\x7b\x30\xa0\x16\x41\x42\xee\xd6\x1c\x9d\xa3\x9c\x44\x34\xa3\x52\x30\x03\xfc\x0f\x7c\xde\xd7\x2c\xb3\x3d\x3e\xa9\xe0\x24\x59\xea\xfe\x87\xa9\xd3\x48\xbc\xd4\xbd\xfa\x5b\xa5\x66\x92\x95\xa1\x2b\x3d\x84\x99\xb6\x77\x3d\xa8\xea\x1e\xee\x39\xf9\x9b\x51\x8d\xf4\x5a\x7c\x70\x7f\x2b\x0e\x45\x48\x2b\x1f\xed\x2c\x70\x26\xad\x07\x8c\x33\x1a\x8a\x65\x67\x69\xf5\x17\x70\xe4\x73\x46\x73\x38\xa2\x77\x24\x62\x69\x3c\xd4\x45\x75\x55\xa7\x63\xb8\x4e\x47\xaf\x7a\x6d\x61\x5c\x28\x52\x50\xe0\x8b\x13\x1a\x53\xb1\xb3\xb9\x43\x4a\x7c\x20\xac\xe4\x47\xaf\x95\x56\xcc\xcb\xcb\xed\x43\x38\xcb\x72\x86\xa3\x35\xe1\xce\x4a\xf4\xb9\x87\x40\x83\x52\xd0\x23\xb6\x16\x39\x29\x56\x34\x55\x5a\x3e\x50\x97\x2a\x5b\x00\xd8\x43\xf9\xe4\x4c\x98\x64\xc7\xda\x74\x5d\xae\xd3\x3f\xdb\xd7\x59\xa5\x5c\x16\x22\xdf\x01\xb4\x16\x73\x7f\x4c\xad\x49\x00\x40\x4e\x75\xfe\xfa\x35\x8e\x58\x12\x1b\xbc\xd4\x3f\x7d\x8d\x32\x92\x47\x5a\x42\xf4\x0b\xb0\x02\x5e\xa6\x60\x28\x91\xaa\x2e\xcb\x0d\x2a\x6b\xc3\xcf\xf4\x20\xfa\x87\x6f\xd1\x9a\x15\x39\x9f\xbb\xe0\x1c\xdf\xc0\x67\xca\x29\xa4\xae\xd6\x3e\x0e\x35\x81\x12\x82\xb9\x40\xdf\x7c\x8d\x36\x34\x2d\xa4\x46\xd5\xf3\xa8\xf6\xb5\x42\x1c\xfb\xe3\x8f\xdf\x06\xbe\xd5\xcf\xf2\xd8\xcf\x23\xd3\xe7\x38\x53\x5d\xc7\xb4\x01\xd2\xcb\x68\x87\xb6\x08\xc0\xbd\xaa\x97\x60\x35\xdb\xc3\x5c\xe7\x3d\x8d\x19\xcd\x0d\xa9\x60\x13\xcb\xc7\x5f\x0a\xb6\xd8\x89\x70\x60\xa3\xff\x50\xdf\xaf\x22\x1a\x99\x0f\xf7\x10\x64\x3b\xc7\xba\xdf\xec\xb2\x04\x90\xed\x78\x71\xe2\xce\xba\x2b\xca\x45\x67\xe3\xd6\x99\xdf\xa5\x1f\xaa\xec\xac\x72\x56\x78\x51\x04\x2a\xcb\x0d\xfe\x04\x63\xbf\x6a\x89\x8b\xa3\x88\x70\x38\xd0\x97\xb6\x83\xbd\x97\x29\x52\xa6\x7e\xdd\xf3\xc5\x67\x04\x8e\x37\x4c\x14\x18\x40\x79\x4c\x20\xd7\xa0\x45\x0a\xb1\x2f\x0c\x7b\xf5\x5c\x25\xf5\x52\xf5\x8c\x71\x9a\xae\xa0\xd5\x21\xda\x14\x89\xa0\x59\x40\x6d\x84\x59\x51\x4b\x50\x5f\xaf\x6e\x50\x04\x3b\x5e\x72\xec\x5f\x22\x79\xa8\x15\x78\x38\x04\xd7\x4e\xcc\x58\x10\x49\x05\x80\xd0\x40\xb6\x39\xc9\x70\x8e\xcd\xb6\x78\x69\x46\x6c\xb3\xc1\xfc\x54\xc7\x67\x30\x64\x40\x29\x29\x2c\x2f\xd4\x1c\x27\x76\x19\xdd\x7c\x90\xa9\x18\x59\x90\x14\xa7\xde\xe0\x6d\xd5\x39\x05\xaf\x20\xf6\x90\x9a\x36\x38\xaa\x73\x73\x4f\x0e\xd6\xaa\xfb\x77\x38\xba\x27\x69\x8c\x3e\x72\xc3\xc7\xf1\x2e\xc5\x1b\x0d\xab\x6e\x1b\xab\x93\xd8\xd0\xf7\x12\xb6\x19\x33\x0a\x37\x48\x21\xfa\x18\x10\x33\xa5\xaf\x4d\xb5\x7a\x05\xef\x89\x31\xfc\x91\x4b\x65\xa6\x5b\x9e\x05\x79\xc9\x39\xc9\xe9\x36\x22\x46\x53\x94\x03\x99\x6a\x52\x5b\x2f\xd6\xdf\xde\xb4\x34\xce\x1f\x75\x4e\x13\x5c\x6f\x36\xc8\x0c\x28\xeb\x38\x91\x22\xca\xaf\x1b\x1b\xcc\xa8\x2a\x43\xc9\x1d\x9c\xac\x39\x78\xbe\x08\x07\x08\x3b\xbe\xfd\xee\xb2\x2a\x8c\x6e\x71\xcc\x38\xfa\x2e\x61\xd1\x3d\xba\x24\xa0\xb2\xfb\xbb\xea\xd7\x91\xe5\x83\x1a\x5d\x77\x52\xf4\x35\xdb\xcb\x17\xf1\x73\xb4\xda\xdb\xe0\x55\xd7\x21\x9d\xa1\x0d\x4b\xa9\x60\xf9\x14\x50\x65\x87\xc6\x6e\xff\x34\x8d\xdd\xf2\x85\xdf\x6b\xf0\xa5\xb6\x75\x93\x47\xa2\x67\x07\xd4\x35\x41\x39\x88\x19\x78\xd9\xf4\xf2\x08\xef\xb4\x59\x39\xfc\xbf\x59\xb3\x87\x99\x60\xb3\x82\x93\x19\xf5\xe6\x84\x05\xcf\xeb\x9e\xec\x20\x69\xae\xd7\xcc\x7e\x50\x2f\x55\x4c\x4d\xc1\xc0\xe3\x0d\x9f\x4b\x25\xe7\xf6\xbb\x4b\x79\x53\x86\x23\x5a\x53\x8e\x5e\x11\x11\xbd\x8a\x48\xb6\x7e\xa5\x87\xf5\xe2\x96\xcb\xc8\xbd\x7e\xeb\x75\x8e\x22\x96\x24\x1a\x67\x8e\x2d\xd1\x05\xc9\xd6\x96\x54\xaf\xf0\xd0\xa3\xaf\xc1\x73\xb4\xf0\xca\x18\xeb\xd7\x56\xc8\x39\x5a\xf2\x5d\x7d\xb2\x1c\x46\xca\x17\xf1\xa4\x3d\xfd\x9f\x82\xb5\x1e\xa1\xab\x48\x30\x6e\x6d\x1b\x34\x6d\x43\x27\xb3\x17\xc5\xad\x8f\xd7\x31\xed\xf8\xce\xbc\x06\xf9\x76\x4e\x58\xb7\x57\x03\x34\xf3\xf3\x15\x91\x88\xae\x97\xca\x2a\x8a\x49\x8c\xd8\x96\xe4\x39\x8d\x09\x37\xa2\xb8\x97\xc4\x4c\x69\xf2\xb4\x32\xf2\xd0\xcb\xad\xf5\xf9\x32\x7a\xb9\xf5\xb6\x77\x1d\x61\x2b\xdf\xdd\x17\xb6\x38\xde\xd0\x80\xb2\xe2\x17\x74\x93\xf3\x08\x27\xe4\xfa\xc7\x60\xf3\xf1\x4e\x7d\xbf\x6a\x41\x9a\x0f\x9d\x96\x15\x23\xe0\xf0\x7f\xb0\x7c\x8a\x52\x16\x77\x47\x26\x26\xb5\xf5\x56\x58\x90\x87\xce\x2b\x7f\x56\x8a\xd0\xee\x6f\xf9\x1a\x4b\x1c\x9a\x5f\xd4\x0d\x38\xe7\x14\x29\x5c\xfd\xa9\x94\x09\xbd\xab\xfd\x9c\x82\x66\x8a\x65\x9f\x2c\x95\x00\xa3\x19\xfd\xfc\xe6\x1a\x7d\xaf\xe8\x4e\xd7\x65\x23\x67\x42\xe9\xc5\x97\x6c\x83\x69\xcf\x26\xcd\x4e\x4b\x23\x77\xa0\x37\x96\x28\x52\x54\xbd\xdb\xe2\x74\x9e\x5e\xd2\x55\x21\xed\x68\x6d\xdb\x1e\x1a\x13\x78\xa6\xfe\x78\x2a\x58\xa9\x81\x39\x3e\x48\x53\xab\x61\xb5\x2a\xef\xd4\x0d\x57\xc0\xe5\x65\xd3\x49\x10\x27\x29\xa7\x10\x1b\x75\xd2\x9e\x40\x35\x13\xeb\x80\x68\x94\x2d\xc2\x50\x6a\xdc\x19\x7a\xcb\x56\x34\x35\xd2\x81\xe9\x74\x82\x25\xa6\x49\xd8\x32\x1e\xf4\xaa\xd6\xe7\xcb\xd0\xab\x38\x4f\xae\x52\xbc\x48\xfc\x99\x68\xd5\x8b\x2b\xc1\x90\xd5\x41\xe0\xdd\x57\x31\xe5\xf2\xbf\xe8\xee\xee\x2d\x44\x95\x8a\x34\xd4\xce\x80\xb8\x8b\x16\xcf\x16\x1c\x47\x09\x8d\xe9\xce\xb1\x92\x89\xbd\xbb\x4a\x5c\xa7\xb1\x9c\x06\xe1\x95\xc4\x4a\x4d\x4d\xf5\xed\x08\x0d\x39\xe9\xbc\xae\x05\x41\x1f\xd6\x34\xba\xbf\x71\x82\x4b\x2c\x97\x9f\xa5\xce\x47\xf6\x82\x0d\x39\xce\xf5\x77\xa7\x12\xfc\x7a\x9a\x37\x7d\x9d\x1c\x1f\x9c\x1b\xed\x4e\x2f\x95\x24\x82\x30\xe7\x2c\xa2\xe1\xd1\x49\x70\xd1\x95\x57\x62\x0c\x57\xe2\x74\xd3\x03\x2d\x68\xd4\xbd\x6d\x18\x41\x2b\x70\x98\x3b\xf7\x70\x48\x0c\x52\xaf\xd2\x64\x53\x52\xac\xd8\xbb\xdf\xe2\x87\x4a\x87\x45\x13\x1a\x54\x01\x33\x1b\x10\x0b\x6c\x6f\x62\x36\xde\xe8\xb4\xba\x81\x6e\x6d\xeb\xdd\x4e\x8b\xfe\x93\x03\xa5\xc8\x93\x2c\x92\xbf\x5c\xb8\xc9\x97\x52\xcb\x06\x50\x9f\xe9\x30\x1a\x1c\xea\x8c\x65\x45\x82\x3d\xe1\x61\xb7\xb9\xe4\xd8\x78\x85\x1a\xc3\x04\x61\xb5\xc7\x6e\xcb\xd3\x52\x88\x55\xeb\xd0\xe3\x57\x73\xeb\x1d\x7c\x42\x3a\xf4\x84\xba\xa3\x60\x40\x5f\xff\xf1\xdb\x6f\x9b\x7a\xfa\x54\x7a\xf6\xf8\x75\x97\xc0\x9e\x3e\xb5\x82\xaa\xb0\x3b\xb2\xb3\xa7\x4f\xbd\x67\x8f\x7f\x49\x03\x7a\xfa\xf4\x2c\x80\x7a\x9c\xa6\x3d\x41\x4e\xfb\x1e\x55\xec\xa6\x36\x3d\x48\x9c\x75\xd5\xae\xb7\x56\xa4\x07\x88\xfe\x4a\xc5\x7a\x48\x1d\x7a\x40\x20\x11\xea\xd4\x27\xad\x3e\xef\x51\x73\x5e\xa9\x24\xf7\x12\xee\xaa\x34\x6f\xad\x1f\x0f\x37\x6d\x80\x56\x50\xd5\xb8\x97\x66\x70\x03\x91\xe0\xbc\xde\xa0\x0a\xf1\x6a\xdd\x77\x98\x7c\x08\xa9\x32\x7b\xdc\xa6\x54\x1d\x95\xdf\xb6\x9a\x3b\xc0\x74\x09\xad\xf7\xee\x55\x72\x13\x5e\x6e\x13\x56\xd1\x1d\x58\x90\xd3\xaf\x18\x27\xb8\x66\x7b\x92\x4a\xed\x9e\x55\x1c\xe1\x55\xd9\x7d\x54\x80\x20\xa7\x85\x7a\x1a\x2b\xb0\x5b\x2a\xaa\x03\x49\x56\xeb\xae\x3d\x75\xd4\x81\x34\xa1\xda\x3a\xa8\x7a\xda\x5c\xe6\x81\x84\x3d\x57\x7e\xe5\x4a\x0f\x26\x39\xc5\xc5\xaf\x69\xf5\xae\x34\xe8\x5b\xe5\x1c\x5e\x61\x10\x54\xd1\xdc\x13\x06\xb2\xbd\x8e\x79\xbf\x2e\x39\x90\xe4\xbb\x06\xf1\xdf\x5e\x8d\x1c\x48\xd4\x81\x0a\x19\x54\x83\x1c\x2c\x16\x42\x6b\x56\xc3\x2b\x55\x6d\x47\x02\xef\x40\xfb\x15\xa8\xf6\xf5\xf8\xf6\x36\xa1\x2b\xfe\x47\x6d\x21\x9a\xfd\x54\x19\x96\x16\x15\xdc\x7f\xad\x81\x6c\x7c\x02\x1b\x11\x05\x9b\xcd\x8a\x34\xeb\xbc\xc3\xaa\xbb\xac\xde\xf8\xf1\xae\x16\x7a\xb4\x1f\x1b\xcd\x57\x47\x15\xbb\x43\x8f\x8f\x1e\x71\x3c\x04\xf8\xbe\x94\xee\xf6\x87\x68\xd4\xf0\x68\x14\xaf\x60\x58\x1a\x3f\x96\xd2\xc4\x42\x02\x52\x6c\xa1\x3b\x61\x28\xa1\x6d\xcf\xf2\xf9\xcd\x35\x8a\x72\x02\x85\xc5\x38\xe1\x73\x34\x00\xd1\xc6\xf8\xfd\x41\xa7\xe3\xd6\xf2\xc4\x42\x90\x4d\x26\x42\x19\xe8\x10\x8c\x6a\x7d\xbe\x8c\x60\xd4\x40\x0f\xf6\x27\xfb\x9a\xf1\x7f\xac\x8b\x0d\x4e\x67\xf2\x94\x43\x58\x4a\xbb\xb7\xc3\x5c\xd8\xb5\x4b\x6a\x8e\x4c\x8d\x09\xac\x36\xd4\x59\x41\xa9\x9b\x6a\x3c\x1f\x64\x9c\x03\x8e\x99\x55\x01\x1e\xc1\xe1\x0f\x74\x07\xae\x99\x6a\x56\x52\x93\x0e\x11\xcb\x82\x57\x4c\x5f\xe6\x7a\xa2\x76\xfd\x8c\x20\x70\x3a\xa2\xb8\x5e\x9d\x10\xd2\x4a\x85\xba\x81\x02\xd5\x92\x4a\x05\xd7\x4a\x03\x55\xe1\x24\x61\x0f\x01\x85\x86\x6b\x52\x51\x20\x24\x5f\xc8\xb9\xea\x1a\xf5\x05\x41\x1b\x9a\xe7\x2c\xd7\x81\x8a\x00\x37\x61\xc9\x2e\x90\x8c\x21\x2d\x3e\x92\x2b\x33\x28\xd7\xb1\xf9\x3b\x22\x9c\xe5\x0e\x51\x00\x71\xaa\x0a\x8e\xe4\xbf\x4d\xa2\xa5\xea\x76\xa5\xe5\xe4\x82\xac\xf1\x96\xb2\x22\x07\xea\x21\x24\x8f\xf4\xab\xf2\xea\x46\x3b\x56\xd8\x26\xf4\x05\xd4\x1e\xd8\xd5\x0d\xee\x66\xef\xec\xf3\xfb\xf2\x65\x30\x52\x63\x66\x3c\x71\x33\xf2\x99\x72\xd1\x7f\x2d\xcd\x16\x1b\xb8\xfd\x29\x4e\xcc\x96\x67\xf2\x02\xff\xe4\xad\x31\xab\x9e\x13\xf7\xad\xaa\x3a\xbb\xbd\x83\x3f\x8d\x51\x66\x35\xb6\x02\x57\x2a\x9c\x2e\xfe\x18\xaf\xd0\x86\xa5\xd0\xa9\x71\x7b\xba\xfd\x1c\x74\xe3\x2f\x45\x37\xb6\x01\xfb\x84\x46\xbb\xeb\xcb\x7e\x5a\xa2\x0d\xd4\xcb\x97\xd1\x77\x98\x93\x18\xbd\xc3\x29\x5e\x29\x47\xc4\xc9\xdd\xcd\x77\xef\xfc\x1d\x01\xb2\x9c\x81\x53\xe5\xfa\xb2\x21\xe4\x6b\xaf\x56\xf5\x23\xef\xa7\x2a\xa8\xdc\x9b\x7b\x6f\xfd\x61\xe2\xd9\x4f\x56\x2a\x8a\xec\x1d\x1f\xd2\xae\x69\x1f\x52\x43\x85\xdf\x0d\xe2\x0f\xaf\x0b\xac\xed\x26\xbe\x1f\x3e\x4c\x9a\x72\x81\x93\xe4\x26\xc1\xe9\x79\x96\xe5\x6c\xdb\xe4\x09\xaa\x02\x45\xe9\xaf\x19\x25\x4d\x65\xb6\x99\x0f\x33\xb5\xf8\x90\x55\x93\xa2\xeb\x92\x7a\xd3\x52\x5e\x0b\xeb\x02\x62\x29\x28\xdb\x47\xe7\x85\x60\x1b\x2c\x68\x74\x84\x58\x8e\x8e\xde\xe1\xb4\xc0\x49\x43\x66\x6a\xc7\x94\x9a\xd5\xfd\x8e\x17\xda\xa0\xd7\xbd\xaf\x74\xe8\x6c\x5d\xef\x0a\x9c\x4b\x29\x76\x71\xf7\x29\xf8\x3d\x2e\xb0\x28\x6a\xb2\xbb\xf5\x16\x69\xbe\x37\x66\x28\xc1\x5c\x7c\xcc\xe2\xbd\x60\x7d\xfb\xe5\x10\x61\x81\x13\xb6\xfa\x77\x82\x93\x26\xce\xad\xf0\xc5\x85\xfb\x5d\xe3\x0c\x55\x2c\x72\x57\x2c\xec\x17\x8f\x39\x92\x06\x51\x3b\xce\x4f\x4e\x12\xb2\xc5\xa9\x30\x04\xef\x54\x4f\x85\x63\xbd\x06\x73\xc9\x35\x14\xaa\x01\x40\x60\xc7\x44\x90\x7c\x43\xd3\xea\xaf\xdc\xc1\x77\x2f\x58\x1a\xd3\x36\xe7\x3c\x38\x93\x15\x8d\xea\x2f\xb5\x31\x5b\x73\xc0\xad\x35\xc4\x56\x95\x4d\xce\xd8\xaa\x0b\xa5\xbe\xb6\xd0\x1a\xfb\x5a\x7d\xc8\x96\x2d\x31\xb6\xca\x48\xf7\xd6\x16\xdd\xa7\xec\x81\x2b\xf4\xbc\xa6\xf3\xe6\xd1\x3b\xba\xf4\x8d\x99\xe1\x05\xf5\xd3\xcd\xd9\xf8\x33\x3d\xfe\x26\x1f\x4c\x3b\xfb\xa9\xc7\xa7\xa1\xd4\x7f\xbe\x4d\x8e\x36\xf1\xa4\x7d\x49\x01\x0c\xd8\xe8\xbf\x8a\x6c\x56\xbe\xd4\x26\xf1\x03\x54\xb6\x10\x1d\x2b\xac\x4b\x62\x55\xde\x96\xdd\xf3\xf6\xdc\x11\x5e\x1d\xd3\x73\x35\x05\x35\x11\xac\xba\x45\xae\x75\x42\x74\xae\x8d\x2d\x8c\x32\x4a\x14\x70\x1e\x4e\xf5\x02\xc1\xad\x42\x70\xb7\x0e\xad\x5e\x90\xb7\x9a\x34\xc5\xe1\xbd\x33\x9d\x6b\xa3\x82\x1d\x3a\x2f\xcb\x84\x55\xb0\x02\x77\xeb\xa4\xf9\xbf\xef\x7e\x7c\xff\xea\x7b\xa6\x93\x3d\x34\x30\x86\x94\x1b\xa0\x01\x9c\x21\x5e\x44\x6b\x84\xb9\x9c\x92\x64\x74\x29\x25\xc8\x7c\x83\x53\xba\x24\x5c\xcc\x6d\x27\x1f\xfe\xd3\x1f\x7e\xee\xbe\xfa\xdf\xb0\x1c\xe9\xfa\xa1\x33\x83\x38\xa6\xe7\x5e\x72\x17\xe5\x6a\x81\x2c\xdd\x4e\x92\xd6\xc3\x90\xb1\x58\x2f\xc4\x03\x2c\x80\xc0\xf7\x10\x64\x35\xb1\xd2\x84\xde\x93\xd7\xe8\x48\xaa\x9e\xce\x90\xff\x4b\x5e\x7b\xff\xdd\x5d\x74\x7f\xf2\x00\x8a\xc3\x91\xfc\xea\x91\x1a\xa8\xcd\x69\x77\x53\x22\x2d\x55\xd0\x3d\x3a\x49\x8a\x9c\xae\x56\x04\x94\xe7\x35\x41\x50\x4c\x7f\xaa\x51\xd8\x52\xe6\x10\x32\xd9\x30\x61\x8e\x83\xfa\xe4\x7e\xfa\xc3\xcf\x47\xe8\xa4\xa4\x06\xba\x28\x4d\x63\xf2\x19\xfd\x41\x85\x68\x28\x97\xeb\x76\xda\xbd\x6b\xe0\x63\xe0\xbb\x54\xe0\xcf\x72\x2c\xd1\x9a\x71\x92\x2a\x37\x90\x60\x68\x8d\xb7\x04\x71\xb6\x21\xe8\x81\x24\xc9\x4c\x07\xa5\x50\x77\x79\x12\xf0\xb1\xd9\x72\x00\x01\x42\x19\xce\x45\xe5\x38\xcc\xb5\xdf\x0e\x46\x29\x59\x6f\xd5\x6d\x44\xeb\x14\x98\x25\x4d\x71\xa2\x33\xbb\x00\xba\x5c\xf2\x34\x00\x3c\x28\x46\x13\x0c\x45\x6b\x9c\xae\x88\x0e\x52\x75\x1b\x76\x85\x28\x72\xd2\x19\x04\x0e\x92\x18\xf7\x34\xed\x01\x7c\xf2\x03\x4d\xeb\x39\x57\xcd\x3e\xd4\x15\x15\xa6\x0c\x4f\x27\x9e\x8b\xdd\x2b\xb9\xdf\x39\x5d\x14\x82\xe5\xfc\x55\x4c\xb6\x24\x79\xc5\xe9\x6a\x86\xf3\x68\x4d\x05\x89\xe4\x84\x5e\xe1\x8c\xce\x22\x96\x4a\xbe\x03\xb4\xaa\x4d\xfc\x1b\x39\x0f\x3e\x93\x03\xed\xec\x54\x15\x34\x5d\x9f\xeb\xf8\x59\x5d\xc6\x93\xcc\xce\xeb\x73\xdc\x9f\xa2\xf2\xdf\x3d\xc1\x3c\xc1\x19\xf5\x6a\xf4\x34\x4d\x23\xa4\xbe\x37\xef\xb1\xee\x17\x16\xd5\x29\xc8\xa3\xa7\xd0\xb6\xe0\x64\x5a\x89\xef\x3b\xd5\x1b\x1c\xab\xeb\x02\xa7\xbb\x47\x3f\x06\x72\xa1\xa1\x8d\x5f\xb4\x9b\x01\x09\x96\xcc\x70\x1a\xcb\x7f\xab\x8a\xd1\x68\x37\x7a\x65\x0b\xda\x43\x18\x7c\xbc\xbe\x7c\x9a\xc3\x51\xd0\x91\x27\x5f\x6b\xb1\x41\x2a\xa6\x52\xe3\x21\xd5\x51\xe4\x05\x31\xca\x40\x55\x51\xa7\xdc\xd0\xfc\x5f\xed\xba\x18\xc4\x34\x2d\xda\x70\xb7\x22\xda\x15\x69\x74\xf4\xec\xa0\x19\xbc\x2d\xbf\xef\x7a\x46\x21\xcf\x14\x73\xa1\x01\x56\x0d\x22\x51\x65\x62\x6a\xf2\xad\x53\x52\xd7\x53\xdb\x55\x1f\xc0\x61\x26\xb7\x48\x0e\x6e\xd6\x80\x6b\x19\x59\x03\xcf\x67\x9c\xda\x2f\x2a\x13\x20\xa1\xdc\x22\x8b\x4a\x33\x90\x0b\x84\xb7\x98\x26\x10\x67\x62\x0b\x4e\xf2\x2d\x6e\x33\x1c\x15\x38\x39\xae\x5b\xb5\xba\x67\xa6\x52\x37\x1f\xdd\x86\x34\xf3\xd9\xdf\xb1\xea\x64\x1a\x17\xd6\x9d\xa0\xaa\x17\xa9\xcd\xa5\x65\x0e\x23\x2d\x48\x65\xc0\x37\xfe\xa9\x05\xdc\xca\x67\x52\x49\xfe\xfc\x77\x82\x73\xb1\x20\x58\x7c\xa0\xed\x77\xf5\x1e\xc3\x57\xde\x32\xae\xac\x92\xdd\x1f\x08\x5a\x31\x21\x55\xb8\x02\x4e\x46\x2b\x8b\x83\x5e\xae\xe0\x0b\x2d\x33\x3e\x1e\xbf\x97\xb3\xfe\x90\x63\xa8\x20\x65\x69\xaf\x69\x57\x5f\xdb\x9f\xb7\xd6\xfe\x3b\xe7\x21\x95\x7e\xa0\x02\xe0\x58\xe0\xb9\x53\x3b\xab\x62\x5e\x5d\x2d\x65\x26\x5b\x82\x0d\xe1\xbc\x03\x12\xab\x9a\xd0\xac\xbe\xab\x0e\x7e\x2d\xa4\xbc\x31\x7f\x53\x35\x82\x5d\x77\x5d\x4c\x04\xa6\x89\xf6\xae\xe8\x25\xb3\xab\xd9\x2d\xad\x3b\x26\x9c\x13\xcc\xdb\x55\x92\x3a\xfa\x2b\x67\xa9\x9a\x06\x4b\xc9\xec\x81\xe5\x31\xba\xc0\x1b\x92\x5c\x60\x4e\x34\x25\xb7\x98\x5c\xed\xe2\x71\x7b\x3c\x75\xaa\x49\x34\x79\x27\x5b\x26\xa1\x1c\x73\x86\xf1\x34\xdf\x94\x66\xa7\x1a\xf2\x99\x71\x07\x7f\xc8\x8b\x8e\x5e\x42\x6f\xe4\x8d\x79\x86\x3e\xa6\xf7\x29\x7b\x18\x3e\x7a\xd1\x11\xf1\xaa\xa6\xa0\xee\x32\x7b\x64\x0c\xf0\x5f\xc5\xfd\x66\x27\x30\x60\x2c\xfa\xfa\x68\x74\x0a\x57\xaf\x32\xfb\x45\x33\x16\xf9\xcf\x3d\x57\xa0\x34\x88\x73\xb6\xca\x09\xe7\xcd\x13\x6f\x82\xc2\x0e\x0b\x14\x7c\x4f\x52\x5d\x67\xee\x19\xea\x75\xd3\x3b\x66\xd4\xe6\xbe\x5c\x95\x7f\x69\xed\x51\xa4\x7f\x3c\x4b\x1a\x54\x9e\xae\x8c\x65\x67\xd0\x8d\x2e\xc3\xb6\xd1\x36\xbb\x0a\x9d\xfb\xd5\xf9\x6e\xd3\xd2\x4a\x65\xa9\xcb\x03\x6e\xe6\x7e\x71\xf7\xa9\x6d\x13\x5a\xee\xd8\xee\x1b\xd1\xe7\x5e\x1c\xe7\x58\xf4\x9c\x24\x8f\x33\x71\xb8\x1b\xb1\x3d\x83\x65\x88\x03\xd1\x38\x09\xdb\xee\x9f\xc7\x73\x1d\x0e\x73\x1a\x76\xa7\x5d\x3c\x8e\xbb\x70\x98\xa3\xb0\x74\x06\xb6\x89\xbf\x7e\x2e\xc2\x46\x37\x60\xdb\x88\x43\x9c\x83\xcd\x0e\xc0\x16\x8a\x7e\xb7\x60\xab\xeb\xaf\x9d\x5b\x5b\x1d\x82\x1e\xa7\x5f\x0b\xc5\x36\x57\x60\xb7\xbb\xcf\x73\x8e\xdb\x5d\x7c\x5f\x82\x73\xcf\x33\xb9\x76\x87\xde\x0b\x74\xe5\x05\xcc\xa5\xc3\x7d\xf7\x42\x1d\x77\x9e\x49\x05\x39\xeb\x1e\xc5\x4d\xf7\xc5\x38\xe8\x3c\x2b\xd8\xea\x94\x7b\x71\xee\x38\xbf\xba\x49\x62\xbf\x42\x7c\xed\x7c\xd5\x55\x89\xb5\x92\x05\x09\x5e\xfa\x1b\x26\x9d\xcc\x55\xc7\x86\x68\xc1\x52\x11\xf5\x8c\xea\x58\x0f\x2b\x58\x8f\x34\x8a\x70\xe3\xed\x69\xac\xba\xca\xc0\xd1\xe5\xd5\xcd\xed\xd5\xc5\xf9\x87\xab\xcb\xba\xf6\xba\xbf\xde\x9d\x5a\x65\xbb\xdf\x66\xe6\xe8\x94\x0d\x7f\x94\x82\xb8\xe1\xe3\xb4\x29\x43\x76\x86\x8a\xa2\x21\x7e\x3b\x4e\xa3\x1d\x7c\x97\x0d\xbe\x27\x7c\xa7\x2f\xec\xf8\xc9\xd3\x07\x9c\xa1\x72\x26\xa5\xf6\xb4\x66\x49\xcc\x75\x3e\x3a\xba\xbe\xd4\x55\x14\x67\x88\xa6\x51\x52\xc4\xed\xae\x89\x8f\x1f\xaf\x2f\xf9\x1c\xa1\xef\x48\x84\x0b\x0e\xbe\xab\x98\xa5\xc7\x02\xfd\xf8\xfe\xed\xff\x81\xba\x10\xf8\x86\x56\x12\xa9\xee\xa4\x40\x71\x47\x9b\x08\x35\x3b\xa0\xa9\x14\x1b\x18\x65\x84\x33\x29\xcb\xb8\xea\x0d\x28\x40\x4b\x59\x93\x24\x93\x72\xf3\x9e\x20\x8b\x5c\xdf\x36\xce\xeb\x4b\x0e\xef\xa8\x0c\x7c\x9d\x5e\xbc\x22\x42\x55\xd5\xb6\x67\x08\x77\xac\x78\xa7\xaf\x7b\x84\x97\xdb\x3d\x67\x0d\x63\xd2\x7e\x8b\x07\xcc\xb5\x7f\xb0\x61\xe4\x9d\x7c\xe2\xf3\x72\xb5\xb9\x85\x5a\x1c\x42\x4a\x88\xc3\xff\xed\x39\x02\xe4\x20\x4b\x1f\x4f\xa3\x74\x11\x0c\x6a\x36\x83\x3c\xd8\x6d\x29\x6d\x4d\x3d\xb0\xf6\x3c\x3f\xa4\xbe\xf4\x95\x9f\xb4\x48\x8a\x5d\x8b\xbf\x37\x0a\x68\x7b\x18\xbf\x86\xe8\x8b\xfa\x40\xe5\x81\xba\x9f\x14\x0b\xa3\x1a\x58\x21\xa3\x7d\x56\xe8\xbf\xfe\xfb\xab\xaf\xfe\xff\x00\x00\x00\xff\xff\x84\x6f\x8d\xe9\xe6\x95\x0c\x00") + +func olmManifests0161CrdsYamlBytes() ([]byte, error) { + return bindataRead( + _olmManifests0161CrdsYaml, + "olm-manifests/0.16.1-crds.yaml", + ) +} + +func olmManifests0161CrdsYaml() (*asset, error) { + bytes, err := olmManifests0161CrdsYamlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "olm-manifests/0.16.1-crds.yaml", size: 824806, mode: os.FileMode(420), modTime: time.Unix(1599228290, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _olmManifests0161OlmYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5a\x59\x6f\x23\xb9\x11\x7e\xd7\xaf\x28\x08\x01\x9c\x04\xd3\x3a\xc6\xc7\xd8\x0d\x2c\xb0\x8e\x77\x76\x67\x91\xb1\x2d\xd8\x9e\xbc\x04\x41\xc0\xee\x2e\x75\x33\xe6\xd1\x4b\xb2\xa5\xd1\x06\xf9\xef\x01\xfb\x66\x8b\x92\x35\x5a\x4f\x26\x0f\xcb\x17\x59\x64\x15\xab\x58\x2c\xd6\xf1\xc9\x41\x10\x8c\x48\x4e\xff\x86\x4a\x53\x29\x42\x58\xcd\x47\xcf\x54\x24\x21\xdc\x11\x8e\x3a\x27\x31\x8e\x38\x1a\x92\x10\x43\xc2\x11\x80\x20\x1c\x43\x90\x8c\x8f\x8e\x63\xcc\x51\x11\x23\x95\x2e\xd9\x2b\xfa\x47\x54\x2b\x1a\xe3\x75\x1c\xcb\x42\x98\xe1\x9e\x5e\xe1\x41\xb3\x4f\xa0\x2b\x66\x52\x33\x57\x34\xa5\x74\xbf\x96\x2a\x22\xf1\x84\x14\x26\x93\x8a\xfe\x4a\x0c\x95\x62\xf2\x7c\xa9\x27\x54\x4e\x5b\xfd\x6f\x58\xa1\x0d\xaa\x07\xc9\x7c\x27\xd0\x1b\x6d\x90\x87\xb1\x14\x46\x49\xc6\x50\x85\xad\x2e\x8c\x2e\x31\xde\xc4\x0c\x03\x4e\x04\x49\x51\x8d\x54\xc1\x50\x87\xa3\x00\x48\x4e\x7f\x52\xb2\xc8\x75\x08\x7f\x1f\xff\x79\xfc\x8f\x11\x80\x42\x2d\x0b\x15\x63\x6f\x6a\x85\x2a\x6a\xbf\x06\x20\xa4\x78\xa8\x89\x3e\x3d\x7c\xdc\x49\xf7\x9b\x4e\xf8\x17\x2a\x12\x2a\xd2\x97\xcc\x1c\x55\x64\x81\x35\xa9\x92\x0c\x1f\x70\x69\x29\x9b\x63\xed\x91\x3a\x02\xd8\x36\xeb\x51\xc6\xd4\x45\xf4\x2f\x8c\x4d\x69\x4f\xaf\xe7\xbc\x8a\x83\x90\x3c\xd7\x9d\xa5\x7e\xc0\x9c\xc9\x0d\x47\x61\x5e\xb0\xd0\xf6\xc6\x00\x8c\x44\xc8\xb4\xa5\xb7\x96\xca\x07\x0c\x3a\xc7\xd8\xae\x69\xa3\x88\xc1\x74\x53\xd1\x99\x4d\x8e\x21\x3c\x48\xc6\xa8\x48\x3f\xe5\x09\x31\x58\xfa\x4a\xce\x68\x4c\x74\x08\x73\xcb\x81\x0c\x63\x23\x55\xc5\xc1\x89\x89\xb3\x8f\x3d\x51\x3e\x61\x00\x06\x79\xce\x88\xc1\x9a\xa9\x77\x18\x3b\x98\xc3\xef\xdf\x01\xa0\x51\xb9\xfc\xdb\xb1\xfd\xdd\x01\x86\xb7\xc3\xde\x34\xa1\x02\x55\x4f\x56\xe0\x37\x67\x33\x62\xc9\x39\x11\x49\xd8\x9b\x0a\x60\x1a\x51\x31\xad\xac\xdc\xaa\xac\x52\xed\x12\x05\x41\x7b\x25\xce\xfc\x1f\xfe\x78\xbf\x78\xff\x70\xfd\x74\xff\xf0\xcf\xbb\xeb\xdb\xf7\x8f\x8b\xeb\x9b\xf7\x7f\x1a\x70\xae\x15\x35\xf8\x68\x88\x29\xb4\x3d\x9b\xb3\x3a\x1e\xf7\xbe\x52\x4e\x52\x0c\xe1\x97\x82\x6c\xec\x1b\x6b\x8f\xbf\x54\x84\xe3\x5a\xaa\x67\xab\xe6\xf7\x3a\x23\x6f\xcf\x2f\xc2\xe8\x2a\x99\xcd\xe7\xf1\x6c\x19\x2d\xa3\x8b\xf3\xe8\xf4\xf2\xdd\xd5\xec\x6c\x79\xb9\x24\xcb\xf8\xec\x1d\xe2\x9c\x5c\x9d\xbd\xbb\x4a\xde\x5e\x26\xa7\x57\xe7\x67\xef\x4e\x4f\xcf\xe6\x6f\x2f\x2f\x11\xe7\x6f\x2f\x30\xb9\xba\x3a\x8d\x86\x72\x17\x05\x63\x0b\xc9\x68\xbc\x09\xe1\xe7\xe5\x9d\x34\x0b\x85\x1a\x5b\x6b\xdb\x91\x4b\x65\x1c\xbb\xd8\x13\xb4\xd7\xb0\x90\xca\x84\x70\x39\xbb\x9c\xbd\x48\x31\x77\x28\x9a\x37\xc0\xd1\x28\x1a\xeb\xc1\x5a\xae\xa4\x91\xb1\x64\x21\x3c\xdd\x2c\x7a\x6b\x8c\xae\x50\xa0\xd6\x0b\x25\x23\x74\x95\xca\x8c\xc9\x7f\x42\x13\x0e\x77\x22\x26\x0b\x61\x9a\x21\x61\x26\xfb\x75\xb8\xe8\xd3\x5e\x21\x49\xe8\xd7\x16\x62\x50\x71\x2a\xca\x38\x77\x8b\x5a\xdb\xab\xa8\xaf\xe1\x47\xc2\x58\x44\xe2\xe7\x27\xf9\x51\xa6\xfa\x5e\xbc\x57\xca\x71\x67\x14\xab\x4e\xbc\xe3\x56\x95\x41\xb7\x5d\xd3\xd1\x67\x45\x58\x81\x3f\x2a\xc9\x87\x67\x58\x52\x64\x49\x1d\x96\x3d\x2b\x8b\xf2\x88\xcd\xb3\x9f\xf8\x1f\x86\x47\x83\x6d\xe1\x3b\x1f\x6a\x97\xd0\x1c\x26\x85\xbf\x14\xa8\x87\x3e\x08\x10\xe7\x45\x08\xf3\x19\x1f\x4c\x73\xe4\x52\x6d\x42\x98\x5f\xcc\x6e\x69\x6f\x6d\xe4\x7c\x08\x99\xe0\xa3\x13\x06\xed\x78\x2e\x22\x54\x02\x0d\x96\xe9\x4e\xea\x10\x18\x15\xc5\xe7\xdf\x12\xe3\x63\x62\x08\x93\xe9\x97\xc5\xf9\x2d\xa6\xaf\x1d\xeb\x3d\x5a\x1e\x11\xef\x3d\xbb\x7c\xed\x98\xef\x15\xd9\xb0\xed\x8a\xfb\x35\xd3\xde\xd8\x7f\xd2\xc5\xfe\x13\x67\xc1\x4d\x1a\x01\x04\xb1\x14\x4b\x9a\x72\x92\xdb\x6a\x02\xd5\xcf\x36\xae\x7e\xb7\x27\x9c\xb7\xf4\xdd\xb1\x15\xa6\x54\x1b\xb5\x09\xad\xc1\xb5\x71\xf7\x2f\x0c\x65\x41\x19\xad\x9d\xf9\x6f\x94\x31\x7e\xcf\x54\xee\xda\xef\x99\xea\xb0\x4c\xe5\xe4\xaa\xd7\x8d\xf4\x97\xaf\x1b\xe8\xb7\xbb\x8d\x83\xbb\xa3\xed\xf0\x4f\xd2\x54\x61\x4a\x0c\xda\xce\x27\xc0\x84\x9a\x41\xbc\xdf\xbd\x5f\xc7\x6a\x64\x40\x12\x4e\x45\x08\x63\xa3\x0a\x1c\x7f\x09\xa3\x15\xd9\xf2\xf9\xdb\xc9\xb6\xa7\x9e\xc4\x52\xa1\xb4\x1f\x7c\xbb\xc3\xd4\x45\xa4\x63\x45\x73\x2b\x49\xbb\x5d\x64\xac\x90\x18\x1c\xbf\x81\x71\x51\x26\x21\xfb\x57\x6e\x33\x8d\xfd\x23\x41\x86\x06\xcb\x7e\xf4\x08\xa9\x71\x75\x0d\x75\x5e\x58\x55\xb7\xa0\xed\xbe\x75\x10\xaf\x69\xed\x0c\x15\xda\x10\xc6\x72\x46\x2a\x8a\x3d\x1a\x77\x4a\x7d\xdd\x0b\x5f\x51\x5c\x7f\xcb\x0b\xff\x02\x3e\xab\xea\xab\x38\xca\xeb\x5d\xd9\x1b\x68\x45\xa6\xa5\x12\xee\x25\xa6\x68\x2c\x09\xa3\xba\xfc\x5c\x97\x1e\xb7\xe5\x67\x39\x89\x9f\x49\x8a\x7a\x72\x98\xf6\x35\x39\x27\x82\x2e\x6d\x2c\xaa\x7c\xd9\x9d\x9b\xd2\x58\x8a\xc3\x74\x19\x14\x8e\x3e\x1d\xba\x42\xf2\xbe\x5e\x2d\x95\xf7\xf8\x56\xca\x64\x44\x58\xd0\x61\x60\x6e\x2d\xe9\x40\x63\xaf\x27\xb5\x5f\xa0\x0d\x45\x32\xde\x96\xa6\x86\xa8\x14\x4d\x8b\xdd\xd5\xde\x1e\x78\x31\x92\x1d\x0a\x11\x96\x67\x64\x80\x31\xd5\x10\x4d\xcd\xea\x51\xaf\xb9\xdf\xb2\xf8\x7a\xa9\xba\x96\x8c\x4f\x56\x8d\x16\xb3\xc9\xfc\x62\x32\x6f\x0f\x90\x50\x9d\x33\xb2\xa9\xaa\xd2\x45\xb5\x2b\x3c\x36\xdb\x26\xd8\x3a\x66\x08\x0f\x98\x57\xd5\x87\x06\x22\x5a\x03\x36\xaa\x80\xc9\x88\x01\xaa\x81\xac\x08\x65\x24\x62\x08\x4b\x25\x39\x10\x48\x6d\x51\x00\x37\xd5\x33\x78\x2c\x9d\x0e\xd6\x19\x8d\x33\x58\x53\xc6\x4a\x47\x64\x2b\x04\x23\x81\xf8\xcf\x3f\x19\x01\x70\x2a\xfe\x5a\x44\xd8\x1a\x73\x3e\x99\xcf\x27\x36\x63\x3f\xe3\x66\x2d\x55\x62\xfd\xf1\x64\xe8\xb2\x27\x6f\xe0\x44\x32\x6e\x3f\x1a\x83\x9d\x58\x07\xe6\x84\xf6\x8b\xeb\xa6\xac\x7e\xc0\x04\x3e\x90\xaa\xb8\x42\x4e\x28\x2b\xef\x4c\xe8\x8c\x2e\x4d\xe7\x0c\xdf\x2b\x4c\x32\x62\xec\xed\x8d\xca\x4a\x68\x45\x13\xac\xb3\xec\x70\x1f\x46\xc5\xb3\x23\x62\xcb\xc2\x00\x85\x62\x61\x59\xb8\xe8\x70\x3a\x4d\xa9\xc9\x8a\xa8\xf4\x0c\x5f\xa5\xb9\x13\xe6\x9b\x1a\x85\x38\xe5\xc4\x1a\x6f\x9a\x3f\xa7\xd3\xfa\xbc\x41\xeb\x21\x75\xd0\xb9\x95\x09\xd6\x1a\x55\x8d\xd4\xfd\x5a\xdc\x39\x6d\xad\x2e\x72\x5b\x12\x61\x12\x82\x0d\x8b\x3d\xd2\x47\x2a\x52\x86\x87\x52\xdf\x16\xcc\xd0\x43\x89\xaf\x19\xeb\x1e\xd1\x0e\xda\xfa\x04\x95\xa5\xdb\x9e\x10\x92\xae\x11\x85\x41\xe7\x55\x07\xe5\x85\x2d\xe6\x74\x19\x90\x9b\x95\xe0\xc8\xae\x0c\xa0\x4e\x12\xcd\xd7\x7e\xdc\x1d\x94\xd8\x3b\x70\xdd\x17\xca\xc1\x00\x6a\xc4\x96\xc4\x31\x6a\xad\xd0\xa6\xa8\x7e\xfd\x5d\x45\xdf\x61\x39\x5f\x16\x23\x83\xc9\x14\xcd\x4b\x7a\x0e\x60\x39\xaf\x4e\x65\xb3\x50\x35\x6f\x7b\xf5\x70\x05\xda\xef\x36\x31\x38\x13\x65\x86\x38\x40\x27\x6f\xd6\x3a\x40\x4f\x27\xd5\xfe\x8f\x74\xdd\x9f\x6a\x5f\x56\x7a\x18\xb4\x8e\x56\xbb\x7b\x08\x3d\x37\xf7\xa7\x8b\x6a\xf4\x9f\x0a\xc0\x10\x67\x69\x86\x1f\x6f\xe9\x0e\xd5\xe0\x2e\x6f\xfb\x3b\x6d\xf5\x1e\xe0\xc7\x61\x9a\x51\x22\x29\x7e\x2d\x87\xa0\x4c\xbb\xdb\x00\x9c\x69\xc6\x10\xa4\x39\x48\xc4\xb6\x31\xe0\x68\xe4\xa6\x19\xfe\x26\xac\x19\xbb\x9a\x31\x97\xca\x87\x02\x55\x63\xff\xd5\x76\xfc\x5b\x70\x50\xc3\x5e\x82\x42\x5b\x69\x62\x48\x15\xac\xbe\x3b\xf3\x4d\x07\x1a\xe3\x42\x61\x60\x63\xb4\x67\x7d\x7c\x7e\x76\x76\x3a\xf6\x32\xd6\xf5\x9c\x0f\x4b\x6d\x88\x5c\xb4\xa9\x1a\xdf\x0a\x87\xe9\x49\xef\xa3\x31\xd7\x6c\x4d\x36\x43\x58\xc4\x8b\xc6\x80\x0f\x6f\xb1\xe6\xd9\xa2\xda\x83\x9e\x54\x63\x07\xbc\x51\x0d\x1d\x67\x68\x1d\xe2\xc3\xd3\xd3\xe2\xd1\x4b\xb1\x17\x06\xe9\xf4\xdf\xa1\xdd\x3e\xdc\xe5\xff\x40\xbd\xe3\x11\x9b\xe6\x78\xde\x74\xdc\x2c\xfa\x31\x9a\x6a\xec\x40\x6a\xaa\xd1\xe0\x35\xe7\x2e\x5e\x53\x1b\xc5\x3e\x22\x6a\x36\x37\x52\x18\xfc\xec\xb5\x9c\x2a\xc4\xb5\xfe\xa4\x51\x59\x11\xb3\xd9\x16\xc5\x4a\xb2\x82\xe3\xad\x8d\x3f\x5e\xc7\xab\xa2\x84\xe1\xf9\x72\xdb\x5b\x01\xb8\xe5\xab\x7e\xe5\x98\x1a\x9e\x8f\x7c\x7b\xef\x0c\x3d\xfe\x4d\x91\xe7\x66\xf3\x03\x55\x21\xfc\xfb\x3f\x65\xad\x6d\xca\x23\x86\x50\x36\x3a\x55\xfb\xe8\xb4\x22\xe5\x0f\xe2\x75\x24\x4d\x70\x49\x05\x35\x5d\xa9\x26\xd7\x02\x93\xa6\xab\x4a\xab\x5f\xcd\xf7\x66\xdc\x5a\x9f\x55\xef\x9f\x21\xaa\x99\xaa\xc1\xaa\x0b\xf0\xdb\x3a\xdb\x36\x78\x59\x3f\x94\x0e\x33\xb1\xaf\x45\x1a\xf0\x3b\x7d\xd2\xf5\x90\xa8\xec\x8a\x5a\x07\x83\x14\x85\x55\x1b\x93\xaa\x41\xc2\xcf\x54\x1b\x2a\x52\xb7\x43\xb2\x3d\x56\x02\x26\x43\xaa\xe0\xa6\x2c\xbf\x6e\xbb\xf2\xab\xcb\xf4\x77\x3b\x73\x80\x2f\xe0\x1c\xd5\x91\xf6\xb5\xda\xf3\xbf\x29\x59\x11\x51\x19\x74\x3f\x32\xec\x68\x98\x2b\x1b\x3c\x95\x35\x45\xaa\xf2\x78\xb4\x33\xb2\x97\x1b\x36\xbf\x5a\x74\xbf\x11\x38\xb7\x71\x23\x39\x2f\x04\x35\x9b\xb6\x1d\xb5\x26\xca\x8b\x88\x51\x9d\xd9\x27\xd3\x4c\x7f\x28\x22\x5b\x7d\xff\x37\x00\x00\xff\xff\x91\x76\x79\xce\xb7\x23\x00\x00") + +func olmManifests0161OlmYamlBytes() ([]byte, error) { + return bindataRead( + _olmManifests0161OlmYaml, + "olm-manifests/0.16.1-olm.yaml", + ) +} + +func olmManifests0161OlmYaml() (*asset, error) { + bytes, err := olmManifests0161OlmYamlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "olm-manifests/0.16.1-olm.yaml", size: 9143, mode: os.FileMode(420), modTime: time.Unix(1599228292, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +// Asset loads and returns the asset for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func Asset(name string) ([]byte, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) + } + return a.bytes, nil + } + return nil, fmt.Errorf("Asset %s not found", name) +} + +// MustAsset is like Asset but panics when Asset would return an error. +// It simplifies safe initialization of global variables. +func MustAsset(name string) []byte { + a, err := Asset(name) + if err != nil { + panic("asset: Asset(" + name + "): " + err.Error()) + } + + return a +} + +// AssetInfo loads and returns the asset info for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func AssetInfo(name string) (os.FileInfo, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) + } + return a.info, nil + } + return nil, fmt.Errorf("AssetInfo %s not found", name) +} + +// AssetNames returns the names of the assets. +func AssetNames() []string { + names := make([]string, 0, len(_bindata)) + for name := range _bindata { + names = append(names, name) + } + return names +} + +// _bindata is a table, holding each asset generator, mapped to its name. +var _bindata = map[string]func() (*asset, error){ + "olm-manifests/0.15.1-crds.yaml": olmManifests0151CrdsYaml, + "olm-manifests/0.15.1-olm.yaml": olmManifests0151OlmYaml, + "olm-manifests/0.16.1-crds.yaml": olmManifests0161CrdsYaml, + "olm-manifests/0.16.1-olm.yaml": olmManifests0161OlmYaml, +} + +// AssetDir returns the file names below a certain +// directory embedded in the file by go-bindata. +// For example if you run go-bindata on data/... and data contains the +// following hierarchy: +// data/ +// foo.txt +// img/ +// a.png +// b.png +// then AssetDir("data") would return []string{"foo.txt", "img"} +// AssetDir("data/img") would return []string{"a.png", "b.png"} +// AssetDir("foo.txt") and AssetDir("notexist") would return an error +// AssetDir("") will return []string{"data"}. +func AssetDir(name string) ([]string, error) { + node := _bintree + if len(name) != 0 { + cannonicalName := strings.Replace(name, "\\", "/", -1) + pathList := strings.Split(cannonicalName, "/") + for _, p := range pathList { + node = node.Children[p] + if node == nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + } + } + if node.Func != nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + rv := make([]string, 0, len(node.Children)) + for childName := range node.Children { + rv = append(rv, childName) + } + return rv, nil +} + +type bintree struct { + Func func() (*asset, error) + Children map[string]*bintree +} + +var _bintree = &bintree{nil, map[string]*bintree{ + "olm-manifests": &bintree{nil, map[string]*bintree{ + "0.15.1-crds.yaml": &bintree{olmManifests0151CrdsYaml, map[string]*bintree{}}, + "0.15.1-olm.yaml": &bintree{olmManifests0151OlmYaml, map[string]*bintree{}}, + "0.16.1-crds.yaml": &bintree{olmManifests0161CrdsYaml, map[string]*bintree{}}, + "0.16.1-olm.yaml": &bintree{olmManifests0161OlmYaml, map[string]*bintree{}}, + }}, +}} + +// RestoreAsset restores an asset under the given directory +func RestoreAsset(dir, name string) error { + data, err := Asset(name) + if err != nil { + return err + } + info, err := AssetInfo(name) + if err != nil { + return err + } + err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) + if err != nil { + return err + } + err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) + if err != nil { + return err + } + err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) + if err != nil { + return err + } + return nil +} + +// RestoreAssets restores an asset under the given directory recursively +func RestoreAssets(dir, name string) error { + children, err := AssetDir(name) + // File + if err != nil { + return RestoreAsset(dir, name) + } + // Dir + for _, child := range children { + err = RestoreAssets(dir, filepath.Join(name, child)) + if err != nil { + return err + } + } + return nil +} + +func _filePath(dir, name string) string { + cannonicalName := strings.Replace(name, "\\", "/", -1) + return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) +} diff --git a/internal/bindata/olm/versions.go b/internal/bindata/olm/versions.go index b5994966006..03d140716c2 100644 --- a/internal/bindata/olm/versions.go +++ b/internal/bindata/olm/versions.go @@ -15,7 +15,8 @@ package olm var availableVersions = map[string]struct{}{ - "0.15.1": struct{}{}, + "0.16.1": {}, + "0.15.1": {}, } // HasVersion returns whether version maps to released OLM manifests as bindata. diff --git a/internal/olm/installer/client.go b/internal/olm/installer/client.go index cbd44acb7db..9214e6dc9b2 100644 --- a/internal/olm/installer/client.go +++ b/internal/olm/installer/client.go @@ -25,6 +25,7 @@ import ( "io" "io/ioutil" "net/http" + "path/filepath" "time" "github.com/blang/semver" @@ -46,10 +47,7 @@ const ( olmOperatorName = "olm-operator" catalogOperatorName = "catalog-operator" packageServerName = "packageserver" - - // These paths are keys to look up internal OLM bindata. - olmManifestBindataPath = "olm-manifests/olm.yaml" - crdManifestBindataPath = "olm-manifests/crds.yaml" + bindataManifestPath = "olm-manifests" ) type Client struct { @@ -183,14 +181,16 @@ func (c Client) getResources(ctx context.Context, version string) ([]unstructure var err error // If the manifests for the requested version are saved as bindata in SDK, use - // them instead of fetching them from + // them instead of fetching them from github. if olmmanifests.HasVersion(version) { - log.Infof("Using locally stored resource manifests for resolved version %q", version) + log.Infof("Using locally stored resource manifests") + crdManifestBindataPath := filepath.Join(bindataManifestPath, version+"-crds.yaml") crdResources, err = getPackagedManifests(crdManifestBindataPath) if err != nil { return nil, err } + olmManifestBindataPath := filepath.Join(bindataManifestPath, version+"-olm.yaml") olmResources, err = getPackagedManifests(olmManifestBindataPath) if err != nil { return nil, err From 7f1b3ea79b0fadf3359074e9df0a2a23be39892b Mon Sep 17 00:00:00 2001 From: Camila Macedo Date: Fri, 13 Nov 2020 22:24:13 +0000 Subject: [PATCH 215/376] Update kubebuilder to commit b6a0bf1b6040 (#4215) **Description of the change:** - Update kubebuilder dependency (See: https://github.com/kubernetes-sigs/kubebuilder/compare/9c02d557f01b...c158f4fa4207) - Align SDK with Kubebuilder and address bug fixes **Motivation for the change:** - Solve tech-debt and keep both projects aligned Signed-off-by: reinvantveer --- ...-kb-from-9c02d557f01b-to-c158f4fa4207.yaml | 8 +++++ go.mod | 2 +- go.sum | 4 +-- .../samples/internal/ansible/memcached.go | 2 +- .../samples/internal/ansible/molecule.go | 2 +- .../internal/go/memcached_with_webhooks.go | 2 +- hack/generate/samples/internal/pkg/utils.go | 2 +- internal/annotations/metrics/metrics.go | 2 +- internal/cmd/operator-sdk/cli/cli.go | 2 +- .../operator-sdk/generate/bundle/bundle.go | 2 +- .../operator-sdk/generate/internal/genutil.go | 2 +- .../generate/kustomize/manifests.go | 2 +- .../packagemanifests/packagemanifests.go | 2 +- .../clusterserviceversion.go | 2 +- .../clusterserviceversion_test.go | 2 +- internal/kubebuilder/cmdutil/cmdutil.go | 2 +- internal/kubebuilder/machinery/errors.go | 2 +- internal/kubebuilder/machinery/scaffold.go | 4 +-- .../kubebuilder/machinery/scaffold_test.go | 4 +-- internal/plugins/ansible/v1/api.go | 30 +++++++++--------- internal/plugins/ansible/v1/init.go | 30 +++++++++--------- internal/plugins/ansible/v1/plugin.go | 23 +++++++------- internal/plugins/ansible/v1/scaffolds/api.go | 10 +++--- internal/plugins/ansible/v1/scaffolds/init.go | 6 ++-- .../internal/templates/config/crd/crd.go | 2 +- .../templates/config/crd/kustomization.go | 2 +- .../config/kdefault/auth_proxy_patch.go | 2 +- .../config/kdefault/kustomization.go | 2 +- .../templates/config/manager/kustomization.go | 2 +- .../templates/config/manager/manager.go | 2 +- .../config/prometheus/kustomization.go | 2 +- .../templates/config/prometheus/monitor.go | 2 +- .../rbac/auth_proxy_client_clusterrole.go | 2 +- .../templates/config/rbac/auth_proxy_role.go | 2 +- .../config/rbac/auth_proxy_role_binding.go | 2 +- .../config/rbac/auth_proxy_service.go | 2 +- .../templates/config/rbac/crd_editor_rbac.go | 2 +- .../templates/config/rbac/crd_viewer_rbac.go | 2 +- .../templates/config/rbac/kustomization.go | 2 +- .../config/rbac/leader_election_role.go | 2 +- .../rbac/leader_election_role_binding.go | 2 +- .../internal/templates/config/rbac/role.go | 2 +- .../templates/config/rbac/role_binding.go | 2 +- .../templates/config/samples/cr_sample.go | 2 +- .../config/testing/debug_logs_patch.go | 2 +- .../templates/config/testing/kustomization.go | 2 +- .../templates/config/testing/manager_image.go | 2 +- .../testing/pullpolicy/always_pull_patch.go | 2 +- .../pullpolicy/ifnotpresent_pull_patch.go | 2 +- .../testing/pullpolicy/never_pull_patch.go | 2 +- .../internal/templates/dockerfile.go | 2 +- .../scaffolds/internal/templates/gitignore.go | 2 +- .../scaffolds/internal/templates/makefile.go | 2 +- .../templates/molecule/mdefault/converge.go | 2 +- .../templates/molecule/mdefault/create.go | 2 +- .../templates/molecule/mdefault/destroy.go | 2 +- .../templates/molecule/mdefault/kustomize.go | 2 +- .../templates/molecule/mdefault/molecule.go | 2 +- .../templates/molecule/mdefault/prepare.go | 2 +- .../molecule/mdefault/tasks_test_resource.go | 2 +- .../templates/molecule/mdefault/verify.go | 2 +- .../templates/molecule/mkind/converge.go | 2 +- .../templates/molecule/mkind/create.go | 2 +- .../templates/molecule/mkind/destroy.go | 2 +- .../templates/molecule/mkind/molecule.go | 2 +- .../templates/playbooks/placeholder.go | 2 +- .../internal/templates/playbooks/playbook.go | 2 +- .../internal/templates/requirements.go | 2 +- .../internal/templates/roles/defaults_main.go | 2 +- .../internal/templates/roles/files_dir.go | 2 +- .../internal/templates/roles/handlers_main.go | 2 +- .../internal/templates/roles/meta_main.go | 2 +- .../internal/templates/roles/placeholder.go | 2 +- .../internal/templates/roles/readme.go | 2 +- .../internal/templates/roles/tasks_main.go | 2 +- .../internal/templates/roles/templates_dir.go | 2 +- .../internal/templates/roles/vars_main.go | 2 +- .../scaffolds/internal/templates/watches.go | 2 +- internal/plugins/envtest/init.go | 2 +- internal/plugins/golang/v2/api.go | 26 +++++++++------- internal/plugins/golang/v2/config.go | 2 +- internal/plugins/golang/v2/init.go | 24 +++++++------- internal/plugins/golang/v2/plugin.go | 31 +++++++++---------- internal/plugins/helm/v1/api.go | 30 +++++++++--------- internal/plugins/helm/v1/chartutil/chart.go | 2 +- .../plugins/helm/v1/chartutil/chart_test.go | 2 +- internal/plugins/helm/v1/init.go | 30 +++++++++--------- internal/plugins/helm/v1/plugin.go | 24 +++++++------- internal/plugins/helm/v1/scaffolds/api.go | 8 ++--- internal/plugins/helm/v1/scaffolds/init.go | 6 ++-- .../internal/templates/config/crd/crd.go | 2 +- .../templates/config/crd/kustomization.go | 2 +- .../config/kdefault/auth_proxy_patch.go | 2 +- .../config/kdefault/kustomization.go | 2 +- .../templates/config/manager/kustomization.go | 2 +- .../templates/config/manager/manager.go | 2 +- .../config/prometheus/kustomization.go | 2 +- .../templates/config/prometheus/monitor.go | 2 +- .../templates/config/rbac/auth_proxy_role.go | 2 +- .../config/rbac/auth_proxy_role_binding.go | 2 +- .../config/rbac/auth_proxy_service.go | 2 +- .../config/rbac/client_cluster_role.go | 2 +- .../templates/config/rbac/crd_editor_rbac.go | 2 +- .../templates/config/rbac/crd_viewer_rbac.go | 2 +- .../templates/config/rbac/kustomization.go | 2 +- .../config/rbac/leader_election_role.go | 2 +- .../rbac/leader_election_role_binding.go | 2 +- .../templates/config/rbac/manager_role.go | 2 +- .../config/rbac/manager_role_binding.go | 2 +- .../templates/config/samples/crd_sample.go | 2 +- .../internal/templates/dockerfile.go | 2 +- .../scaffolds/internal/templates/gitignore.go | 2 +- .../scaffolds/internal/templates/makefile.go | 2 +- .../scaffolds/internal/templates/watches.go | 2 +- internal/plugins/manifests/api.go | 6 ++-- internal/plugins/manifests/init.go | 2 +- internal/plugins/manifests/samples.go | 4 +-- internal/plugins/scorecard/init.go | 2 +- internal/testutils/olm.go | 2 +- internal/testutils/utils.go | 2 +- internal/util/projutil/project_util.go | 2 +- test/e2e-ansible/e2e_ansible_cluster_test.go | 2 +- test/e2e-ansible/e2e_ansible_suite_test.go | 2 +- test/e2e-go/e2e_go_cluster_test.go | 2 +- test/e2e-go/e2e_go_suite_test.go | 2 +- test/e2e-helm/e2e_helm_cluster_test.go | 2 +- .../content/en/docs/cli/operator-sdk_edit.md | 3 +- 127 files changed, 267 insertions(+), 258 deletions(-) create mode 100644 changelog/fragments/update-kb-from-9c02d557f01b-to-c158f4fa4207.yaml diff --git a/changelog/fragments/update-kb-from-9c02d557f01b-to-c158f4fa4207.yaml b/changelog/fragments/update-kb-from-9c02d557f01b-to-c158f4fa4207.yaml new file mode 100644 index 00000000000..d96e11e3eeb --- /dev/null +++ b/changelog/fragments/update-kb-from-9c02d557f01b-to-c158f4fa4207.yaml @@ -0,0 +1,8 @@ +# entries is a list of entries to include in +# release notes and/or the migration guide +entries: + - description: > + (go/v2) Fixed controller imports scaffolded by `create api` when `--resource=false` + ([kubebuilder#1770](https://github.com/kubernetes-sigs/kubebuilder/pull/1770)) + kind: "bugfix" + breaking: false diff --git a/go.mod b/go.mod index 129750c29a5..4ec6a3bcf1e 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( rsc.io/letsencrypt v0.0.3 // indirect sigs.k8s.io/controller-runtime v0.6.3 sigs.k8s.io/controller-tools v0.3.0 - sigs.k8s.io/kubebuilder v1.0.9-0.20201030182622-9c02d557f01b + sigs.k8s.io/kubebuilder/v2 v2.3.2-0.20201111001842-c158f4fa4207 sigs.k8s.io/yaml v1.2.0 ) diff --git a/go.sum b/go.sum index 01a3237091e..8278f5466fa 100644 --- a/go.sum +++ b/go.sum @@ -1229,8 +1229,8 @@ sigs.k8s.io/controller-runtime v0.6.3 h1:SBbr+inLPEKhvlJtrvDcwIpm+uhDvp63Bl72xYJ sigs.k8s.io/controller-runtime v0.6.3/go.mod h1:WlZNXcM0++oyaQt4B7C2lEE5JYRs8vJUzRP4N4JpdAY= sigs.k8s.io/controller-tools v0.3.0 h1:y3YD99XOyWaXkiF1kd41uRvfp/64teWcrEZFuHxPhJ4= sigs.k8s.io/controller-tools v0.3.0/go.mod h1:enhtKGfxZD1GFEoMgP8Fdbu+uKQ/cq1/WGJhdVChfvI= -sigs.k8s.io/kubebuilder v1.0.9-0.20201030182622-9c02d557f01b h1:IDxyhHz2vQ5DRRp0azVMPC5rtSWz3ziFDWWnjC+TH5Q= -sigs.k8s.io/kubebuilder v1.0.9-0.20201030182622-9c02d557f01b/go.mod h1:NatUhFMh/ci8gR+qETvZBIlZ4RTQoNa+9uei7okpgcY= +sigs.k8s.io/kubebuilder/v2 v2.3.2-0.20201111001842-c158f4fa4207 h1:JtlaBrtWymJbh6ea+TJUZkzBb0x0dMKV+P0+ZPaldxk= +sigs.k8s.io/kubebuilder/v2 v2.3.2-0.20201111001842-c158f4fa4207/go.mod h1:J/D/179LBZhQOhRvmMRNbje/Bk+PjbN0/fzUupmO7+U= sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0= sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU= sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= diff --git a/hack/generate/samples/internal/ansible/memcached.go b/hack/generate/samples/internal/ansible/memcached.go index 76b9808dcea..2a4252c0ba7 100644 --- a/hack/generate/samples/internal/ansible/memcached.go +++ b/hack/generate/samples/internal/ansible/memcached.go @@ -20,7 +20,7 @@ import ( "strings" log "github.com/sirupsen/logrus" - kbtestutils "sigs.k8s.io/kubebuilder/test/e2e/utils" + kbtestutils "sigs.k8s.io/kubebuilder/v2/test/e2e/utils" "github.com/operator-framework/operator-sdk/hack/generate/samples/internal/pkg" "github.com/operator-framework/operator-sdk/internal/testutils" diff --git a/hack/generate/samples/internal/ansible/molecule.go b/hack/generate/samples/internal/ansible/molecule.go index 5c960b353e8..bf00dc11850 100644 --- a/hack/generate/samples/internal/ansible/molecule.go +++ b/hack/generate/samples/internal/ansible/molecule.go @@ -20,7 +20,7 @@ import ( "path/filepath" "strings" - kbtestutils "sigs.k8s.io/kubebuilder/test/e2e/utils" + kbtestutils "sigs.k8s.io/kubebuilder/v2/test/e2e/utils" "github.com/operator-framework/operator-sdk/hack/generate/samples/internal/pkg" "github.com/operator-framework/operator-sdk/internal/testutils" diff --git a/hack/generate/samples/internal/go/memcached_with_webhooks.go b/hack/generate/samples/internal/go/memcached_with_webhooks.go index cf925b82d43..c88d141ef6e 100644 --- a/hack/generate/samples/internal/go/memcached_with_webhooks.go +++ b/hack/generate/samples/internal/go/memcached_with_webhooks.go @@ -21,7 +21,7 @@ import ( "strings" log "github.com/sirupsen/logrus" - kbtestutils "sigs.k8s.io/kubebuilder/test/e2e/utils" + kbtestutils "sigs.k8s.io/kubebuilder/v2/test/e2e/utils" "github.com/operator-framework/operator-sdk/hack/generate/samples/internal/pkg" "github.com/operator-framework/operator-sdk/internal/testutils" diff --git a/hack/generate/samples/internal/pkg/utils.go b/hack/generate/samples/internal/pkg/utils.go index 6af0efc42d3..98bd05e6ae0 100644 --- a/hack/generate/samples/internal/pkg/utils.go +++ b/hack/generate/samples/internal/pkg/utils.go @@ -22,7 +22,7 @@ import ( "regexp" log "github.com/sirupsen/logrus" - "sigs.k8s.io/kubebuilder/pkg/model/config" + "sigs.k8s.io/kubebuilder/v2/pkg/model/config" "github.com/operator-framework/operator-sdk/internal/annotations/metrics" ) diff --git a/internal/annotations/metrics/metrics.go b/internal/annotations/metrics/metrics.go index 8c0869c2de9..1d2ce56760d 100644 --- a/internal/annotations/metrics/metrics.go +++ b/internal/annotations/metrics/metrics.go @@ -18,7 +18,7 @@ import ( "regexp" "strings" - "sigs.k8s.io/kubebuilder/pkg/model/config" + "sigs.k8s.io/kubebuilder/v2/pkg/model/config" sdkversion "github.com/operator-framework/operator-sdk/internal/version" ) diff --git a/internal/cmd/operator-sdk/cli/cli.go b/internal/cmd/operator-sdk/cli/cli.go index 5cced6680f9..453c2648c46 100644 --- a/internal/cmd/operator-sdk/cli/cli.go +++ b/internal/cmd/operator-sdk/cli/cli.go @@ -32,7 +32,7 @@ import ( log "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/spf13/viper" - "sigs.k8s.io/kubebuilder/pkg/cli" + "sigs.k8s.io/kubebuilder/v2/pkg/cli" ) var commands = []*cobra.Command{ diff --git a/internal/cmd/operator-sdk/generate/bundle/bundle.go b/internal/cmd/operator-sdk/generate/bundle/bundle.go index a0326cee391..e002254ab75 100644 --- a/internal/cmd/operator-sdk/generate/bundle/bundle.go +++ b/internal/cmd/operator-sdk/generate/bundle/bundle.go @@ -25,7 +25,7 @@ import ( "github.com/operator-framework/api/pkg/apis/scorecard/v1alpha3" "github.com/operator-framework/operator-registry/pkg/lib/bundle" - "sigs.k8s.io/kubebuilder/pkg/model/config" + "sigs.k8s.io/kubebuilder/v2/pkg/model/config" "sigs.k8s.io/yaml" metricsannotations "github.com/operator-framework/operator-sdk/internal/annotations/metrics" diff --git a/internal/cmd/operator-sdk/generate/internal/genutil.go b/internal/cmd/operator-sdk/generate/internal/genutil.go index 3a6dfcf9dd5..00062e33358 100644 --- a/internal/cmd/operator-sdk/generate/internal/genutil.go +++ b/internal/cmd/operator-sdk/generate/internal/genutil.go @@ -28,7 +28,7 @@ import ( apiextv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" "k8s.io/apimachinery/pkg/util/validation" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - "sigs.k8s.io/kubebuilder/pkg/model/config" + "sigs.k8s.io/kubebuilder/v2/pkg/model/config" "sigs.k8s.io/yaml" ) diff --git a/internal/cmd/operator-sdk/generate/kustomize/manifests.go b/internal/cmd/operator-sdk/generate/kustomize/manifests.go index 8c0061a51bb..c0d35b55e22 100644 --- a/internal/cmd/operator-sdk/generate/kustomize/manifests.go +++ b/internal/cmd/operator-sdk/generate/kustomize/manifests.go @@ -21,7 +21,7 @@ import ( log "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/spf13/pflag" - "sigs.k8s.io/kubebuilder/pkg/model/config" + "sigs.k8s.io/kubebuilder/v2/pkg/model/config" genutil "github.com/operator-framework/operator-sdk/internal/cmd/operator-sdk/generate/internal" gencsv "github.com/operator-framework/operator-sdk/internal/generate/clusterserviceversion" diff --git a/internal/cmd/operator-sdk/generate/packagemanifests/packagemanifests.go b/internal/cmd/operator-sdk/generate/packagemanifests/packagemanifests.go index aac1db468d6..9f7abe6385b 100644 --- a/internal/cmd/operator-sdk/generate/packagemanifests/packagemanifests.go +++ b/internal/cmd/operator-sdk/generate/packagemanifests/packagemanifests.go @@ -20,7 +20,7 @@ import ( "os" "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/config" + "sigs.k8s.io/kubebuilder/v2/pkg/model/config" genutil "github.com/operator-framework/operator-sdk/internal/cmd/operator-sdk/generate/internal" gencsv "github.com/operator-framework/operator-sdk/internal/generate/clusterserviceversion" diff --git a/internal/generate/clusterserviceversion/clusterserviceversion.go b/internal/generate/clusterserviceversion/clusterserviceversion.go index 686e301ea41..b74b3e02c8a 100644 --- a/internal/generate/clusterserviceversion/clusterserviceversion.go +++ b/internal/generate/clusterserviceversion/clusterserviceversion.go @@ -25,7 +25,7 @@ import ( operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1" "github.com/operator-framework/operator-registry/pkg/lib/bundle" "k8s.io/apimachinery/pkg/runtime/schema" - "sigs.k8s.io/kubebuilder/pkg/model/config" + "sigs.k8s.io/kubebuilder/v2/pkg/model/config" metricsannotations "github.com/operator-framework/operator-sdk/internal/annotations/metrics" "github.com/operator-framework/operator-sdk/internal/generate/clusterserviceversion/bases" diff --git a/internal/generate/clusterserviceversion/clusterserviceversion_test.go b/internal/generate/clusterserviceversion/clusterserviceversion_test.go index f9d47a52761..578bc7643bc 100644 --- a/internal/generate/clusterserviceversion/clusterserviceversion_test.go +++ b/internal/generate/clusterserviceversion/clusterserviceversion_test.go @@ -30,7 +30,7 @@ import ( "github.com/operator-framework/api/pkg/operators/v1alpha1" "github.com/operator-framework/operator-registry/pkg/lib/bundle" appsv1 "k8s.io/api/apps/v1" - "sigs.k8s.io/kubebuilder/pkg/model/config" + "sigs.k8s.io/kubebuilder/v2/pkg/model/config" "sigs.k8s.io/yaml" metricsannotations "github.com/operator-framework/operator-sdk/internal/annotations/metrics" diff --git a/internal/kubebuilder/cmdutil/cmdutil.go b/internal/kubebuilder/cmdutil/cmdutil.go index 602bc707427..1999b912974 100644 --- a/internal/kubebuilder/cmdutil/cmdutil.go +++ b/internal/kubebuilder/cmdutil/cmdutil.go @@ -16,7 +16,7 @@ limitations under the License. package cmdutil -import "sigs.k8s.io/kubebuilder/pkg/plugin/scaffold" +import "sigs.k8s.io/kubebuilder/v2/pkg/plugin/scaffold" // RunOptions represent the types used to implement the different commands type RunOptions interface { diff --git a/internal/kubebuilder/machinery/errors.go b/internal/kubebuilder/machinery/errors.go index aef82aeb569..31dcc101c92 100644 --- a/internal/kubebuilder/machinery/errors.go +++ b/internal/kubebuilder/machinery/errors.go @@ -20,7 +20,7 @@ import ( "errors" "fmt" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) // This file contains the errors returned by the scaffolding machinery diff --git a/internal/kubebuilder/machinery/scaffold.go b/internal/kubebuilder/machinery/scaffold.go index 632740b073b..9d653784bc9 100644 --- a/internal/kubebuilder/machinery/scaffold.go +++ b/internal/kubebuilder/machinery/scaffold.go @@ -26,8 +26,8 @@ import ( "text/template" "golang.org/x/tools/imports" - "sigs.k8s.io/kubebuilder/pkg/model" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" "github.com/operator-framework/operator-sdk/internal/kubebuilder/filesystem" ) diff --git a/internal/kubebuilder/machinery/scaffold_test.go b/internal/kubebuilder/machinery/scaffold_test.go index e7112918977..65d4222dba9 100644 --- a/internal/kubebuilder/machinery/scaffold_test.go +++ b/internal/kubebuilder/machinery/scaffold_test.go @@ -22,8 +22,8 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo/extensions/table" . "github.com/onsi/gomega" - "sigs.k8s.io/kubebuilder/pkg/model" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" "github.com/operator-framework/operator-sdk/internal/kubebuilder/filesystem" ) diff --git a/internal/plugins/ansible/v1/api.go b/internal/plugins/ansible/v1/api.go index 15134fe67c8..96cfdbc5b47 100644 --- a/internal/plugins/ansible/v1/api.go +++ b/internal/plugins/ansible/v1/api.go @@ -19,10 +19,10 @@ import ( "strings" "github.com/spf13/pflag" - "sigs.k8s.io/kubebuilder/pkg/model/config" - "sigs.k8s.io/kubebuilder/pkg/model/resource" - "sigs.k8s.io/kubebuilder/pkg/plugin" - "sigs.k8s.io/kubebuilder/pkg/plugin/scaffold" + "sigs.k8s.io/kubebuilder/v2/pkg/model/config" + "sigs.k8s.io/kubebuilder/v2/pkg/model/resource" + "sigs.k8s.io/kubebuilder/v2/pkg/plugin" + "sigs.k8s.io/kubebuilder/v2/pkg/plugin/scaffold" "github.com/operator-framework/operator-sdk/internal/kubebuilder/cmdutil" "github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/scaffolds" @@ -39,18 +39,18 @@ const ( crdVersionV1beta1 = "v1beta1" ) -type createAPIPlugin struct { +type createAPIPSubcommand struct { config *config.Config createOptions scaffolds.CreateOptions } var ( - _ plugin.CreateAPI = &createAPIPlugin{} - _ cmdutil.RunOptions = &createAPIPlugin{} + _ plugin.CreateAPISubcommand = &createAPIPSubcommand{} + _ cmdutil.RunOptions = &createAPIPSubcommand{} ) // UpdateContext injects documentation for the command -func (p *createAPIPlugin) UpdateContext(ctx *plugin.Context) { +func (p *createAPIPSubcommand) UpdateContext(ctx *plugin.Context) { ctx.Description = `Scaffold a Kubernetes API in which the controller is an Ansible role or playbook. - generates a Custom Resource Definition and sample @@ -89,7 +89,7 @@ func (p *createAPIPlugin) UpdateContext(ctx *plugin.Context) { ) } -func (p *createAPIPlugin) BindFlags(fs *pflag.FlagSet) { +func (p *createAPIPSubcommand) BindFlags(fs *pflag.FlagSet) { fs.SortFlags = false fs.StringVar(&p.createOptions.GVK.Group, groupFlag, "", "resource group") @@ -100,11 +100,11 @@ func (p *createAPIPlugin) BindFlags(fs *pflag.FlagSet) { fs.BoolVarP(&p.createOptions.GenerateRole, "generate-role", "", false, "Generate an Ansible role skeleton.") } -func (p *createAPIPlugin) InjectConfig(c *config.Config) { +func (p *createAPIPSubcommand) InjectConfig(c *config.Config) { p.config = c } -func (p *createAPIPlugin) Run() error { +func (p *createAPIPSubcommand) Run() error { if err := cmdutil.Run(p); err != nil { return err } @@ -118,12 +118,12 @@ func (p *createAPIPlugin) Run() error { } // SDK phase 2 plugins. -func (p *createAPIPlugin) runPhase2() error { +func (p *createAPIPSubcommand) runPhase2() error { gvk := p.createOptions.GVK return manifests.RunCreateAPI(p.config, config.GVK{Group: gvk.Group, Version: gvk.Version, Kind: gvk.Kind}) } -func (p *createAPIPlugin) Validate() error { +func (p *createAPIPSubcommand) Validate() error { if p.createOptions.CRDVersion != crdVersionV1 && p.createOptions.CRDVersion != crdVersionV1beta1 { return fmt.Errorf("value of --%s must be either %q or %q", crdVersionFlag, crdVersionV1, crdVersionV1beta1) } @@ -152,10 +152,10 @@ func (p *createAPIPlugin) Validate() error { return nil } -func (p *createAPIPlugin) GetScaffolder() (scaffold.Scaffolder, error) { +func (p *createAPIPSubcommand) GetScaffolder() (scaffold.Scaffolder, error) { return scaffolds.NewCreateAPIScaffolder(p.config, p.createOptions), nil } -func (p *createAPIPlugin) PostScaffold() error { +func (p *createAPIPSubcommand) PostScaffold() error { return nil } diff --git a/internal/plugins/ansible/v1/init.go b/internal/plugins/ansible/v1/init.go index 72d65824c85..7e26f7310dc 100644 --- a/internal/plugins/ansible/v1/init.go +++ b/internal/plugins/ansible/v1/init.go @@ -22,9 +22,9 @@ import ( "github.com/spf13/pflag" "k8s.io/apimachinery/pkg/util/validation" - "sigs.k8s.io/kubebuilder/pkg/model/config" - "sigs.k8s.io/kubebuilder/pkg/plugin" - "sigs.k8s.io/kubebuilder/pkg/plugin/scaffold" + "sigs.k8s.io/kubebuilder/v2/pkg/model/config" + "sigs.k8s.io/kubebuilder/v2/pkg/plugin" + "sigs.k8s.io/kubebuilder/v2/pkg/plugin/scaffold" "github.com/operator-framework/operator-sdk/internal/kubebuilder/cmdutil" "github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/scaffolds" @@ -32,9 +32,9 @@ import ( "github.com/operator-framework/operator-sdk/internal/plugins/scorecard" ) -type initPlugin struct { +type initSubcommand struct { config *config.Config - apiPlugin createAPIPlugin + apiPlugin createAPIPSubcommand // If true, run the `create api` plugin. doCreateAPI bool @@ -44,12 +44,12 @@ type initPlugin struct { } var ( - _ plugin.Init = &initPlugin{} - _ cmdutil.RunOptions = &initPlugin{} + _ plugin.InitSubcommand = &initSubcommand{} + _ cmdutil.RunOptions = &initSubcommand{} ) // UpdateContext injects documentation for the command -func (p *initPlugin) UpdateContext(ctx *plugin.Context) { +func (p *initSubcommand) UpdateContext(ctx *plugin.Context) { ctx.Description = ` Initialize a new Ansible-based operator project. @@ -95,20 +95,20 @@ Optionally creates a new API, using the same flags as "create api" p.commandName = ctx.CommandName } -func (p *initPlugin) BindFlags(fs *pflag.FlagSet) { +func (p *initSubcommand) BindFlags(fs *pflag.FlagSet) { fs.SortFlags = false fs.StringVar(&p.config.Domain, "domain", "my.domain", "domain for groups") fs.StringVar(&p.config.ProjectName, "project-name", "", "name of this project, the default being directory name") p.apiPlugin.BindFlags(fs) } -func (p *initPlugin) InjectConfig(c *config.Config) { +func (p *initSubcommand) InjectConfig(c *config.Config) { c.Layout = pluginKey p.config = c p.apiPlugin.config = p.config } -func (p *initPlugin) Run() error { +func (p *initSubcommand) Run() error { if err := cmdutil.Run(p); err != nil { return err } @@ -122,7 +122,7 @@ func (p *initPlugin) Run() error { } // SDK phase 2 plugins. -func (p *initPlugin) runPhase2() error { +func (p *initSubcommand) runPhase2() error { if err := manifests.RunInit(p.config); err != nil { return err } @@ -139,7 +139,7 @@ func (p *initPlugin) runPhase2() error { return nil } -func (p *initPlugin) Validate() error { +func (p *initSubcommand) Validate() error { // Check if the project name is a valid k8s namespace (DNS 1123 label). if p.config.ProjectName == "" { dir, err := os.Getwd() @@ -160,7 +160,7 @@ func (p *initPlugin) Validate() error { return nil } -func (p *initPlugin) GetScaffolder() (scaffold.Scaffolder, error) { +func (p *initSubcommand) GetScaffolder() (scaffold.Scaffolder, error) { var ( apiScaffolder scaffold.Scaffolder err error @@ -174,7 +174,7 @@ func (p *initPlugin) GetScaffolder() (scaffold.Scaffolder, error) { return scaffolds.NewInitScaffolder(p.config, apiScaffolder), nil } -func (p *initPlugin) PostScaffold() error { +func (p *initSubcommand) PostScaffold() error { if !p.doCreateAPI { fmt.Printf("Next: define a resource with:\n$ %s create api\n", p.commandName) } diff --git a/internal/plugins/ansible/v1/plugin.go b/internal/plugins/ansible/v1/plugin.go index 33e79ba20cc..fd7f8f679eb 100644 --- a/internal/plugins/ansible/v1/plugin.go +++ b/internal/plugins/ansible/v1/plugin.go @@ -15,8 +15,8 @@ package ansible import ( - "sigs.k8s.io/kubebuilder/pkg/model/config" - "sigs.k8s.io/kubebuilder/pkg/plugin" + "sigs.k8s.io/kubebuilder/v2/pkg/model/config" + "sigs.k8s.io/kubebuilder/v2/pkg/plugin" "github.com/operator-framework/operator-sdk/internal/plugins" ) @@ -30,17 +30,18 @@ var ( ) var ( - _ plugin.Base = Plugin{} - _ plugin.InitPluginGetter = Plugin{} + _ plugin.Plugin = Plugin{} + _ plugin.Init = Plugin{} + _ plugin.CreateAPI = Plugin{} ) type Plugin struct { - initPlugin - createAPIPlugin + initSubcommand + createAPIPSubcommand } -func (Plugin) Name() string { return pluginName } -func (Plugin) Version() plugin.Version { return pluginVersion } -func (Plugin) SupportedProjectVersions() []string { return supportedProjectVersions } -func (p Plugin) GetInitPlugin() plugin.Init { return &p.initPlugin } -func (p Plugin) GetCreateAPIPlugin() plugin.CreateAPI { return &p.createAPIPlugin } +func (Plugin) Name() string { return pluginName } +func (Plugin) Version() plugin.Version { return pluginVersion } +func (Plugin) SupportedProjectVersions() []string { return supportedProjectVersions } +func (p Plugin) GetInitSubcommand() plugin.InitSubcommand { return &p.initSubcommand } +func (p Plugin) GetCreateAPISubcommand() plugin.CreateAPISubcommand { return &p.createAPIPSubcommand } diff --git a/internal/plugins/ansible/v1/scaffolds/api.go b/internal/plugins/ansible/v1/scaffolds/api.go index f3b460684df..334b52f412c 100644 --- a/internal/plugins/ansible/v1/scaffolds/api.go +++ b/internal/plugins/ansible/v1/scaffolds/api.go @@ -21,11 +21,11 @@ import ( "errors" "k8s.io/apimachinery/pkg/runtime/schema" - "sigs.k8s.io/kubebuilder/pkg/model" - "sigs.k8s.io/kubebuilder/pkg/model/config" - "sigs.k8s.io/kubebuilder/pkg/model/file" - "sigs.k8s.io/kubebuilder/pkg/model/resource" - "sigs.k8s.io/kubebuilder/pkg/plugin/scaffold" + "sigs.k8s.io/kubebuilder/v2/pkg/model" + "sigs.k8s.io/kubebuilder/v2/pkg/model/config" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/resource" + "sigs.k8s.io/kubebuilder/v2/pkg/plugin/scaffold" "github.com/operator-framework/operator-sdk/internal/kubebuilder/machinery" "github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/constants" diff --git a/internal/plugins/ansible/v1/scaffolds/init.go b/internal/plugins/ansible/v1/scaffolds/init.go index 8a36534b04a..b0947daeda4 100644 --- a/internal/plugins/ansible/v1/scaffolds/init.go +++ b/internal/plugins/ansible/v1/scaffolds/init.go @@ -18,9 +18,9 @@ limitations under the License. package scaffolds import ( - "sigs.k8s.io/kubebuilder/pkg/model" - "sigs.k8s.io/kubebuilder/pkg/model/config" - "sigs.k8s.io/kubebuilder/pkg/plugin/scaffold" + "sigs.k8s.io/kubebuilder/v2/pkg/model" + "sigs.k8s.io/kubebuilder/v2/pkg/model/config" + "sigs.k8s.io/kubebuilder/v2/pkg/plugin/scaffold" "github.com/operator-framework/operator-sdk/internal/kubebuilder/machinery" "github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/scaffolds/internal/templates" diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/crd/crd.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/crd/crd.go index b03ac74d48a..a8921873be6 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/crd/crd.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/crd/crd.go @@ -20,7 +20,7 @@ import ( "path/filepath" "github.com/kr/text" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &CRD{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/crd/kustomization.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/crd/kustomization.go index 917cadddb03..a3281e96bfe 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/crd/kustomization.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/crd/kustomization.go @@ -21,7 +21,7 @@ import ( "fmt" "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &Kustomization{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/kdefault/auth_proxy_patch.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/kdefault/auth_proxy_patch.go index 2abb40cc6e9..df600ad9dba 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/kdefault/auth_proxy_patch.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/kdefault/auth_proxy_patch.go @@ -20,7 +20,7 @@ package kdefault import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &AuthProxyPatch{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/kdefault/kustomization.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/kdefault/kustomization.go index 71e4dbd76db..3fe665b7923 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/kdefault/kustomization.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/kdefault/kustomization.go @@ -20,7 +20,7 @@ package kdefault import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &Kustomize{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/manager/kustomization.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/manager/kustomization.go index 84af806d0e1..1318302ed2c 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/manager/kustomization.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/manager/kustomization.go @@ -19,7 +19,7 @@ package manager import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &Kustomization{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/manager/manager.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/manager/manager.go index e4084882566..9a076261186 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/manager/manager.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/manager/manager.go @@ -20,7 +20,7 @@ package manager import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &Manager{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/prometheus/kustomization.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/prometheus/kustomization.go index a630cddcf29..c72539da6fe 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/prometheus/kustomization.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/prometheus/kustomization.go @@ -19,7 +19,7 @@ package prometheus import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &Kustomization{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/prometheus/monitor.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/prometheus/monitor.go index 03fe1f3a4f8..23e309c3954 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/prometheus/monitor.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/prometheus/monitor.go @@ -19,7 +19,7 @@ package prometheus import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &ServiceMonitor{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/auth_proxy_client_clusterrole.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/auth_proxy_client_clusterrole.go index 39cda25ad22..a3cbb04c38f 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/auth_proxy_client_clusterrole.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/auth_proxy_client_clusterrole.go @@ -19,7 +19,7 @@ package rbac import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &ClientClusterRole{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/auth_proxy_role.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/auth_proxy_role.go index f05e7767023..761ea8bcc61 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/auth_proxy_role.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/auth_proxy_role.go @@ -19,7 +19,7 @@ package rbac import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &AuthProxyRole{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/auth_proxy_role_binding.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/auth_proxy_role_binding.go index d0d43cf071d..8342bf58517 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/auth_proxy_role_binding.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/auth_proxy_role_binding.go @@ -19,7 +19,7 @@ package rbac import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &AuthProxyRoleBinding{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/auth_proxy_service.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/auth_proxy_service.go index 31a66347de6..03857ba1546 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/auth_proxy_service.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/auth_proxy_service.go @@ -19,7 +19,7 @@ package rbac import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &AuthProxyService{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/crd_editor_rbac.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/crd_editor_rbac.go index 44c28e88866..39f18cb726a 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/crd_editor_rbac.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/crd_editor_rbac.go @@ -19,7 +19,7 @@ package rbac import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &CRDEditorRole{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/crd_viewer_rbac.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/crd_viewer_rbac.go index 2591e509167..fb8efa1252a 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/crd_viewer_rbac.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/crd_viewer_rbac.go @@ -19,7 +19,7 @@ package rbac import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &CRDViewerRole{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/kustomization.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/kustomization.go index f3de8307aa2..9d5711cd8a4 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/kustomization.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/kustomization.go @@ -19,7 +19,7 @@ package rbac import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &Kustomization{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/leader_election_role.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/leader_election_role.go index d8b0aaa61dd..b220d947ca4 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/leader_election_role.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/leader_election_role.go @@ -19,7 +19,7 @@ package rbac import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &LeaderElectionRole{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/leader_election_role_binding.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/leader_election_role_binding.go index 875fff93fb0..00124b7709d 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/leader_election_role_binding.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/leader_election_role_binding.go @@ -19,7 +19,7 @@ package rbac import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &LeaderElectionRoleBinding{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/role.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/role.go index 5ceb6a06dc4..fa04ccb8203 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/role.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/role.go @@ -20,7 +20,7 @@ import ( "path/filepath" "text/template" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &ManagerRole{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/role_binding.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/role_binding.go index 7afd1a317de..0e83dfce178 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/role_binding.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/role_binding.go @@ -20,7 +20,7 @@ package rbac import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &RoleBinding{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/samples/cr_sample.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/samples/cr_sample.go index 2dc60284e6a..54fb2958dda 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/samples/cr_sample.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/samples/cr_sample.go @@ -22,7 +22,7 @@ import ( "strings" "text/template" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &CR{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/testing/debug_logs_patch.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/testing/debug_logs_patch.go index c7ea338b399..f4622e5d7bf 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/testing/debug_logs_patch.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/testing/debug_logs_patch.go @@ -17,7 +17,7 @@ package testing import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &DebugLogsPatch{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/testing/kustomization.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/testing/kustomization.go index a244e48fb02..37dc7ca4e41 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/testing/kustomization.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/testing/kustomization.go @@ -17,7 +17,7 @@ package testing import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &Kustomization{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/testing/manager_image.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/testing/manager_image.go index 5c6ffa4abee..d25d8c7702f 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/testing/manager_image.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/testing/manager_image.go @@ -17,7 +17,7 @@ package testing import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &ManagerImage{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/testing/pullpolicy/always_pull_patch.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/testing/pullpolicy/always_pull_patch.go index 8ec7e02fa19..c0b5ce5a5dd 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/testing/pullpolicy/always_pull_patch.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/testing/pullpolicy/always_pull_patch.go @@ -17,7 +17,7 @@ package pullpolicy import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &AlwaysPullPatch{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/testing/pullpolicy/ifnotpresent_pull_patch.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/testing/pullpolicy/ifnotpresent_pull_patch.go index fd8d067d67b..0a107451370 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/testing/pullpolicy/ifnotpresent_pull_patch.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/testing/pullpolicy/ifnotpresent_pull_patch.go @@ -17,7 +17,7 @@ package pullpolicy import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &IfNotPresentPullPatch{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/testing/pullpolicy/never_pull_patch.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/testing/pullpolicy/never_pull_patch.go index f2f258559d3..8d762e2b397 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/testing/pullpolicy/never_pull_patch.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/testing/pullpolicy/never_pull_patch.go @@ -17,7 +17,7 @@ package pullpolicy import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &NeverPullPatch{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/dockerfile.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/dockerfile.go index 0ded63efd59..974d360a3ac 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/dockerfile.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/dockerfile.go @@ -17,7 +17,7 @@ package templates import ( "errors" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" "github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/constants" ) diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/gitignore.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/gitignore.go index e309be025bb..745db8daec7 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/gitignore.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/gitignore.go @@ -18,7 +18,7 @@ limitations under the License. package templates import ( - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &GitIgnore{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/makefile.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/makefile.go index eed94ddd3bf..2a927b26faf 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/makefile.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/makefile.go @@ -20,7 +20,7 @@ package templates import ( "errors" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &Makefile{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mdefault/converge.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mdefault/converge.go index 33449b2fc52..04f2d42bc7e 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mdefault/converge.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mdefault/converge.go @@ -17,7 +17,7 @@ package mdefault import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &Converge{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mdefault/create.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mdefault/create.go index 861d43201c2..270347d6b5f 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mdefault/create.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mdefault/create.go @@ -17,7 +17,7 @@ package mdefault import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &Create{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mdefault/destroy.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mdefault/destroy.go index 1f34f95f16c..476bfde2213 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mdefault/destroy.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mdefault/destroy.go @@ -17,7 +17,7 @@ package mdefault import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &Destroy{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mdefault/kustomize.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mdefault/kustomize.go index c66d86b4c21..41d272790e1 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mdefault/kustomize.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mdefault/kustomize.go @@ -17,7 +17,7 @@ package mdefault import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &Kustomize{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mdefault/molecule.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mdefault/molecule.go index 3108d2bc9a8..e98b60cf9d4 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mdefault/molecule.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mdefault/molecule.go @@ -17,7 +17,7 @@ package mdefault import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &Molecule{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mdefault/prepare.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mdefault/prepare.go index 56cb7b3fa22..bd4da756d4d 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mdefault/prepare.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mdefault/prepare.go @@ -17,7 +17,7 @@ package mdefault import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &Prepare{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mdefault/tasks_test_resource.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mdefault/tasks_test_resource.go index a69511576f0..d60925414b2 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mdefault/tasks_test_resource.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mdefault/tasks_test_resource.go @@ -17,7 +17,7 @@ package mdefault import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &ResourceTest{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mdefault/verify.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mdefault/verify.go index 985dd8727d0..2370425c9a4 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mdefault/verify.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mdefault/verify.go @@ -17,7 +17,7 @@ package mdefault import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &Verify{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mkind/converge.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mkind/converge.go index b3adfad88f2..f0669170653 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mkind/converge.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mkind/converge.go @@ -17,7 +17,7 @@ package mkind import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &Converge{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mkind/create.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mkind/create.go index 78b4721aea3..1221e190d3d 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mkind/create.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mkind/create.go @@ -17,7 +17,7 @@ package mkind import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &Create{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mkind/destroy.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mkind/destroy.go index 40839480ec1..68f1fb8a84c 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mkind/destroy.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mkind/destroy.go @@ -17,7 +17,7 @@ package mkind import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &Destroy{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mkind/molecule.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mkind/molecule.go index ad4a2f7e731..7a2f789d8c7 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mkind/molecule.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mkind/molecule.go @@ -17,7 +17,7 @@ package mkind import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &Molecule{} diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/playbooks/placeholder.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/playbooks/placeholder.go index b2923d67415..6dec7eef4ea 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/playbooks/placeholder.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/playbooks/placeholder.go @@ -15,7 +15,7 @@ package playbooks import ( - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" "github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/constants" ) diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/playbooks/playbook.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/playbooks/playbook.go index b7e038a3db2..8fd47ceee07 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/playbooks/playbook.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/playbooks/playbook.go @@ -17,7 +17,7 @@ package playbooks import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) type Playbook struct { diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/requirements.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/requirements.go index a7ff6a89ce1..b2e1e7f0abf 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/requirements.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/requirements.go @@ -15,7 +15,7 @@ package templates import ( - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) // RequirementsYml - A requirements file for Ansible collection dependencies diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/roles/defaults_main.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/roles/defaults_main.go index 1d85cf01042..457ad0c1309 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/roles/defaults_main.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/roles/defaults_main.go @@ -17,7 +17,7 @@ package roles import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" "github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/constants" ) diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/roles/files_dir.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/roles/files_dir.go index 5685f904f75..b06c3834414 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/roles/files_dir.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/roles/files_dir.go @@ -17,7 +17,7 @@ package roles import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" "github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/constants" ) diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/roles/handlers_main.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/roles/handlers_main.go index 8a3a80195ee..88cf11eccdb 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/roles/handlers_main.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/roles/handlers_main.go @@ -17,7 +17,7 @@ package roles import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" "github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/constants" ) diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/roles/meta_main.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/roles/meta_main.go index 6986c8b2d13..2a73731c629 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/roles/meta_main.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/roles/meta_main.go @@ -17,7 +17,7 @@ package roles import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" "github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/constants" ) diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/roles/placeholder.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/roles/placeholder.go index cc957e61d51..ffcfd1973d9 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/roles/placeholder.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/roles/placeholder.go @@ -15,7 +15,7 @@ package roles import ( - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" "github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/constants" ) diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/roles/readme.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/roles/readme.go index 7f337466835..b5cf1d61e3d 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/roles/readme.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/roles/readme.go @@ -17,7 +17,7 @@ package roles import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" "github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/constants" ) diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/roles/tasks_main.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/roles/tasks_main.go index 1130177c6a2..60c596e0777 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/roles/tasks_main.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/roles/tasks_main.go @@ -17,7 +17,7 @@ package roles import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" "github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/constants" ) diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/roles/templates_dir.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/roles/templates_dir.go index bd67873e225..cdb38fdf1e3 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/roles/templates_dir.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/roles/templates_dir.go @@ -17,7 +17,7 @@ package roles import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" "github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/constants" ) diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/roles/vars_main.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/roles/vars_main.go index f77ea8ec083..10cf23c3d54 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/roles/vars_main.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/roles/vars_main.go @@ -17,7 +17,7 @@ package roles import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" "github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/constants" ) diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/watches.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/watches.go index 9274567c7a6..cca37d2f8e2 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/watches.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/watches.go @@ -19,7 +19,7 @@ import ( "fmt" "text/template" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &Watches{} diff --git a/internal/plugins/envtest/init.go b/internal/plugins/envtest/init.go index 4e6e6b89d5a..c0b599cb399 100644 --- a/internal/plugins/envtest/init.go +++ b/internal/plugins/envtest/init.go @@ -22,7 +22,7 @@ import ( "os" "strings" - "sigs.k8s.io/kubebuilder/pkg/model/config" + "sigs.k8s.io/kubebuilder/v2/pkg/model/config" ) // controllerRuntimeVersion version to be used to download the envtest setup script diff --git a/internal/plugins/golang/v2/api.go b/internal/plugins/golang/v2/api.go index d209db023ce..8823b6293e2 100644 --- a/internal/plugins/golang/v2/api.go +++ b/internal/plugins/golang/v2/api.go @@ -16,35 +16,37 @@ package v2 import ( "github.com/spf13/pflag" - "sigs.k8s.io/kubebuilder/pkg/model/config" - "sigs.k8s.io/kubebuilder/pkg/plugin" + "sigs.k8s.io/kubebuilder/v2/pkg/model/config" + "sigs.k8s.io/kubebuilder/v2/pkg/plugin" "github.com/operator-framework/operator-sdk/internal/plugins/manifests" ) -type createAPIPlugin struct { - plugin.CreateAPI +type createAPISubcommand struct { + plugin.CreateAPISubcommand config *config.Config } -var _ plugin.CreateAPI = &createAPIPlugin{} +var _ plugin.CreateAPISubcommand = &createAPISubcommand{} -func (p *createAPIPlugin) UpdateContext(ctx *plugin.Context) { p.CreateAPI.UpdateContext(ctx) } -func (p *createAPIPlugin) BindFlags(fs *pflag.FlagSet) { p.CreateAPI.BindFlags(fs) } +func (p *createAPISubcommand) UpdateContext(ctx *plugin.Context) { + p.CreateAPISubcommand.UpdateContext(ctx) +} +func (p *createAPISubcommand) BindFlags(fs *pflag.FlagSet) { p.CreateAPISubcommand.BindFlags(fs) } -func (p *createAPIPlugin) InjectConfig(c *config.Config) { - p.CreateAPI.InjectConfig(c) +func (p *createAPISubcommand) InjectConfig(c *config.Config) { + p.CreateAPISubcommand.InjectConfig(c) p.config = c } -func (p *createAPIPlugin) Run() error { +func (p *createAPISubcommand) Run() error { // Run() may add a new resource to the config, so we can compare resources before/after to get the new resource. oldResources := make(map[config.GVK]struct{}, len(p.config.Resources)) for _, r := range p.config.Resources { oldResources[r] = struct{}{} } - if err := p.CreateAPI.Run(); err != nil { + if err := p.CreateAPISubcommand.Run(); err != nil { return err } @@ -68,6 +70,6 @@ func (p *createAPIPlugin) Run() error { } // SDK phase 2 plugins. -func (p *createAPIPlugin) runPhase2(gvk config.GVK) error { +func (p *createAPISubcommand) runPhase2(gvk config.GVK) error { return manifests.RunCreateAPI(p.config, gvk) } diff --git a/internal/plugins/golang/v2/config.go b/internal/plugins/golang/v2/config.go index 063ad939bc8..d2de599e07a 100644 --- a/internal/plugins/golang/v2/config.go +++ b/internal/plugins/golang/v2/config.go @@ -14,7 +14,7 @@ package v2 -import "sigs.k8s.io/kubebuilder/pkg/model/config" +import "sigs.k8s.io/kubebuilder/v2/pkg/model/config" // Config configures this plugin, and is saved in the project config file. type Config struct{} diff --git a/internal/plugins/golang/v2/init.go b/internal/plugins/golang/v2/init.go index 6d0eab216a8..1b9dc774820 100644 --- a/internal/plugins/golang/v2/init.go +++ b/internal/plugins/golang/v2/init.go @@ -18,32 +18,32 @@ import ( "fmt" "github.com/spf13/pflag" - "sigs.k8s.io/kubebuilder/pkg/model/config" - "sigs.k8s.io/kubebuilder/pkg/plugin" + "sigs.k8s.io/kubebuilder/v2/pkg/model/config" + "sigs.k8s.io/kubebuilder/v2/pkg/plugin" "github.com/operator-framework/operator-sdk/internal/plugins/envtest" "github.com/operator-framework/operator-sdk/internal/plugins/manifests" "github.com/operator-framework/operator-sdk/internal/plugins/scorecard" ) -type initPlugin struct { - plugin.Init +type initSubcommand struct { + plugin.InitSubcommand config *config.Config } -var _ plugin.Init = &initPlugin{} +var _ plugin.InitSubcommand = &initSubcommand{} -func (p *initPlugin) UpdateContext(ctx *plugin.Context) { p.Init.UpdateContext(ctx) } -func (p *initPlugin) BindFlags(fs *pflag.FlagSet) { p.Init.BindFlags(fs) } +func (p *initSubcommand) UpdateContext(ctx *plugin.Context) { p.InitSubcommand.UpdateContext(ctx) } +func (p *initSubcommand) BindFlags(fs *pflag.FlagSet) { p.InitSubcommand.BindFlags(fs) } -func (p *initPlugin) InjectConfig(c *config.Config) { - p.Init.InjectConfig(c) +func (p *initSubcommand) InjectConfig(c *config.Config) { + p.InitSubcommand.InjectConfig(c) p.config = c } -func (p *initPlugin) Run() error { - if err := p.Init.Run(); err != nil { +func (p *initSubcommand) Run() error { + if err := p.InitSubcommand.Run(); err != nil { return err } @@ -64,7 +64,7 @@ func (p *initPlugin) Run() error { } // SDK phase 2 plugins. -func (p *initPlugin) runPhase2() error { +func (p *initSubcommand) runPhase2() error { if err := envtest.RunInit(p.config); err != nil { return err } diff --git a/internal/plugins/golang/v2/plugin.go b/internal/plugins/golang/v2/plugin.go index eb2792fc669..a4dbffe6de7 100644 --- a/internal/plugins/golang/v2/plugin.go +++ b/internal/plugins/golang/v2/plugin.go @@ -17,8 +17,8 @@ package v2 import ( "github.com/operator-framework/operator-sdk/internal/plugins" - "sigs.k8s.io/kubebuilder/pkg/plugin" - kbgov2 "sigs.k8s.io/kubebuilder/pkg/plugin/v2" + "sigs.k8s.io/kubebuilder/v2/pkg/plugin" + kbgov2 "sigs.k8s.io/kubebuilder/v2/pkg/plugin/v2" ) // Plugin name/version used in this file will also be used in phase 2 plugins when we can @@ -35,11 +35,8 @@ var ( ) var ( - _ plugin.Base = Plugin{} - _ plugin.InitPluginGetter = Plugin{} - _ plugin.CreateAPIPluginGetter = Plugin{} - _ plugin.CreateWebhookPluginGetter = Plugin{} - _ plugin.EditPluginGetter = Plugin{} + _ plugin.Plugin = Plugin{} + _ plugin.Full = Plugin{} ) // Plugin defines an Operator SDK Go scaffold and CLI plugin. Its current purpose is to @@ -52,22 +49,22 @@ func (Plugin) SupportedProjectVersions() []string { return (kbgov2.Plugin{}).SupportedProjectVersions() } -func (p Plugin) GetInitPlugin() plugin.Init { - return &initPlugin{ - Init: (kbgov2.Plugin{}).GetInitPlugin(), +func (p Plugin) GetInitSubcommand() plugin.InitSubcommand { + return &initSubcommand{ + InitSubcommand: (kbgov2.Plugin{}).GetInitSubcommand(), } } -func (p Plugin) GetCreateAPIPlugin() plugin.CreateAPI { - return &createAPIPlugin{ - CreateAPI: (kbgov2.Plugin{}).GetCreateAPIPlugin(), +func (p Plugin) GetCreateAPISubcommand() plugin.CreateAPISubcommand { + return &createAPISubcommand{ + CreateAPISubcommand: (kbgov2.Plugin{}).GetCreateAPISubcommand(), } } -func (p Plugin) GetCreateWebhookPlugin() plugin.CreateWebhook { - return (kbgov2.Plugin{}).GetCreateWebhookPlugin() +func (p Plugin) GetCreateWebhookSubcommand() plugin.CreateWebhookSubcommand { + return (kbgov2.Plugin{}).GetCreateWebhookSubcommand() } -func (p Plugin) GetEditPlugin() plugin.Edit { - return (kbgov2.Plugin{}).GetEditPlugin() +func (p Plugin) GetEditSubcommand() plugin.EditSubcommand { + return (kbgov2.Plugin{}).GetEditSubcommand() } diff --git a/internal/plugins/helm/v1/api.go b/internal/plugins/helm/v1/api.go index 83873cd656b..179ba7d8d56 100644 --- a/internal/plugins/helm/v1/api.go +++ b/internal/plugins/helm/v1/api.go @@ -19,10 +19,10 @@ import ( "strings" "github.com/spf13/pflag" - "sigs.k8s.io/kubebuilder/pkg/model/config" - "sigs.k8s.io/kubebuilder/pkg/model/resource" - "sigs.k8s.io/kubebuilder/pkg/plugin" - "sigs.k8s.io/kubebuilder/pkg/plugin/scaffold" + "sigs.k8s.io/kubebuilder/v2/pkg/model/config" + "sigs.k8s.io/kubebuilder/v2/pkg/model/resource" + "sigs.k8s.io/kubebuilder/v2/pkg/plugin" + "sigs.k8s.io/kubebuilder/v2/pkg/plugin/scaffold" "github.com/operator-framework/operator-sdk/internal/kubebuilder/cmdutil" "github.com/operator-framework/operator-sdk/internal/plugins/helm/v1/chartutil" @@ -30,19 +30,19 @@ import ( "github.com/operator-framework/operator-sdk/internal/plugins/manifests" ) -type createAPIPlugin struct { +type createAPISubcommand struct { config *config.Config createOptions chartutil.CreateOptions } var ( - _ plugin.CreateAPI = &createAPIPlugin{} - _ cmdutil.RunOptions = &createAPIPlugin{} + _ plugin.CreateAPISubcommand = &createAPISubcommand{} + _ cmdutil.RunOptions = &createAPISubcommand{} ) // UpdateContext define plugin context -func (p createAPIPlugin) UpdateContext(ctx *plugin.Context) { +func (p createAPISubcommand) UpdateContext(ctx *plugin.Context) { ctx.Description = `Scaffold a Kubernetes API that is backed by a Helm chart. ` ctx.Examples = fmt.Sprintf(` $ %s create api \ @@ -101,7 +101,7 @@ const ( ) // BindFlags will set the flags for the plugin -func (p *createAPIPlugin) BindFlags(fs *pflag.FlagSet) { +func (p *createAPISubcommand) BindFlags(fs *pflag.FlagSet) { p.createOptions = chartutil.CreateOptions{} fs.SortFlags = false @@ -117,12 +117,12 @@ func (p *createAPIPlugin) BindFlags(fs *pflag.FlagSet) { } // InjectConfig will inject the PROJECT file/config in the plugin -func (p *createAPIPlugin) InjectConfig(c *config.Config) { +func (p *createAPISubcommand) InjectConfig(c *config.Config) { p.config = c } // Run will call the plugin actions according to the definitions done in RunOptions interface -func (p *createAPIPlugin) Run() error { +func (p *createAPISubcommand) Run() error { if err := cmdutil.Run(p); err != nil { return err } @@ -136,13 +136,13 @@ func (p *createAPIPlugin) Run() error { } // SDK phase 2 plugins. -func (p *createAPIPlugin) runPhase2() error { +func (p *createAPISubcommand) runPhase2() error { gvk := p.createOptions.GVK return manifests.RunCreateAPI(p.config, config.GVK{Group: gvk.Group, Version: gvk.Version, Kind: gvk.Kind}) } // Validate perform the required validations for this plugin -func (p *createAPIPlugin) Validate() error { +func (p *createAPISubcommand) Validate() error { if p.createOptions.CRDVersion != crdVersionV1 && p.createOptions.CRDVersion != crdVersionV1beta1 { return fmt.Errorf("value of --%s must be either %q or %q", crdVersionFlag, crdVersionV1, crdVersionV1beta1) } @@ -182,11 +182,11 @@ func (p *createAPIPlugin) Validate() error { } // GetScaffolder returns scaffold.Scaffolder which will be executed due the RunOptions interface implementation -func (p *createAPIPlugin) GetScaffolder() (scaffold.Scaffolder, error) { +func (p *createAPISubcommand) GetScaffolder() (scaffold.Scaffolder, error) { return scaffolds.NewAPIScaffolder(p.config, p.createOptions), nil } // PostScaffold runs all actions that should be executed after the default plugin scaffold -func (p *createAPIPlugin) PostScaffold() error { +func (p *createAPISubcommand) PostScaffold() error { return nil } diff --git a/internal/plugins/helm/v1/chartutil/chart.go b/internal/plugins/helm/v1/chartutil/chart.go index 9a6e1fbca20..55d9d2a9973 100644 --- a/internal/plugins/helm/v1/chartutil/chart.go +++ b/internal/plugins/helm/v1/chartutil/chart.go @@ -32,7 +32,7 @@ import ( "helm.sh/helm/v3/pkg/getter" "helm.sh/helm/v3/pkg/repo" "k8s.io/apimachinery/pkg/runtime/schema" - "sigs.k8s.io/kubebuilder/pkg/model/resource" + "sigs.k8s.io/kubebuilder/v2/pkg/model/resource" ) const ( diff --git a/internal/plugins/helm/v1/chartutil/chart_test.go b/internal/plugins/helm/v1/chartutil/chart_test.go index 202bd68b53c..b489fa093ed 100644 --- a/internal/plugins/helm/v1/chartutil/chart_test.go +++ b/internal/plugins/helm/v1/chartutil/chart_test.go @@ -24,7 +24,7 @@ import ( "helm.sh/helm/v3/pkg/chart/loader" "helm.sh/helm/v3/pkg/repo/repotest" "k8s.io/apimachinery/pkg/runtime/schema" - "sigs.k8s.io/kubebuilder/pkg/model/resource" + "sigs.k8s.io/kubebuilder/v2/pkg/model/resource" "github.com/operator-framework/operator-sdk/internal/plugins/helm/v1/chartutil" ) diff --git a/internal/plugins/helm/v1/init.go b/internal/plugins/helm/v1/init.go index 30cf0678afc..312b9434915 100644 --- a/internal/plugins/helm/v1/init.go +++ b/internal/plugins/helm/v1/init.go @@ -22,9 +22,9 @@ import ( "github.com/spf13/pflag" "k8s.io/apimachinery/pkg/util/validation" - "sigs.k8s.io/kubebuilder/pkg/model/config" - "sigs.k8s.io/kubebuilder/pkg/plugin" - "sigs.k8s.io/kubebuilder/pkg/plugin/scaffold" + "sigs.k8s.io/kubebuilder/v2/pkg/model/config" + "sigs.k8s.io/kubebuilder/v2/pkg/plugin" + "sigs.k8s.io/kubebuilder/v2/pkg/plugin/scaffold" "github.com/operator-framework/operator-sdk/internal/kubebuilder/cmdutil" "github.com/operator-framework/operator-sdk/internal/plugins/helm/v1/chartutil" @@ -33,9 +33,9 @@ import ( "github.com/operator-framework/operator-sdk/internal/plugins/scorecard" ) -type initPlugin struct { +type initSubcommand struct { config *config.Config - apiPlugin createAPIPlugin + apiPlugin createAPISubcommand // If true, run the `create api` plugin. doCreateAPI bool @@ -45,12 +45,12 @@ type initPlugin struct { } var ( - _ plugin.Init = &initPlugin{} - _ cmdutil.RunOptions = &initPlugin{} + _ plugin.InitSubcommand = &initSubcommand{} + _ cmdutil.RunOptions = &initSubcommand{} ) // UpdateContext define plugin context -func (p *initPlugin) UpdateContext(ctx *plugin.Context) { +func (p *initSubcommand) UpdateContext(ctx *plugin.Context) { ctx.Description = `Initialize a new Helm-based operator project. Writes the following files: @@ -125,7 +125,7 @@ Writes the following files: } // BindFlags will set the flags for the plugin -func (p *initPlugin) BindFlags(fs *pflag.FlagSet) { +func (p *initSubcommand) BindFlags(fs *pflag.FlagSet) { fs.SortFlags = false fs.StringVar(&p.config.Domain, "domain", "my.domain", "domain for groups") fs.StringVar(&p.config.ProjectName, "project-name", "", "name of this project, the default being directory name") @@ -133,7 +133,7 @@ func (p *initPlugin) BindFlags(fs *pflag.FlagSet) { } // InjectConfig will inject the PROJECT file/config in the plugin -func (p *initPlugin) InjectConfig(c *config.Config) { +func (p *initSubcommand) InjectConfig(c *config.Config) { // v3 project configs get a 'layout' value. c.Layout = pluginKey p.config = c @@ -141,7 +141,7 @@ func (p *initPlugin) InjectConfig(c *config.Config) { } // Run will call the plugin actions -func (p *initPlugin) Run() error { +func (p *initSubcommand) Run() error { if err := cmdutil.Run(p); err != nil { return err } @@ -155,7 +155,7 @@ func (p *initPlugin) Run() error { } // SDK phase 2 plugins. -func (p *initPlugin) runPhase2() error { +func (p *initSubcommand) runPhase2() error { if err := manifests.RunInit(p.config); err != nil { return err } @@ -173,7 +173,7 @@ func (p *initPlugin) runPhase2() error { } // Validate perform the required validations for this plugin -func (p *initPlugin) Validate() error { +func (p *initSubcommand) Validate() error { // Check if the project name is a valid k8s namespace (DNS 1123 label). if p.config.ProjectName == "" { @@ -197,7 +197,7 @@ func (p *initPlugin) Validate() error { } // GetScaffolder returns scaffold.Scaffolder which will be executed due the RunOptions interface implementation -func (p *initPlugin) GetScaffolder() (scaffold.Scaffolder, error) { +func (p *initSubcommand) GetScaffolder() (scaffold.Scaffolder, error) { var ( apiScaffolder scaffold.Scaffolder err error @@ -212,7 +212,7 @@ func (p *initPlugin) GetScaffolder() (scaffold.Scaffolder, error) { } // PostScaffold will run the required actions after the default plugin scaffold -func (p *initPlugin) PostScaffold() error { +func (p *initSubcommand) PostScaffold() error { if p.doCreateAPI { return p.apiPlugin.PostScaffold() diff --git a/internal/plugins/helm/v1/plugin.go b/internal/plugins/helm/v1/plugin.go index e981fdd5881..563e01df3ba 100644 --- a/internal/plugins/helm/v1/plugin.go +++ b/internal/plugins/helm/v1/plugin.go @@ -15,8 +15,8 @@ package v1 import ( - "sigs.k8s.io/kubebuilder/pkg/model/config" - "sigs.k8s.io/kubebuilder/pkg/plugin" + "sigs.k8s.io/kubebuilder/v2/pkg/model/config" + "sigs.k8s.io/kubebuilder/v2/pkg/plugin" "github.com/operator-framework/operator-sdk/internal/plugins" ) @@ -30,18 +30,18 @@ var ( ) var ( - _ plugin.Base = Plugin{} - _ plugin.InitPluginGetter = Plugin{} - _ plugin.CreateAPIPluginGetter = Plugin{} + _ plugin.Plugin = Plugin{} + _ plugin.Init = Plugin{} + _ plugin.CreateAPI = Plugin{} ) type Plugin struct { - initPlugin - createAPIPlugin + initSubcommand + createAPISubcommand } -func (Plugin) Name() string { return pluginName } -func (Plugin) Version() plugin.Version { return pluginVersion } -func (Plugin) SupportedProjectVersions() []string { return supportedProjectVersions } -func (p Plugin) GetInitPlugin() plugin.Init { return &p.initPlugin } -func (p Plugin) GetCreateAPIPlugin() plugin.CreateAPI { return &p.createAPIPlugin } +func (Plugin) Name() string { return pluginName } +func (Plugin) Version() plugin.Version { return pluginVersion } +func (Plugin) SupportedProjectVersions() []string { return supportedProjectVersions } +func (p Plugin) GetInitSubcommand() plugin.InitSubcommand { return &p.initSubcommand } +func (p Plugin) GetCreateAPISubcommand() plugin.CreateAPISubcommand { return &p.createAPISubcommand } diff --git a/internal/plugins/helm/v1/scaffolds/api.go b/internal/plugins/helm/v1/scaffolds/api.go index bde661fa616..7f653373702 100644 --- a/internal/plugins/helm/v1/scaffolds/api.go +++ b/internal/plugins/helm/v1/scaffolds/api.go @@ -23,10 +23,10 @@ import ( "os" "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model" - "sigs.k8s.io/kubebuilder/pkg/model/config" - "sigs.k8s.io/kubebuilder/pkg/model/resource" - "sigs.k8s.io/kubebuilder/pkg/plugin/scaffold" + "sigs.k8s.io/kubebuilder/v2/pkg/model" + "sigs.k8s.io/kubebuilder/v2/pkg/model/config" + "sigs.k8s.io/kubebuilder/v2/pkg/model/resource" + "sigs.k8s.io/kubebuilder/v2/pkg/plugin/scaffold" "github.com/operator-framework/operator-sdk/internal/kubebuilder/machinery" "github.com/operator-framework/operator-sdk/internal/plugins/helm/v1/chartutil" diff --git a/internal/plugins/helm/v1/scaffolds/init.go b/internal/plugins/helm/v1/scaffolds/init.go index 6c37374ae30..2fedbaf1a48 100644 --- a/internal/plugins/helm/v1/scaffolds/init.go +++ b/internal/plugins/helm/v1/scaffolds/init.go @@ -20,9 +20,9 @@ package scaffolds import ( "os" - "sigs.k8s.io/kubebuilder/pkg/model" - "sigs.k8s.io/kubebuilder/pkg/model/config" - "sigs.k8s.io/kubebuilder/pkg/plugin/scaffold" + "sigs.k8s.io/kubebuilder/v2/pkg/model" + "sigs.k8s.io/kubebuilder/v2/pkg/model/config" + "sigs.k8s.io/kubebuilder/v2/pkg/plugin/scaffold" "github.com/operator-framework/operator-sdk/internal/kubebuilder/machinery" "github.com/operator-framework/operator-sdk/internal/plugins/helm/v1/chartutil" diff --git a/internal/plugins/helm/v1/scaffolds/internal/templates/config/crd/crd.go b/internal/plugins/helm/v1/scaffolds/internal/templates/config/crd/crd.go index b03ac74d48a..a8921873be6 100644 --- a/internal/plugins/helm/v1/scaffolds/internal/templates/config/crd/crd.go +++ b/internal/plugins/helm/v1/scaffolds/internal/templates/config/crd/crd.go @@ -20,7 +20,7 @@ import ( "path/filepath" "github.com/kr/text" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &CRD{} diff --git a/internal/plugins/helm/v1/scaffolds/internal/templates/config/crd/kustomization.go b/internal/plugins/helm/v1/scaffolds/internal/templates/config/crd/kustomization.go index 917cadddb03..a3281e96bfe 100644 --- a/internal/plugins/helm/v1/scaffolds/internal/templates/config/crd/kustomization.go +++ b/internal/plugins/helm/v1/scaffolds/internal/templates/config/crd/kustomization.go @@ -21,7 +21,7 @@ import ( "fmt" "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &Kustomization{} diff --git a/internal/plugins/helm/v1/scaffolds/internal/templates/config/kdefault/auth_proxy_patch.go b/internal/plugins/helm/v1/scaffolds/internal/templates/config/kdefault/auth_proxy_patch.go index 2abb40cc6e9..df600ad9dba 100644 --- a/internal/plugins/helm/v1/scaffolds/internal/templates/config/kdefault/auth_proxy_patch.go +++ b/internal/plugins/helm/v1/scaffolds/internal/templates/config/kdefault/auth_proxy_patch.go @@ -20,7 +20,7 @@ package kdefault import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &AuthProxyPatch{} diff --git a/internal/plugins/helm/v1/scaffolds/internal/templates/config/kdefault/kustomization.go b/internal/plugins/helm/v1/scaffolds/internal/templates/config/kdefault/kustomization.go index 497a1f88d39..afbe8e0b6d2 100644 --- a/internal/plugins/helm/v1/scaffolds/internal/templates/config/kdefault/kustomization.go +++ b/internal/plugins/helm/v1/scaffolds/internal/templates/config/kdefault/kustomization.go @@ -20,7 +20,7 @@ package kdefault import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &Kustomization{} diff --git a/internal/plugins/helm/v1/scaffolds/internal/templates/config/manager/kustomization.go b/internal/plugins/helm/v1/scaffolds/internal/templates/config/manager/kustomization.go index 84af806d0e1..1318302ed2c 100644 --- a/internal/plugins/helm/v1/scaffolds/internal/templates/config/manager/kustomization.go +++ b/internal/plugins/helm/v1/scaffolds/internal/templates/config/manager/kustomization.go @@ -19,7 +19,7 @@ package manager import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &Kustomization{} diff --git a/internal/plugins/helm/v1/scaffolds/internal/templates/config/manager/manager.go b/internal/plugins/helm/v1/scaffolds/internal/templates/config/manager/manager.go index 79b6a0759ef..6568b0467fc 100644 --- a/internal/plugins/helm/v1/scaffolds/internal/templates/config/manager/manager.go +++ b/internal/plugins/helm/v1/scaffolds/internal/templates/config/manager/manager.go @@ -20,7 +20,7 @@ package manager import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &Manager{} diff --git a/internal/plugins/helm/v1/scaffolds/internal/templates/config/prometheus/kustomization.go b/internal/plugins/helm/v1/scaffolds/internal/templates/config/prometheus/kustomization.go index a630cddcf29..c72539da6fe 100644 --- a/internal/plugins/helm/v1/scaffolds/internal/templates/config/prometheus/kustomization.go +++ b/internal/plugins/helm/v1/scaffolds/internal/templates/config/prometheus/kustomization.go @@ -19,7 +19,7 @@ package prometheus import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &Kustomization{} diff --git a/internal/plugins/helm/v1/scaffolds/internal/templates/config/prometheus/monitor.go b/internal/plugins/helm/v1/scaffolds/internal/templates/config/prometheus/monitor.go index d32402f15aa..54a2bcab94d 100644 --- a/internal/plugins/helm/v1/scaffolds/internal/templates/config/prometheus/monitor.go +++ b/internal/plugins/helm/v1/scaffolds/internal/templates/config/prometheus/monitor.go @@ -19,7 +19,7 @@ package prometheus import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &ServiceMonitor{} diff --git a/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/auth_proxy_role.go b/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/auth_proxy_role.go index f05e7767023..761ea8bcc61 100644 --- a/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/auth_proxy_role.go +++ b/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/auth_proxy_role.go @@ -19,7 +19,7 @@ package rbac import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &AuthProxyRole{} diff --git a/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/auth_proxy_role_binding.go b/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/auth_proxy_role_binding.go index d0d43cf071d..8342bf58517 100644 --- a/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/auth_proxy_role_binding.go +++ b/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/auth_proxy_role_binding.go @@ -19,7 +19,7 @@ package rbac import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &AuthProxyRoleBinding{} diff --git a/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/auth_proxy_service.go b/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/auth_proxy_service.go index 31a66347de6..03857ba1546 100644 --- a/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/auth_proxy_service.go +++ b/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/auth_proxy_service.go @@ -19,7 +19,7 @@ package rbac import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &AuthProxyService{} diff --git a/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/client_cluster_role.go b/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/client_cluster_role.go index 39cda25ad22..a3cbb04c38f 100644 --- a/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/client_cluster_role.go +++ b/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/client_cluster_role.go @@ -19,7 +19,7 @@ package rbac import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &ClientClusterRole{} diff --git a/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/crd_editor_rbac.go b/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/crd_editor_rbac.go index 44c28e88866..39f18cb726a 100644 --- a/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/crd_editor_rbac.go +++ b/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/crd_editor_rbac.go @@ -19,7 +19,7 @@ package rbac import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &CRDEditorRole{} diff --git a/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/crd_viewer_rbac.go b/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/crd_viewer_rbac.go index 2591e509167..fb8efa1252a 100644 --- a/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/crd_viewer_rbac.go +++ b/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/crd_viewer_rbac.go @@ -19,7 +19,7 @@ package rbac import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &CRDViewerRole{} diff --git a/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/kustomization.go b/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/kustomization.go index f3de8307aa2..9d5711cd8a4 100644 --- a/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/kustomization.go +++ b/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/kustomization.go @@ -19,7 +19,7 @@ package rbac import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &Kustomization{} diff --git a/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/leader_election_role.go b/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/leader_election_role.go index d8b0aaa61dd..b220d947ca4 100644 --- a/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/leader_election_role.go +++ b/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/leader_election_role.go @@ -19,7 +19,7 @@ package rbac import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &LeaderElectionRole{} diff --git a/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/leader_election_role_binding.go b/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/leader_election_role_binding.go index 875fff93fb0..00124b7709d 100644 --- a/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/leader_election_role_binding.go +++ b/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/leader_election_role_binding.go @@ -19,7 +19,7 @@ package rbac import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &LeaderElectionRoleBinding{} diff --git a/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/manager_role.go b/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/manager_role.go index ba920f76c90..14488342574 100644 --- a/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/manager_role.go +++ b/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/manager_role.go @@ -32,7 +32,7 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/client-go/discovery" crconfig "sigs.k8s.io/controller-runtime/pkg/client/config" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" "sigs.k8s.io/yaml" ) diff --git a/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/manager_role_binding.go b/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/manager_role_binding.go index ffa553528ac..fd02baa91e6 100644 --- a/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/manager_role_binding.go +++ b/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/manager_role_binding.go @@ -19,7 +19,7 @@ package rbac import ( "path/filepath" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &ManagerRoleBinding{} diff --git a/internal/plugins/helm/v1/scaffolds/internal/templates/config/samples/crd_sample.go b/internal/plugins/helm/v1/scaffolds/internal/templates/config/samples/crd_sample.go index 10daa6ad3db..c858a06c9b2 100644 --- a/internal/plugins/helm/v1/scaffolds/internal/templates/config/samples/crd_sample.go +++ b/internal/plugins/helm/v1/scaffolds/internal/templates/config/samples/crd_sample.go @@ -24,7 +24,7 @@ import ( "text/template" "helm.sh/helm/v3/pkg/chart" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" "sigs.k8s.io/yaml" ) diff --git a/internal/plugins/helm/v1/scaffolds/internal/templates/dockerfile.go b/internal/plugins/helm/v1/scaffolds/internal/templates/dockerfile.go index f02fc1b546b..26a169496fa 100644 --- a/internal/plugins/helm/v1/scaffolds/internal/templates/dockerfile.go +++ b/internal/plugins/helm/v1/scaffolds/internal/templates/dockerfile.go @@ -17,7 +17,7 @@ package templates import ( "errors" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &Dockerfile{} diff --git a/internal/plugins/helm/v1/scaffolds/internal/templates/gitignore.go b/internal/plugins/helm/v1/scaffolds/internal/templates/gitignore.go index e309be025bb..745db8daec7 100644 --- a/internal/plugins/helm/v1/scaffolds/internal/templates/gitignore.go +++ b/internal/plugins/helm/v1/scaffolds/internal/templates/gitignore.go @@ -18,7 +18,7 @@ limitations under the License. package templates import ( - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &GitIgnore{} diff --git a/internal/plugins/helm/v1/scaffolds/internal/templates/makefile.go b/internal/plugins/helm/v1/scaffolds/internal/templates/makefile.go index 95adbe5dba4..f5af0f1039b 100644 --- a/internal/plugins/helm/v1/scaffolds/internal/templates/makefile.go +++ b/internal/plugins/helm/v1/scaffolds/internal/templates/makefile.go @@ -20,7 +20,7 @@ package templates import ( "errors" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &Makefile{} diff --git a/internal/plugins/helm/v1/scaffolds/internal/templates/watches.go b/internal/plugins/helm/v1/scaffolds/internal/templates/watches.go index 4204820a305..7e8256bd347 100644 --- a/internal/plugins/helm/v1/scaffolds/internal/templates/watches.go +++ b/internal/plugins/helm/v1/scaffolds/internal/templates/watches.go @@ -17,7 +17,7 @@ package templates import ( "fmt" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &Watches{} diff --git a/internal/plugins/manifests/api.go b/internal/plugins/manifests/api.go index 655349026f7..20f02eff8e2 100644 --- a/internal/plugins/manifests/api.go +++ b/internal/plugins/manifests/api.go @@ -18,9 +18,9 @@ package manifests import ( "fmt" - "sigs.k8s.io/kubebuilder/pkg/model" - "sigs.k8s.io/kubebuilder/pkg/model/config" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model" + "sigs.k8s.io/kubebuilder/v2/pkg/model/config" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" "github.com/operator-framework/operator-sdk/internal/kubebuilder/machinery" ) diff --git a/internal/plugins/manifests/init.go b/internal/plugins/manifests/init.go index 65dd97f4675..f8e78148f44 100644 --- a/internal/plugins/manifests/init.go +++ b/internal/plugins/manifests/init.go @@ -20,7 +20,7 @@ import ( "io/ioutil" "os" - "sigs.k8s.io/kubebuilder/pkg/model/config" + "sigs.k8s.io/kubebuilder/v2/pkg/model/config" "github.com/operator-framework/operator-sdk/internal/util/projutil" ) diff --git a/internal/plugins/manifests/samples.go b/internal/plugins/manifests/samples.go index 65e9ca5f5d0..9aae78406ab 100644 --- a/internal/plugins/manifests/samples.go +++ b/internal/plugins/manifests/samples.go @@ -18,8 +18,8 @@ import ( "path/filepath" "strings" - "sigs.k8s.io/kubebuilder/pkg/model/config" - "sigs.k8s.io/kubebuilder/pkg/model/file" + "sigs.k8s.io/kubebuilder/v2/pkg/model/config" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" ) var _ file.Template = &kustomization{} diff --git a/internal/plugins/scorecard/init.go b/internal/plugins/scorecard/init.go index 6db3d2510ec..7747d8bd070 100644 --- a/internal/plugins/scorecard/init.go +++ b/internal/plugins/scorecard/init.go @@ -24,7 +24,7 @@ import ( "github.com/operator-framework/api/pkg/apis/scorecard/v1alpha3" "k8s.io/apimachinery/pkg/runtime/schema" - "sigs.k8s.io/kubebuilder/pkg/model/config" + "sigs.k8s.io/kubebuilder/v2/pkg/model/config" "sigs.k8s.io/yaml" "github.com/operator-framework/operator-sdk/internal/plugins/util/kustomize" diff --git a/internal/testutils/olm.go b/internal/testutils/olm.go index 31285e4dc42..f10ac2f85aa 100644 --- a/internal/testutils/olm.go +++ b/internal/testutils/olm.go @@ -20,7 +20,7 @@ import ( "path/filepath" "strings" - "sigs.k8s.io/kubebuilder/pkg/model/config" + "sigs.k8s.io/kubebuilder/v2/pkg/model/config" ) const ( diff --git a/internal/testutils/utils.go b/internal/testutils/utils.go index 8a8283ddd34..ae7199f39a9 100644 --- a/internal/testutils/utils.go +++ b/internal/testutils/utils.go @@ -28,7 +28,7 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - kbtestutils "sigs.k8s.io/kubebuilder/test/e2e/utils" + kbtestutils "sigs.k8s.io/kubebuilder/v2/test/e2e/utils" ) const BinaryName = "operator-sdk" diff --git a/internal/util/projutil/project_util.go b/internal/util/projutil/project_util.go index 57b2d5f7280..455bb405f67 100644 --- a/internal/util/projutil/project_util.go +++ b/internal/util/projutil/project_util.go @@ -22,7 +22,7 @@ import ( "strings" log "github.com/sirupsen/logrus" - "sigs.k8s.io/kubebuilder/pkg/model/config" + "sigs.k8s.io/kubebuilder/v2/pkg/model/config" ) const ( diff --git a/test/e2e-ansible/e2e_ansible_cluster_test.go b/test/e2e-ansible/e2e_ansible_cluster_test.go index acb7ff836e1..8a2e639c9a0 100644 --- a/test/e2e-ansible/e2e_ansible_cluster_test.go +++ b/test/e2e-ansible/e2e_ansible_cluster_test.go @@ -23,7 +23,7 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - kbtestutils "sigs.k8s.io/kubebuilder/test/e2e/utils" + kbtestutils "sigs.k8s.io/kubebuilder/v2/test/e2e/utils" "github.com/operator-framework/operator-sdk/internal/testutils" ) diff --git a/test/e2e-ansible/e2e_ansible_suite_test.go b/test/e2e-ansible/e2e_ansible_suite_test.go index 6ea680ffd11..c2256ccacc7 100644 --- a/test/e2e-ansible/e2e_ansible_suite_test.go +++ b/test/e2e-ansible/e2e_ansible_suite_test.go @@ -21,7 +21,7 @@ import ( "strings" "testing" - kbtestutils "sigs.k8s.io/kubebuilder/test/e2e/utils" + kbtestutils "sigs.k8s.io/kubebuilder/v2/test/e2e/utils" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" diff --git a/test/e2e-go/e2e_go_cluster_test.go b/test/e2e-go/e2e_go_cluster_test.go index 1511fb29d05..126cce378eb 100644 --- a/test/e2e-go/e2e_go_cluster_test.go +++ b/test/e2e-go/e2e_go_cluster_test.go @@ -25,7 +25,7 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - kbtestutils "sigs.k8s.io/kubebuilder/test/e2e/utils" + kbtestutils "sigs.k8s.io/kubebuilder/v2/test/e2e/utils" ) var _ = Describe("operator-sdk", func() { diff --git a/test/e2e-go/e2e_go_suite_test.go b/test/e2e-go/e2e_go_suite_test.go index e5add77c4ce..49e923db4ca 100644 --- a/test/e2e-go/e2e_go_suite_test.go +++ b/test/e2e-go/e2e_go_suite_test.go @@ -23,7 +23,7 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - kbtestutils "sigs.k8s.io/kubebuilder/test/e2e/utils" + kbtestutils "sigs.k8s.io/kubebuilder/v2/test/e2e/utils" "github.com/operator-framework/operator-sdk/internal/testutils" ) diff --git a/test/e2e-helm/e2e_helm_cluster_test.go b/test/e2e-helm/e2e_helm_cluster_test.go index 23cdbdbbd22..1e89f1457ab 100644 --- a/test/e2e-helm/e2e_helm_cluster_test.go +++ b/test/e2e-helm/e2e_helm_cluster_test.go @@ -23,7 +23,7 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - kbtestutils "sigs.k8s.io/kubebuilder/test/e2e/utils" + kbtestutils "sigs.k8s.io/kubebuilder/v2/test/e2e/utils" "github.com/operator-framework/operator-sdk/internal/testutils" ) diff --git a/website/content/en/docs/cli/operator-sdk_edit.md b/website/content/en/docs/cli/operator-sdk_edit.md index 4e6ed12e4a3..63c908c3b79 100644 --- a/website/content/en/docs/cli/operator-sdk_edit.md +++ b/website/content/en/docs/cli/operator-sdk_edit.md @@ -7,7 +7,8 @@ This command will edit the project configuration ### Synopsis -This command will edit the project configuration. You can have single or multi group project. +Edit the project configuration. + Note: unable to find configuration file, project must be initialized ``` From f2769aeb3255ecd79b21883eaded7267ed64ea21 Mon Sep 17 00:00:00 2001 From: Varsha Date: Mon, 16 Nov 2020 16:36:24 -0800 Subject: [PATCH 216/376] fix: modify bindata script to use curl (#4224) Modify bindata script to use curl instead of wget. Signed-off-by: reinvantveer --- hack/generate/olm_bindata.sh | 4 ++-- internal/bindata/olm/manifests.go | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hack/generate/olm_bindata.sh b/hack/generate/olm_bindata.sh index 4c7e7eb3e84..e92e52ea035 100755 --- a/hack/generate/olm_bindata.sh +++ b/hack/generate/olm_bindata.sh @@ -2,8 +2,8 @@ function get_olm_manifests() { echo "downloading olm manifests for version ${1}" - wget -O olm-manifests/$1-olm.yaml "https://github.com/operator-framework/operator-lifecycle-manager/releases/download/${1}/olm.yaml" - wget -O olm-manifests/$1-crds.yaml "https://github.com/operator-framework/operator-lifecycle-manager/releases/download/${1}/crds.yaml" + curl -L -o olm-manifests/$1-olm.yaml "https://github.com/operator-framework/operator-lifecycle-manager/releases/download/${1}/olm.yaml" + curl -L -o olm-manifests/$1-crds.yaml "https://github.com/operator-framework/operator-lifecycle-manager/releases/download/${1}/crds.yaml" } function remove_olm_manifests { diff --git a/internal/bindata/olm/manifests.go b/internal/bindata/olm/manifests.go index 6db90fd6b08..20aa7101bd5 100644 --- a/internal/bindata/olm/manifests.go +++ b/internal/bindata/olm/manifests.go @@ -96,7 +96,7 @@ func olmManifests0151CrdsYaml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "olm-manifests/0.15.1-crds.yaml", size: 814667, mode: os.FileMode(420), modTime: time.Unix(1591299779, 0)} + info := bindataFileInfo{name: "olm-manifests/0.15.1-crds.yaml", size: 814667, mode: os.FileMode(420), modTime: time.Unix(1605551831, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -116,7 +116,7 @@ func olmManifests0151OlmYaml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "olm-manifests/0.15.1-olm.yaml", size: 9184, mode: os.FileMode(420), modTime: time.Unix(1591299779, 0)} + info := bindataFileInfo{name: "olm-manifests/0.15.1-olm.yaml", size: 9184, mode: os.FileMode(420), modTime: time.Unix(1605551830, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -136,7 +136,7 @@ func olmManifests0161CrdsYaml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "olm-manifests/0.16.1-crds.yaml", size: 824806, mode: os.FileMode(420), modTime: time.Unix(1599228290, 0)} + info := bindataFileInfo{name: "olm-manifests/0.16.1-crds.yaml", size: 824806, mode: os.FileMode(420), modTime: time.Unix(1605551830, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -156,7 +156,7 @@ func olmManifests0161OlmYaml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "olm-manifests/0.16.1-olm.yaml", size: 9143, mode: os.FileMode(420), modTime: time.Unix(1599228292, 0)} + info := bindataFileInfo{name: "olm-manifests/0.16.1-olm.yaml", size: 9143, mode: os.FileMode(420), modTime: time.Unix(1605551829, 0)} a := &asset{bytes: bytes, info: info} return a, nil } From 48011f787958cdb09b48e76c6943ae3bd9e5ee9d Mon Sep 17 00:00:00 2001 From: Joe Lanford Date: Wed, 18 Nov 2020 14:20:46 -0500 Subject: [PATCH 217/376] website: remove confusing/unnecessary install helm/ansible instructions (#4227) Signed-off-by: reinvantveer --- website/content/en/docs/installation/_index.md | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/website/content/en/docs/installation/_index.md b/website/content/en/docs/installation/_index.md index 02d0fbc651d..82ae5658797 100644 --- a/website/content/en/docs/installation/_index.md +++ b/website/content/en/docs/installation/_index.md @@ -36,12 +36,8 @@ $ brew install operator-sdk $ RELEASE_VERSION=v1.2.0 # Linux $ curl -LO https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu -$ curl -LO https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/ansible-operator-${RELEASE_VERSION}-x86_64-linux-gnu -$ curl -LO https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/helm-operator-${RELEASE_VERSION}-x86_64-linux-gnu # macOS $ curl -LO https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin -$ curl -LO https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/ansible-operator-${RELEASE_VERSION}-x86_64-apple-darwin -$ curl -LO https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/helm-operator-${RELEASE_VERSION}-x86_64-apple-darwin ``` #### Verify the downloaded release binaries @@ -49,12 +45,8 @@ $ curl -LO https://github.com/operator-framework/operator-sdk/releases/download/ ```sh # Linux $ curl -LO https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu.asc -$ curl -LO https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/ansible-operator-${RELEASE_VERSION}-x86_64-linux-gnu.asc -$ curl -LO https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/helm-operator-${RELEASE_VERSION}-x86_64-linux-gnu.asc # macOS $ curl -LO https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin.asc -$ curl -LO https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/ansible-operator-${RELEASE_VERSION}-x86_64-apple-darwin.asc -$ curl -LO https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/helm-operator-${RELEASE_VERSION}-x86_64-apple-darwin.asc ``` To verify a release binary using the provided asc files, place the binary and corresponding asc file into the same directory and use the corresponding command: @@ -62,12 +54,8 @@ To verify a release binary using the provided asc files, place the binary and co ```sh # Linux $ gpg --verify operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu.asc -$ gpg --verify ansible-operator-${RELEASE_VERSION}-x86_64-linux-gnu.asc -$ gpg --verify helm-operator-${RELEASE_VERSION}-x86_64-linux-gnu.asc # macOS $ gpg --verify operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin.asc -$ gpg --verify ansible-operator-${RELEASE_VERSION}-x86_64-apple-darwin.asc -$ gpg --verify helm-operator-${RELEASE_VERSION}-x86_64-apple-darwin.asc ``` If you do not have the maintainers public key on your machine, you will get an error message similar to this: @@ -99,12 +87,8 @@ Now you should be able to verify the binary. ```sh # Linux $ chmod +x operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu && sudo mkdir -p /usr/local/bin/ && sudo cp operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu /usr/local/bin/operator-sdk && rm operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu -$ chmod +x ansible-operator-${RELEASE_VERSION}-x86_64-linux-gnu && sudo mkdir -p /usr/local/bin/ && sudo cp ansible-operator-${RELEASE_VERSION}-x86_64-linux-gnu /usr/local/bin/ansible-operator && rm ansible-operator-${RELEASE_VERSION}-x86_64-linux-gnu -$ chmod +x helm-operator-${RELEASE_VERSION}-x86_64-linux-gnu && sudo mkdir -p /usr/local/bin/ && sudo cp helm-operator-${RELEASE_VERSION}-x86_64-linux-gnu /usr/local/bin/helm-operator && rm helm-operator-${RELEASE_VERSION}-x86_64-linux-gnu # macOS $ chmod +x operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin && sudo mkdir -p /usr/local/bin/ && sudo cp operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin /usr/local/bin/operator-sdk && rm operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin -$ chmod +x ansible-operator-${RELEASE_VERSION}-x86_64-apple-darwin && sudo mkdir -p /usr/local/bin/ && sudo cp ansible-operator-${RELEASE_VERSION}-x86_64-apple-darwin /usr/local/bin/ansible-operator && rm ansible-operator-${RELEASE_VERSION}-x86_64-apple-darwin -$ chmod +x helm-operator-${RELEASE_VERSION}-x86_64-apple-darwin && sudo mkdir -p /usr/local/bin/ && sudo cp helm-operator-${RELEASE_VERSION}-x86_64-apple-darwin /usr/local/bin/helm-operator && rm helm-operator-${RELEASE_VERSION}-x86_64-apple-darwin ``` ## Compile and install from master From c0ffa98d830cc2cf0caa1e5a40cd1e94888e085c Mon Sep 17 00:00:00 2001 From: Joe Lanford Date: Tue, 24 Nov 2020 08:16:50 -0500 Subject: [PATCH 218/376] internal/cmd: add build info metric in helm/ansible operators (#4220) Signed-off-by: reinvantveer --- .../helm-ansible-version-metric.yaml | 9 ++++ internal/ansible/metrics/metrics.go | 18 ++++++++ internal/cmd/ansible-operator/run/cmd.go | 3 ++ internal/cmd/helm-operator/run/cmd.go | 3 ++ internal/helm/metrics/metrics.go | 44 +++++++++++++++++++ 5 files changed, 77 insertions(+) create mode 100644 changelog/fragments/helm-ansible-version-metric.yaml create mode 100644 internal/helm/metrics/metrics.go diff --git a/changelog/fragments/helm-ansible-version-metric.yaml b/changelog/fragments/helm-ansible-version-metric.yaml new file mode 100644 index 00000000000..67a740de210 --- /dev/null +++ b/changelog/fragments/helm-ansible-version-metric.yaml @@ -0,0 +1,9 @@ +entries: + - description: > + In Ansible-based operators, added the `ansible_operator_build_info` + metric to instrument commit and version information. + kind: "addition" + - description: > + In Helm-based operators, added the `helm_operator_build_info` + metric to instrument commit and version information. + kind: "addition" diff --git a/internal/ansible/metrics/metrics.go b/internal/ansible/metrics/metrics.go index 4b238c04bb8..ffd560c48d3 100644 --- a/internal/ansible/metrics/metrics.go +++ b/internal/ansible/metrics/metrics.go @@ -20,6 +20,8 @@ import ( "github.com/prometheus/client_golang/prometheus" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/metrics" + + sdkVersion "github.com/operator-framework/operator-sdk/internal/version" ) const ( @@ -27,6 +29,17 @@ const ( ) var ( + buildInfo = prometheus.NewGauge( + prometheus.GaugeOpts{ + Subsystem: subsystem, + Name: "build_info", + Help: "Build information for the ansible-operator binary", + ConstLabels: map[string]string{ + "commit": sdkVersion.GitCommit, + "version": sdkVersion.Version, + }, + }) + reconcileResults = prometheus.NewGaugeVec( prometheus.GaugeOpts{ Subsystem: subsystem, @@ -64,6 +77,11 @@ func recoverMetricPanic() { } } +func RegisterBuildInfo(r prometheus.Registerer) { + buildInfo.Set(1) + r.MustRegister(buildInfo) +} + func ReconcileSucceeded(gvk string) { defer recoverMetricPanic() reconcileResults.WithLabelValues(gvk, "succeeded").Inc() diff --git a/internal/cmd/ansible-operator/run/cmd.go b/internal/cmd/ansible-operator/run/cmd.go index b7183cdc448..58661752b7c 100644 --- a/internal/cmd/ansible-operator/run/cmd.go +++ b/internal/cmd/ansible-operator/run/cmd.go @@ -33,9 +33,11 @@ import ( zapf "sigs.k8s.io/controller-runtime/pkg/log/zap" "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/manager/signals" + crmetrics "sigs.k8s.io/controller-runtime/pkg/metrics" "github.com/operator-framework/operator-sdk/internal/ansible/controller" "github.com/operator-framework/operator-sdk/internal/ansible/flags" + "github.com/operator-framework/operator-sdk/internal/ansible/metrics" "github.com/operator-framework/operator-sdk/internal/ansible/proxy" "github.com/operator-framework/operator-sdk/internal/ansible/proxy/controllermap" "github.com/operator-framework/operator-sdk/internal/ansible/runner" @@ -81,6 +83,7 @@ func NewCmd() *cobra.Command { func run(cmd *cobra.Command, f *flags.Flags) { printVersion() + metrics.RegisterBuildInfo(crmetrics.Registry) cfg, err := config.GetConfig() if err != nil { diff --git a/internal/cmd/helm-operator/run/cmd.go b/internal/cmd/helm-operator/run/cmd.go index b5f672d8e7c..7b99c33a0bd 100644 --- a/internal/cmd/helm-operator/run/cmd.go +++ b/internal/cmd/helm-operator/run/cmd.go @@ -31,9 +31,11 @@ import ( zapf "sigs.k8s.io/controller-runtime/pkg/log/zap" "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/manager/signals" + crmetrics "sigs.k8s.io/controller-runtime/pkg/metrics" "github.com/operator-framework/operator-sdk/internal/helm/controller" "github.com/operator-framework/operator-sdk/internal/helm/flags" + "github.com/operator-framework/operator-sdk/internal/helm/metrics" "github.com/operator-framework/operator-sdk/internal/helm/release" "github.com/operator-framework/operator-sdk/internal/helm/watches" "github.com/operator-framework/operator-sdk/internal/util/k8sutil" @@ -73,6 +75,7 @@ func NewCmd() *cobra.Command { func run(cmd *cobra.Command, f *flags.Flags) { printVersion() + metrics.RegisterBuildInfo(crmetrics.Registry) cfg, err := config.GetConfig() if err != nil { diff --git a/internal/helm/metrics/metrics.go b/internal/helm/metrics/metrics.go new file mode 100644 index 00000000000..992eb405eb0 --- /dev/null +++ b/internal/helm/metrics/metrics.go @@ -0,0 +1,44 @@ +// Copyright 2020 The Operator-SDK 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. + +package metrics + +import ( + "github.com/prometheus/client_golang/prometheus" + + sdkVersion "github.com/operator-framework/operator-sdk/internal/version" +) + +const ( + subsystem = "helm_operator" +) + +var ( + buildInfo = prometheus.NewGauge( + prometheus.GaugeOpts{ + Subsystem: subsystem, + Name: "build_info", + Help: "Build information for the helm-operator binary", + ConstLabels: map[string]string{ + "commit": sdkVersion.GitCommit, + "version": sdkVersion.Version, + }, + }, + ) +) + +func RegisterBuildInfo(r prometheus.Registerer) { + buildInfo.Set(1) + r.MustRegister(buildInfo) +} From f684b5513c83c472e22491e2a38c8da030f5e429 Mon Sep 17 00:00:00 2001 From: Joe Lanford Date: Tue, 24 Nov 2020 09:41:18 -0500 Subject: [PATCH 219/376] sample generation fixes (#4247) Signed-off-by: reinvantveer --- hack/generate/samples/internal/helm/memcached.go | 14 ++------------ hack/generate/samples/internal/pkg/utils.go | 3 --- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/hack/generate/samples/internal/helm/memcached.go b/hack/generate/samples/internal/helm/memcached.go index a78a57cb8b6..9abf434e5a7 100644 --- a/hack/generate/samples/internal/helm/memcached.go +++ b/hack/generate/samples/internal/helm/memcached.go @@ -17,7 +17,6 @@ package helm import ( "os" "path/filepath" - "strings" log "github.com/sirupsen/logrus" @@ -55,12 +54,6 @@ func (mh *MemcachedHelm) Prepare() { // Run runs the steps to generate the sample func (mh *MemcachedHelm) Run() { - current, err := os.Getwd() - if err != nil { - log.Error(err) - os.Exit(1) - } - // When operator-sdk scaffolds Helm projects, it tries to use the discovery API of a Kubernetes // cluster to intelligently build the RBAC rules that the operator will require based on the // content of the helm chart. @@ -73,15 +66,12 @@ func (mh *MemcachedHelm) Run() { os.Setenv("KUBECONFIG", "broken_so_we_generate_static_default_rules") log.Infof("creating the project") - err = mh.ctx.Init( + err := mh.ctx.Init( "--plugins", "helm", "--domain", mh.ctx.Domain) pkg.CheckError("creating the project", err) - log.Infof("handling work path to get helm chart mock data") - projectPath := strings.Split(current, "operator-sdk/")[0] - projectPath = strings.Replace(projectPath, "operator-sdk", "", 1) - helmChartPath := filepath.Join(projectPath, "operator-sdk/hack/generate/samples/internal/helm/testdata/memcached-0.0.1.tgz") + helmChartPath := "../../../hack/generate/samples/internal/helm/testdata/memcached-0.0.1.tgz" log.Infof("using the helm chart in: (%v)", helmChartPath) err = mh.ctx.CreateAPI( diff --git a/hack/generate/samples/internal/pkg/utils.go b/hack/generate/samples/internal/pkg/utils.go index 98bd05e6ae0..c7c63c8b9cd 100644 --- a/hack/generate/samples/internal/pkg/utils.go +++ b/hack/generate/samples/internal/pkg/utils.go @@ -46,9 +46,6 @@ func (ctx *SampleContext) CreateBundle() { err = ctx.StripBundleAnnotations() CheckError("stripping bundle annotations", err) - - err = ctx.Make("bundle-build", "BUNDLE_IMG="+ctx.BundleImageName) - CheckError("running make bundle-build", err) } // StripBundleAnnotations removes all annotations applied to bundle manifests and metadata From 777c4ac0da0f322fe2f7926b57c0f330a184c3e6 Mon Sep 17 00:00:00 2001 From: Joe Lanford Date: Tue, 24 Nov 2020 18:02:00 -0500 Subject: [PATCH 220/376] Run PR tests via GitHub Actions (#4253) Co-authored-by: Eric Stroczynski Signed-off-by: reinvantveer --- .github/workflows/integration.yml | 16 +++++++++++++ .github/workflows/test-ansible.yml | 37 ++++++++++++++++++++++++++++++ .github/workflows/test-go.yml | 32 ++++++++++++++++++++++++++ .github/workflows/test-helm.yml | 17 ++++++++++++++ .github/workflows/test-sanity.yml | 28 ++++++++++++++++++++++ hack/tests/e2e-ansible-molecule.sh | 1 + 6 files changed, 131 insertions(+) create mode 100644 .github/workflows/integration.yml create mode 100644 .github/workflows/test-ansible.yml create mode 100644 .github/workflows/test-go.yml create mode 100644 .github/workflows/test-helm.yml create mode 100644 .github/workflows/test-sanity.yml diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml new file mode 100644 index 00000000000..1e216c12574 --- /dev/null +++ b/.github/workflows/integration.yml @@ -0,0 +1,16 @@ +name: integration +on: + pull_request: {} + +jobs: + integration: + name: integration + runs-on: ubuntu-18.04 + steps: + - uses: actions/setup-go@v2 + with: + go-version: 1.15 + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - run: make test-e2e-integration diff --git a/.github/workflows/test-ansible.yml b/.github/workflows/test-ansible.yml new file mode 100644 index 00000000000..0eb41f7af64 --- /dev/null +++ b/.github/workflows/test-ansible.yml @@ -0,0 +1,37 @@ +name: ansible +on: + pull_request: {} + +jobs: + e2e: + name: e2e + runs-on: ubuntu-18.04 + steps: + - uses: actions/setup-go@v2 + with: + go-version: 1.15 + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - run: sudo rm -rf /usr/local/bin/kustomize + - run: make test-e2e-ansible + + e2e-molecule: + name: e2e-molecule + runs-on: ubuntu-18.04 + steps: + - uses: actions/setup-go@v2 + with: + go-version: 1.15 + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - run: sudo rm -rf /usr/local/bin/kustomize + - run: | + env + export PATH=/opt/python/3.6.7/bin:${PATH} + sudo apt-get install python3 python3-pip + sudo pip3 install wheel + sudo pip3 install --upgrade setuptools pip + sudo pip3 install ansible~=2.9.13 + make test-e2e-ansible-molecule diff --git a/.github/workflows/test-go.yml b/.github/workflows/test-go.yml new file mode 100644 index 00000000000..9423fa0579f --- /dev/null +++ b/.github/workflows/test-go.yml @@ -0,0 +1,32 @@ +name: go +on: + pull_request: {} + +jobs: + e2e: + name: e2e + runs-on: ubuntu-18.04 + steps: + - uses: actions/setup-go@v2 + with: + go-version: 1.15 + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - run: sudo rm -rf /usr/local/bin/kustomize + - run: make test-e2e-go + + unit: + name: unit + runs-on: ubuntu-18.04 + steps: + - uses: actions/setup-go@v2 + with: + go-version: 1.15 + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - run: make test-unit + - uses: shogo82148/actions-goveralls@v1 + with: + path-to-profile: coverage.out diff --git a/.github/workflows/test-helm.yml b/.github/workflows/test-helm.yml new file mode 100644 index 00000000000..0809e4d511d --- /dev/null +++ b/.github/workflows/test-helm.yml @@ -0,0 +1,17 @@ +name: helm +on: + pull_request: {} + +jobs: + e2e: + name: e2e + runs-on: ubuntu-18.04 + steps: + - uses: actions/setup-go@v2 + with: + go-version: 1.15 + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - run: sudo rm -rf /usr/local/bin/kustomize + - run: make test-e2e-helm diff --git a/.github/workflows/test-sanity.yml b/.github/workflows/test-sanity.yml new file mode 100644 index 00000000000..bb194f97468 --- /dev/null +++ b/.github/workflows/test-sanity.yml @@ -0,0 +1,28 @@ +name: sanity +on: + pull_request: {} + +jobs: + sanity: + name: sanity + runs-on: ubuntu-18.04 + steps: + - uses: actions/setup-go@v2 + with: + go-version: 1.15 + id: go + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - run: sudo rm -rf /usr/local/bin/kustomize + - run: make test-sanity + + links: + name: doc links + runs-on: ubuntu-18.04 + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + submodules: recursive + - run: make test-links diff --git a/hack/tests/e2e-ansible-molecule.sh b/hack/tests/e2e-ansible-molecule.sh index a2449fe734e..a4dbbda3e2c 100755 --- a/hack/tests/e2e-ansible-molecule.sh +++ b/hack/tests/e2e-ansible-molecule.sh @@ -10,6 +10,7 @@ header_text "Running tests to check ansible molecule" ROOTDIR="$(pwd)" TMPDIR="$(mktemp -d)" trap_add 'rm -rf $TMPDIR' EXIT +export PATH=${HOME}/.local/bin:${PATH} pip3 install --user pyasn1==0.4.7 pyasn1-modules==0.2.6 idna==2.8 ipaddress==1.0.22 pip3 install --user molecule==3.0.2 pip3 install --user ansible-lint yamllint From f1e7a9972ea0b2164884e31cf4e3e7f4bab0191a Mon Sep 17 00:00:00 2001 From: Rico Berger Date: Wed, 25 Nov 2020 19:25:15 +0100 Subject: [PATCH 221/376] doc: fix log statement in multi namespace example (#4250) Co-authored-by: Eric Stroczynski Signed-off-by: reinvantveer --- .../content/en/docs/building-operators/golang/operator-scope.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/content/en/docs/building-operators/golang/operator-scope.md b/website/content/en/docs/building-operators/golang/operator-scope.md index ccf57d67512..3a402e14018 100644 --- a/website/content/en/docs/building-operators/golang/operator-scope.md +++ b/website/content/en/docs/building-operators/golang/operator-scope.md @@ -264,7 +264,7 @@ options := ctrl.Options{ // Add support for MultiNamespace set in WATCH_NAMESPACE (e.g ns1,ns2) if strings.Contains(watchNamespace, ",") { - setupLog.Infof("manager will be watching namespace %q", watchNamespace) + setupLog.Info("manager set up with multiple namespaces", "namespaces", watchNamespace) // configure cluster-scoped with MultiNamespacedCacheBuilder options.Namespace = "" options.NewCache = cache.MultiNamespacedCacheBuilder(strings.Split(watchNamespace, ",")) From 9433cc1c1f2f7587dd5a07f0bf06e35dd09ce0f6 Mon Sep 17 00:00:00 2001 From: Varsha Date: Wed, 25 Nov 2020 17:52:21 -0800 Subject: [PATCH 222/376] cleanup: refactor cleanup to let olm delete resources (#4233) Refactor cleanup to delete crds and csv instead of individually deleting the resources referenced in install plan. OLM applies an ownerref on every namespaced resource to the CSV, and an owner label on cluster scoped resources. OLM and kube garbage collector will delete the resources referenced in csv. Signed-off-by: reinvantveer --- internal/olm/operator/uninstall.go | 92 +++++++++++++----------------- 1 file changed, 40 insertions(+), 52 deletions(-) diff --git a/internal/olm/operator/uninstall.go b/internal/olm/operator/uninstall.go index c7e5d11e1ca..427964e1540 100644 --- a/internal/olm/operator/uninstall.go +++ b/internal/olm/operator/uninstall.go @@ -22,7 +22,6 @@ import ( v1 "github.com/operator-framework/api/pkg/operators/v1" "github.com/operator-framework/api/pkg/operators/v1alpha1" - "github.com/operator-framework/operator-registry/pkg/lib/bundle" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" @@ -31,7 +30,11 @@ import ( "k8s.io/kubectl/pkg/util/slice" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - "sigs.k8s.io/yaml" +) + +const ( + csvKind = "ClusterServiceVersion" + crdKind = "CustomResourceDefinition" ) type Uninstall struct { @@ -91,22 +94,13 @@ func (u *Uninstall) Run(ctx context.Context) error { return fmt.Errorf("get catalog source: %v", err) } - // Since the install plan is owned by the subscription, we need to - // read all of the resource references from the install plan before - // deleting the subscription. - var crds, csvs, others []controllerutil.Object - if sub.Status.InstallPlanRef != nil { - ipKey := types.NamespacedName{ - Namespace: sub.Status.InstallPlanRef.Namespace, - Name: sub.Status.InstallPlanRef.Name, - } - var err error - crds, csvs, others, err = u.getInstallPlanResources(ctx, ipKey) - if err != nil { - return fmt.Errorf("get install plan resources: %v", err) - } + csv, err := u.getInstalledCSV(ctx, sub) + if err != nil { + return fmt.Errorf("get installed CSV %q: %v", sub.Status.InstalledCSV, err) } + crds := getCRDs(csv) + // Delete the subscription first, so that no further installs or upgrades // of the operator occur while we're cleaning up. if err := u.deleteObjects(ctx, false, sub); err != nil { @@ -121,11 +115,13 @@ func (u *Uninstall) Run(ctx context.Context) error { } } - // Delete CSVs and all other objects created by the install plan. - objects := append(csvs, others...) - if err := u.deleteObjects(ctx, true, objects...); err != nil { + // OLM puts an ownerref on every namespaced resource to the CSV, + // and an owner label on every cluster scoped resource. When CSV is deleted + // kube and olm gc will remove all the referenced resources. + if err := u.deleteObjects(ctx, true, csv); err != nil { return err } + } else { catsrc.SetNamespace(u.config.Namespace) catsrc.SetName(CatalogNameForPackage(u.Package)) @@ -194,43 +190,35 @@ func (u *Uninstall) deleteObjects(ctx context.Context, waitForDelete bool, objs return nil } -func (u *Uninstall) getInstallPlanResources(ctx context.Context, installPlanKey types.NamespacedName) (crds, csvs, others []controllerutil.Object, err error) { - installPlan := &v1alpha1.InstallPlan{} - if err := u.config.Client.Get(ctx, installPlanKey, installPlan); err != nil { - return nil, nil, nil, fmt.Errorf("get install plan: %v", err) +// getInstalledCSV looks up the installed CSV name from the provided subscription and fetches it. +func (u *Uninstall) getInstalledCSV(ctx context.Context, subscription *v1alpha1.Subscription) (*v1alpha1.ClusterServiceVersion, error) { + key := types.NamespacedName{ + Name: subscription.Status.InstalledCSV, + Namespace: subscription.GetNamespace(), } - for _, step := range installPlan.Status.Plan { - lowerKind := strings.ToLower(step.Resource.Kind) - obj := &unstructured.Unstructured{Object: map[string]interface{}{}} - if err := yaml.Unmarshal([]byte(step.Resource.Manifest), &obj.Object); err != nil { - return nil, nil, nil, fmt.Errorf("parse %s manifest %q: %v", lowerKind, step.Resource.Name, err) - } - obj.SetGroupVersionKind(schema.GroupVersionKind{ - Group: step.Resource.Group, - Version: step.Resource.Version, - Kind: step.Resource.Kind, - }) - - // TODO(joelanford): This seems necessary for namespaced resources - // See: https://github.com/operator-framework/operator-lifecycle-manager/blob/c9405d035bc50d9aa290220cb8d75b0402e72707/pkg/controller/registry/resolver/rbac.go#L133 - if supported, namespaced := bundle.IsSupported(step.Resource.Kind); supported && bool(namespaced) { - obj.SetNamespace(installPlanKey.Namespace) - } + installedCSV := &v1alpha1.ClusterServiceVersion{} + if err := u.config.Client.Get(ctx, key, installedCSV); err != nil { + return nil, err + } - switch step.Resource.Kind { - case "CustomResourceDefinition": + installedCSV.SetGroupVersionKind(v1alpha1.SchemeGroupVersion.WithKind(csvKind)) + return installedCSV, nil +} + +// getCRDs returns the list of CRDs required by a CSV. +func getCRDs(csv *v1alpha1.ClusterServiceVersion) (crds []controllerutil.Object) { + for _, resource := range csv.Status.RequirementStatus { + if resource.Kind == crdKind { + obj := &unstructured.Unstructured{} + obj.SetGroupVersionKind(schema.GroupVersionKind{ + Group: resource.Group, + Version: resource.Version, + Kind: resource.Kind, + }) + obj.SetName(resource.Name) crds = append(crds, obj) - case "ClusterServiceVersion": - csvs = append(csvs, obj) - default: - // Skip non-CRD/non-CSV resources in the install plan that were not created by the install plan. - // This means we avoid deleting things like the default service account. - if step.Status != v1alpha1.StepStatusCreated { - continue - } - others = append(others, obj) } } - return crds, csvs, others, nil + return } From 835ac9839beacdefac02148a4c87232f00f97c79 Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Mon, 30 Nov 2020 15:05:01 -0800 Subject: [PATCH 223/376] *: automate releases with goreleaser (#4034) This commit adds tooling for automated releases in CI using goreleaser, agnostic of CI platform (albeit with some environment configuration). Any Github user with write capabilities to the SDK repo can start a release. .ci/gpg: GPG public key, encrypted private subkey (used for signing), and script to decrypt private subkey in CI website/scripts: scripts to update versions in release commits and branches at build time .goreleaser.yml: goreleaser config file *: script and Makefile updates to support automated releases docs: release and installation guide simplifications, related docs cleanup Signed-off-by: reinvantveer --- .ci/gpg/create-keyring.sh | 33 ++ .ci/gpg/pubring.auto | 64 +++ .ci/gpg/secring.auto.gpg | Bin 0 -> 4408 bytes .gitignore | 3 + .goreleaser.yml | 90 ++++ .travis.yml | 19 +- CHANGELOG.md | 2 + Makefile | 33 +- README.md | 33 ++ hack/image/push-image-tags.sh | 28 -- hack/image/push-manifest-list.sh | 12 +- netlify.toml | 8 +- release.sh | 51 --- release/Makefile | 116 ++--- tools/scripts/fetch | 4 + website/config.toml | 2 + .../developer-guide.md | 16 - .../docs/contribution-guidelines/releasing.md | 428 ++++++------------ .../docs/contribution-guidelines/testing.md | 27 +- .../content/en/docs/installation/_index.md | 98 ++-- website/scripts/set_menu_version.sh | 19 + website/scripts/update_branch_mappings.sh | 27 ++ 22 files changed, 579 insertions(+), 534 deletions(-) create mode 100755 .ci/gpg/create-keyring.sh create mode 100644 .ci/gpg/pubring.auto create mode 100644 .ci/gpg/secring.auto.gpg create mode 100644 .goreleaser.yml delete mode 100755 release.sh create mode 100755 website/scripts/set_menu_version.sh create mode 100755 website/scripts/update_branch_mappings.sh diff --git a/.ci/gpg/create-keyring.sh b/.ci/gpg/create-keyring.sh new file mode 100755 index 00000000000..a7f1dce9b1b --- /dev/null +++ b/.ci/gpg/create-keyring.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" + +# Modified from https://blogs.itemis.com/en/secure-your-travis-ci-releases-part-2-signature-with-openpgp + +function err_exit() { + echo "ERROR: ${1:-"Unknown Error"} Exiting." 1>&2 + exit 1 +} + +declare -r GPG_HOME="${DIR}/keyring" +declare -r SECRING_AUTO="${GPG_HOME}/secring.auto" +declare -r PUBRING_AUTO="${GPG_HOME}/pubring.auto" + +mkdir -p "$GPG_HOME" +cp "${DIR}"/*.auto* "${GPG_HOME}" + +echo -e "\nDecrypting secret key..." +{ + # $GPG_PASSWORD is taken from the script's env (injected by Travis CI). + echo $GPG_PASSWORD | gpg --decrypt \ + --pinentry-mode loopback --batch \ + --passphrase-fd 0 \ + --output "${SECRING_AUTO}" \ + "${SECRING_AUTO}".gpg ; \ +} || { err_exit "Failed to decrypt secret key." ; } +echo "Success!" + +echo -e "\nImporting keys..." +{ gpg --home "${GPG_HOME}" --import "${PUBRING_AUTO}" ; } || { err_exit "Could not import public key into gpg." ; } +{ gpg --home "${GPG_HOME}" --import "${SECRING_AUTO}" ; } || { err_exit "Could not import secret key into gpg." ; } +echo "Success!" diff --git a/.ci/gpg/pubring.auto b/.ci/gpg/pubring.auto new file mode 100644 index 00000000000..41fa49fabb0 --- /dev/null +++ b/.ci/gpg/pubring.auto @@ -0,0 +1,64 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQINBF+clTQBEADMHVz8qS+dcYC0qxlSNe4Yipbr/BtVuWGJay26OAbS4K7sjzs3 +XP+RhjUsJGOnPXn+N/zM6wVNczV7MrdfWNK1UAWBPVC4HjD/ysj/m5lMv/j0RNym +W6VNdSgV4YWyQHn6eD279gT4p6GAVvQj0eXnWtX7eA0SaITi6dMNqw8QcTOBxzFI +PXw+4MDJJKDAammtNKgj6LtmYc3o9d8aqbwtPfj3Vvi5d3SWfMx8a+2aSDkVcsva +bloGUBXYWFzO11T4OYvUYXgQdaKHyT+ZWGCpDsnQV/KqG5S456jmV+Qp+98vwe8k +XhXhlkjauhbvVR0uGAv0RJ4NZPSmWpie6f7ApQ3XTg3+ZvsrTvi3STCkOKA8/CLm +/xRhAF/aFZSOLlgzyAxr45j0PRjzX3XJfPePkV1D1cFso3JGDT5Y2oku8bNqYTof +fV/vw6jxylSNKApn1VyViwZ0+aE9kjMHXytKWWLK+woxrFOG74nGcI+xBOAOHvSU +GRh5EVXydbyMxqEpq2Su+rHlzfzgPh+hORNQgrag+qdbTVMimCoD+datX4854Hkb +nah+mq7RtI0k5Nn+ENm4ufbHEKiNb56qFTNgMkquG5vxpA6NOlZ0QfKUxiDU08+g +Pix7+TY7lzNhGipD7QjqfuJJr+1k3p/GrIpoHlU8/8FvlNYBDG3oMUvxNwARAQAB +tDJPcGVyYXRvciBTREsgKHJlbGVhc2UpIDxjbmNmLW9wZXJhdG9yLXNka0BjbmNm +LmlvPokCVAQTAQgAPhYhBDsvFIHRRiOAgLNGuwUpluKiC1x+BQJfnJU0AhsBBQkD +w7iABQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAAAoJEAUpluKiC1x+P5IQAJXpQMA1 +kIr6S2N9A4TE6z+dhN0g3oPdZqOYwlKpX32H4nLdv219Ns1mwBHUfTFmcbUuQLwH +1TjF7cVya/tUoyh/P7bBBOy/vC0NvvaOuhRXxeJJD7Q8neuXyCpIoCW8x2Eq47ut +21AL79ZrzZEBpavJ80S2uNTx7HGKYug491OKkEWO3Y+FOmTV38WsN+lpM+atn1LP +gWkEhWaxwkfLrYUgZ/lDBAIhPZ7n3gYptmTQdCzlp4dSEwJXesV35aMWfJOM848M +fVJFyFcMNo6ww0tHD+7btrGc4fHSJC/dKZcYVoiSHmpuAqRBXHWMxKPfijgwWQs5 +6JjxCWt4bwouF0D2uE6SD/MYsxN05yZL6OGfzzQES5Ilt0DS3QRLktN8PdeuS+WN +jLVo7/Q2SUGZcANm+5/ul7Qwj9JeFSK3VloLKY0YFEbnyTHw2TU4oDqyffUWTn+h +Pt34Wy+OWRM+2ykxFP1VklgCN07ESRSZOTN6iUzqets50rKpY3okNiZeMPcblxQo +uQ5/NFmYV/de87JuSmOKXB2yy/xdr7oxkbw9uYZmBEvw4etxH2yyzVxr0BJ4r0DW +5DlSxOeHaNa7aUVQnlK+Xf27Pj1XyYvV6G7NWEZYZQ/pclO0rhFH21ZiGo3DHgSo +cAGv6SWU01nELYYHTn3QFdmdjxmbqjSC0t+EuQINBF+clhYBEACj1YQhSMK8kp1W +oDL5As2yFlljmdkXTrYtMBLjLnkUaKoxIEGbrB/aeyph9PC84iKGLrHGC6rNBdVq +2mnGyJCXKKeJLovJnopz3+2bTOnypaOdk1QhovFw8CXRMVhjRehDe9PWQYXk2aL7 +sPvtLl5clw2iULdjxs2KfBGwSlEV6eXjGCFUGfIvMEQ/gjbTIiUtkhqaMCsEuyrB +aliNNfuBYsmnP5pHvn7yI/kMiNB8d0LmI8PCb+zdzZVbu9mID8P0Eyy6imbfwzIt +f21OP78lvGBVGzd2mH/EYyBswHEUblqBcb9maTz2Yy85dTFXKWU7n+OjKCCYpOK7 +SVffQFdR2ylUtv2JvLOCR/gH1Z0ac8ZF2DEI9C+owsVS9dqMk9l4p3cNeQzgRshN +qhO9eP9qGZ1LIgEKOeyLm5TgUcPLnq49vS4/eCo+p+Qa1FcGEs+b6rqIxSzyxNxs +v2lRmUQ/A3BToV321De2zfr51u1rJJVpYIEvbMPRyiciZzkDu/D5Z5fR1nytoFcR +t3osFILI0lilvzpSzxlHmnM480JADiTlKGz6YTnYG2mrZCFOxrmAsA/yDO4v41Ii +7O7z0cJO3l3mZ1fbqqAqqyHU0EGcxYOAmfM8azSrxj0MOM2jfGDMPWg3g3SXTXIl +6qyWOVUWfP4+QBsHrByHTSpGCgyTWwARAQABiQRyBBgBCAAmFiEEOy8UgdFGI4CA +s0a7BSmW4qILXH4FAl+clhYCGwIFCQPDuIACQAkQBSmW4qILXH7BdCAEGQEIAB0W +IQSGE9uHpbqCXvP9Dr4qhZ0Iv5iG2wUCX5yWFgAKCRAqhZ0Iv5iG2x3cD/9KqFC6 +gbhzNpIvZ2yrri1l1SIrB+PKvCeZSOYDlxDJ3YgAu/3+d7EwOovP8IuEb340R8w0 +onsdYDHCHODCgda+Pu/WvWxx5/wSObyd0kHPM55RLx5C5UHPdlt+yKJ0QwiMPF8g +AqVDXkc2XIghBID4ykP0V5re9ug87hVd2EYnrkMDa6N+lXtlvzptFTjBJVdu3reM +pLwHqS/GAmxhgwF6kVPxZRHcMIKLweLN2JgGd2aFaIQBj+O43XROhL5or+F/E60w +c4ZTUp/a8aRxJRrzlHgNFBbV6oknzwTQRaB1CD0YXjFZL2k5rEEfvyfXguCTDyZT +jJjYvCO0MDxL/KI9fyJpcU+entGod83Ne893XXCS2SmaTY3LvQ+v/e99trh4m7St +oOQ8xm6b10sI6TbhbgPOYgtTPLxw3BldTrU5Hphz+suPrcHybKn357l7bf9yYTfK +tsrAKPVOMNF7QEdR3UldqoGzkTo55l4omvMS93tWSG+w47W7QIAQjwTlqDyjYVg3 +2l8XlfDtcR0k+Y6ObguEMUwtsikK+FvqVS5ZCPIyvv4kMCIazMlEWocsfvrINjQ4 +II2W+oQv5vJmOyY30tPELq35taH9oOMjtY3KWZVmPzw6+DGRTA2RDR+7qm2v3lgl +i49Nzi/iSBvDeVZxSBHRRjH/OL7TKWN+WwC2I4wYD/4iox1+WcKPsI+77HaULvsP +qa+bXnKbZidrsqSejbPnLg3M9an2gDo0d62QxrnJLl9OhuhObXP/bzCjrcMkg9hY +BAHaTXbRtVlSKpXYEyuwO6HYQ7WyHlY9y9srHIvcWuBrpI9Kgd28rkT4QZB5WJD/ +Cgj4ksJAe+TsSmccdw3zG3OWWVs4HujQnWnh+NbBE7cyYqZaByKiDjL3vKP+0Zfj +M/TF8nnY7zqgSljQxScbW7//U3GiB9DKg1r9TEMzmSTDugwv7u2kM/iZPjq+dvUs +KqKuyX23WDKRLyzusDqIWKsRrkd+g1vBfxSUhWwxtwzyy1rL/tNcXGBuLOxjUit9 +LhdowjFRG93Tswac/Q8VGPEB5XjBgRNlW9vSYgw+5wTHf01UBWgEWtFhl6SJnD6u +AjnMBtduqXBXmncTA6Gz5XB1h7xM32pLncWJGHfixXiJcOgGqW+Lv1Y3eaPqCFOm +4yfYDfBL+UN8Y7sR3WrVy1R6Ut/8bf4sD/i1UyBNKSzeN5sBpi7KgA6yY7PpVIN7 +H7V1QN41Bw9vAG5WXCO8vmY0GoCMQAKM5p04mMuBr6nswy1W94q6uuINwq6q1ycf +YQJyoKhXifPhdicwDMYeuW7aP7WnPIb3VwdtlEyD+ycBsak0Jsq/+yrov3pXgrdL +dlF2O4uTr4frwKRl28eGEQ== +=ebPb +-----END PGP PUBLIC KEY BLOCK----- diff --git a/.ci/gpg/secring.auto.gpg b/.ci/gpg/secring.auto.gpg new file mode 100644 index 0000000000000000000000000000000000000000..29f151e6d87990c6d626434c6274b3531ecbc7f3 GIT binary patch literal 4408 zcmV-85y$R~4Fm}T0`BCE0@k*x-0{-v0isK%L6&BSY(l~*(J)bZO5FGFwdJBrYlhq1 z*lROY)A4&3+wXp^&kLx6AQ3#+?P8R)8r*g-(9<>wvo@-$S3YW#e+sbE&7gE7jerwn zROAgCNN-vCp|-LGL5}^}r>dp_xI~T!jGpk_mg&=TK4>zWREsY}HCXa#JH)A_PJJ3y zLf~AUo#`^Wp%W5pf<|xZUGZ#9Zx(P5`K^pae}p4Q#+wIn-dxk8MJvN6-*xcZ##m9~ z$I9s#!3-XXOhmdRq8YZ;GDqAF(wt9pWV00!A0a2%%ZX){ zE1J)*Ah)j?(R*yXd*BW5*a~<7j;!W7nx&z8QP1tCz^Avi~6O_N`1{P{MkD-NLH@Zg`F* zPDBU=>2+twmG^2z5Y)~$;U z_xS9Ek+HW_+vp?93<>D|R(+lmf$zZ*x&@|5Q5Fq%D8c;O7qzjb1T9s>PrHvvzM%L? z!^|{*e8*)d1r)gs6e0Dj#&wiU)k2pEjdHS%FSKtGfXCc_|Gt-mU-u&!b z__FBOTKy_0vjK4eTJx&*@J=~!Ng^X8;@qG@W+ELztV$J8K%MV_NfIJ6M9@eRHb^3b zTUaALrD{RKt!v>0K7x}>GI|XtC$RkUp%TKeEY2Dqngo`x(vwu*m+fM*$vF$}d0P_m zeonc>5yM;Yf_>F?H!+Gh7wPgi(HBXn4avBPCB5a7-erm;k*EmXkWbU1s!1_matx z{+Bf}k{~&MM=kQNc`E5)yBinO*osMoKL6jHYq$vG>csKQQM~j7d@kSXXV_%(F?s=@ zO#_%@iW(+~cX)C|JsdhJ3VDbwgRD!ElTCx5NUd9s0{SMMMGCPw7gB!PH9oK?sK}_B z5T;CSxnT))S4ayn=bQy=5TPEPBWdi{+m4_3sPI5Ny%Mh{02UNIHA9#Em-6FGi{n`J?JgZ3DX)>7_?CISKl< z?19o)G$ehJT0uK(^D<+my*_+c{l$wkOVD9Y?q0p0vJU3mZv9iukjK__fSC7~qB{U( z{04&zu_+Z^-YSS3@WSG`eoUE;ljG#DH2JX zW{7=ynV`V{A|6|b<{adMXMGuak%uGUJJ$iu?3HwxUgR`Z`uLhH9B~~dA4ckOU4a!C zkRB?YBlXq~fa&p0Of9jusxC8Pp=$&<&H~yWwZJS^E!S!CpII`r_7-6Q+B#O`5lPjN zvVvS>kO?ro4_|ZYF^iZS73IX{cj<A3_ll z)9U&)B0)Qn__prty{FR~vc0H*ce-RHJ7VNV=Vc}!Feb6mHD?F+F+vbxXapi72QR5F zl0Ij%HOFbv2R`pE?~8cB2QL;_M3tJLg1O!A`cEniyqRzEl)3VjwWJ1u0I9QP=~Gs9 z6}qpcsQ|>wLFxmnNdrQ`&67E#&r8z3Tg`14!cdb~b<2;wA5B_?82Rjz;9@*wjD+^+ z3asAYLF-us-YLpPho$qCzLL1$rzoh+rdIy0@3sc)+RTseBw*pXNBmPr_0&zF%N&mg zYo1OoED^JU?GEP7s3H0x$RPJ-)zvGR>K6?j+<_?3fu48|ZVO1htM3)WFXSHtqLkc=d=nOW^b2l%jh&{*lg;l3rT z4Pu=iKPP$>|1R7v`FU23!7%!0Thnl<<5iLJDRiO|4Bi~R>o)?2)@X$Kt~jJ*nVM7K zm>>us89W&PI>y<&K6a?yPnQTq{;Qoirzt)oZbg~P4oc)D-%;90D&73(SFU;$6EXe; zeKhod!%vn|Gp{v3%1y+EXnHnSqLSuzIMS^1CN_v>pITcP=B3@~oQ0!d|yWLL~e6=o&rr~!n7F7(lbo`dI*%)Y_m;j}b z92?{_N}l-3X@8#ktAZT@%-?S|0}y#R#1C42P}w9I-7FHn6H#CV=}YWI#9CKj9h%*Q zK2)j3Fj7h!kxLJR3Qroo5Ip+6vUvxi2f#NZ*9-r=MwQ7X@cPq))Gnw=57LWz6xk$> z;a@Dh;^LuQ0S#m`btcM$dF_KlG#va(x4`VIP$WP81}B>OMd6L1YsDeKv59d|#BAz{ z1bWY8CSsM_PE|4IW9v8#(K9%*sJ6|)*J5$X5(odXq8&A;GOC6JX-qU+>qS;EoXDvag2`$EzvUZtkN{V8=^kj)jO` zO4Bv0V!d-j`z;E_fE?Hm4u+E?<%-cDHOglKq2i|;9BbjKDS^meT1&xNJYIIgC1T=` zn1X6%sdutZl_0SnWp?o~(YNOO&=$A(keAKWQg)7~^iN4iw)M&RfQNwa)VN?KO%)Ki z3FGCsFsgKQcD=QY6}=(x`te=fx4JLh8@1MqjPWH%Xmr19hH%z|7tN_e%2{G4xxslXKEg)<0&)upCR?B*)f>yey7@T?bBVmhI- z;yw`(H!V;ppohwdl23;v`A;=|^>Nz@l&f#9;tsRr)@tz186uQKk*mTsX|CG)v}fI% z>){1ui}1oW8No=-{j9&``dx>rSVYlRI<;8nsrm}E!qqC^O>g2&QB<xagAqrCwQ;{Esmx(0zj;XaNLT z${~Vgj9CZeHKjr7#^W8P$>p3<*ibn3>lOEwF!Jk{54Yz;= z7oJzT1VGqrK9LrNq0ya)#76mkVtas{`v{C9l@=vpCjDOEuz)DN)D|5AO~1RSf6&Er zWh)#-C3^C};$l<;W!qAo{6Z8iMKjB;v~i;QjCHRXZ{7)a0RY`$V`9z)2N=k5kDdxN zNen%mxwfy>T>nvOVXNHDuEcC3z7yJ*S1I<7cw%ko44X%`?nWFz@F?54`m`s7>Hu=J zDO=l#sg|>@vPEM`mQGn5E!l!sU&7S%g$5-GJ6u@PUqDAD^Ii0^*%S#a z%xd+DI#N7AAE-ut)KnZQ%X5q!`aflmT_8w}#BU`_$H$C0*Y$F_GEjtU6s<^MUblPB zpPlJln#vmIW<4NP@o<{Rzn8|*PK9jGwP~(sBt_pL3GWD~D8%MOlwTKr3ZwyjiSR~s$`TJM6Ph&PkBm?SvxG=&ncT$r?KTxzdg z_EKsRzv$$xars)xzzXvy{7kP{UBCoaJ<=%T!HB0^l>pz*hkR)pP_jDgntMJ^4b#y<|9j&&tf6iD5lXIKB`2R4l%Gu*S1#Y|}->&I78u zjolES;fb}qNsV2~d-!e^?}g<*)Mr$hbJ+;ORjIsRUt}m;vNwp~UI>tUjCRklhEVWEOSYjt@>TCbdgwiVw9e``iNj zy~kNdKG-WchIl+~ly1yU7wPurwKm+D19Z_Srh}92*62r#KYPWd(Ib>>UKXo`BO+G=bI$?IISAXOF2DoT^A zKR0P*qs!R6^#W$`v^*;K2T>tvSzG;zlop@c6(&P7QSP=HCGyO77pPj;YcXoOy2_? z3&?>5H?*<)eR`m-^vzhh8m+a!+VG&Z@91G(`7$;B_NKE{qf}^knmv zUkj7wkM!2?*m+M84L~0rbY!;tM_VssXE&-g*?YqD;B97u%>3hLrEqF?qGdoUVfTl5 zhjcOH5;TG*NqZ}VB#cxy)}^fRFO`xvhm3T7BPB8a0>-BlDAj?GaRwzU;lfBcYyV2z zmRIi{f6%fbVz44K(elcx$BI9NpX5?*z zOz|oxNu_2O$NYcXo*e0NGW8PQ1GZ6Z0Hk{+PnVUH_W(L|A&ZJ4;tEO7kszdjL=UNw zZfiEo7|@B*Qk;N})@MlZDhSX%*)H!jfnGo!rXw^P)r--i>KyG!up z{t)P29Hj~v!qee6r7fTla|73-$@8&pAZq|-w99Xf;$SVAn(%vTXWJl(Vx_}pK!eE>fSko$fWPFPAht=!{v zyY)FZ6&U87HaMCz=$tyX=nLbP(7{7drU=eZNqtQgAe&cXFaWOZxoN581Wd1vQFGi? y?bo|yB{PMH8u+vL6x0XuFCxE*rs2|FuZY${?qI08B}@((mEl3%InH|u0i^Pn;FDSa literal 0 HcmV?d00001 diff --git a/.gitignore b/.gitignore index c5bc0b3edce..7e83314920d 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,9 @@ /tools/bin /images/*/bin +# CI GPG keyring +/.ci/gpg/keyring + # Website website/public/ website/resources/ diff --git a/.goreleaser.yml b/.goreleaser.yml new file mode 100644 index 00000000000..f9944da90c6 --- /dev/null +++ b/.goreleaser.yml @@ -0,0 +1,90 @@ +# Global environment variables for builds. +env: + - CGO_ENABLED=0 + - GO111MODULE=on + - GOPROXY=https://proxy.golang.org|direct + - REPO=github.com/operator-framework/operator-sdk + +# Hooks to run before any build is run. +before: + hooks: + - go version | grep --quiet "go1\.15\.5" || echo "Go binary version must be 1.15.5" + - go mod download + +# Binary builds. +builds: + # operator-sdk build steps + - id: operator-sdk + main: ./cmd/operator-sdk + binary: operator-sdk + mod_timestamp: "{{ .CommitTimestamp }}" + asmflags: &build-asmflags + - all=-trimpath={{ .Env.PWD }} + gcflags: &build-gcflags + - all=-trimpath={{ .Env.PWD }} + ldflags: &build-ldflags + - -X {{ .Env.REPO }}/internal/version.Version={{ .Env.SIMPLE_VERSION }} + - -X {{ .Env.REPO }}/internal/version.GitVersion={{ .Env.GIT_VERSION }} + - -X {{ .Env.REPO }}/internal/version.GitCommit={{ .Env.GIT_COMMIT }} + - -X {{ .Env.REPO }}/internal/version.KubernetesVersion={{ .Env.K8S_VERSION }} + - -X {{ .Env.REPO }}/internal/version.ImageVersion={{ .Env.IMAGE_VERSION }} + targets: &build-targets + - darwin_amd64 + - linux_amd64 + - linux_arm64 + - linux_ppc64le + - linux_s390x + + # ansible-operator build steps + - id: ansible-operator + main: ./cmd/ansible-operator + binary: ansible-operator + mod_timestamp: "{{ .CommitTimestamp }}" + asmflags: *build-asmflags + gcflags: *build-gcflags + ldflags: *build-ldflags + targets: *build-targets + + # helm-operator build steps + - id: helm-operator + main: ./cmd/helm-operator + binary: helm-operator + mod_timestamp: "{{ .CommitTimestamp }}" + asmflags: *build-asmflags + gcflags: *build-gcflags + ldflags: *build-ldflags + targets: *build-targets + +# Use most recent tag and short commit for snapshot version. +snapshot: + name_template: "{{ .Env.GIT_VERSION }}" + +# We don't use archives, so skip creating them. +archives: + - format: binary + name_template: "{{ .Binary }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}{{ if .Mips }}_{{ .Mips }}{{ end }}" + +checksum: + name_template: "checksums.txt" + +# Sign the checksum file with the CI GPG key. +signs: + - signature: "${artifact}.asc" + artifacts: checksum + # Use the CI signing subkey A20B5C7E decrypted into .ci/gpg/keyring to sign the release. + args: ["--home", ".ci/gpg/keyring", "-u", "A20B5C7E", "--output", "${signature}", "--detach-sign", "${artifact}"] + +# We use a custom changelog generator. +changelog: + +# TODO(estroz): configure homebrew publishing +# brews: +# - name: operator-sdk +# ids: +# - operator-sdk + +# Uncomment for testing +# release: +# github: +# owner: +# name: operator-sdk diff --git a/.travis.yml b/.travis.yml index b87d5f9a956..ea48597d120 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ dist: xenial language: go go: -- 1.15.x +- 1.15.5 go_import_path: github.com/operator-framework/operator-sdk cache: @@ -47,12 +47,16 @@ x_base_steps: - docker stages: - - check - - test + - name: check + if: type == pull_request + - name: test + if: type == pull_request - name: deploy if: type != pull_request AND ( tag IS present OR branch = master OR commit_message =~ /\[travis deploy\]/ ) - name: deploy-manifest-multiarch if: type != pull_request AND ( tag IS present OR branch = master OR commit_message =~ /\[travis deploy\]/ ) + - name: release + if: type != pull_request AND tag IS present jobs: include: @@ -151,3 +155,12 @@ jobs: name: push manifest lists <<: *manifest-deploy script: make -f release/Makefile image-push-multiarch + + ## Release jobs ## + + - stage: release + name: publish release + before_install: git fetch origin --unshallow --tags + install: sudo ln -sf $(command -v gpg2) $(dirname $(command -v gpg2))/gpg + before_script: .ci/gpg/create-keyring.sh + script: make release diff --git a/CHANGELOG.md b/CHANGELOG.md index 08efe9354e1..9e0ae251732 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,5 @@ +**This file will no longer be updated. Instead, refer to generated `changelog/generated/.md`** + ## v1.2.0 ### Additions diff --git a/Makefile b/Makefile index e5a0960891f..ae2f7908244 100644 --- a/Makefile +++ b/Makefile @@ -12,10 +12,10 @@ export GIT_COMMIT = $(shell git rev-parse HEAD) export K8S_VERSION = 1.18.8 # Build settings +export TOOLS_DIR = tools/bin +export SCRIPTS_DIR = tools/scripts REPO = $(shell go list -m) BUILD_DIR = build -TOOLS_DIR = tools/bin -SCRIPTS_DIR = tools/scripts GO_ASMFLAGS = -asmflags "all=-trimpath=$(shell dirname $(PWD))" GO_GCFLAGS = -gcflags "all=-trimpath=$(shell dirname $(PWD))" GO_BUILD_ARGS = \ @@ -73,7 +73,7 @@ build/scorecard-test build/scorecard-test-kuttl build/custom-scorecard-tests: build/operator-sdk build/ansible-operator build/helm-operator: go build $(GO_BUILD_ARGS) -o $(BUILD_DIR)/$(@F) ./cmd/$(@F) -##@ Dev images +##@ Dev image build # Convenience wrapper for building all remotely hosted images. .PHONY: image-build @@ -90,6 +90,23 @@ image/%: build/% docker build -t $(BUILD_IMAGE_REPO)/$*:dev -f ./images/$*/Dockerfile ./images/$* rm -rf $(BUILD_DIR) +##@ Release + +.PHONY: release +release: ## Release target. See 'make -f release/Makefile help' for more information. + $(MAKE) -f release/Makefile $@ + +.PHONY: prerelease +prerelease: ## Write release commit changes. See 'make -f release/Makefile help' for more information. +ifneq ($(RELEASE_VERSION),$(IMAGE_VERSION)) + $(error "IMAGE_VERSION "$(IMAGE_VERSION)" must be updated to match RELEASE_VERSION "$(RELEASE_VERSION)" prior to creating a release commit") +endif + $(MAKE) -f release/Makefile $@ + +.PHONY: tag +tag: ## Tag a release commit. See 'make -f release/Makefile help' for more information. + $(MAKE) -f release/Makefile $@ + ##@ Test .PHONY: test-all @@ -156,16 +173,6 @@ test-e2e-integration:: ## Run integration tests ./hack/tests/integration.sh ./hack/tests/subcommand-olm-install.sh -# TODO(estroz): remove changelog/release when goreleaser is added as release tool (they shouldn't be exposed as dev targets). - -.PHONY: changelog -changelog: ## Generate CHANGELOG.md and migration guide updates - $(MAKE) -f release/Makefile changelog - -.PHONY: release -release: clean ## Release the Operator SDK - $(MAKE) -f release/Makefile GO_BUILD_ARGS='$(GO_BUILD_ARGS)' - .DEFAULT_GOAL := help .PHONY: help help: ## Show this help screen. diff --git a/README.md b/README.md index b8a0c35c420..5b2096f52c7 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,39 @@ operators easier by providing: - Tools for scaffolding and code generation to bootstrap a new project fast - Extensions to cover common operator use cases +## Dependency and platform support + +### Go version + +Release binaries will be built with the Go compiler version specified in the Operator SDK's [prerequisites section][doc-readme-prereqs]. + +### Kubernetes versions + +As the Operator SDK interacts directly with the Kubernetes API, certain API features are assumed to exist in the target cluster. +The currently supported Kubernetes version will always be listed in the SDK [prerequisites section][doc-readme-prereqs]. + +### Platforms + +The following matrix defines which architectures are supported for GNU Linux: + +| | `amd64` | `arm64` | `ppc64le` | `s390x` | +|-------------------------------|-----------------|-----------------|-----------------|-----------------| +| `operator-sdk` | ✓ | ✓ | ✓ | ✓ | +| `ansible-operator` | ✓ | ✓ | ✓ | ✓ | +| `helm-operator` | ✓ | ✓ | ✓ | ✓ | +| `scorecard-test` image | ✓ | ✓ | ✓ | ✓ | +| `scorecard-test-kuttl` image | ✓ | ✓ | ✓ | - | + +The following matrix defines which architectures are supported for MacOS Darwin: + +| | `amd64` | +|-------------------------------|-----------------| +| `operator-sdk` | ✓ | +| `ansible-operator` | ✓ | +| `helm-operator` | ✓ | + +Support for the Windows platform is not on the roadmap at this time. + ## License Operator SDK is under Apache 2.0 license. See the [LICENSE][license_file] file for details. diff --git a/hack/image/push-image-tags.sh b/hack/image/push-image-tags.sh index 88cb6383f8a..b47b0593610 100755 --- a/hack/image/push-image-tags.sh +++ b/hack/image/push-image-tags.sh @@ -16,7 +16,6 @@ function push_image_tags() { push_image=$1; shift || push_image=$source_image print_image_info $source_image - print_git_tags docker_login $push_image @@ -53,31 +52,4 @@ function print_image_info() { fi } -# -# print_git_tags -# -# print_git_tags prints all tags present in the git repository. -# -function print_git_tags() { - git_tags=$(git tag -l | sed 's|^| |') - if [[ -n "$git_tags" ]]; then - echo "Found git tags:" - echo "$git_tags" - echo "" - fi -} - - -# -# latest_git_version -# -# latest_git_version returns the highest semantic version -# number found in the repository, with the form "vX.Y.Z". -# Version numbers not matching the semver release format -# are ignored. -# -function latest_git_version() { - git tag -l | egrep "${semver_regex}" | sort -V | tail -1 -} - push_image_tags "$@" diff --git a/hack/image/push-manifest-list.sh b/hack/image/push-manifest-list.sh index 9b84ce8443e..b3af06942a3 100755 --- a/hack/image/push-manifest-list.sh +++ b/hack/image/push-manifest-list.sh @@ -28,12 +28,12 @@ function push_manifest_list() { } function get_arch_images(){ - image=$1; shift || fatal "${FUNCNAME} usage error" - tag=$1; shift || fatal "${FUNCNAME} usage error" - arches="$@" - for arch in $arches; do - echo "$image-$arch:$tag" - done + image=$1; shift || fatal "${FUNCNAME} usage error" + tag=$1; shift || fatal "${FUNCNAME} usage error" + arches="$@" + for arch in $arches; do + echo "$image-$arch:$tag" + done } push_manifest_list "$@" diff --git a/netlify.toml b/netlify.toml index b3fc59a5686..cf743111880 100644 --- a/netlify.toml +++ b/netlify.toml @@ -5,7 +5,13 @@ [build] publish = "public" base = "website" - command = "cd themes/docsy && git submodule update -f --init && cd ../.. && npm install postcss-cli autoprefixer@^9.0.0 && hugo version && hugo" + command = """ +git submodule update -f --init themes/docsy && \ +npm install postcss-cli autoprefixer@^9.0.0 && \ +./scripts/set_menu_version.sh && \ +hugo version && \ +hugo +""" # "production" environment specific build settings [build.environment] diff --git a/release.sh b/release.sh deleted file mode 100755 index cacff2da225..00000000000 --- a/release.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env bash - -set -eu - -if [[ $# != 1 ]]; then - echo "usage: $0 vX.Y.Z" - exit 1 -fi - -VER=$1 - -NUMRE="0|[1-9][0-9]*" -PRERE="\-(alpha|beta|rc)\.[1-9][0-9]*" - -if ! [[ "$VER" =~ ^v($NUMRE)\.($NUMRE)\.($NUMRE)($PRERE)?$ ]]; then - echo "malformed version: \"$VER\"" - exit 1 -fi - -if git ls-files --others --exclude-standard | grep -Ev 'build/operator-sdk-v.+'; then - echo "directory has untracked files" - exit 1 -fi - -if ! git diff-index --quiet HEAD --; then - echo "directory has uncommitted files" - exit 1 -fi - -GO_VER="1.15" -if ! go version | cut -d" " -f3 | grep -q "$GO_VER"; then - echo "must compile binaries with Go compiler version v${GO_VER}" - exit 1 -fi - -INSTALL_GUIDE_FILE="website/content/en/docs/installation/install-operator-sdk.md" -CURR_VER_INSTALL_GUIDE_FILE="$(sed -nr 's/.*RELEASE_VERSION=(.+)/\1/p' "$INSTALL_GUIDE_FILE" | tr -d ' \t\n')" -if [[ "$VER" != "$CURR_VER_INSTALL_GUIDE_FILE" ]]; then - echo "version '$VER' is not set correctly in $INSTALL_GUIDE_FILE" - exit 1 -fi - -# Tag the release commit and verify its tag. -git tag --sign --message "Operator SDK $VER" "$VER" -git verify-tag --verbose "$VER" - -# Run the release builds. -make release - -# Verify the signatures -for f in $(ls dist/*.asc); do gpg --verify $f; done diff --git a/release/Makefile b/release/Makefile index 0d748ed3c12..9d085684804 100644 --- a/release/Makefile +++ b/release/Makefile @@ -1,33 +1,60 @@ -## This Makefile should only be called from the project root ## +## This Makefile should only be called from the project root Makefile ## # Needed for glob expansion. SHELL = /bin/bash .SHELLFLAGS = -O extglob -c +# Dry run flags. ifneq ($(DRY_RUN),) -TAG ?= $(GIT_VERSION) +SNAPSHOT_FLAGS = --snapshot --skip-publish --rm-dist endif # Ensure that this Makefile is run from the project root (always contains the 'cmd/' directory). ifeq (,$(wildcard cmd)) -$(error "This Makefile must be invoked from the operator-sdk project root") + $(error "This Makefile must be invoked from the operator-sdk project root") endif -.PHONY: all -all: release +##@ Release -.PHONY: check_tag -check_tag: -ifeq ($(TAG),) - $(error "TAG must be set to a release tag") +.PHONY: release +release: ## Publish an operator-sdk release, with option for a dry run with DRY_RUN. +ifeq (,$(GIT_VERSION)) + $(error "GIT_VERSION must be set to a git tag") +endif + $(SCRIPTS_DIR)/fetch goreleaser 0.147.2 + GORELEASER_CURRENT_TAG=$(GIT_VERSION) $(TOOLS_DIR)/goreleaser $(SNAPSHOT_FLAGS) --release-notes=changelog/generated/$(GIT_VERSION).md --parallelism 5 + +##@ Pre-Release + +.PHONY: check_release_version +check_release_version: +ifeq (,$(RELEASE_VERSION)) + $(error "RELEASE_VERSION must be set to a release tag") endif +.PHONY: prerelease +prerelease: check_release_version changelog ## Create release commit changes to commit. + ./website/scripts/update_branch_mappings.sh $(RELEASE_VERSION) + .PHONY: changelog -changelog: check_tag ## Generate the changelog. - go run ./release/changelog/gen-changelog.go -tag=$(TAG) -changelog=CHANGELOG.md -ifeq ($(DRY_RUN),) +changelog: check_release_version ## Generate the changelog. + @mkdir -p changelog/generated && rm -f changelog/generated/$(RELEASE_VERSION).md + go run ./release/changelog/gen-changelog.go -tag=$(RELEASE_VERSION) -changelog=changelog/generated/$(RELEASE_VERSION).md rm -f ./changelog/fragments/!(00-template.yaml) + +.PHONY: tag +VERSION_REGEXP := ^v[0-9]+\.[0-9]+\.[0-9]+(\-(alpha|beta|rc)\.[0-9]+)?$ +tag: ## Create a release tag. +ifeq (,$(RELEASE_VERSION)) + $(error "RELEASE_VERSION must be set to tag HEAD") endif +ifeq (,$(shell [[ "$(RELEASE_VERSION)" =~ $(VERSION_REGEXP) ]] && echo 1)) + $(error "Version $(RELEASE_VERSION) must match regexp $(VERSION_REGEXP)") +endif + git tag --sign --message "Operator SDK $(RELEASE_VERSION)" $(RELEASE_VERSION) + git verify-tag --verbose $(RELEASE_VERSION) + +##@ Image deploy # Convenience wrappers for pushing all remotely hosted images. .PHONY: image-push image-push-multiarch @@ -51,60 +78,11 @@ image-push-multiarch/%: IMAGE_PUSH_TAG = $(IMAGE_REPO)/$* image-push-multiarch/%: ./hack/image/push-manifest-list.sh $(IMAGE_PUSH_TAG) $(ARCHES) -# Build/install/release the SDK. -release_builds := \ - dist/operator-sdk-$(GIT_VERSION)-aarch64-linux-gnu \ - dist/operator-sdk-$(GIT_VERSION)-x86_64-linux-gnu \ - dist/operator-sdk-$(GIT_VERSION)-x86_64-apple-darwin \ - dist/operator-sdk-$(GIT_VERSION)-ppc64le-linux-gnu \ - dist/operator-sdk-$(GIT_VERSION)-s390x-linux-gnu \ - dist/ansible-operator-$(GIT_VERSION)-aarch64-linux-gnu \ - dist/ansible-operator-$(GIT_VERSION)-x86_64-linux-gnu \ - dist/ansible-operator-$(GIT_VERSION)-x86_64-apple-darwin \ - dist/ansible-operator-$(GIT_VERSION)-ppc64le-linux-gnu \ - dist/ansible-operator-$(GIT_VERSION)-s390x-linux-gnu \ - dist/helm-operator-$(GIT_VERSION)-aarch64-linux-gnu \ - dist/helm-operator-$(GIT_VERSION)-x86_64-linux-gnu \ - dist/helm-operator-$(GIT_VERSION)-x86_64-apple-darwin \ - dist/helm-operator-$(GIT_VERSION)-ppc64le-linux-gnu \ - dist/helm-operator-$(GIT_VERSION)-s390x-linux-gnu - -.PHONY: release -release: $(release_builds) $(release_builds:=.asc) ## Release the Operator SDK - -dist/operator-sdk-%-aarch64-linux-gnu: GOARGS = GOOS=linux GOARCH=arm64 -dist/operator-sdk-%-x86_64-linux-gnu: GOARGS = GOOS=linux GOARCH=amd64 -dist/operator-sdk-%-x86_64-apple-darwin: GOARGS = GOOS=darwin GOARCH=amd64 -dist/operator-sdk-%-ppc64le-linux-gnu: GOARGS = GOOS=linux GOARCH=ppc64le -dist/operator-sdk-%-s390x-linux-gnu: GOARGS = GOOS=linux GOARCH=s390x - -dist/ansible-operator-%-aarch64-linux-gnu: GOARGS = GOOS=linux GOARCH=arm64 -dist/ansible-operator-%-x86_64-linux-gnu: GOARGS = GOOS=linux GOARCH=amd64 -dist/ansible-operator-%-x86_64-apple-darwin: GOARGS = GOOS=darwin GOARCH=amd64 -dist/ansible-operator-%-ppc64le-linux-gnu: GOARGS = GOOS=linux GOARCH=ppc64le -dist/ansible-operator-%-s390x-linux-gnu: GOARGS = GOOS=linux GOARCH=s390x - -dist/helm-operator-%-aarch64-linux-gnu: GOARGS = GOOS=linux GOARCH=arm64 -dist/helm-operator-%-x86_64-linux-gnu: GOARGS = GOOS=linux GOARCH=amd64 -dist/helm-operator-%-x86_64-apple-darwin: GOARGS = GOOS=darwin GOARCH=amd64 -dist/helm-operator-%-ppc64le-linux-gnu: GOARGS = GOOS=linux GOARCH=ppc64le -dist/helm-operator-%-s390x-linux-gnu: GOARGS = GOOS=linux GOARCH=s390x - -dist/%: ## Build the operator-sdk release binaries - { \ - cmdpkg=$$(echo $* | sed -E "s/(operator-sdk|ansible-operator|helm-operator).*/\1/"); \ - $(GOARGS) go build $(GO_BUILD_ARGS) -o $@ ./cmd/$$cmdpkg; \ - } - -dist/%.asc: ## Create release signatures for operator-sdk release binaries - { \ - default_key=$$(gpgconf --list-options gpg | awk -F: '$$1 == "default-key" { gsub(/"/,""); print toupper($$10)}'); \ - git_key=$$(git config --get user.signingkey | awk '{ print toupper($$0) }'); \ - if [ "$${default_key}" = "$${git_key}" ]; then \ - gpg --output $@ --detach-sig dist/$*; \ - gpg --verify $@ dist/$*; \ - else \ - echo "git and/or gpg are not configured to have default signing key $${default_key}"; \ - exit 1; \ - fi; \ - } +.DEFAULT_GOAL := help +.PHONY: help +help: ## Show this help screen. + @echo 'Usage: make ... ' + @echo '' + @echo 'Available targets are:' + @echo '' + @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z0-9_-]+:.*?##/ { printf " \033[36m%-25s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) diff --git a/tools/scripts/fetch b/tools/scripts/fetch index 577cf0d7d77..a6d5873f23c 100755 --- a/tools/scripts/fetch +++ b/tools/scripts/fetch @@ -34,6 +34,10 @@ fetch() { ver_cmd="cat ${DEST}/.envtest_version 2>/dev/null" fetch_cmd="(test -f ${DEST}/setup-envtest.sh || curl -sSLo ${DEST}/setup-envtest.sh https://raw.githubusercontent.com/kubernetes-sigs/controller-runtime/v${ver}/hack/setup-envtest.sh) && (source ${DEST}/setup-envtest.sh; fetch_envtest_tools ${DEST}/../) && echo ${ver} > ${DEST}/.envtest_version" ;; + "goreleaser") + ver_cmd="${DEST}/goreleaser --version 2>/dev/null | grep version | cut -d' ' -f3" + fetch_cmd="curl -sSfL https://install.goreleaser.com/github.com/goreleaser/goreleaser.sh | sh -s -- -b \"${DEST}\" -d \"v${ver}\"" + ;; *) echo "unknown tool $tool" return 1 diff --git a/website/config.toml b/website/config.toml index 4fb81698b8f..4a5943b1ae6 100644 --- a/website/config.toml +++ b/website/config.toml @@ -94,6 +94,8 @@ algolia_docsearch = false version = "Latest Release" url = "https://sdk.operatorframework.io" +##RELEASE_ADDME## + [[params.versions]] version = "v1.2" url = "https://v1-2-x.sdk.operatorframework.io" diff --git a/website/content/en/docs/contribution-guidelines/developer-guide.md b/website/content/en/docs/contribution-guidelines/developer-guide.md index d84300f46bf..fa07d2d4eed 100644 --- a/website/content/en/docs/contribution-guidelines/developer-guide.md +++ b/website/content/en/docs/contribution-guidelines/developer-guide.md @@ -55,22 +55,6 @@ as an environment variable in `.travis.yml`, ex. `export SCORECARD_TEST_IMAGE= Branches` in the SDK repo. + 1. Under `Branch protection rules`, click `Edit` on the `master` branch rule. + 1. In section `Protect matching branches` of the `Rule settings` box, increase the number of required approving reviewers to 6. -Make sure you've [uploaded your GPG key][link-github-gpg-key-upload] and configured git to [use that signing key][link-git-config-gpg-key] either globally or for the Operator SDK repository. Tagging will be handled by `release.sh`. +### 1. Create and push a release commit -**Note:** the email the key is issued for must be the email you use for git. +Create a new branch to push the release commit: ```sh -$ git config [--global] user.signingkey "$GPG_KEY_ID" -$ git config [--global] user.email "$GPG_EMAIL" +git checkout master +git pull +git checkout -b release-v1.3.0 ``` -Also, make sure that you setup the git gpg config as follows. -```console -$ cat ~/.gnupg/gpg.conf -default-key $GPG_KEY_ID -``` +Run the pre-release `make` target: -**NOTE** If you do a release from an OSX machine, you need to configure `gnu-gpg` to sign the release's tag: -- Install the requirements by running: `brew install gpg2 gnupg pinentry-mac` -- Append the following to your ~/.bash_profile or ~/.bashrc or ~/.zshrc -```sh -export GPG_TTY=`tty` -``` -- Restart your Terminal or source your ~/.\*rc file -- Then, make sure git uses gpg2 and not gpg -```sh -$ git config --global gpg.program gpg2 -``` -- To make sure gpg2 itself is working ```sh -$ echo "test" | gpg2 --clearsign +make prerelease RELEASE_VERSION=v1.3.0 ``` -## Release branches - -Each minor release has a corresponding release branch of the form `vX.Y.x`, where `X` and `Y` are the major and minor -release version numbers and the `x` is literal. This branch accepts bug fixes according to our [backport policy][backports]. - -After the minor release is made, this branch must be fast-forwarded to that release's tag and a post-release PR made -against this branch. See the [release process](#8-create-a-pr-for-post-release-version-updates) for more details. +The following changes should be present: -#### Cherry-picking +- `changelog/generated/v1.3.0.md`: commit changes (created by changelog generation). +- `changelog/fragments/*`: commit deleted fragment files (deleted by changelog generation). +- `website/content/en/docs/upgrading-sdk-version/v1.3.0.md`: commit changes (created by changelog generation). +- `website/config.toml`: commit changes (modified by release script). -Once a minor release is complete, bug fixes can be merged into the release branch for the next patch release. -Fixes can be added automatically by posting a `/cherry-pick v1.3.x` comment in the `master` PR, or manually by running: +Commit these changes and push: ```sh -$ git checkout v1.3.x -$ git checkout -b cherrypick/some-bug -$ git cherry-pick "$GIT_COMMIT_HASH" # Hash of the merge commit to master. -$ git push upstream cherrypick/some-bug +git add --all +git commit -m "Release v1.3.0" +git push -u origin release-v1.3.0 ``` -Create and merge a PR from your branch to `v1.3.x`. +### 2. Create and merge a new PR -## GitHub release information +Create and merge a new PR for the commit created in step 1. You can force-merge your PR to the locked-down `master` +if you have admin access to the operator-sdk repo, or ask an administrator to do so. -### Locking down branches +### 3. Unlock the `master` branch -Once a release PR has been made and all tests pass, the SDK's `master` branch, or [release branch](#release-branches) for patch releases, -should be locked so commits cannot happen between the release PR and release tag push. To lock down a branch: +Unlock the branch by changing the number of required approving reviewers in the `master` branch rule back to 1. -1. Go to `Settings -> Branches` in the SDK repo. -1. Under `Branch protection rules`, click `Edit` on the `master` or release branches rule. -1. In section `Protect matching branches` of the `Rule settings` box, increase the number of required approving reviewers to its maximum allowed value. - -Now only administrators (maintainers) should be able to force merge PRs. Make sure everyone in the relevant Slack channel is aware of the release so they do not force merge by accident. - -Unlock `master` or release branch after the release has completed (after step 6 is complete) by changing the number of required approving reviewers back to 1. - -### Releasing - -The GitHub [`Releases` tab][release-page] in the operator-sdk repo is where all SDK releases live. -To create a GitHub release see the [releasing binaries section](#9-releasing-binaries-signatures-and-release-notes). - -#### Release notes - -GitHub release notes should thoroughly describe changes made to code, documentation, and design of the SDK. PR links should be included wherever possible. - -The following sections, often directly copied from our [changelog][doc-changelog], are used as release notes: - -```Markdown -[Version as title, ex. v1.2.3] - -### Added -- [Short description of feature added] (#PR) -... - -### Changed -- [Short description of change made] (#PR) -... - -### Deprecated -- [Short description of feature deprecated] (#PR) -... - -### Removed -- [Short description of feature removed] (#PR) -... - -### Bug Fixes -- [Short description of bug and fix] (#PR) -... -``` - -## Release Signing - -When a new release is created, the tag for the commit it signed with a maintainers' gpg key and -the binaries for the release are also signed by the same key. All keys used by maintainers will -be available via public PGP keyservers such as pool.sks-keyservers.net. - -For new maintainers who have not done a release and do not have their PGP key on a public -keyserver, output your armored public key using this command: +### 4. Create and push a release tag ```sh -$ gpg --armor --export "$GPG_EMAIL" > mykey.asc +make tag RELEASE_VERSION=v1.3.0 +git push upstream v1.3.0 ``` -Then, copy and paste the content of the outputted file into the `Submit a key` section on -pool.sks-keyservers.net or any other public keyserver that synchronizes -the key to other public keyservers. Once that is done, other people can download your public -key and you are ready to sign releases. - -## Verifying a release +### 5. Fast-forward the `latest` and release branches -To verify a git tag, use this command: +The `latest` branch points to the latest release tag to keep the main website subdomain up-to-date. +Run the following commands to do so: ```sh -$ git verify-tag --verbose "$TAG_NAME" -``` - -If you do not have the mantainers public key on your machine, you will get an error message similiar to this: - -```console -$ git verify-tag --verbose "$TAG_NAME" -object 61e0c23e9d2e217f8d95ac104a8f2545c102b5c3 -type commit -tag v0.6.0 -tagger Ish Shah 1552688145 -0700 - -Operator SDK v0.6.0 -gpg: Signature made Fri Mar 15 23:15:45 2019 CET -gpg: using RSA key -gpg: Can't check signature: No public key +git checkout latest +git reset --hard tags/v1.3.0 +git push -f upstream latest ``` -To download the key, use the following command, replacing `$KEY_ID` with the RSA key string provided in the output of the previous command: +Similarly, to update the release branch, run: ```sh -$ gpg --recv-key "$KEY_ID" +git checkout v1.3.x +git reset --hard tags/v1.3.0 +git push -f upstream v1.3.x ``` -To verify a release binary using the provided asc files see the [installation guide.][install-guide] - -## Release steps - -These steps describe how to conduct a release of the SDK, upgrading from `v1.2.0` to `v1.3.0`. -Replace these versions with the current and new version you are releasing, respectively. - -For major and minor releases, `master` should be locked between steps 3 and 6 so that all commits will be either in the new release -or have a pre-release version, ex. `v1.2.0+git`. Otherwise commits might be built into a release that shouldn't be. -For patch releases, ensure all required bugs are [cherry-picked](#cherry-picking), then the release branch `v1.3.x` should be locked down. +### 6. Post release steps -### 1. Update OLM bindata +- Make an [operator-framework Google Group][of-ggroup] post. +- Post to Kubernetes slack in #kubernetes-operators and #operator-sdk-dev. +- In the [GitHub milestone][gh-milestones], bump any open issues to the following release. -This step is to be preferably performed only during major releases. Update the `OLM_VERSION` variable in Makefile to the latest successful release of OLM. Run `make bindata` so that `internal/bindata/olm` is updated. Also, update the `availableVersions` map in `internal/bindata/olm/versions.go` to contain the version of OLM which you have specified in the Makefile. -Submit a PR with the changes and merge it with master. +## Patch releases -**Important:** -- Update OLM bindata just before starting the release so that we have the latest OLM version. -- Verify that the release of OLM version which you specify in Makefile is successful. +We will use the `v1.3.1` release version in this example. -### 2. Netlify configuration +### Before starting -**Important:** ensure a release branch-to-subdomain mapping exists in the SDK's Netlify configuration _prior to creating a release_, -ex. `v1.3.x` to `https://v1-3-x.sdk.operatorframework.io`. You can ping SDK [approvers][doc-owners] to ensure a -[release branch](#release-branches) is created prior to the release and that this mapping is created. - -### 3. Create release branch for Netlify +1. Create and merge a commit that updates the top-level [Makefile] variable `IMAGE_VERSION` +to the upcoming release tag `v1.3.1`. This variable ensures sample projects have been tagged +correctly prior to the release commit. -The release branch must be created before the release occurs to appease the Netlify website configuration demons. -You can do so by running the following before proceeding with the release, assuming the upstream SDK is the `upstream` remote repo: + ```sh + sed -i -E 's/(IMAGE_VERSION = ).+/\1v1\.3\.1/g' Makefile + ``` -```sh -$ git checkout master -$ git pull -$ git checkout -b v1.3.x -$ git push -u upstream v1.3.x -``` +1. Lock down the `v1.3.x` branch to prevent further commits before the release completes: + 1. Go to `Settings -> Branches` in the SDK repo. + 1. Under `Branch protection rules`, click `Edit` on the `v.*` branch rule. + 1. In section `Protect matching branches` of the `Rule settings` box, increase the number of required approving reviewers to 6. -### 4. Create a PR for release version, CHANGELOG.md, and migration guide updates +### 1. Create and push a release commit -Once all PR's needed for a release have been merged, branch from `master`: +Create a new branch from the release branch, which should already exist for the desired minor version, +to push the release commit to: ```sh -$ git checkout master -$ git pull +git checkout v1.3.x +git pull +git checkout -b release-v1.3.1 ``` -If making a patch release, check out the corresponding minor version branch: +Run the pre-release `make` target: ```sh -$ git checkout v1.2.x -$ git pull +make prerelease RELEASE_VERSION=v1.3.1 ``` -Create a new branch to push release commits: +The following changes should be present: -```sh -$ git checkout -b release-v1.3.0 -``` +- `changelog/generated/v1.3.0.md`: commit changes (created by changelog generation). +- `changelog/fragments/*`: commit deleted fragment files (deleted by changelog generation). -Run the CHANGELOG and migration guide generator: +Commit these changes and push: ```sh -$ GEN_CHANGELOG_TAG=v1.3.0 make changelog +git add --all +git commit -m "Release v1.3.1" +git push -u origin release-v1.3.1 ``` -Commit the following changes: - -- `website/content/en/docs/installation/install-operator-sdk.md`: update the linux and macOS URLs to point to the new release URLs. -- `CHANGELOG.md`: commit changes (updated by changelog generation). -- `website/content/en/docs/upgrading-sdk-version/v1.3.0.md`: commit changes (created by changelog generation). -- `changelog/fragments/*`: commit deleted fragment files (deleted by changelog generation). -- **(Major and minor releases only)** `website/config.toml`: update `version_menu = "Releases"` with the patch-less version string `version_menu = "v1.3"`, -and add the following lines under `[[params.versions]]` for `master`: - ```toml - [[params.versions]] - version = "v1.3" - url = "https://v1-3-x.sdk.operatorframework.io" - ``` - -### 5. Lock down proper branch -Create and merge a new PR for `release-v1.3.0`. Once this PR is merged, lock down the master or release branch -to prevent further commits between this and step 7. See [this section](#locking-down-branches) for steps to do so. +### 2. Create and merge a new PR -### 6. Create a release tag, binaries, and signatures +Create and merge a new PR for the commit created in step 1. You can force-merge your PR to the locked-down `v1.3.x` +if you have admin access to the operator-sdk repo, or ask an administrator to do so. -The top-level `release.sh` script will take care of verifying versions in files described in step 3, and tagging and verifying the tag, as well as building binaries and generating signatures by calling `make release`. +### 3. Unlock the `v1.3.x` branch -Prerequisites: -- [`git`][doc-git-default-key] and [`gpg`][doc-gpg-default-key] default PGP keys are set locally. -- Your PGP key is publicly available in a [public key server](#release-signing). -- _For macOS users:_ GNU `sed` and `make` which are not installed by default. Install them with - ```sh - $ brew install gnu-sed make - ``` - then ensure they are present in your `$PATH`. +Unlock the branch by changing the number of required approving reviewers in the `v.*` branch rule back to 1. -Call the script with the only argument being the new SDK version: +### 4. Create and push a release tag ```sh -$ ./release.sh v1.3.0 +make tag RELEASE_VERSION=v1.3.1 +git push upstream v1.3.1 ``` -`operator-sdk` release binaries and signatures will be in `dist/`. Both binary and signature file names contain version, architecture, -and platform information; signature file names correspond to the binary they were generated from suffixed with `.asc`. -For example, signature file `operator-sdk-v1.3.0-x86_64-apple-darwin.asc` was generated from a binary named `operator-sdk-v1.3.0-x86_64-apple-darwin`. -To verify binaries and tags, see the [verification section](#verifying-a-release). - - -`ansible-operator` and `helm-operator` release binaries and signatures are similarly built for upload so `make run` -can download them in their respective operator type projects. See [#3327](https://github.com/operator-framework/operator-sdk/issues/3327) for details. - -Push tag `v1.3.0` upstream, assuming `upstream` is the name of the upstream remote: - -```sh -$ git push upstream v1.3.0 -``` - -Once this tag passes CI, go to step 6. For more info on tagging, see the [release tags section](#release-tags). - -**Note:** If CI fails for some reason, you will have to revert the tagged commit, re-commit, and make a new PR. - -### 7. Fast-forward the `latest` and release branches +### 5. Fast-forward the `latest` branch The `latest` branch points to the latest release tag to keep the main website subdomain up-to-date. Run the following commands to do so: ```sh -$ git checkout latest -$ git reset --hard tags/v1.3.0 -$ git push -f upstream latest +git checkout latest +git reset --hard tags/v1.3.1 +git push -f upstream latest ``` -Similarly, to update the release branch, run: - -```sh -$ git checkout v1.3.x -$ git reset --hard tags/v1.3.0 -$ git push -f upstream v1.3.x -``` - -### 8. Create a PR for post-release version updates +### 6. Post release steps -Check out a new branch from `master` or release branch and commit the following changes: +- Make an [operator-framework Google Group][of-ggroup] post. +- Post to Kubernetes slack in #kubernetes-operators and #operator-sdk-dev. +- In the [GitHub milestone][gh-milestones], bump any open issues to the following release. -- **(Major and minor releases only)** `website/config.toml`: update `version_menu = "v1.3"` to `version_menu = "Releases"`. ---- +## Further reading -Create a new PR for this branch targeting the `master` or release branch. +### Binaries and signatures -### 9. Releasing binaries, signatures, and release notes +Binaries will be signed using our CI system's GPG key. Both binary and signature will be uploaded to the release. -The final step is to upload binaries, their signature files, and release notes from `CHANGELOG.md` for `v1.3.0`. -To create a GitHub release: +### Release branches -1. Go to the SDK [`Releases` tab][release-page] and click the `Draft a new release` button in the top right corner. -1. Select the tag version `v1.3.0`, and set the title to `v1.3.0`. -1. Copy and paste `CHANGELOG.md` updates under the `v1.3.0` header into the description form (see [below](#release-notes)). -1. Attach all binaries and `.asc` signature files to the release by dragging and dropping them. -1. Click the `Publish release` button. - -**Note:** if this is a pre-release, make sure to check the `This is a pre-release` box under the file attachment frame. If you are not sure what this means, ask another maintainer. +Each minor release has a corresponding release branch of the form `vX.Y.x`, where `X` and `Y` are the major and minor +release version numbers and the `x` is literal. This branch accepts bug fixes according to our [backport policy][backports]. -### 10. Unlock proper branch -Unlock the `master` or release branch after the Github release is complete. -See [this section](#locking-down-branches) for steps to do so. +##### Cherry-picking -### 11. Announce the release +Once a minor release is complete, bug fixes can be merged into the release branch for the next patch release. +Fixes can be added automatically by posting a `/cherry-pick v1.3.x` comment in the `master` PR, or manually by running: -Send an email to the [mailing list][mailing-list] -Post to Kubernetes slack in #kubernetes-operators and #operator-sdk-dev. +```sh +git checkout v1.3.x +git checkout -b cherrypick/some-bug +git cherry-pick +git push upstream cherrypick/some-bug +``` -### 12. Bump open issues to the next release. +Create and merge a PR from your branch to `v1.3.x`. -In the [GitHub milestone][gh-milestones], bump any open issues to the -following release. +### GitHub release information ---- +GitHub releases live under the [`Releases` tab][release-page] in the operator-sdk repo. -You've now fully released a new version of the Operator SDK. Good work! -[install-guide]: /docs/installation/ -[doc-maintainers]: https://github.com/operator-framework/operator-sdk/blob/master/MAINTAINERS +[git]:https://git-scm.com/downloads +[gpg]:https://gnupg.org/download/ +[gpg-key-create]:https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/managing-commit-signature-verification +[gpg-upload]:https://www.gnupg.org/gph/en/manual/x457.html +[netlify-deploy]:https://docs.netlify.com/site-deploys/overview/#deploy-summary [doc-owners]: https://github.com/operator-framework/operator-sdk/blob/master/OWNERS -[doc-readme-prereqs]: /docs/installation/#prerequisites-for-compilation -[doc-git-default-key]:https://help.github.com/en/articles/telling-git-about-your-signing-key -[doc-gpg-default-key]:https://lists.gnupg.org/pipermail/gnupg-users/2001-September/010163.html -[link-github-gpg-key-upload]:https://github.com/settings/keys -[link-git-config-gpg-key]:https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work -[doc-changelog]: https://github.com/operator-framework/operator-sdk/blob/master/CHANGELOG.md -[backports]:/docs/upgrading-sdk-version/backport-policy [release-page]:https://github.com/operator-framework/operator-sdk/releases -[homebrew]:https://brew.sh/ -[homebrew-formula]:https://github.com/Homebrew/homebrew-core/blob/master/Formula/operator-sdk.rb -[homebrew-readme]:https://github.com/Homebrew/homebrew-core/blob/master/CONTRIBUTING.md#to-submit-a-version-upgrade-for-the-foo-formula -[homebrew-repo]:https://github.com/Homebrew/homebrew-core -[sdk-samples-repo]:https://github.com/operator-framework/operator-sdk-samples -[mailing-list]:https://groups.google.com/g/operator-framework +[backports]:/docs/upgrading-sdk-version/backport-policy +[of-ggroup]:https://groups.google.com/g/operator-framework [gh-milestones]:https://github.com/operator-framework/operator-sdk/milestones +[Makefile]:https://github.com/operator-framework/operator-sdk/blob/master/Makefile diff --git a/website/content/en/docs/contribution-guidelines/testing.md b/website/content/en/docs/contribution-guidelines/testing.md index 742785ba6cf..bce6c72a22e 100644 --- a/website/content/en/docs/contribution-guidelines/testing.md +++ b/website/content/en/docs/contribution-guidelines/testing.md @@ -15,6 +15,23 @@ Cluster tests consist of several test types: bound to external projects, such as [OLM][olm]. - Subcommand: ensure individual subcommands function as intended with a variety of input options. +## Before submitting a PR + +Always run tests before submitting a PR to reduce the number of needless CI errors. + +##### Docs only + +```sh +make test-static +``` + +##### Code + +```sh +make test-all +``` + + ## Local Test Environment If running tests locally, access to a Kubernetes cluster of server version v1.11.3 or higher is required. @@ -25,18 +42,10 @@ for setup instructions. ### Local clusters -Two options for testing with a local cluster are [minikube][minikube] and [kind][kind]. -Ensure `KUBECONFIG` is set correctly for the chosen cluster type. +A local [kind][kind] cluster is used for running tests. ## Running Tests -On any PR, the entire test suite is run against your changes in a CI environment. -Therefore it is advantageous to run all tests before pushing changes to the remote repo: - -```sh -make test-sanity test-links test-unit test-subcommand test-integration test-e2e -``` - All the tests are run through the [`Makefile`][makefile]. Run `make help` for a full list of available tests. [unit-tests]: https://onsi.github.io/gomega/ diff --git a/website/content/en/docs/installation/_index.md b/website/content/en/docs/installation/_index.md index 82ae5658797..5b8f7ccbdd0 100644 --- a/website/content/en/docs/installation/_index.md +++ b/website/content/en/docs/installation/_index.md @@ -1,99 +1,91 @@ --- -title: "Installation" -linkTitle: "Installation" -date: 2020-03-25 +title: Installation +linkTitle: Installation weight: 2 description: Install the Operator SDK CLI --- -- [Prerequisites](#prerequisites) - [Install from Homebrew (macOS)](#install-from-homebrew-macos) - [Install from GitHub release](#install-from-github-release) - [Compile and install from master](#compile-and-install-from-master) -## Prerequisites - -- [docker][docker-tool] version 17.03+ (or another tool compatible with multi-stage Dockerfiles). -- [kubectl][kubectl-tool] version v1.11.3+ (v1.16.0+ if using `apiextensions.k8s.io/v1` CRDs). - -[docker-tool]:https://docs.docker.com/install/ -[kubectl-tool]:https://kubernetes.io/docs/tasks/tools/install-kubectl/ - ## Install from Homebrew (macOS) If you are using [Homebrew][homebrew_tool], you can install the SDK CLI tool with the following command: ```sh -$ brew install operator-sdk +brew install operator-sdk ``` ## Install from GitHub release -### Download the release binaries +#### Prerequisites + +- [curl](https://curl.haxx.se/) +- [gpg](https://gnupg.org/) version 2.0+ + +#### 1. Download the release binary + +Set platform information: ```sh -# Set the release version variable -$ RELEASE_VERSION=v1.2.0 -# Linux -$ curl -LO https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu -# macOS -$ curl -LO https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin +export ARCH=$(case $(arch) in x86_64) echo -n amd64 ;; aarch64) echo -n arm64 ;; *) echo -n $(arch) ;; esac) +export OS=$(uname | awk '{print tolower($0)}') ``` -#### Verify the downloaded release binaries +Download the binary for your platform: ```sh -# Linux -$ curl -LO https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu.asc -# macOS -$ curl -LO https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin.asc +export OPERATOR_SDK_DL_URL=https://github.com/operator-framework/operator-sdk/releases/latest/download +curl -LO ${OPERATOR_SDK_DL_URL}/operator-sdk_${OS}_${ARCH} ``` -To verify a release binary using the provided asc files, place the binary and corresponding asc file into the same directory and use the corresponding command: +#### 2. Verify the downloaded binary + +Import the operator-sdk release GPG key: ```sh -# Linux -$ gpg --verify operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu.asc -# macOS -$ gpg --verify operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin.asc +gpg --recv-keys 052996E2A20B5C7E ``` -If you do not have the maintainers public key on your machine, you will get an error message similar to this: +Download the checksums file and its signature, then verify the signature: ```sh -$ gpg --verify operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin.asc -$ gpg: assuming signed data in 'operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin' -$ gpg: Signature made Fri Apr 5 20:03:22 2019 CEST -$ gpg: using RSA key -$ gpg: Can't check signature: No public key +curl -LO ${OPERATOR_SDK_DL_URL}/checksums.txt +curl -LO ${OPERATOR_SDK_DL_URL}/checksums.txt.asc +gpg -u "Operator SDK (release) " --verify checksums.txt.asc ``` -To download the key, use the following command, replacing `$KEY_ID` with the RSA key string provided in the output of the previous command: +You should see something similar to the following: -```sh -$ gpg --recv-key "$KEY_ID" +```console +gpg: assuming signed data in 'checksums.txt' +gpg: Signature made Fri 30 Oct 2020 12:15:15 PM PDT +gpg: using RSA key ADE83605E945FA5A1BD8639C59E5B47624962185 +gpg: Good signature from "Operator SDK (release) " [ultimate] ``` -You'll need to specify a key server if one hasn't been configured. For example: +Make sure the checksums match: ```sh -$ gpg --keyserver keyserver.ubuntu.com --recv-key "$KEY_ID" +grep operator-sdk_${OS}_${ARCH} checksums.txt | sha256sum -c - ``` -Now you should be able to verify the binary. +You should see something similar to the following: + +```console +operator-sdk_linux_amd64: OK +``` -### Install the release binary in your PATH +#### 3. Install the release binary in your PATH ```sh -# Linux -$ chmod +x operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu && sudo mkdir -p /usr/local/bin/ && sudo cp operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu /usr/local/bin/operator-sdk && rm operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu -# macOS -$ chmod +x operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin && sudo mkdir -p /usr/local/bin/ && sudo cp operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin /usr/local/bin/operator-sdk && rm operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin +chmod +x operator-sdk_${OS}_${ARCH} && sudo mv operator-sdk_${OS}_${ARCH} /usr/local/bin/operator-sdk ``` ## Compile and install from master -### Prerequisites for compilation +#### Prerequisites - [git][git_tool] - [mercurial][mercurial_tool] version 3.9+ @@ -101,14 +93,14 @@ $ chmod +x operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin && sudo mkdir -p - [go][go_tool] version v1.15+. ```sh -$ git clone https://github.com/operator-framework/operator-sdk -$ cd operator-sdk -$ git checkout master -$ make install +git clone https://github.com/operator-framework/operator-sdk +cd operator-sdk +git checkout master +make install ``` **Note:** Ensure that your `GOPROXY` is set with its default value for Go -versions 1.15+ which is `https://proxy.golang.org,direct`. +versions 1.15+ which is `"https://proxy.golang.org|direct"`. [homebrew_tool]:https://brew.sh/ [git_tool]:https://git-scm.com/downloads diff --git a/website/scripts/set_menu_version.sh b/website/scripts/set_menu_version.sh new file mode 100755 index 00000000000..a326725d9eb --- /dev/null +++ b/website/scripts/set_menu_version.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +# This script updates the hugo config's "version_menu" param +# to the current ${MAJOR}.${MINOR} string. + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" +CONFIG_PATH="${DIR}/../config.toml" + +BRANCH_NAME="$(git rev-parse --abbrev-ref HEAD)" +if [[ "$BRANCH_NAME" =~ v[0-9]+\.[0-9]+\.x ]]; then + VERSION_MENU="$(echo $BRANCH_NAME | awk -F. '{ print v$1"."$2 }')" + sed -i -E 's/version_menu = ".+"/version_menu = "'${VERSION_MENU}'"/g' "$CONFIG_PATH" + + # Ensure config.toml was updated. + if ! grep -q "version_menu = \"${VERSION_MENU}\"" "$CONFIG_PATH"; then + echo "$0 failed to update config.toml" + exit 1 + fi +fi diff --git a/website/scripts/update_branch_mappings.sh b/website/scripts/update_branch_mappings.sh new file mode 100755 index 00000000000..17ad9e6f070 --- /dev/null +++ b/website/scripts/update_branch_mappings.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +# This script writes a branch-to-subdomain mapping for the previously created +# release branch to the hugo config. This change should be committed in the prerelease commit. + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" +CONFIG_PATH="${DIR}/../config.toml" + +VERSION="${1?"A Version is required"}" +VERSION_PATCHLESS="$(echo $VERSION | awk -F. '{ print v$1"."$2 }')" +VERSION_X_DOMAIN="$(echo $VERSION | awk -F. '{ print v$1"-"$2"-x" }')" + +if grep -C 1 "\[\[params\.versions\]\]" website/config.toml | grep -q "version = \"${VERSION_PATCHLESS}\""; then + echo "Version mapping ${VERSION_PATCHLESS} already exists, skipping" + exit 0 +fi + +MARKER="##RELEASE_ADDME##" +PARAMS_VERSION="[[params.versions]]\\n version = \"${VERSION_PATCHLESS}\"\\n url = \"https://${VERSION_X_DOMAIN}.sdk.operatorframework.io\"" + +sed -i -E $'s@'${MARKER}'@'"${MARKER}\\n\\n${PARAMS_VERSION}"'@g' "$CONFIG_PATH" + +# Ensure config.toml was updated. +if ! grep -q "url = \"https://${VERSION_X_DOMAIN}.sdk.operatorframework.io\"" "$CONFIG_PATH"; then + echo "$0 failed to update config.toml" + exit 1 +fi From 0d4f76064e67768441727f91db84b8d60b7a2523 Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Tue, 1 Dec 2020 08:30:21 -0800 Subject: [PATCH 224/376] .github/workflows: skip e2e/integration tests when PR is docs-only (#4266) Signed-off-by: reinvantveer --- .github/workflows/integration.yml | 16 ++++++++++++++++ .../workflows/markdown-link-check-config.json | 2 +- .github/workflows/markdown.yml | 17 ----------------- .github/workflows/test-ansible.yml | 18 ++++++++++++++++++ .github/workflows/test-go.yml | 18 ++++++++++++++++++ .github/workflows/test-helm.yml | 16 ++++++++++++++++ .github/workflows/test-sanity.yml | 4 ++++ .travis.yml | 2 +- hack/ci/check-doc-only-update.sh | 13 ++++++------- 9 files changed, 80 insertions(+), 26 deletions(-) delete mode 100644 .github/workflows/markdown.yml diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 1e216c12574..629a1983957 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -3,9 +3,25 @@ on: pull_request: {} jobs: + check_docs_only: + name: check_docs_only + runs-on: ubuntu-18.04 + outputs: + should_skip_tests: ${{ steps.check_docs_only.outputs.skip-tests }} + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - id: check_docs_only + run: | + REPO_MASTER_REF=$(git show-ref ${{ github.base_ref }} | head -1 | cut -d' ' -f2) + echo "::set-output name=skip-tests::$(hack/ci/check-doc-only-update.sh $REPO_MASTER_REF)" + integration: name: integration runs-on: ubuntu-18.04 + needs: check_docs_only + if: needs.check_docs_only.outputs.should_skip_tests != 'true' steps: - uses: actions/setup-go@v2 with: diff --git a/.github/workflows/markdown-link-check-config.json b/.github/workflows/markdown-link-check-config.json index 9068496a695..c50351f477d 100644 --- a/.github/workflows/markdown-link-check-config.json +++ b/.github/workflows/markdown-link-check-config.json @@ -1,6 +1,6 @@ { "ignorePatterns": [ - { "pattern": "^https://github.com/\\S+/\\S+/(issues|pull)/[0-9]+" }, + { "pattern": "^https://github.com/.+" }, { "pattern": "^mailto:" } ] } diff --git a/.github/workflows/markdown.yml b/.github/workflows/markdown.yml deleted file mode 100644 index 3f90624e96a..00000000000 --- a/.github/workflows/markdown.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: Check Markdown links - -on: - pull_request: - push: - branches: - - master - -jobs: - markdown-link-check: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@master - - uses: gaurav-nelson/github-action-markdown-link-check@1.0.2 - with: - max-depth: 1 - config-file: '.github/workflows/markdown-link-check-config.json' diff --git a/.github/workflows/test-ansible.yml b/.github/workflows/test-ansible.yml index 0eb41f7af64..c681898addf 100644 --- a/.github/workflows/test-ansible.yml +++ b/.github/workflows/test-ansible.yml @@ -3,9 +3,25 @@ on: pull_request: {} jobs: + check_docs_only: + name: check_docs_only + runs-on: ubuntu-18.04 + outputs: + should_skip_tests: ${{ steps.check_docs_only.outputs.skip-tests }} + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - id: check_docs_only + run: | + REPO_MASTER_REF=$(git show-ref ${{ github.base_ref }} | head -1 | cut -d' ' -f2) + echo "::set-output name=skip-tests::$(hack/ci/check-doc-only-update.sh $REPO_MASTER_REF)" + e2e: name: e2e runs-on: ubuntu-18.04 + needs: check_docs_only + if: needs.check_docs_only.outputs.should_skip_tests != 'true' steps: - uses: actions/setup-go@v2 with: @@ -19,6 +35,8 @@ jobs: e2e-molecule: name: e2e-molecule runs-on: ubuntu-18.04 + needs: check_docs_only + if: needs.check_docs_only.outputs.should_skip_tests != 'true' steps: - uses: actions/setup-go@v2 with: diff --git a/.github/workflows/test-go.yml b/.github/workflows/test-go.yml index 9423fa0579f..004cb6b9a3c 100644 --- a/.github/workflows/test-go.yml +++ b/.github/workflows/test-go.yml @@ -3,9 +3,25 @@ on: pull_request: {} jobs: + check_docs_only: + name: check_docs_only + runs-on: ubuntu-18.04 + outputs: + should_skip_tests: ${{ steps.check_docs_only.outputs.skip-tests }} + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - id: check_docs_only + run: | + REPO_MASTER_REF=$(git show-ref ${{ github.base_ref }} | head -1 | cut -d' ' -f2) + echo "::set-output name=skip-tests::$(hack/ci/check-doc-only-update.sh $REPO_MASTER_REF)" + e2e: name: e2e runs-on: ubuntu-18.04 + needs: check_docs_only + if: needs.check_docs_only.outputs.should_skip_tests != 'true' steps: - uses: actions/setup-go@v2 with: @@ -19,6 +35,8 @@ jobs: unit: name: unit runs-on: ubuntu-18.04 + needs: check_docs_only + if: needs.check_docs_only.outputs.should_skip_tests != 'true' steps: - uses: actions/setup-go@v2 with: diff --git a/.github/workflows/test-helm.yml b/.github/workflows/test-helm.yml index 0809e4d511d..08911e7e3d5 100644 --- a/.github/workflows/test-helm.yml +++ b/.github/workflows/test-helm.yml @@ -3,9 +3,25 @@ on: pull_request: {} jobs: + check_docs_only: + name: check_docs_only + runs-on: ubuntu-18.04 + outputs: + should_skip_tests: ${{ steps.check_docs_only.outputs.skip-tests }} + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - id: check_docs_only + run: | + REPO_MASTER_REF=$(git show-ref ${{ github.base_ref }} | head -1 | cut -d' ' -f2) + echo "::set-output name=skip-tests::$(hack/ci/check-doc-only-update.sh $REPO_MASTER_REF)" + e2e: name: e2e runs-on: ubuntu-18.04 + needs: check_docs_only + if: needs.check_docs_only.outputs.should_skip_tests != 'true' steps: - uses: actions/setup-go@v2 with: diff --git a/.github/workflows/test-sanity.yml b/.github/workflows/test-sanity.yml index bb194f97468..12b7f8003fe 100644 --- a/.github/workflows/test-sanity.yml +++ b/.github/workflows/test-sanity.yml @@ -26,3 +26,7 @@ jobs: fetch-depth: 0 submodules: recursive - run: make test-links + - uses: gaurav-nelson/github-action-markdown-link-check@1.0.2 + with: + max-depth: 1 + config-file: '.github/workflows/markdown-link-check-config.json' diff --git a/.travis.yml b/.travis.yml index ea48597d120..2926c7fcec2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,7 +20,7 @@ x_base_steps: before_install: # hack/ci/check-doc-only-update.sh needs to be sourced so # that it can properly exit the test early with success - - source hack/ci/check-doc-only-update.sh + - source hack/ci/check-doc-only-update.sh "$TRAVIS_COMMIT_RANGE" - git fetch origin --unshallow --tags after_failure: - kubectl get all --all-namespaces diff --git a/hack/ci/check-doc-only-update.sh b/hack/ci/check-doc-only-update.sh index b6e410bb277..82540f97cc4 100755 --- a/hack/ci/check-doc-only-update.sh +++ b/hack/ci/check-doc-only-update.sh @@ -2,11 +2,9 @@ set -e -# Make sure the TRAVIS_COMMIT_RANGE is valid, by catching any errors and exiting. -if [ -z "$TRAVIS_COMMIT_RANGE" ] || ! git rev-list --quiet $TRAVIS_COMMIT_RANGE; then - echo "Invalid commit range. Skipping check for doc only update" - return 0 -fi +# If running in Github actions: this should be set to "github.base_ref". +# If running in Travis CI: this should be set to "$TRAVIS_COMMIT_RANGE". +: ${1?"the first argument must be set to a commit-ish reference"} # Patterns to ignore. declare -a DOC_PATTERNS @@ -23,9 +21,10 @@ DOC_PATTERNS=( "^(MAINTAINERS)" "^(SECURITY)" "^(LICENSE)" + "^(\.github/workflows/)" ) -if ! git diff --name-only $TRAVIS_COMMIT_RANGE | grep -qvE "$(IFS="|"; echo "${DOC_PATTERNS[*]}")"; then - echo "Only doc files were updated, not running the CI." +if ! git diff --name-only $1 | grep -qvE "$(IFS="|"; echo "${DOC_PATTERNS[*]}")"; then + echo "true" exit 0 fi From 026477ccd4bf4fe61d7820eaa3ecc1d57ff4e4a3 Mon Sep 17 00:00:00 2001 From: Shuhei Kitagawa Date: Wed, 2 Dec 2020 14:32:44 +0900 Subject: [PATCH 225/376] Add an import statement to the Go building operators tutorial (#4264) Signed-off-by: reinvantveer --- .../content/en/docs/building-operators/golang/tutorial.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/website/content/en/docs/building-operators/golang/tutorial.md b/website/content/en/docs/building-operators/golang/tutorial.md index 27a5ed6bd10..9e184b36775 100644 --- a/website/content/en/docs/building-operators/golang/tutorial.md +++ b/website/content/en/docs/building-operators/golang/tutorial.md @@ -173,6 +173,12 @@ The next two subsections explain how the controller watches resources and how th The `SetupWithManager()` function in `controllers/memcached_controller.go` specifies how the controller is built to watch a CR and other resources that are owned and managed by that controller. ```Go +import ( + ... + appsv1 "k8s.io/api/apps/v1" + ... +) + func (r *MemcachedReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). For(&cachev1alpha1.Memcached{}). From 4920db20a8e4a33b0083134d96b13706a3e1b56a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=A7=E5=BD=AC?= Date: Fri, 4 Dec 2020 02:44:42 +0800 Subject: [PATCH 226/376] Fix missing url for operator_install (#4236) Signed-off-by: reinvantveer --- website/content/en/docs/building-operators/golang/tutorial.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/content/en/docs/building-operators/golang/tutorial.md b/website/content/en/docs/building-operators/golang/tutorial.md index 9e184b36775..0a88e0533f7 100644 --- a/website/content/en/docs/building-operators/golang/tutorial.md +++ b/website/content/en/docs/building-operators/golang/tutorial.md @@ -459,7 +459,7 @@ The following guides build off the operator created in this example, adding adva Also see the [advanced topics][advanced_topics] doc for more use cases and under the hood details. - +[operator_install]: https://sdk.operatorframework.io/docs/installation/install-operator-sdk/ [go_tool]:https://golang.org/dl/ [docker_tool]:https://docs.docker.com/install/ [kubectl_tool]:https://kubernetes.io/docs/tasks/tools/install-kubectl/ @@ -505,4 +505,4 @@ Also see the [advanced topics][advanced_topics] doc for more use cases and under [legacy_CLI]:https://v0-19-x.sdk.operatorframework.io/docs/cli/ [env-test-setup]: /docs/building-operators/golang/references/envtest-setup [role-based-access-control]: https://cloud.google.com/kubernetes-engine/docs/how-to/role-based-access-control#iam-rolebinding-bootstrap -[multigroup-kubebuilder-doc]: https://book.kubebuilder.io/migration/multi-group.html \ No newline at end of file +[multigroup-kubebuilder-doc]: https://book.kubebuilder.io/migration/multi-group.html From 8167e6d60546fb09e9bdbaa377a8e9cd57ed953f Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Thu, 3 Dec 2020 12:22:13 -0800 Subject: [PATCH 227/376] generate: add `order=` CSV marker fields (#4254) This commit adds the `order=` field to the set of CSV marker definitions on both types and fields, which will order that type or field with all others of the same order in a descending manner. internal/generate/clusterserviceversion/bases/definitions: add Order to Description and Descriptor marker types, which are considered when adding elements to `.spec.customresourcedefinitions` Signed-off-by: reinvantveer --- changelog/fragments/csv-order.yaml | 5 + .../bases/definitions/crd.go | 136 ++++++------ .../bases/definitions/crd_test.go | 208 ++++++++++++++++++ .../bases/definitions/definitions.go | 61 +++-- .../definitions/definitions_suite_test.go | 27 +++ .../bases/definitions/definitions_test.go | 206 ++++++++++++++--- .../bases/definitions/markers.go | 55 +++-- .../definitions/zz_generated.markerhelp.go | 8 + .../golang/references/markers.md | 5 +- 9 files changed, 570 insertions(+), 141 deletions(-) create mode 100644 changelog/fragments/csv-order.yaml create mode 100644 internal/generate/clusterserviceversion/bases/definitions/crd_test.go create mode 100644 internal/generate/clusterserviceversion/bases/definitions/definitions_suite_test.go diff --git a/changelog/fragments/csv-order.yaml b/changelog/fragments/csv-order.yaml new file mode 100644 index 00000000000..3d122e9fd99 --- /dev/null +++ b/changelog/fragments/csv-order.yaml @@ -0,0 +1,5 @@ +entries: + - description: > + Added [`order=`](https://sdk.operatorframework.io/docs/building-operators/golang/references/markers/#usage) marker fields to CSV markers. + + kind: addition diff --git a/internal/generate/clusterserviceversion/bases/definitions/crd.go b/internal/generate/clusterserviceversion/bases/definitions/crd.go index 267d28bb114..5167b790952 100644 --- a/internal/generate/clusterserviceversion/bases/definitions/crd.go +++ b/internal/generate/clusterserviceversion/bases/definitions/crd.go @@ -16,6 +16,7 @@ package definitions import ( "fmt" + "math" "reflect" "sort" "strings" @@ -53,7 +54,7 @@ func getHalfBySep(s, sep string, half uint) string { // buildCRDDescriptionFromType builds a crdDescription for the Go API defined // by key from markers and type information in g.types. -func (g generator) buildCRDDescriptionFromType(gvk schema.GroupVersionKind, kindType *markers.TypeInfo) (v1alpha1.CRDDescription, error) { +func (g generator) buildCRDDescriptionFromType(gvk schema.GroupVersionKind, kindType *markers.TypeInfo) (v1alpha1.CRDDescription, int, error) { // Initialize the description. description := v1alpha1.CRDDescription{ @@ -64,17 +65,21 @@ func (g generator) buildCRDDescriptionFromType(gvk schema.GroupVersionKind, kind } // Parse resources and displayName from the kind type's markers. + descriptionOrder := math.MaxInt32 for _, markers := range kindType.Markers { for _, marker := range markers { switch d := marker.(type) { case Description: + if d.Order != nil { + descriptionOrder = *d.Order + } if d.DisplayName != "" { description.DisplayName = d.DisplayName } if len(d.Resources) != 0 { refs, err := d.Resources.toResourceReferences() if err != nil { - return v1alpha1.CRDDescription{}, err + return v1alpha1.CRDDescription{}, 0, err } description.Resources = append(description.Resources, refs...) } @@ -89,113 +94,106 @@ func (g generator) buildCRDDescriptionFromType(gvk schema.GroupVersionKind, kind if description.Name == "" { description.Name = fmt.Sprintf("%s.%s", inflect.Pluralize(strings.ToLower(gvk.Kind)), gvk.Group) } - sortDescription(description.Resources) + sortResources(description.Resources) - // Find spec and status in the kind type. - spec, err := findChildForDescType(kindType, specDescType) + specDescriptors, err := g.getTypedDescriptors(kindType, reflect.TypeOf(v1alpha1.SpecDescriptor{}), spec) if err != nil { - return v1alpha1.CRDDescription{}, err + return v1alpha1.CRDDescription{}, 0, err } - status, err := findChildForDescType(kindType, statusDescType) - if err != nil { - return v1alpha1.CRDDescription{}, err + for _, d := range specDescriptors { + description.SpecDescriptors = append(description.SpecDescriptors, d.(v1alpha1.SpecDescriptor)) } - // Find annotated fields of spec and parse them into specDescriptors. - markedFields, err := g.getMarkedChildrenOfField(spec) + statusDescriptors, err := g.getTypedDescriptors(kindType, reflect.TypeOf(v1alpha1.StatusDescriptor{}), status) if err != nil { - return v1alpha1.CRDDescription{}, err + return v1alpha1.CRDDescription{}, 0, err } - specDescriptors := []v1alpha1.SpecDescriptor{} - for _, fields := range markedFields { - for _, field := range fields { - if descriptor, include := field.toSpecDescriptor(); include { - specDescriptors = append(specDescriptors, descriptor) - } - } + for _, d := range statusDescriptors { + description.StatusDescriptors = append(description.StatusDescriptors, d.(v1alpha1.StatusDescriptor)) } - sortDescriptors(specDescriptors) - description.SpecDescriptors = specDescriptors - // Find annotated fields of status and parse them into statusDescriptors. - markedFields, err = g.getMarkedChildrenOfField(status) + return description, descriptionOrder, nil +} + +func (g generator) getTypedDescriptors(kindType *markers.TypeInfo, t reflect.Type, descType string) ([]interface{}, error) { + // Find child in the kind type. + child, err := findChildForDescType(kindType, descType) + if err != nil { + return nil, err + } + + // Find annotated fields of child and parse them into descriptors. + markedFields, err := g.getMarkedChildrenOfField(child) if err != nil { - return v1alpha1.CRDDescription{}, err + return nil, err } - statusDescriptors := []v1alpha1.StatusDescriptor{} + + return getTypedDescriptors(markedFields, t, descType), nil +} + +func getTypedDescriptors(markedFields map[string][]*fieldInfo, t reflect.Type, descType string) (descriptors []interface{}) { + descriptorBuckets := make(map[int][]reflect.Value) + orders := make([]int, 0) for _, fields := range markedFields { for _, field := range fields { - if descriptor, include := field.toStatusDescriptor(); include { - statusDescriptors = append(statusDescriptors, descriptor) + v := reflect.New(t) + if order, include := field.setDescriptorFields(v, descType); include { + descriptorBuckets[order] = append(descriptorBuckets[order], reflect.Indirect(v)) + orders = append(orders, order) } } } - sortDescriptors(statusDescriptors) - description.StatusDescriptors = statusDescriptors + sort.Ints(orders) + + descriptorVals := make([]reflect.Value, 0) + for _, order := range orders { + if bucket, hasOrder := descriptorBuckets[order]; hasOrder { + sortDescriptors(bucket) + descriptorVals = append(descriptorVals, bucket...) + delete(descriptorBuckets, order) + } + } + + for _, v := range descriptorVals { + descriptors = append(descriptors, v.Interface()) + } - return description, nil + return descriptors } // findChildForDescType returns a field with a tag matching string(typ) by searching all top-level fields in info. // If no field is found, an error is returned. -func findChildForDescType(info *markers.TypeInfo, typ descType) (markers.FieldInfo, error) { +func findChildForDescType(info *markers.TypeInfo, descType string) (markers.FieldInfo, error) { for _, field := range info.Fields { tags, err := structtag.Parse(string(field.Tag)) if err != nil { return markers.FieldInfo{}, err } jsonTag, err := tags.Get("json") - if err == nil && jsonTag.Name == string(typ) { + if err == nil && jsonTag.Name == descType { return field, nil } } - return markers.FieldInfo{}, fmt.Errorf("no %s found for type %s", typ, info.Name) + return markers.FieldInfo{}, fmt.Errorf("no %s found for type %s", descType, info.Name) } // sortDescriptors sorts a slice of structs with a Path field by comparing Path strings naturally. -func sortDescriptors(v interface{}) { - slice := reflect.ValueOf(v) - values := toValueSlice(slice) +func sortDescriptors(values []reflect.Value) { sort.Slice(values, func(i, j int) bool { return values[i].FieldByName("Path").String() < values[j].FieldByName("Path").String() }) - for i := 0; i < slice.Len(); i++ { - slice.Index(i).Set(values[i]) - } } -// sortDescription sorts a slice of structs with Name, Kind, and Version fields +// sortResources sorts a slice of structs with Name, Kind, and Version fields // by comparing those field's strings in natural order. -func sortDescription(v interface{}) { - slice := reflect.ValueOf(v) - values := toValueSlice(slice) - sort.Slice(values, func(i, j int) bool { - nameI := values[i].FieldByName("Name").String() - nameJ := values[j].FieldByName("Name").String() - if nameI == nameJ { - kindI := values[i].FieldByName("Kind").String() - kindJ := values[j].FieldByName("Kind").String() - if kindI == kindJ { - versionI := values[i].FieldByName("Version").String() - versionJ := values[j].FieldByName("Version").String() - return version.CompareKubeAwareVersionStrings(versionI, versionJ) > 0 +func sortResources(rs []v1alpha1.APIResourceReference) { + sort.Slice(rs, func(i, j int) bool { + if rs[i].Name == rs[j].Name { + if rs[i].Kind == rs[j].Kind { + return version.CompareKubeAwareVersionStrings(rs[i].Version, rs[j].Version) > 0 } - return kindI < kindJ + return rs[i].Kind < rs[j].Kind } - return nameI < nameJ + return rs[i].Name < rs[j].Name }) - for i := 0; i < slice.Len(); i++ { - slice.Index(i).Set(values[i]) - } -} - -// toValueSlice creates a slice of values that can be sorted by arbitrary fields. -func toValueSlice(slice reflect.Value) []reflect.Value { - sliceCopy := reflect.MakeSlice(slice.Type(), slice.Len(), slice.Len()) - reflect.Copy(sliceCopy, slice) - values := make([]reflect.Value, sliceCopy.Len()) - for i := 0; i < sliceCopy.Len(); i++ { - values[i] = sliceCopy.Index(i) - } - return values } diff --git a/internal/generate/clusterserviceversion/bases/definitions/crd_test.go b/internal/generate/clusterserviceversion/bases/definitions/crd_test.go new file mode 100644 index 00000000000..37426574fe8 --- /dev/null +++ b/internal/generate/clusterserviceversion/bases/definitions/crd_test.go @@ -0,0 +1,208 @@ +// Copyright 2020 The Operator-SDK 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. + +package definitions + +import ( + "math/rand" + "reflect" + "sort" + "strings" + "time" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "github.com/operator-framework/api/pkg/operators/v1alpha1" + "sigs.k8s.io/controller-tools/pkg/markers" + "sigs.k8s.io/kubebuilder/v2/test/e2e/utils" +) + +var _ = Describe("getTypedDescriptors", func() { + var ( + markedFields map[string][]*fieldInfo + out []interface{} + ) + + BeforeEach(func() { + markedFields = make(map[string][]*fieldInfo) + }) + + It("handles an empty set of marked fields", func() { + out = getTypedDescriptors(markedFields, reflect.TypeOf(v1alpha1.SpecDescriptor{}), spec) + Expect(out).To(HaveLen(0)) + }) + It("returns one spec descriptor for one spec marker on a field", func() { + markedFields[""] = []*fieldInfo{ + { + FieldInfo: markers.FieldInfo{ + Markers: markers.MarkerValues{ + "": []interface{}{ + Descriptor{"spec", "Foo", []string{"urn:alm:descriptor:com.tectonic.ui:text"}, nil}, + }, + }, + }, + }, + } + out = getTypedDescriptors(markedFields, reflect.TypeOf(v1alpha1.SpecDescriptor{}), spec) + Expect(out).To(HaveLen(1)) + Expect(out).To(BeEquivalentTo([]interface{}{ + v1alpha1.SpecDescriptor{ + DisplayName: "Foo", + XDescriptors: []string{"urn:alm:descriptor:com.tectonic.ui:text"}, + }, + })) + }) + It("returns no spec descriptors for one status marker on a field", func() { + markedFields[""] = []*fieldInfo{ + { + FieldInfo: markers.FieldInfo{ + Markers: markers.MarkerValues{ + "": []interface{}{ + Descriptor{"status", "Foo", []string{"urn:alm:descriptor:com.tectonic.ui:text"}, nil}, + }, + }, + }, + }, + } + out = getTypedDescriptors(markedFields, reflect.TypeOf(v1alpha1.SpecDescriptor{}), spec) + Expect(out).To(HaveLen(0)) + }) + It("returns one status descriptor for one status marker on a field", func() { + markedFields[""] = []*fieldInfo{ + { + FieldInfo: markers.FieldInfo{ + Markers: markers.MarkerValues{ + "": []interface{}{ + Descriptor{"status", "Foo", []string{"urn:alm:descriptor:com.tectonic.ui:text"}, nil}, + }, + }, + }, + }, + } + out = getTypedDescriptors(markedFields, reflect.TypeOf(v1alpha1.StatusDescriptor{}), status) + Expect(out).To(HaveLen(1)) + Expect(out).To(BeEquivalentTo([]interface{}{ + v1alpha1.StatusDescriptor{ + DisplayName: "Foo", + XDescriptors: []string{"urn:alm:descriptor:com.tectonic.ui:text"}, + }, + })) + }) + It("returns one spec descriptor for three spec markers and one status marker on a field", func() { + markedFields[""] = []*fieldInfo{ + { + FieldInfo: markers.FieldInfo{ + Markers: markers.MarkerValues{ + "": []interface{}{ + Descriptor{"spec", "Foo", nil, nil}, + Descriptor{"spec", "", nil, intPtr(2)}, + Descriptor{"spec", "", []string{"urn:alm:descriptor:com.tectonic.ui:text"}, nil}, + Descriptor{"status", "", []string{"urn:alm:descriptor:com.tectonic.ui:arrayFieldGroup:blah"}, nil}, + }, + }, + }, + pathSegments: []string{"foo", inlinedTag, "bar", "baz"}, + }, + } + out = getTypedDescriptors(markedFields, reflect.TypeOf(v1alpha1.SpecDescriptor{}), spec) + Expect(out).To(HaveLen(1)) + Expect(out).To(BeEquivalentTo([]interface{}{ + v1alpha1.SpecDescriptor{ + DisplayName: "Foo", + XDescriptors: []string{"urn:alm:descriptor:com.tectonic.ui:text"}, + Path: "foo.bar.baz", + }, + })) + }) + It("returns two spec descriptor for spec markers on two different fields", func() { + markedFields[""] = []*fieldInfo{ + { + FieldInfo: markers.FieldInfo{ + Markers: markers.MarkerValues{ + "": []interface{}{Descriptor{"spec", "Foo", nil, intPtr(1)}}, + }, + }, + pathSegments: []string{"foo"}, + }, + { + FieldInfo: markers.FieldInfo{ + Markers: markers.MarkerValues{ + "": []interface{}{Descriptor{"spec", "Bar", nil, intPtr(0)}}, + }, + }, + pathSegments: []string{"bar"}, + }, + } + out = getTypedDescriptors(markedFields, reflect.TypeOf(v1alpha1.SpecDescriptor{}), spec) + Expect(out).To(HaveLen(2)) + Expect(out).To(BeEquivalentTo([]interface{}{ + v1alpha1.SpecDescriptor{DisplayName: "Bar", Path: "bar"}, + v1alpha1.SpecDescriptor{DisplayName: "Foo", Path: "foo"}, + })) + }) + It("returns multiple sorted spec descriptors with all orders set", func() { + markedFields, expected := makeMockMarkedFields() + out = getTypedDescriptors(markedFields, reflect.TypeOf(v1alpha1.SpecDescriptor{}), spec) + Expect(out).To(HaveLen(len(expected))) + Expect(out).To(BeEquivalentTo(expected)) + }) +}) + +func intPtr(i int) *int { return &i } + +// makeMockMarkedFields returns a randomly generated mock marked field set, +// and the expected sorted set of descriptors. +func makeMockMarkedFields() (markedFields map[string][]*fieldInfo, expected []interface{}) { + descBuckets := make(map[int][]v1alpha1.SpecDescriptor, 100) + r := rand.New(rand.NewSource(time.Now().UnixNano())) + markedFields = make(map[string][]*fieldInfo, 100) + for i := 0; i < 100; i++ { + s, err := utils.RandomSuffix() + if err != nil { + panic(err) + } + name := strings.Title(s) + order := r.Int() % 200 // Very likely to get one conflict. + if _, hasName := markedFields[name]; hasName { + continue + } + markedFields[name] = []*fieldInfo{ + { + FieldInfo: markers.FieldInfo{ + Markers: markers.MarkerValues{ + "": []interface{}{Descriptor{"spec", name, nil, intPtr(order)}}, + }, + }, + pathSegments: []string{s}, + }, + } + descBuckets[order] = append(descBuckets[order], v1alpha1.SpecDescriptor{DisplayName: name, Path: s}) + } + + orders := make([]int, 0, 100) + for order := range descBuckets { + orders = append(orders, order) + } + sort.Ints(orders) + + for _, order := range orders { + bucket := descBuckets[order] + sort.Slice(bucket, func(i, j int) bool { return bucket[i].DisplayName < bucket[j].DisplayName }) + for _, d := range bucket { + expected = append(expected, d) + } + } + + return markedFields, expected +} diff --git a/internal/generate/clusterserviceversion/bases/definitions/definitions.go b/internal/generate/clusterserviceversion/bases/definitions/definitions.go index 4d148db00f0..7efd5b471bd 100644 --- a/internal/generate/clusterserviceversion/bases/definitions/definitions.go +++ b/internal/generate/clusterserviceversion/bases/definitions/definitions.go @@ -18,6 +18,7 @@ import ( "errors" "os" "path/filepath" + "sort" "github.com/operator-framework/api/pkg/operators/v1alpha1" log "github.com/sirupsen/logrus" @@ -29,7 +30,8 @@ import ( ) type descriptionValues struct { - crd v1alpha1.CRDDescription + crdOrder int + crd v1alpha1.CRDDescription // TODO(estroz): support apiServiceDescriptions } @@ -70,12 +72,13 @@ func ApplyDefinitionsForKeysGo(csv *v1alpha1.ClusterServiceVersion, apisRootDir log.Warnf("Skipping CSV annotation parsing for API %s: type %s not found", gvk, gvk.Kind) continue } - crd, err := g.buildCRDDescriptionFromType(gvk, kindType) + crd, crdOrder, err := g.buildCRDDescriptionFromType(gvk, kindType) if err != nil { return err } definitionsByGVK[gvk] = &descriptionValues{ - crd: crd, + crdOrder: crdOrder, + crd: crd, } } @@ -109,27 +112,51 @@ func makeAPIPaths(apisRootDir string, gvks []schema.GroupVersionKind) (paths []s // updateDefinitionsByKey updates owned definitions that already exist in csv or adds new definitions that do not. func updateDefinitionsByKey(csv *v1alpha1.ClusterServiceVersion, defsByGVK map[schema.GroupVersionKind]*descriptionValues) { + // Create a set of buckets for all generated descriptions. + // Multiple descriptions can belong to the same order. + crdBuckets := make(map[int][]v1alpha1.CRDDescription) + for _, values := range defsByGVK { + crdBuckets[values.crdOrder] = append(crdBuckets[values.crdOrder], values.crd) + } - // Overwrite crdDescriptions we've parsed from Go source. - for i := 0; i < len(csv.Spec.CustomResourceDefinitions.Owned); i++ { - crd := csv.Spec.CustomResourceDefinitions.Owned[i] - gvk := schema.GroupVersionKind{ - Group: MakeFullGroupFromName(crd.Name), - Version: crd.Version, - Kind: crd.Kind, - } - if values, hasKey := defsByGVK[gvk]; hasKey { - csv.Spec.CustomResourceDefinitions.Owned[i] = values.crd - delete(defsByGVK, gvk) + // Sort generated buckets before adding non-generated descriptions so users can + // set their order manually. + for _, bucket := range crdBuckets { + sort.Slice(bucket, func(i, j int) bool { + return bucket[i].Name < bucket[j].Name + }) + } + + // Append non-generated descriptions to the end of their buckets, + // treating their indices as order. + for i, crd := range csv.Spec.CustomResourceDefinitions.Owned { + if _, hasKey := defsByGVK[descToGVK(crd)]; !hasKey { + crdBuckets[i] = append(crdBuckets[i], csv.Spec.CustomResourceDefinitions.Owned[i]) } } - // Add any new crdDescriptions to the CSV. - for _, values := range defsByGVK { - csv.Spec.CustomResourceDefinitions.Owned = append(csv.Spec.CustomResourceDefinitions.Owned, values.crd) + // De-duplciate and sort order ints for appending bucket contents in-order. + crdOrders := make([]int, 0, len(crdBuckets)) + for order := range crdBuckets { + crdOrders = append(crdOrders, order) + } + sort.Ints(crdOrders) + + // Update descriptions. + csv.Spec.CustomResourceDefinitions.Owned = make([]v1alpha1.CRDDescription, 0, len(crdBuckets)) + for _, order := range crdOrders { + csv.Spec.CustomResourceDefinitions.Owned = append(csv.Spec.CustomResourceDefinitions.Owned, crdBuckets[order]...) } } +// descToGVK convert desc to a GVK type. +func descToGVK(desc v1alpha1.CRDDescription) (gvk schema.GroupVersionKind) { + gvk.Group = MakeFullGroupFromName(desc.Name) + gvk.Version = desc.Version + gvk.Kind = desc.Kind + return gvk +} + func isDirExist(path string) (bool, error) { fileInfo, err := os.Stat(path) if err != nil { diff --git a/internal/generate/clusterserviceversion/bases/definitions/definitions_suite_test.go b/internal/generate/clusterserviceversion/bases/definitions/definitions_suite_test.go new file mode 100644 index 00000000000..0ceac50eeba --- /dev/null +++ b/internal/generate/clusterserviceversion/bases/definitions/definitions_suite_test.go @@ -0,0 +1,27 @@ +// Copyright 2020 The Operator-SDK 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. + +package definitions + +import ( + "testing" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +func TestGenerator(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Definitions Suite") +} diff --git a/internal/generate/clusterserviceversion/bases/definitions/definitions_test.go b/internal/generate/clusterserviceversion/bases/definitions/definitions_test.go index e5fda6fdda5..c1f7c689c95 100644 --- a/internal/generate/clusterserviceversion/bases/definitions/definitions_test.go +++ b/internal/generate/clusterserviceversion/bases/definitions/definitions_test.go @@ -17,8 +17,11 @@ package definitions import ( "os" "path/filepath" + "sort" "testing" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" "github.com/operator-framework/api/pkg/operators/v1alpha1" "github.com/stretchr/testify/assert" "k8s.io/apimachinery/pkg/runtime/schema" @@ -88,13 +91,11 @@ func TestApplyDefinitionsForKeysGo(t *testing.T) { }}, }, StatusDescriptors: []v1alpha1.StatusDescriptor{ - {Path: "hog.engine", DisplayName: "boss-hog-engine", XDescriptors: []string{}, - Description: "Should be in status but not spec, since Hog isn't in DummySpec"}, - {Path: "hog.foo", DisplayName: "Public", XDescriptors: []string{}}, - {Path: "hog.seatMaterial", DisplayName: "Seat Material", XDescriptors: []string{}}, - {Path: "hog.seatMaterial", DisplayName: "Seat Material", XDescriptors: []string{}}, - {Path: "nodes", DisplayName: "Nodes", XDescriptors: []string{}, - Description: "Should be in status but not spec, since DummyStatus isn't in DummySpec"}, + {Path: "hog.engine", DisplayName: "boss-hog-engine", Description: "Should be in status but not spec, since Hog isn't in DummySpec"}, + {Path: "hog.foo", DisplayName: "Public"}, + {Path: "hog.seatMaterial", DisplayName: "Seat Material"}, + {Path: "hog.seatMaterial", DisplayName: "Seat Material"}, + {Path: "nodes", DisplayName: "Nodes", Description: "Should be in status but not spec, since DummyStatus isn't in DummySpec"}, }, }, }, @@ -120,15 +121,13 @@ func TestApplyDefinitionsForKeysGo(t *testing.T) { {Name: "other-dummy-service", Kind: "Service", Version: "v1"}, }, SpecDescriptors: []v1alpha1.SpecDescriptor{ - {Path: "engine", DisplayName: "Engine", XDescriptors: []string{}, - Description: "Should be in status but not spec, since Hog isn't in DummySpec"}, - {Path: "foo", DisplayName: "Public", XDescriptors: []string{}}, - {Path: "seatMaterial", DisplayName: "Seat Material", XDescriptors: []string{}}, - {Path: "seatMaterial", DisplayName: "Seat Material", XDescriptors: []string{}}, + {Path: "engine", DisplayName: "Engine", Description: "Should be in status but not spec, since Hog isn't in DummySpec"}, + {Path: "foo", DisplayName: "Public"}, + {Path: "seatMaterial", DisplayName: "Seat Material"}, + {Path: "seatMaterial", DisplayName: "Seat Material"}, }, StatusDescriptors: []v1alpha1.StatusDescriptor{ - {Path: "nothing", DisplayName: "Nothing", XDescriptors: []string{}, - Description: "Should be in status but not spec, since this isn't a spec type"}, + {Path: "nothing", DisplayName: "Nothing", Description: "Should be in status but not spec, since this isn't a spec type"}, }, }, }, @@ -149,12 +148,10 @@ func TestApplyDefinitionsForKeysGo(t *testing.T) { {Name: "dummy-pod", Kind: "Pod", Version: "v1"}, }, SpecDescriptors: []v1alpha1.SpecDescriptor{ - {Path: "foo", DisplayName: "Foo", XDescriptors: []string{}, - Description: "Should not be removed"}, + {Path: "foo", DisplayName: "Foo", Description: "Should not be removed"}, }, StatusDescriptors: []v1alpha1.StatusDescriptor{ - {Path: "bar", DisplayName: "Bar", XDescriptors: []string{}, - Description: "Should not be removed"}, + {Path: "bar", DisplayName: "Bar", Description: "Should not be removed"}, }, }, }, @@ -174,12 +171,10 @@ func TestApplyDefinitionsForKeysGo(t *testing.T) { {Name: "dummy-pod", Kind: "Pod", Version: "v1"}, }, SpecDescriptors: []v1alpha1.SpecDescriptor{ - {Path: "foo", DisplayName: "Foo", XDescriptors: []string{}, - Description: "Should not be removed"}, + {Path: "foo", DisplayName: "Foo", Description: "Should not be removed"}, }, StatusDescriptors: []v1alpha1.StatusDescriptor{ - {Path: "bar", DisplayName: "Bar", XDescriptors: []string{}, - Description: "Should not be removed"}, + {Path: "bar", DisplayName: "Bar", Description: "Should not be removed"}, }, }, }, @@ -200,12 +195,10 @@ func TestApplyDefinitionsForKeysGo(t *testing.T) { {Name: "no-kind-pod", Kind: "Pod", Version: "v1"}, }, SpecDescriptors: []v1alpha1.SpecDescriptor{ - {Path: "foo", DisplayName: "Foo", XDescriptors: []string{}, - Description: "Should not be removed"}, + {Path: "foo", DisplayName: "Foo", Description: "Should not be removed"}, }, StatusDescriptors: []v1alpha1.StatusDescriptor{ - {Path: "bar", DisplayName: "Bar", XDescriptors: []string{}, - Description: "Should not be removed"}, + {Path: "bar", DisplayName: "Bar", Description: "Should not be removed"}, }, }, }, @@ -225,12 +218,10 @@ func TestApplyDefinitionsForKeysGo(t *testing.T) { {Name: "no-kind-pod", Kind: "Pod", Version: "v1"}, }, SpecDescriptors: []v1alpha1.SpecDescriptor{ - {Path: "foo", DisplayName: "Foo", XDescriptors: []string{}, - Description: "Should not be removed"}, + {Path: "foo", DisplayName: "Foo", Description: "Should not be removed"}, }, StatusDescriptors: []v1alpha1.StatusDescriptor{ - {Path: "bar", DisplayName: "Bar", XDescriptors: []string{}, - Description: "Should not be removed"}, + {Path: "bar", DisplayName: "Bar", Description: "Should not be removed"}, }, }, }, @@ -251,3 +242,158 @@ func TestApplyDefinitionsForKeysGo(t *testing.T) { }) } } + +var _ = Describe("updateDefinitionsByKey", func() { + var ( + startingCSV *v1alpha1.ClusterServiceVersion + defsByGVK map[schema.GroupVersionKind]*descriptionValues + ) + + BeforeEach(func() { + startingCSV = &v1alpha1.ClusterServiceVersion{} + defsByGVK = make(map[schema.GroupVersionKind]*descriptionValues) + }) + + It("handles an empty CSV and descriptions without error", func() { + updateDefinitionsByKey(startingCSV, defsByGVK) + Expect(startingCSV.Spec.CustomResourceDefinitions.Owned).To(Equal([]v1alpha1.CRDDescription{})) + }) + It("preserves ordering of two existing descriptions with no new descriptions", func() { + owned := []v1alpha1.CRDDescription{ + {Name: "memcacheds.cache.example.com", Version: "v1alpha1", Kind: "Memcached"}, + {Name: "memcached2s.cache.example.com", Version: "v1alpha1", Kind: "Memcached2"}, + } + startingCSV.Spec.CustomResourceDefinitions.Owned = owned + csv := startingCSV.DeepCopy() + updateDefinitionsByKey(csv, defsByGVK) + Expect(csv.Spec.CustomResourceDefinitions.Owned).To(Equal(owned)) + }) + It("orders two unordered existing descriptions with no new descriptions", func() { + owned := []v1alpha1.CRDDescription{ + {Name: "memcached2s.cache.example.com", Version: "v1alpha1", Kind: "Memcached2"}, + {Name: "memcacheds.cache.example.com", Version: "v1alpha1", Kind: "Memcached"}, + } + startingCSV.Spec.CustomResourceDefinitions.Owned = owned + csv := startingCSV.DeepCopy() + updateDefinitionsByKey(csv, defsByGVK) + sort.Slice(owned, func(i, j int) bool { return owned[i].Name < owned[j].Name }) + Expect(csv.Spec.CustomResourceDefinitions.Owned).To(Equal(owned)) + }) + It("orders two new descriptions with increasing orders with no existing descriptions", func() { + desc1 := v1alpha1.CRDDescription{Name: "memcached3s.cache.example.com", Version: "v1alpha1", Kind: "Memcached3"} + desc2 := v1alpha1.CRDDescription{Name: "memcached4s.cache.example.com", Version: "v1alpha1", Kind: "Memcached4"} + defsByGVK[descToGVK(desc1)] = &descriptionValues{crdOrder: 0, crd: desc1} + defsByGVK[descToGVK(desc2)] = &descriptionValues{crdOrder: 1, crd: desc2} + + expected := []v1alpha1.CRDDescription{desc1, desc2} + updateDefinitionsByKey(startingCSV, defsByGVK) + Expect(startingCSV.Spec.CustomResourceDefinitions.Owned).To(Equal(expected)) + }) + It("orders two new descriptions with decreasing orders with no existing descriptions", func() { + desc1 := v1alpha1.CRDDescription{Name: "memcached3s.cache.example.com", Version: "v1alpha1", Kind: "Memcached3"} + desc2 := v1alpha1.CRDDescription{Name: "memcached4s.cache.example.com", Version: "v1alpha1", Kind: "Memcached4"} + defsByGVK[descToGVK(desc1)] = &descriptionValues{crdOrder: 1, crd: desc1} + defsByGVK[descToGVK(desc2)] = &descriptionValues{crdOrder: 0, crd: desc2} + + expected := []v1alpha1.CRDDescription{desc2, desc1} + updateDefinitionsByKey(startingCSV, defsByGVK) + Expect(startingCSV.Spec.CustomResourceDefinitions.Owned).To(Equal(expected)) + }) + It("orders two new descriptions with the same order with no existing descriptions", func() { + desc1 := v1alpha1.CRDDescription{Name: "memcached3s.cache.example.com", Version: "v1alpha1", Kind: "Memcached3"} + desc2 := v1alpha1.CRDDescription{Name: "memcached4s.cache.example.com", Version: "v1alpha1", Kind: "Memcached4"} + defsByGVK[descToGVK(desc1)] = &descriptionValues{crdOrder: 0, crd: desc1} + defsByGVK[descToGVK(desc2)] = &descriptionValues{crdOrder: 0, crd: desc2} + + expected := []v1alpha1.CRDDescription{desc1, desc2} + updateDefinitionsByKey(startingCSV, defsByGVK) + Expect(startingCSV.Spec.CustomResourceDefinitions.Owned).To(Equal(expected)) + }) + + It("orders one new description after two existing descriptions", func() { + desc1 := v1alpha1.CRDDescription{Name: "memcached3s.cache.example.com", Version: "v1alpha1", Kind: "Memcached3"} + defsByGVK[descToGVK(desc1)] = &descriptionValues{crdOrder: 2, crd: desc1} + + owned := []v1alpha1.CRDDescription{ + {Name: "memcached2s.cache.example.com", Version: "v1alpha1", Kind: "Memcached2"}, + {Name: "memcacheds.cache.example.com", Version: "v1alpha1", Kind: "Memcached"}, + } + expected := []v1alpha1.CRDDescription{owned[0], owned[1], desc1} + startingCSV.Spec.CustomResourceDefinitions.Owned = owned + csv := startingCSV.DeepCopy() + updateDefinitionsByKey(csv, defsByGVK) + Expect(csv.Spec.CustomResourceDefinitions.Owned).To(Equal(expected)) + }) + It("orders one new description between two existing descriptions", func() { + desc1 := v1alpha1.CRDDescription{Name: "memcached3s.cache.example.com", Version: "v1alpha1", Kind: "Memcached3"} + defsByGVK[descToGVK(desc1)] = &descriptionValues{crdOrder: 0, crd: desc1} + + owned := []v1alpha1.CRDDescription{ + {Name: "memcached2s.cache.example.com", Version: "v1alpha1", Kind: "Memcached2"}, + {Name: "memcacheds.cache.example.com", Version: "v1alpha1", Kind: "Memcached"}, + } + expected := []v1alpha1.CRDDescription{desc1, owned[0], owned[1]} + startingCSV.Spec.CustomResourceDefinitions.Owned = owned + csv := startingCSV.DeepCopy() + updateDefinitionsByKey(csv, defsByGVK) + Expect(csv.Spec.CustomResourceDefinitions.Owned).To(Equal(expected)) + }) + It("orders two new descriptions with the same order with overlapping orders of two existing descriptions", func() { + desc1 := v1alpha1.CRDDescription{Name: "memcached3s.cache.example.com", Version: "v1alpha1", Kind: "Memcached3"} + desc2 := v1alpha1.CRDDescription{Name: "memcached4s.cache.example.com", Version: "v1alpha1", Kind: "Memcached4"} + defsByGVK[descToGVK(desc1)] = &descriptionValues{crdOrder: 0, crd: desc1} + defsByGVK[descToGVK(desc2)] = &descriptionValues{crdOrder: 0, crd: desc2} + + owned := []v1alpha1.CRDDescription{ + {Name: "memcached2s.cache.example.com", Version: "v1alpha1", Kind: "Memcached2"}, + {Name: "memcacheds.cache.example.com", Version: "v1alpha1", Kind: "Memcached"}, + } + expected := []v1alpha1.CRDDescription{desc1, desc2, owned[0], owned[1]} + startingCSV.Spec.CustomResourceDefinitions.Owned = owned + csv := startingCSV.DeepCopy() + updateDefinitionsByKey(csv, defsByGVK) + Expect(csv.Spec.CustomResourceDefinitions.Owned).To(Equal(expected)) + }) + It("orders one new description with two existing descriptions, one of which is in defsByGVK", func() { + desc1 := v1alpha1.CRDDescription{Name: "memcached1s.cache.example.com", Version: "v1alpha1", Kind: "Memcached1"} + desc2 := v1alpha1.CRDDescription{Name: "memcached2s.cache.example.com", Version: "v1alpha1", Kind: "Memcached2"} + defsByGVK[descToGVK(desc1)] = &descriptionValues{crdOrder: 1, crd: desc1} + defsByGVK[descToGVK(desc2)] = &descriptionValues{crdOrder: 0, crd: desc2} + + owned := []v1alpha1.CRDDescription{ + desc1, + {Name: "memcacheds.cache.example.com", Version: "v1alpha1", Kind: "Memcached"}, + } + expected := []v1alpha1.CRDDescription{desc2, desc1, owned[1]} + startingCSV.Spec.CustomResourceDefinitions.Owned = owned + csv := startingCSV.DeepCopy() + updateDefinitionsByKey(csv, defsByGVK) + Expect(csv.Spec.CustomResourceDefinitions.Owned).To(Equal(expected)) + }) + It("orders multiple new descriptions and existing descriptions", func() { + desc1 := v1alpha1.CRDDescription{Name: "memcached3s.cache.example.com", Version: "v1alpha1", Kind: "Memcached3"} + desc2 := v1alpha1.CRDDescription{Name: "memcached4s.cache.example.com", Version: "v1alpha1", Kind: "Memcached4"} + desc3 := v1alpha1.CRDDescription{Name: "foo1s.bar.example.com", Version: "v1alpha1", Kind: "Foo1"} + desc4 := v1alpha1.CRDDescription{Name: "foo2s.bar.example.com", Version: "v1alpha1", Kind: "Foo2"} + desc5 := v1alpha1.CRDDescription{Name: "bazs.bar.example.com", Version: "v1alpha1", Kind: "Baz"} + defsByGVK[descToGVK(desc1)] = &descriptionValues{crdOrder: 0, crd: desc1} + defsByGVK[descToGVK(desc2)] = &descriptionValues{crdOrder: 3, crd: desc2} + defsByGVK[descToGVK(desc3)] = &descriptionValues{crdOrder: 1, crd: desc3} + defsByGVK[descToGVK(desc4)] = &descriptionValues{crdOrder: 0, crd: desc4} + defsByGVK[descToGVK(desc5)] = &descriptionValues{crdOrder: 10000, crd: desc5} + + owned := []v1alpha1.CRDDescription{ + desc2, // Has order 3 above. + {Name: "memcached2s.cache.example.com", Version: "v1alpha1", Kind: "Memcached2"}, + {Name: "memcacheds.cache.example.com", Version: "v1alpha1", Kind: "Memcached"}, + desc1, // Has order 0 above + {Name: "bar2.cache.example.com", Version: "v1alpha1", Kind: "Bar2"}, + {Name: "bar1.cache.example.com", Version: "v1alpha1", Kind: "Bar1"}, + } + expected := []v1alpha1.CRDDescription{desc4, desc1, desc3, owned[1], owned[2], desc2, owned[4], owned[5], desc5} + startingCSV.Spec.CustomResourceDefinitions.Owned = owned + csv := startingCSV.DeepCopy() + updateDefinitionsByKey(csv, defsByGVK) + Expect(csv.Spec.CustomResourceDefinitions.Owned).To(Equal(expected)) + }) +}) diff --git a/internal/generate/clusterserviceversion/bases/definitions/markers.go b/internal/generate/clusterserviceversion/bases/definitions/markers.go index 2aee5b5f579..4865631d0b5 100644 --- a/internal/generate/clusterserviceversion/bases/definitions/markers.go +++ b/internal/generate/clusterserviceversion/bases/definitions/markers.go @@ -16,6 +16,7 @@ package definitions import ( "fmt" + "math" "reflect" "strings" "unicode" @@ -79,6 +80,11 @@ type Description struct { Resources Resources `marker:",optional"` // DisplayName is the displayName of a CRD description. DisplayName string `marker:",optional"` + // Order determines which position in the list this description will take. + // Markers with Order omitted have the highest Order, i.e. at the end of the list. + // If more than one marker has the same Order, the corresponding descriptions + // will be sorted alphabetically and placed above others with higher Orders. + Order *int `marker:",optional"` } // +controllertools:marker:generateHelp:category=Descriptor @@ -92,6 +98,11 @@ type Descriptor struct { // XDescriptors is a list of UI path strings. The marker format is: // "ui:element:foo,ui:element:bar" XDescriptors []string `marker:",optional"` + // Order determines which position in the list this descriptor will take. + // Markers with Order omitted have the highest Order, i.e. at the end of the list. + // If more than one marker has the same Order, the corresponding descriptors + // will be sorted alphabetically and placed above others with higher Orders. + Order *int `marker:",optional"` } // toResourceReferences transforms Resources into a apiResourceReference slice. @@ -118,39 +129,31 @@ type fieldInfo struct { pathSegments []string } -// descType is a string identifying a descriptor type. -type descType string - const ( - specDescType descType = "spec" - statusDescType descType = "status" + spec = "spec" + status = "status" ) -// toStatusDescriptor transforms a fieldInfo into a specDescriptor. -func (fi fieldInfo) toSpecDescriptor() (descriptor v1alpha1.SpecDescriptor, include bool) { - include = fi.setDescriptorFields(&descriptor, specDescType) - return -} - -// toStatusDescriptor transforms a fieldInfo into a statusDescriptor. -func (fi fieldInfo) toStatusDescriptor() (descriptor v1alpha1.StatusDescriptor, include bool) { - include = fi.setDescriptorFields(&descriptor, statusDescType) - return -} - // setDescriptorFields sets a struct with Description, Path, DisplayName, and XDescriptors fields by reflection. -func (fi fieldInfo) setDescriptorFields(d interface{}, typ descType) bool { +func (fi fieldInfo) setDescriptorFields(v reflect.Value, descType string) (int, bool) { path, include := makePath(fi.pathSegments) if !include { - return false + return 0, false } - seenDescType := false - displayName, xDescriptors := "", []string{} + var ( + seenDescType bool + displayName string + xDescriptors []string + orderPtr *int + ) for _, markers := range fi.Markers { for _, marker := range markers { d, isDescriptor := marker.(Descriptor) - if isDescriptor && d.Type == string(typ) { + if isDescriptor && d.Type == descType { + if d.Order != nil { + orderPtr = d.Order + } if d.DisplayName != "" && displayName == "" { displayName = d.DisplayName } @@ -163,13 +166,17 @@ func (fi fieldInfo) setDescriptorFields(d interface{}, typ descType) bool { displayName = k8sutil.GetDisplayName(fi.Name) } - v := reflect.ValueOf(d) v.Elem().FieldByName("Description").SetString(fi.Doc) v.Elem().FieldByName("Path").SetString(path) v.Elem().FieldByName("DisplayName").SetString(displayName) v.Elem().FieldByName("XDescriptors").Set(reflect.ValueOf(xDescriptors)) - return seenDescType + order := math.MaxInt64 + if orderPtr != nil { + order = *orderPtr + } + + return order, seenDescType } // makePath creates a path string from raw path segments. These segments can encode extra information diff --git a/internal/generate/clusterserviceversion/bases/definitions/zz_generated.markerhelp.go b/internal/generate/clusterserviceversion/bases/definitions/zz_generated.markerhelp.go index 15798e1c85d..aac44a1e6f3 100644 --- a/internal/generate/clusterserviceversion/bases/definitions/zz_generated.markerhelp.go +++ b/internal/generate/clusterserviceversion/bases/definitions/zz_generated.markerhelp.go @@ -38,6 +38,10 @@ func (Description) Help() *markers.DefinitionHelp { Summary: "is the displayName of a CRD description.", Details: "", }, + "Order": markers.DetailedHelp{ + Summary: "determines which position in the list this description will take. Markers with Order omitted have the highest Order. If more than one marker has the same Order, the corresponding descriptions will be sorted alphabetically and placed above others with higher Orders.", + Details: "", + }, }, } } @@ -62,6 +66,10 @@ func (Descriptor) Help() *markers.DefinitionHelp { Summary: "is a list of UI path strings. The marker format is: \"ui:element:foo,ui:element:bar\"", Details: "", }, + "Order": markers.DetailedHelp{ + Summary: "determines which position in the list this descriptor will take. Markers with Order omitted have the highest Order. If more than one marker has the same Order, the corresponding descriptors will be sorted alphabetically and placed above others with higher Orders.", + Details: "", + }, }, } } diff --git a/website/content/en/docs/building-operators/golang/references/markers.md b/website/content/en/docs/building-operators/golang/references/markers.md index cda65ae340e..ac76d2e4fa7 100644 --- a/website/content/en/docs/building-operators/golang/references/markers.md +++ b/website/content/en/docs/building-operators/golang/references/markers.md @@ -25,13 +25,16 @@ Possible type-level markers: - Configures the kind's display name. - `+operator-sdk:csv:customresourcedefinitions:resources={{Kind1,v1alpha1,dns-name-1},{Kind2,v1,"dns-name-2"},...}` - Configures the kind's resources. +- `+operator-sdk:csv:customresourcedefinitions:order=1` + - Configures the order of this type in the list. Markers with order omitted have the highest order, i.e. are at the end of the list. If more than one marker has the same order, the corresponding descriptions will be sorted alphabetically and placed above others with higher orders. Pre-existing list elements in the CSV will be appended to the set of other elements in the order corresponding to its index. Possible field-level markers, all of which must contain the `type=[spec,status]` key-value pair: - `+operator-sdk:csv:customresourcedefinitions:type=[spec,status],displayName="some field display name"` - Configures the field's display name. - `+operator-sdk:csv:customresourcedefinitions:type=[spec,status],xDescriptors={"urn:alm:descriptor:com.tectonic.ui:podCount","urn:alm:descriptor:io.kubernetes:custom"}` - Configures the field's x-descriptors. - +- `+operator-sdk:csv:customresourcedefinitions:type=[spec,status],order=1` + - Configures the order of this type in the list. Markers with order omitted have the highest order, i.e. are at the end of the list. If more than one marker has the same order, the corresponding descriptions will be sorted alphabetically and placed above others with higher orders. Top-level `kind`, `name`, and `version` fields are parsed from API code. All `description` fields are parsed from type declaration and `struct` type field comments. From 77e41e96affcb006ef9f0e993cf5deb557e56793 Mon Sep 17 00:00:00 2001 From: anmol372 Date: Thu, 3 Dec 2020 16:12:23 -0500 Subject: [PATCH 228/376] generate: add `--package` and permit extra-project use of `` (#4074) This commit allows CSVs to be passed into 'generate ' commands and updated verbatim, and removes their dependency on a project config. Version is used to overwrite CSV name and `.spec.version` if `--version` is set, otherwise all metadata fields are unmodified. This allows, for example, `.spec.replaces` to be set or unset depending on what is in the input CSV. The `--package` flag was added to 'generate' subcommands to specify a package name different than the project config's `projectName`, which is used by default when available. internal/cmd/operator-sdk/generate: remove WithBase() option and read base directly from file if one was not passed into stdin. Also add the `--package` flag, which is required if not running in a project internal/generate/clusterserviceversion: remove dependency on bases in generator, change OperatorName -> PackageName internal/generate/collector: add CSV type to collector Co-authored-by: Eric Stroczynski Signed-off-by: reinvantveer --- .../refactor-generate-subcommands.yaml | 9 + hack/generate/samples/internal/pkg/utils.go | 5 +- internal/annotations/metrics/metrics.go | 19 +- .../operator-sdk/generate/bundle/bundle.go | 67 +++-- .../cmd/operator-sdk/generate/bundle/cmd.go | 24 +- .../operator-sdk/generate/internal/genutil.go | 26 +- .../generate/kustomize/manifests.go | 83 +++++- .../generate/packagemanifests/cmd.go | 19 +- .../packagemanifests/packagemanifests.go | 55 ++-- .../clusterserviceversion.go | 143 +++------- .../clusterserviceversion_test.go | 229 ++++++---------- internal/generate/collector/manifests.go | 20 ++ ...cached-operator.clusterserviceversion.yaml | 27 +- ...cached-operator.clusterserviceversion.yaml | 58 +--- ...ith-ui-metadata.clusterserviceversion.yaml | 255 ++++++++++++++++++ internal/util/projutil/project_util.go | 9 + .../docs/cli/operator-sdk_generate_bundle.md | 1 + ...erator-sdk_generate_kustomize_manifests.md | 3 +- .../operator-sdk_generate_packagemanifests.md | 1 + 19 files changed, 602 insertions(+), 451 deletions(-) create mode 100644 changelog/fragments/refactor-generate-subcommands.yaml create mode 100644 internal/generate/testdata/clusterserviceversions/output/with-ui-metadata.clusterserviceversion.yaml diff --git a/changelog/fragments/refactor-generate-subcommands.yaml b/changelog/fragments/refactor-generate-subcommands.yaml new file mode 100644 index 00000000000..54f70d00526 --- /dev/null +++ b/changelog/fragments/refactor-generate-subcommands.yaml @@ -0,0 +1,9 @@ +entries: + - description: > + Added the `--package ` flag to all `generate` subcommands. This flag is required by `generate bundle|packagemanifests` when not run in a project. + kind: "addition" + breaking: false + - description: > + Refactored the `generate bundle|packagemanifest` commands to generate bundles/package manifest data outside of projects. + kind: "bugfix" + breaking: false diff --git a/hack/generate/samples/internal/pkg/utils.go b/hack/generate/samples/internal/pkg/utils.go index c7c63c8b9cd..d1dbefeb5c8 100644 --- a/hack/generate/samples/internal/pkg/utils.go +++ b/hack/generate/samples/internal/pkg/utils.go @@ -22,7 +22,6 @@ import ( "regexp" log "github.com/sirupsen/logrus" - "sigs.k8s.io/kubebuilder/v2/pkg/model/config" "github.com/operator-framework/operator-sdk/internal/annotations/metrics" ) @@ -54,7 +53,7 @@ func (ctx *SampleContext) CreateBundle() { // available in git history. func (ctx SampleContext) StripBundleAnnotations() (err error) { // Remove metadata labels. - metadataAnnotations := metrics.MakeBundleMetadataLabels(&config.Config{}) + metadataAnnotations := metrics.MakeBundleMetadataLabels("") metadataFiles := []string{ filepath.Join(ctx.Dir, "bundle", "metadata", "annotations.yaml"), filepath.Join(ctx.Dir, "bundle.Dockerfile"), @@ -64,7 +63,7 @@ func (ctx SampleContext) StripBundleAnnotations() (err error) { } // Remove manifests annotations. - manifestsAnnotations := metrics.MakeBundleObjectAnnotations(&config.Config{}) + manifestsAnnotations := metrics.MakeBundleObjectAnnotations("") manifestsFiles := []string{ filepath.Join(ctx.Dir, "bundle", "manifests", ctx.ProjectName+".clusterserviceversion.yaml"), filepath.Join(ctx.Dir, "config", "manifests", "bases", ctx.ProjectName+".clusterserviceversion.yaml"), diff --git a/internal/annotations/metrics/metrics.go b/internal/annotations/metrics/metrics.go index 1d2ce56760d..fa364590215 100644 --- a/internal/annotations/metrics/metrics.go +++ b/internal/annotations/metrics/metrics.go @@ -18,8 +18,6 @@ import ( "regexp" "strings" - "sigs.k8s.io/kubebuilder/v2/pkg/model/config" - sdkversion "github.com/operator-framework/operator-sdk/internal/version" ) @@ -43,20 +41,20 @@ const ( // MakeBundleMetadataLabels returns the SDK metric labels which will be added // to bundle resources like bundle.Dockerfile and annotations.yaml. -func MakeBundleMetadataLabels(cfg *config.Config) map[string]string { +func MakeBundleMetadataLabels(layout string) map[string]string { return map[string]string{ mediaTypeBundleAnnotation: mediaTypeV1, builderBundleAnnotation: getSDKBuilder(sdkversion.Version), - layoutBundleAnnotation: getSDKProjectLayout(cfg), + layoutBundleAnnotation: layout, } } // MakeObjectAnnotations returns the SDK metric annotations which will be added // to CustomResourceDefinitions and ClusterServiceVersions. -func MakeBundleObjectAnnotations(cfg *config.Config) map[string]string { +func MakeBundleObjectAnnotations(layout string) map[string]string { return map[string]string{ BuilderObjectAnnotation: getSDKBuilder(sdkversion.Version), - LayoutObjectAnnotation: getSDKProjectLayout(cfg), + LayoutObjectAnnotation: layout, } } @@ -85,12 +83,3 @@ func isUnreleased(input string) bool { re := regexp.MustCompile(`v[0-9]+\.[0-9]+\.[0-9]+-.+`) return re.MatchString(input) } - -// getSDKProjectLayout returns the `layout` field in PROJECT file that is v3. -// If not, it will return "go" because that was the only project type supported for project versions < v3. -func getSDKProjectLayout(cfg *config.Config) string { - if !cfg.IsV3() || cfg.Layout == "" { - return "go" - } - return cfg.Layout -} diff --git a/internal/cmd/operator-sdk/generate/bundle/bundle.go b/internal/cmd/operator-sdk/generate/bundle/bundle.go index e002254ab75..d2e06dceec9 100644 --- a/internal/cmd/operator-sdk/generate/bundle/bundle.go +++ b/internal/cmd/operator-sdk/generate/bundle/bundle.go @@ -25,13 +25,13 @@ import ( "github.com/operator-framework/api/pkg/apis/scorecard/v1alpha3" "github.com/operator-framework/operator-registry/pkg/lib/bundle" - "sigs.k8s.io/kubebuilder/v2/pkg/model/config" "sigs.k8s.io/yaml" metricsannotations "github.com/operator-framework/operator-sdk/internal/annotations/metrics" scorecardannotations "github.com/operator-framework/operator-sdk/internal/annotations/scorecard" genutil "github.com/operator-framework/operator-sdk/internal/cmd/operator-sdk/generate/internal" gencsv "github.com/operator-framework/operator-sdk/internal/generate/clusterserviceversion" + "github.com/operator-framework/operator-sdk/internal/generate/clusterserviceversion/bases" "github.com/operator-framework/operator-sdk/internal/generate/collector" "github.com/operator-framework/operator-sdk/internal/registry" "github.com/operator-framework/operator-sdk/internal/scorecard" @@ -105,15 +105,27 @@ https://github.com/operator-framework/operator-registry/#manifest-format const defaultRootDir = "bundle" // setDefaults sets defaults useful to all modes of this subcommand. -func (c *bundleCmd) setDefaults(cfg *config.Config) (err error) { - if c.projectName, err = genutil.GetOperatorName(cfg); err != nil { - return err +func (c *bundleCmd) setDefaults() error { + if projutil.HasProjectFile() { + cfg, err := projutil.ReadConfig() + if err != nil { + return err + } + if c.packageName == "" { + c.packageName = cfg.ProjectName + } + c.layout = projutil.GetProjectLayout(cfg) + } else { + if c.packageName == "" { + return fmt.Errorf("package name is required if PROJECT config file is not present") + } + c.layout = "unknown" } return nil } // validateManifests validates c for bundle manifests generation. -func (c bundleCmd) validateManifests(*config.Config) (err error) { +func (c bundleCmd) validateManifests() (err error) { if c.version != "" { if err := genutil.ValidateVersion(c.version); err != nil { return err @@ -143,7 +155,7 @@ func (c bundleCmd) validateManifests(*config.Config) (err error) { } // runManifests generates bundle manifests. -func (c bundleCmd) runManifests(cfg *config.Config) (err error) { +func (c bundleCmd) runManifests() (err error) { if !c.quiet && !c.stdout { if c.version == "" { @@ -174,26 +186,31 @@ func (c bundleCmd) runManifests(cfg *config.Config) (err error) { } } - csvGen := gencsv.Generator{ - OperatorName: c.projectName, - OperatorType: projutil.PluginKeyToOperatorType(cfg.Layout), - Version: c.version, - Collector: col, + // If no CSV is passed via stdin, an on-disk base is expected at basePath. + if len(col.ClusterServiceVersions) == 0 { + basePath := filepath.Join(c.kustomizeDir, "bases", c.packageName+".clusterserviceversion.yaml") + base, err := bases.ClusterServiceVersion{BasePath: basePath}.GetBase() + if err != nil { + return fmt.Errorf("error reading CSV base: %v", err) + } + col.ClusterServiceVersions = append(col.ClusterServiceVersions, *base) } + var opts []gencsv.Option stdout := genutil.NewMultiManifestWriter(os.Stdout) - opts := []gencsv.Option{ - // By not passing apisDir and turning interactive prompts on, we forcibly rely on the kustomize base - // for UI metadata and uninferrable data. - gencsv.WithBase(c.kustomizeDir, "", projutil.InteractiveHardOff), - } if c.stdout { opts = append(opts, gencsv.WithWriter(stdout)) } else { opts = append(opts, gencsv.WithBundleWriter(c.outputDir)) } - if err := csvGen.Generate(cfg, opts...); err != nil { + csvGen := gencsv.Generator{ + OperatorName: c.packageName, + Version: c.version, + Collector: col, + Annotations: metricsannotations.MakeBundleObjectAnnotations(c.layout), + } + if err := csvGen.Generate(opts...); err != nil { return fmt.Errorf("error generating ClusterServiceVersion: %v", err) } @@ -241,12 +258,12 @@ func writeScorecardConfig(dir string, cfg v1alpha3.Configuration) error { } // validateMetadata validates c for bundle metadata generation. -func (c bundleCmd) validateMetadata(*config.Config) (err error) { +func (c bundleCmd) validateMetadata() (err error) { return nil } // runMetadata generates a bundle.Dockerfile and bundle metadata. -func (c bundleCmd) runMetadata(cfg *config.Config) error { +func (c bundleCmd) runMetadata() error { directory := c.inputDir if directory == "" { @@ -266,14 +283,14 @@ func (c bundleCmd) runMetadata(cfg *config.Config) error { outputDir = "" } - return c.generateMetadata(cfg, directory, outputDir) + return c.generateMetadata(directory, outputDir) } // generateMetadata wraps the operator-registry bundle Dockerfile/metadata generator. -func (c bundleCmd) generateMetadata(cfg *config.Config, manifestsDir, outputDir string) error { +func (c bundleCmd) generateMetadata(manifestsDir, outputDir string) error { metadataExists := isMetatdataExist(outputDir, manifestsDir) - err := bundle.GenerateFunc(manifestsDir, outputDir, c.projectName, c.channels, c.defaultChannel, c.overwrite) + err := bundle.GenerateFunc(manifestsDir, outputDir, c.packageName, c.channels, c.defaultChannel, c.overwrite) if err != nil { return fmt.Errorf("error generating bundle metadata: %v", err) } @@ -285,7 +302,7 @@ func (c bundleCmd) generateMetadata(cfg *config.Config, manifestsDir, outputDir bundleRoot = filepath.Dir(manifestsDir) } - if err = updateMetadata(cfg, bundleRoot); err != nil { + if err = updateMetadata(c.layout, bundleRoot); err != nil { return err } } @@ -294,8 +311,8 @@ func (c bundleCmd) generateMetadata(cfg *config.Config, manifestsDir, outputDir // TODO(estroz): these updates need to be atomic because the bundle's Dockerfile and annotations.yaml // cannot be out-of-sync. -func updateMetadata(cfg *config.Config, bundleRoot string) error { - bundleLabels := metricsannotations.MakeBundleMetadataLabels(cfg) +func updateMetadata(layout, bundleRoot string) error { + bundleLabels := metricsannotations.MakeBundleMetadataLabels(layout) for key, value := range scorecardannotations.MakeBundleMetadataLabels(scorecard.DefaultConfigDir) { if _, hasKey := bundleLabels[key]; hasKey { return fmt.Errorf("internal error: duplicate bundle annotation key %s", key) diff --git a/internal/cmd/operator-sdk/generate/bundle/cmd.go b/internal/cmd/operator-sdk/generate/bundle/cmd.go index 9f33d34b9c1..d2178eb9994 100644 --- a/internal/cmd/operator-sdk/generate/bundle/cmd.go +++ b/internal/cmd/operator-sdk/generate/bundle/cmd.go @@ -21,8 +21,6 @@ import ( log "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/spf13/pflag" - - "github.com/operator-framework/operator-sdk/internal/util/projutil" ) //nolint:maligned @@ -32,7 +30,6 @@ type bundleCmd struct { metadata bool // Common options. - projectName string version string inputDir string outputDir string @@ -46,6 +43,10 @@ type bundleCmd struct { channels string defaultChannel string overwrite bool + + // These are set if a PROJECT config is not present. + layout string + packageName string } // NewCmd returns the 'bundle' command configured for the new project layout. @@ -68,36 +69,31 @@ func NewCmd() *cobra.Command { c.metadata = true } - cfg, err := projutil.ReadConfig() - if err != nil { - return fmt.Errorf("error reading configuration: %v", err) - } - - if err := c.setDefaults(cfg); err != nil { + if err := c.setDefaults(); err != nil { return err } // Validate command args before running so a preceding mode doesn't run // before a following validation fails. if c.manifests { - if err = c.validateManifests(cfg); err != nil { + if err := c.validateManifests(); err != nil { return fmt.Errorf("invalid command options: %v", err) } } if c.metadata { - if err = c.validateMetadata(cfg); err != nil { + if err := c.validateMetadata(); err != nil { return fmt.Errorf("invalid command options: %v", err) } } // Run command logic. if c.manifests { - if err = c.runManifests(cfg); err != nil { + if err := c.runManifests(); err != nil { log.Fatalf("Error generating bundle manifests: %v", err) } } if c.metadata { - if err = c.runMetadata(cfg); err != nil { + if err := c.runMetadata(); err != nil { log.Fatalf("Error generating bundle metadata: %v", err) } } @@ -131,4 +127,6 @@ func (c *bundleCmd) addFlagsTo(fs *pflag.FlagSet) { fs.StringVar(&c.defaultChannel, "default-channel", "", "The default channel for the bundle") fs.BoolVar(&c.overwrite, "overwrite", true, "Overwrite the bundle's metadata and Dockerfile if they exist") fs.BoolVarP(&c.quiet, "quiet", "q", false, "Run in quiet mode") + + fs.StringVar(&c.packageName, "package", "", "Bundle's package name") } diff --git a/internal/cmd/operator-sdk/generate/internal/genutil.go b/internal/cmd/operator-sdk/generate/internal/genutil.go index 00062e33358..46590416f27 100644 --- a/internal/cmd/operator-sdk/generate/internal/genutil.go +++ b/internal/cmd/operator-sdk/generate/internal/genutil.go @@ -26,9 +26,7 @@ import ( "github.com/blang/semver" apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" apiextv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" - "k8s.io/apimachinery/pkg/util/validation" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - "sigs.k8s.io/kubebuilder/v2/pkg/model/config" "sigs.k8s.io/yaml" ) @@ -152,23 +150,11 @@ func IsNotExist(path string) bool { return err != nil && errors.Is(err, os.ErrNotExist) } -// GetOperatorName returns the name of the operator which is by default the projectName attribute of the PROJECT file -// However, the Go projects built with the plugin version v2 has not this attribute and then, for this case -// the operatorName will be the current directory. -func GetOperatorName(cfg *config.Config) (string, error) { - if cfg.ProjectName != "" { - return cfg.ProjectName, nil - } - if cfg.IsV3() { - return "", errors.New("project config file must contain 'projectName'") - } - dir, err := os.Getwd() - if err != nil { - return "", fmt.Errorf("error getting current directory: %v", err) - } - projectName := strings.ToLower(filepath.Base(dir)) - if err := validation.IsDNS1123Label(projectName); err != nil { - return "", fmt.Errorf("project name (%s) is invalid: %v", projectName, err) +// IsExist returns true if path exists on disk. +func IsExist(path string) bool { + if path == "" { + return false } - return projectName, nil + _, err := os.Stat(path) + return err == nil || errors.Is(err, os.ErrExist) } diff --git a/internal/cmd/operator-sdk/generate/kustomize/manifests.go b/internal/cmd/operator-sdk/generate/kustomize/manifests.go index c0d35b55e22..954c3f99a51 100644 --- a/internal/cmd/operator-sdk/generate/kustomize/manifests.go +++ b/internal/cmd/operator-sdk/generate/kustomize/manifests.go @@ -16,16 +16,23 @@ package kustomize import ( "fmt" + "io/ioutil" + "os" "path/filepath" + "strings" log "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/spf13/pflag" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/validation" "sigs.k8s.io/kubebuilder/v2/pkg/model/config" + "sigs.k8s.io/yaml" genutil "github.com/operator-framework/operator-sdk/internal/cmd/operator-sdk/generate/internal" - gencsv "github.com/operator-framework/operator-sdk/internal/generate/clusterserviceversion" + "github.com/operator-framework/operator-sdk/internal/generate/clusterserviceversion/bases" "github.com/operator-framework/operator-sdk/internal/plugins/util/kustomize" + "github.com/operator-framework/operator-sdk/internal/util/k8sutil" "github.com/operator-framework/operator-sdk/internal/util/projutil" ) @@ -60,7 +67,7 @@ const examples = ` //nolint:maligned type manifestsCmd struct { - projectName string + packageName string inputDir string outputDir string apisDir string @@ -99,7 +106,7 @@ func newManifestsCmd() *cobra.Command { return fmt.Errorf("error reading configuration: %v", err) } - if err := c.setDefaults(cfg); err != nil { + if err = c.setDefaults(cfg); err != nil { return err } @@ -118,11 +125,12 @@ func newManifestsCmd() *cobra.Command { } func (c *manifestsCmd) addFlagsTo(fs *pflag.FlagSet) { + fs.StringVar(&c.packageName, "package", "", "Package name") fs.StringVar(&c.inputDir, "input-dir", "", "Directory containing existing kustomize files") fs.StringVar(&c.outputDir, "output-dir", "", "Directory to write kustomize files") fs.StringVar(&c.apisDir, "apis-dir", "", "Root directory for API type defintions") fs.BoolVarP(&c.quiet, "quiet", "q", false, "Run in quiet mode") - fs.BoolVar(&c.interactive, "interactive", false, "When set or no kustomize base exists, an interactive "+ + fs.BoolVar(&c.interactive, "interactive", false, "When set to false, if no kustomize base exists, an interactive "+ "command prompt will be presented to accept non-inferrable metadata") } @@ -130,9 +138,9 @@ func (c *manifestsCmd) addFlagsTo(fs *pflag.FlagSet) { var defaultDir = filepath.Join("config", "manifests") // setDefaults sets command defaults. -func (c *manifestsCmd) setDefaults(cfg *config.Config) (err error) { - if c.projectName, err = genutil.GetOperatorName(cfg); err != nil { - return err +func (c *manifestsCmd) setDefaults(cfg *config.Config) error { + if c.packageName == "" { + c.packageName = cfg.ProjectName } if c.inputDir == "" { @@ -141,6 +149,7 @@ func (c *manifestsCmd) setDefaults(cfg *config.Config) (err error) { if c.outputDir == "" { c.outputDir = defaultDir } + if c.apisDir == "" { if cfg.MultiGroup { c.apisDir = "apis" @@ -166,16 +175,48 @@ func (c manifestsCmd) run(cfg *config.Config) error { fmt.Println("Generating kustomize files in", c.outputDir) } - csvGen := gencsv.Generator{ - OperatorName: c.projectName, + // Older config layouts do not have a ProjectName field, so use the current directory name. + if c.packageName == "" { + dir, err := os.Getwd() + if err != nil { + return fmt.Errorf("error getting current directory: %v", err) + } + c.packageName = strings.ToLower(filepath.Base(dir)) + if err := validation.IsDNS1123Label(c.packageName); err != nil { + return fmt.Errorf("project name (%s) is invalid: %v", c.packageName, err) + } + } + + base := bases.ClusterServiceVersion{ + OperatorName: c.packageName, OperatorType: projutil.PluginKeyToOperatorType(cfg.Layout), + APIsDir: c.apisDir, + Interactive: isInteractive(c.interactiveLevel), + GVKs: getGVKs(cfg), } - opts := []gencsv.Option{ - gencsv.WithBase(c.inputDir, c.apisDir, c.interactiveLevel), - gencsv.WithBaseWriter(c.outputDir), + relBasePath := filepath.Join("bases", c.packageName+".clusterserviceversion.yaml") + basePath := filepath.Join(c.inputDir, relBasePath) + + // Set BasePath only if it exists. If it doesn't, a new base will be generated + // if BasePath is empty. + if genutil.IsExist(basePath) { + base.BasePath = basePath } - if err := csvGen.Generate(cfg, opts...); err != nil { - return fmt.Errorf("error generating kustomize bases: %v", err) + csv, err := base.GetBase() + if err != nil { + return fmt.Errorf("error getting ClusterServiceVersion base: %v", err) + } + + csvBytes, err := k8sutil.GetObjectBytes(csv, yaml.Marshal) + if err != nil { + return fmt.Errorf("error marshaling CSV base: %v", err) + } + if err = os.MkdirAll(filepath.Join(c.outputDir, "bases"), 0755); err != nil { + return err + } + outputPath := filepath.Join(c.outputDir, relBasePath) + if err = ioutil.WriteFile(outputPath, csvBytes, 0644); err != nil { + return fmt.Errorf("error writing CSV base: %v", err) } // Write a kustomization.yaml to outputDir if one does not exist. @@ -189,3 +230,17 @@ func (c manifestsCmd) run(cfg *config.Config) error { return nil } + +func isInteractive(ilvl projutil.InteractiveLevel) bool { + return (ilvl == projutil.InteractiveSoftOff || ilvl == projutil.InteractiveOnAll) +} + +func getGVKs(cfg *config.Config) []schema.GroupVersionKind { + gvks := make([]schema.GroupVersionKind, len(cfg.Resources)) + for i, gvk := range cfg.Resources { + gvks[i].Group = fmt.Sprintf("%s.%s", gvk.Group, cfg.Domain) + gvks[i].Version = gvk.Version + gvks[i].Kind = gvk.Kind + } + return gvks +} diff --git a/internal/cmd/operator-sdk/generate/packagemanifests/cmd.go b/internal/cmd/operator-sdk/generate/packagemanifests/cmd.go index fc5d7e0ff8b..d75488d3c4f 100644 --- a/internal/cmd/operator-sdk/generate/packagemanifests/cmd.go +++ b/internal/cmd/operator-sdk/generate/packagemanifests/cmd.go @@ -21,14 +21,11 @@ import ( log "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/spf13/pflag" - - "github.com/operator-framework/operator-sdk/internal/util/projutil" ) //nolint:maligned type packagemanifestsCmd struct { // Common options. - projectName string version string fromVersion string inputDir string @@ -43,6 +40,10 @@ type packagemanifestsCmd struct { // Package manifest options. channelName string isDefaultChannel bool + + // These are set if a PROJECT config is not present. + layout string + packageName string } // NewCmd returns the 'packagemanifests' command configured for the new project layout. @@ -59,18 +60,14 @@ func NewCmd() *cobra.Command { return fmt.Errorf("command %s doesn't accept any arguments", cmd.CommandPath()) } - cfg, err := projutil.ReadConfig() - if err != nil { - log.Fatal(fmt.Errorf("error reading configuration: %v", err)) - } - if err := c.setDefaults(cfg); err != nil { + if err := c.setDefaults(); err != nil { return err } - if err = c.validate(); err != nil { + if err := c.validate(); err != nil { return fmt.Errorf("invalid command options: %v", err) } - if err = c.run(cfg); err != nil { + if err := c.run(); err != nil { log.Fatalf("Error generating package manifests: %v", err) } @@ -101,4 +98,6 @@ func (c *packagemanifestsCmd) addFlagsTo(fs *pflag.FlagSet) { "ex. CustomResoureDefinitions, Roles") fs.BoolVarP(&c.quiet, "quiet", "q", false, "Run in quiet mode") fs.BoolVar(&c.stdout, "stdout", false, "Write package to stdout") + + fs.StringVar(&c.packageName, "package", "", "Package name") } diff --git a/internal/cmd/operator-sdk/generate/packagemanifests/packagemanifests.go b/internal/cmd/operator-sdk/generate/packagemanifests/packagemanifests.go index 9f7abe6385b..103bed33597 100644 --- a/internal/cmd/operator-sdk/generate/packagemanifests/packagemanifests.go +++ b/internal/cmd/operator-sdk/generate/packagemanifests/packagemanifests.go @@ -20,10 +20,10 @@ import ( "os" "path/filepath" - "sigs.k8s.io/kubebuilder/v2/pkg/model/config" - + metricsannotations "github.com/operator-framework/operator-sdk/internal/annotations/metrics" genutil "github.com/operator-framework/operator-sdk/internal/cmd/operator-sdk/generate/internal" gencsv "github.com/operator-framework/operator-sdk/internal/generate/clusterserviceversion" + "github.com/operator-framework/operator-sdk/internal/generate/clusterserviceversion/bases" "github.com/operator-framework/operator-sdk/internal/generate/collector" genpkg "github.com/operator-framework/operator-sdk/internal/generate/packagemanifest" "github.com/operator-framework/operator-sdk/internal/util/projutil" @@ -78,9 +78,21 @@ https://github.com/operator-framework/operator-registry/#manifest-format const defaultRootDir = "packagemanifests" // setDefaults sets command defaults. -func (c *packagemanifestsCmd) setDefaults(cfg *config.Config) (err error) { - if c.projectName, err = genutil.GetOperatorName(cfg); err != nil { - return err +func (c *packagemanifestsCmd) setDefaults() error { + if projutil.HasProjectFile() { + cfg, err := projutil.ReadConfig() + if err != nil { + return err + } + if c.packageName == "" { + c.packageName = cfg.ProjectName + } + c.layout = projutil.GetProjectLayout(cfg) + } else { + if c.packageName == "" { + return fmt.Errorf("package name is required if PROJECT config file is not present") + } + c.layout = "unknown" } if c.inputDir == "" { @@ -141,7 +153,7 @@ func (c packagemanifestsCmd) validate() error { } // run generates package manifests. -func (c packagemanifestsCmd) run(cfg *config.Config) error { +func (c packagemanifestsCmd) run() error { if !c.quiet && !c.stdout { fmt.Println("Generating package manifests version", c.version) @@ -163,27 +175,32 @@ func (c packagemanifestsCmd) run(cfg *config.Config) error { } } - csvGen := gencsv.Generator{ - OperatorName: c.projectName, - OperatorType: projutil.PluginKeyToOperatorType(cfg.Layout), - Version: c.version, - FromVersion: c.fromVersion, - Collector: col, + // If no CSV is passed via stdin, an on-disk base is expected at basePath. + if len(col.ClusterServiceVersions) == 0 { + basePath := filepath.Join(c.kustomizeDir, "bases", c.packageName+".clusterserviceversion.yaml") + base, err := bases.ClusterServiceVersion{BasePath: basePath}.GetBase() + if err != nil { + return fmt.Errorf("error reading CSV base: %v", err) + } + col.ClusterServiceVersions = append(col.ClusterServiceVersions, *base) } + var opts []gencsv.Option stdout := genutil.NewMultiManifestWriter(os.Stdout) - opts := []gencsv.Option{ - // By not passing apisDir and turning interactive prompts on, we forcibly rely on the kustomize base - // for UI metadata and uninferrable data. - gencsv.WithBase(c.kustomizeDir, "", projutil.InteractiveHardOff), - } if c.stdout { opts = append(opts, gencsv.WithWriter(stdout)) } else { opts = append(opts, gencsv.WithPackageWriter(c.outputDir)) } - if err := csvGen.Generate(cfg, opts...); err != nil { + csvGen := gencsv.Generator{ + OperatorName: c.packageName, + Version: c.version, + FromVersion: c.fromVersion, + Collector: col, + Annotations: metricsannotations.MakeBundleObjectAnnotations(c.layout), + } + if err := csvGen.Generate(opts...); err != nil { return fmt.Errorf("error generating ClusterServiceVersion: %v", err) } @@ -210,7 +227,7 @@ func (c packagemanifestsCmd) run(cfg *config.Config) error { func (c packagemanifestsCmd) generatePackageManifest() error { pkgGen := genpkg.Generator{ - OperatorName: c.projectName, + OperatorName: c.packageName, Version: c.version, ChannelName: c.channelName, IsDefaultChannel: c.isDefaultChannel, diff --git a/internal/generate/clusterserviceversion/clusterserviceversion.go b/internal/generate/clusterserviceversion/clusterserviceversion.go index b74b3e02c8a..ba95f1ec066 100644 --- a/internal/generate/clusterserviceversion/clusterserviceversion.go +++ b/internal/generate/clusterserviceversion/clusterserviceversion.go @@ -24,10 +24,7 @@ import ( "github.com/operator-framework/api/pkg/operators/v1alpha1" operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1" "github.com/operator-framework/operator-registry/pkg/lib/bundle" - "k8s.io/apimachinery/pkg/runtime/schema" - "sigs.k8s.io/kubebuilder/v2/pkg/model/config" - metricsannotations "github.com/operator-framework/operator-sdk/internal/annotations/metrics" "github.com/operator-framework/operator-sdk/internal/generate/clusterserviceversion/bases" "github.com/operator-framework/operator-sdk/internal/generate/collector" genutil "github.com/operator-framework/operator-sdk/internal/generate/internal" @@ -41,17 +38,13 @@ const ( var ( // Internal errors. - noGetBaseError = genutil.InternalError("getBase must be set") - noGetWriterError = genutil.InternalError("getWriter must be set") - baseVersionNotAllowedError = genutil.InternalError("cannot set version when generating a base") - baseCollectorNotAllowedError = genutil.InternalError("cannot set collector when generating a base") + noGetWriterError = genutil.InternalError("getWriter must be set") ) // ClusterServiceVersion configures ClusterServiceVersion manifest generation. type Generator struct { // OperatorName is the operator's name, ex. app-operator. OperatorName string - // OperatorType determines what code API types are written in for getBase. OperatorType projutil.OperatorType // Version is the CSV current version. Version string @@ -59,11 +52,9 @@ type Generator struct { FromVersion string // Collector holds all manifests relevant to the Generator. Collector *collector.Manifests + // Annotations are applied to the resulting CSV. + Annotations map[string]string - // Project configuration. - config *config.Config - // Func that returns a base CSV. - getBase getBaseFunc // Func that returns the writer the generated CSV's bytes are written to. getWriter func() (io.Writer, error) // If the CSV is destined for a bundle this will be the path of the updated @@ -72,20 +63,9 @@ type Generator struct { bundledPath string } -// Type of Generator.getBase. -type getBaseFunc func() (*operatorsv1alpha1.ClusterServiceVersion, error) - // Option is a function that modifies a Generator. type Option func(*Generator) error -// WithBase sets a Generator's base CSV to a kustomize-style base. -func WithBase(inputDir, apisDir string, ilvl projutil.InteractiveLevel) Option { - return func(g *Generator) error { - g.getBase = g.makeKustomizeBaseGetter(inputDir, apisDir, ilvl) - return nil - } -} - // WithWriter sets a Generator's writer to w. func WithWriter(w io.Writer) Option { return func(g *Generator) error { @@ -96,25 +76,6 @@ func WithWriter(w io.Writer) Option { } } -// WithBaseWriter sets a Generator's writer to a kustomize-style base file -// under /bases. -func WithBaseWriter(dir string) Option { - return func(g *Generator) error { - fileName := makeCSVFileName(g.OperatorName) - g.getWriter = func() (io.Writer, error) { - return genutil.Open(filepath.Join(dir, "bases"), fileName) - } - // Bases should not be updated with a version or manifests. - if g.Version != "" { - return baseVersionNotAllowedError - } - if g.Collector != nil { - return baseCollectorNotAllowedError - } - return nil - } -} - // WithBundleWriter sets a Generator's writer to a bundle CSV file under // /manifests. func WithBundleWriter(dir string) Option { @@ -143,9 +104,8 @@ func WithPackageWriter(dir string) Option { } } -// Generate configures the generator with cfg and opts then runs it. -func (g *Generator) Generate(cfg *config.Config, opts ...Option) (err error) { - g.config = cfg +// Generate configures the generator with col and opts then runs it. +func (g *Generator) Generate(opts ...Option) (err error) { for _, opt := range opts { if err = opt(g); err != nil { return err @@ -161,8 +121,8 @@ func (g *Generator) Generate(cfg *config.Config, opts ...Option) (err error) { return err } - // Add sdk labels to csv - g.setSDKAnnotations(csv) + // Add extra annotations to csv + g.setAnnotations(csv) w, err := g.getWriter() if err != nil { @@ -172,39 +132,56 @@ func (g *Generator) Generate(cfg *config.Config, opts ...Option) (err error) { } // setSDKAnnotations adds SDK metric labels to the base if they do not exist. -func (g Generator) setSDKAnnotations(csv *v1alpha1.ClusterServiceVersion) { +func (g Generator) setAnnotations(csv *v1alpha1.ClusterServiceVersion) { annotations := csv.GetAnnotations() if annotations == nil { annotations = make(map[string]string) } - - for key, value := range metricsannotations.MakeBundleObjectAnnotations(g.config) { - annotations[key] = value + for k, v := range g.Annotations { + annotations[k] = v } csv.SetAnnotations(annotations) } // generate runs a configured Generator. -func (g *Generator) generate() (*operatorsv1alpha1.ClusterServiceVersion, error) { - if g.getBase == nil { - return nil, noGetBaseError +func (g *Generator) generate() (base *operatorsv1alpha1.ClusterServiceVersion, err error) { + if g.Collector == nil { + return nil, fmt.Errorf("cannot generate CSV without a manifests collection") + } + + // Search for a CSV in the collector with a name matching the package name, + // but prefer an exact match ".vX.Y.Z" to preserve existing behavior. + var oldBase *operatorsv1alpha1.ClusterServiceVersion + csvNamePrefix := g.OperatorName + "." + oldBaseCSVName := genutil.MakeCSVName(g.OperatorName, "X.Y.Z") + for _, csv := range g.Collector.ClusterServiceVersions { + if csv.GetName() == oldBaseCSVName { + oldBase = csv.DeepCopy() + } else if base == nil && strings.HasPrefix(csv.GetName(), csvNamePrefix) { + base = csv.DeepCopy() + } } - base, err := g.getBase() - if err != nil { - return nil, fmt.Errorf("error getting ClusterServiceVersion base: %v", err) + if base == nil && oldBase == nil { + return nil, fmt.Errorf("no CSV found with name prefix %q", csvNamePrefix) + } else if oldBase != nil { + // Only update versions in the old way to preserve existing behavior. + base = oldBase + if err := g.updateVersionsWithReplaces(base); err != nil { + return nil, err + } + } else if g.Version != "" { + // Use the existing version/name unless g.Version is set. + base.SetName(genutil.MakeCSVName(g.OperatorName, g.Version)) + if base.Spec.Version.Version, err = semver.Parse(g.Version); err != nil { + return nil, err + } } - if err = g.updateVersions(base); err != nil { + if err := ApplyTo(g.Collector, base); err != nil { return nil, err } - if g.Collector != nil { - if err := ApplyTo(g.Collector, base); err != nil { - return nil, err - } - } - return base, nil } @@ -213,49 +190,16 @@ func makeCSVFileName(name string) string { return strings.ToLower(name) + csvYamlFileExt } -// makeKustomizeBaseGetter returns a function that gets a kustomize-style base. -func (g Generator) makeKustomizeBaseGetter(inputDir, apisDir string, ilvl projutil.InteractiveLevel) getBaseFunc { - basePath := filepath.Join(inputDir, "bases", makeCSVFileName(g.OperatorName)) - if genutil.IsNotExist(basePath) { - basePath = "" - } - - return g.makeBaseGetter(basePath, apisDir, requiresInteraction(basePath, ilvl)) -} - -// makeBaseGetter returns a function that gets a base from inputDir. -// apisDir is used by getBaseFunc to populate base fields. -func (g Generator) makeBaseGetter(basePath, apisDir string, interactive bool) getBaseFunc { - gvks := make([]schema.GroupVersionKind, len(g.config.Resources)) - for i, gvk := range g.config.Resources { - gvks[i].Group = fmt.Sprintf("%s.%s", gvk.Group, g.config.Domain) - gvks[i].Version = gvk.Version - gvks[i].Kind = gvk.Kind - } - - return func() (*operatorsv1alpha1.ClusterServiceVersion, error) { - b := bases.ClusterServiceVersion{ - OperatorName: g.OperatorName, - OperatorType: g.OperatorType, - BasePath: basePath, - APIsDir: apisDir, - GVKs: gvks, - Interactive: interactive, - } - return b.GetBase() - } -} - // requiresInteraction checks if the combination of ilvl and basePath existence // requires the generator prompt a user interactively. func requiresInteraction(basePath string, ilvl projutil.InteractiveLevel) bool { return (ilvl == projutil.InteractiveSoftOff && genutil.IsNotExist(basePath)) || ilvl == projutil.InteractiveOnAll } -// updateVersions updates csv's version and data involving the version, +// updateVersionsWithReplaces updates csv's version and data involving the version, // ex. ObjectMeta.Name, and place the old version in the `replaces` object, // if there is an old version to replace. -func (g Generator) updateVersions(csv *operatorsv1alpha1.ClusterServiceVersion) (err error) { +func (g Generator) updateVersionsWithReplaces(csv *operatorsv1alpha1.ClusterServiceVersion) (err error) { oldVer, newVer := csv.Spec.Version.String(), g.Version newName := genutil.MakeCSVName(g.OperatorName, newVer) @@ -279,7 +223,6 @@ func (g Generator) updateVersions(csv *operatorsv1alpha1.ClusterServiceVersion) } // Set replaces by default. - // TODO: consider all possible CSV versioning schemes supported by OLM. if oldVer != "0.0.0" && newVer != oldVer { csv.Spec.Replaces = oldName } diff --git a/internal/generate/clusterserviceversion/clusterserviceversion_test.go b/internal/generate/clusterserviceversion/clusterserviceversion_test.go index 578bc7643bc..ef6428c8d4c 100644 --- a/internal/generate/clusterserviceversion/clusterserviceversion_test.go +++ b/internal/generate/clusterserviceversion/clusterserviceversion_test.go @@ -16,11 +16,9 @@ package clusterserviceversion import ( "bytes" - "fmt" "io/ioutil" "os" "path/filepath" - "regexp" "github.com/blang/semver" . "github.com/onsi/ginkgo" @@ -30,10 +28,8 @@ import ( "github.com/operator-framework/api/pkg/operators/v1alpha1" "github.com/operator-framework/operator-registry/pkg/lib/bundle" appsv1 "k8s.io/api/apps/v1" - "sigs.k8s.io/kubebuilder/v2/pkg/model/config" "sigs.k8s.io/yaml" - metricsannotations "github.com/operator-framework/operator-sdk/internal/annotations/metrics" "github.com/operator-framework/operator-sdk/internal/generate/collector" genutil "github.com/operator-framework/operator-sdk/internal/generate/internal" "github.com/operator-framework/operator-sdk/internal/util/projutil" @@ -46,32 +42,28 @@ var ( csvNewLayoutBundleDir = filepath.Join(csvDir, "output") goTestDataDir = filepath.Join(testDataDir, "go") - goAPIsDir = filepath.Join(goTestDataDir, "api") goStaticDir = filepath.Join(goTestDataDir, "static") goBasicOperatorPath = filepath.Join(goStaticDir, "basic.operator.yaml") ) var ( col *collector.Manifests - cfg *config.Config -) - -const ( - testSDKbuilderAnnotationKey = "operators.operatorframework.io/builder" - testSDKlayoutAnnotationKey = "operators.operatorframework.io/project_layout" ) var ( - baseCSV, baseCSVUIMeta, newCSV *v1alpha1.ClusterServiceVersion - baseCSVStr, baseCSVUIMetaStr, newCSVStr string + // Base CSVs + baseCSV, baseCSVUIMeta *v1alpha1.ClusterServiceVersion + baseCSVStr, baseCSVUIMetaStr string + + // Updated CSVs + newCSV, newCSVUIMeta *v1alpha1.ClusterServiceVersion + newCSVUIMetaStr string ) var _ = BeforeSuite(func() { col = &collector.Manifests{} collectManifestsFromFileHelper(col, goBasicOperatorPath) - cfg = readConfigHelper(goTestDataDir) - initTestCSVsHelper() }) @@ -83,8 +75,8 @@ var _ = Describe("Generating a ClusterServiceVersion", func() { g Generator buf *bytes.Buffer operatorName = "memcached-operator" - operatorType = projutil.OperatorTypeGo - version = "0.0.1" + zeroZeroOne = "0.0.1" + zeroZeroTwo = "0.0.2" ) BeforeEach(func() { @@ -103,94 +95,55 @@ var _ = Describe("Generating a ClusterServiceVersion", func() { BeforeEach(func() { tmp, err = ioutil.TempDir(".", "") Expect(err).ToNot(HaveOccurred()) + col.ClusterServiceVersions = []v1alpha1.ClusterServiceVersion{*baseCSVUIMeta} }) AfterEach(func() { if tmp != "" { os.RemoveAll(tmp) } + col.ClusterServiceVersions = nil }) It("should write a ClusterServiceVersion manifest to an io.Writer", func() { g = Generator{ OperatorName: operatorName, - OperatorType: operatorType, - Version: version, + Version: zeroZeroOne, Collector: col, } opts := []Option{ - WithBase(csvBasesDir, goAPIsDir, projutil.InteractiveHardOff), WithWriter(buf), } - Expect(g.Generate(cfg, opts...)).ToNot(HaveOccurred()) - outputCSV := removeSDKAnnotationsFromCSVString(buf.String()) - Expect(outputCSV).To(MatchYAML(newCSVStr)) - }) - It("should write a ClusterServiceVersion manifest to a base file", func() { - g = Generator{ - OperatorName: operatorName, - OperatorType: operatorType, - } - opts := []Option{ - WithBase(csvBasesDir, goAPIsDir, projutil.InteractiveHardOff), - WithBaseWriter(tmp), - } - Expect(g.Generate(cfg, opts...)).ToNot(HaveOccurred()) - outputFile := filepath.Join(tmp, "bases", makeCSVFileName(operatorName)) - Expect(outputFile).To(BeAnExistingFile()) - Expect(readFileHelper(outputFile)).To(MatchYAML(baseCSVUIMetaStr)) - }) - It("should have sdk labels in annotations", func() { - g = Generator{ - OperatorName: operatorName, - OperatorType: operatorType, - } - opts := []Option{ - WithBase(csvBasesDir, goAPIsDir, projutil.InteractiveHardOff), - WithBaseWriter(tmp), - } - Expect(g.Generate(cfg, opts...)).ToNot(HaveOccurred()) - outputFile := filepath.Join(tmp, "bases", makeCSVFileName(operatorName)) - outputCSV, _, err := getCSVFromFile(outputFile) - Expect(err).ToNot(HaveOccurred()) - Expect(outputFile).To(BeAnExistingFile()) - - annotations := outputCSV.GetAnnotations() - Expect(annotations).ToNot(BeNil()) - Expect(annotations).Should(HaveKey(metricsannotations.BuilderObjectAnnotation)) - Expect(annotations).Should(HaveKey(metricsannotations.LayoutObjectAnnotation)) + Expect(g.Generate(opts...)).ToNot(HaveOccurred()) + Expect(buf.String()).To(MatchYAML(newCSVUIMetaStr)) }) It("should write a ClusterServiceVersion manifest to a bundle file", func() { g = Generator{ OperatorName: operatorName, - OperatorType: operatorType, - Version: version, + Version: zeroZeroOne, Collector: col, } opts := []Option{ - WithBase(csvBasesDir, goAPIsDir, projutil.InteractiveHardOff), WithBundleWriter(tmp), } - Expect(g.Generate(cfg, opts...)).ToNot(HaveOccurred()) + Expect(g.Generate(opts...)).ToNot(HaveOccurred()) outputFile := filepath.Join(tmp, bundle.ManifestsDir, makeCSVFileName(operatorName)) Expect(outputFile).To(BeAnExistingFile()) - Expect(readFileHelper(outputFile)).To(MatchYAML(newCSVStr)) + Expect(readFileHelper(outputFile)).To(MatchYAML(newCSVUIMetaStr)) }) It("should write a ClusterServiceVersion manifest to a package file", func() { g = Generator{ OperatorName: operatorName, - OperatorType: operatorType, - Version: version, + Version: zeroZeroOne, Collector: col, } opts := []Option{ - WithBase(csvBasesDir, goAPIsDir, projutil.InteractiveHardOff), WithPackageWriter(tmp), } - Expect(g.Generate(cfg, opts...)).ToNot(HaveOccurred()) + Expect(g.Generate(opts...)).ToNot(HaveOccurred()) outputFile := filepath.Join(tmp, g.Version, makeCSVFileName(operatorName)) Expect(outputFile).To(BeAnExistingFile()) - Expect(readFileHelper(outputFile)).To(MatchYAML(newCSVStr)) + Expect(readFileHelper(outputFile)).To(MatchYAML(newCSVUIMetaStr)) }) }) @@ -199,68 +152,68 @@ var _ = Describe("Generating a ClusterServiceVersion", func() { BeforeEach(func() { g = Generator{ OperatorName: operatorName, - OperatorType: operatorType, - Version: version, + Version: zeroZeroOne, Collector: col, } }) It("should return an error without any Options", func() { opts := []Option{} - Expect(g.Generate(cfg, opts...)).To(MatchError(noGetWriterError)) - }) - It("should return an error without a getWriter", func() { - opts := []Option{ - WithBase(csvBasesDir, goAPIsDir, projutil.InteractiveHardOff), - } - Expect(g.Generate(cfg, opts...)).To(MatchError(noGetWriterError)) - }) - It("should return an error without a getBase", func() { - opts := []Option{ - WithWriter(&bytes.Buffer{}), - } - Expect(g.Generate(cfg, opts...)).To(MatchError(noGetBaseError)) + Expect(g.Generate(opts...)).To(MatchError(noGetWriterError)) }) }) - Context("to create a new base ClusterServiceVersion", func() { - It("should return the default base object", func() { + Context("to create a new ClusterServiceVersion", func() { + It("should return a valid object", func() { + col.ClusterServiceVersions = []v1alpha1.ClusterServiceVersion{*baseCSV} g = Generator{ OperatorName: operatorName, - OperatorType: operatorType, - config: cfg, - getBase: makeBaseGetter(baseCSV), + Version: zeroZeroOne, + Collector: col, } csv, err := g.generate() Expect(err).ToNot(HaveOccurred()) - Expect(csv).To(Equal(baseCSV)) + Expect(csv).To(Equal(newCSV)) }) - It("should return a base object with customresourcedefinitions", func() { + It("should return an object with '.spec.replaces' and '.metadata.annotations['olm.skipRange']'", func() { + baseCSVUIMetaIn := baseCSVUIMeta.DeepCopy() + baseCSVUIMetaIn.GetAnnotations()["olm.skipRange"] = "<0.0.2" + baseCSVUIMetaIn.Spec.Replaces = "memcached-operator.v0.0.2" + col.ClusterServiceVersions = []v1alpha1.ClusterServiceVersion{*baseCSVUIMetaIn} g = Generator{ OperatorName: operatorName, - OperatorType: operatorType, - config: cfg, - getBase: makeBaseGetter(baseCSVUIMeta), + Version: "0.0.3", + Collector: col, } csv, err := g.generate() Expect(err).ToNot(HaveOccurred()) - Expect(csv).To(Equal(baseCSVUIMeta)) + csvExp := newCSVUIMeta.DeepCopy() + csvExp.SetName("memcached-operator.v0.0.3") + csvExp.GetAnnotations()["olm.skipRange"] = "<0.0.2" + csvExp.Spec.Replaces = "memcached-operator.v0.0.2" + csvExp.Spec.Version.Patch = 3 + Expect(csv).To(Equal(csvExp)) }) - }) - - Context("to create a new ClusterServiceVersion", func() { - It("should return a new object", func() { + It("should return a new object with version set", func() { + col.ClusterServiceVersions = []v1alpha1.ClusterServiceVersion{*baseCSVUIMeta} g = Generator{ OperatorName: operatorName, - OperatorType: operatorType, - Version: version, + Version: zeroZeroOne, Collector: col, - config: cfg, - getBase: makeBaseGetter(baseCSVUIMeta), } csv, err := g.generate() Expect(err).ToNot(HaveOccurred()) - Expect(csv).To(Equal(newCSV)) + Expect(csv).To(Equal(newCSVUIMeta)) + }) + It("should return a new object with base version and name preserved", func() { + col.ClusterServiceVersions = []v1alpha1.ClusterServiceVersion{*newCSVUIMeta} + g = Generator{ + OperatorName: operatorName, + Collector: col, + } + csv, err := g.generate() + Expect(err).ToNot(HaveOccurred()) + Expect(csv).To(Equal(newCSVUIMeta)) }) }) @@ -268,18 +221,17 @@ var _ = Describe("Generating a ClusterServiceVersion", func() { It("should return an updated object", func() { g = Generator{ OperatorName: operatorName, - OperatorType: operatorType, - Version: version, - Collector: &collector.Manifests{}, - config: cfg, - getBase: makeBaseGetter(newCSV), + Version: zeroZeroOne, + Collector: &collector.Manifests{ + ClusterServiceVersions: []v1alpha1.ClusterServiceVersion{*newCSVUIMeta}, + }, } // Update the input's and expected CSV's Deployment image. collectManifestsFromFileHelper(g.Collector, goBasicOperatorPath) Expect(len(g.Collector.Deployments)).To(BeNumerically(">=", 1)) imageTag := "controller:v" + g.Version modifyDepImageHelper(&g.Collector.Deployments[0].Spec, imageTag) - updatedCSV := updateCSV(newCSV, modifyCSVDepImageHelper(imageTag)) + updatedCSV := updateCSV(newCSVUIMeta, modifyCSVDepImageHelper(imageTag)) csv, err := g.generate() Expect(err).ToNot(HaveOccurred()) @@ -289,24 +241,30 @@ var _ = Describe("Generating a ClusterServiceVersion", func() { Context("to upgrade an existing ClusterServiceVersion", func() { It("should return an upgraded object", func() { + col.ClusterServiceVersions = []v1alpha1.ClusterServiceVersion{*newCSVUIMeta} g = Generator{ OperatorName: operatorName, - OperatorType: operatorType, - Version: "0.0.2", + Version: zeroZeroTwo, Collector: col, - config: cfg, - getBase: makeBaseGetter(newCSV), - // Bundles need a path, usually set by an Option, to an existing - // CSV manifest so "replaces" can be set correctly. - bundledPath: filepath.Join(csvNewLayoutBundleDir, "memcached-operator.clusterserviceversion.yaml"), } csv, err := g.generate() Expect(err).ToNot(HaveOccurred()) - Expect(csv).To(Equal(upgradeCSV(newCSV, g.OperatorName, g.Version))) + Expect(csv).To(Equal(upgradeCSV(newCSVUIMeta, g.OperatorName, g.Version))) }) }) }) + Context("with incorrect configuration", func() { + It("should return an error when a base CSV has an invalid name", func() { + col.ClusterServiceVersions = []v1alpha1.ClusterServiceVersion{*baseCSV} + g = Generator{ + OperatorName: operatorName, + Collector: col, + } + _, err := g.generate() + Expect(err).To(HaveOccurred()) + }) + }) }) var _ = Describe("Generation requires interaction", func() { @@ -353,16 +311,6 @@ func collectManifestsFromFileHelper(col *collector.Manifests, path string) { ExpectWithOffset(1, f.Close()).Should(Succeed()) } -func readConfigHelper(dir string) *config.Config { - wd, err := os.Getwd() - ExpectWithOffset(1, err).ToNot(HaveOccurred()) - ExpectWithOffset(1, os.Chdir(dir)).ToNot(HaveOccurred()) - cfg, err := projutil.ReadConfig() - ExpectWithOffset(1, err).ToNot(HaveOccurred()) - ExpectWithOffset(1, os.Chdir(wd)).ToNot(HaveOccurred()) - return cfg -} - func initTestCSVsHelper() { var err error path := filepath.Join(csvBasesDir, "memcached-operator.clusterserviceversion.yaml") @@ -372,14 +320,17 @@ func initTestCSVsHelper() { baseCSVUIMeta, baseCSVUIMetaStr, err = getCSVFromFile(path) ExpectWithOffset(1, err).ToNot(HaveOccurred()) path = filepath.Join(csvNewLayoutBundleDir, "memcached-operator.clusterserviceversion.yaml") - newCSV, newCSVStr, err = getCSVFromFile(path) + newCSV, _, err = getCSVFromFile(path) + ExpectWithOffset(1, err).ToNot(HaveOccurred()) + path = filepath.Join(csvNewLayoutBundleDir, "with-ui-metadata.clusterserviceversion.yaml") + newCSVUIMeta, newCSVUIMetaStr, err = getCSVFromFile(path) ExpectWithOffset(1, err).ToNot(HaveOccurred()) } func readFileHelper(path string) string { b, err := ioutil.ReadFile(path) ExpectWithOffset(1, err).ToNot(HaveOccurred()) - return removeSDKAnnotationsFromCSVString(string(b)) + return string(b) } func modifyCSVDepImageHelper(tag string) func(csv *v1alpha1.ClusterServiceVersion) { @@ -396,12 +347,6 @@ func modifyDepImageHelper(depSpec *appsv1.DeploymentSpec, tag string) { containers[0].Image = tag } -func makeBaseGetter(csv *v1alpha1.ClusterServiceVersion) getBaseFunc { - return func() (*v1alpha1.ClusterServiceVersion, error) { - return csv.DeepCopy(), nil - } -} - func getCSVFromFile(path string) (*v1alpha1.ClusterServiceVersion, string, error) { b, err := ioutil.ReadFile(path) if err != nil { @@ -440,23 +385,9 @@ func updateCSV(csv *v1alpha1.ClusterServiceVersion, func upgradeCSV(csv *v1alpha1.ClusterServiceVersion, name, version string) *v1alpha1.ClusterServiceVersion { upgraded := csv.DeepCopy() - // Update CSV name and upgrade version, then add "replaces" for the old CSV name. - oldName := upgraded.GetName() + // Update CSV name and upgrade version. upgraded.SetName(genutil.MakeCSVName(name, version)) upgraded.Spec.Version = operatorversion.OperatorVersion{Version: semver.MustParse(version)} - upgraded.Spec.Replaces = oldName return upgraded } - -// removeSDKAnnotationsFromCSVString removes SDK annotations from test CSVs. -// These annotations will update on each new release and will cause tests to fail erroneously, -// so they should be removed for each test case. -func removeSDKAnnotationsFromCSVString(csv string) string { - builderRe := regexp.MustCompile(fmt.Sprintf(".*%s: .[^\n]+\n", regexp.QuoteMeta(testSDKbuilderAnnotationKey))) - layoutRe := regexp.MustCompile(fmt.Sprintf(".*%s: .[^\n]+\n", regexp.QuoteMeta(testSDKlayoutAnnotationKey))) - - csv = builderRe.ReplaceAllString(csv, "") - csv = layoutRe.ReplaceAllString(csv, "") - return csv -} diff --git a/internal/generate/collector/manifests.go b/internal/generate/collector/manifests.go index eece184f292..5e161a00ee1 100644 --- a/internal/generate/collector/manifests.go +++ b/internal/generate/collector/manifests.go @@ -24,6 +24,7 @@ import ( "path/filepath" scorecardv1alpha3 "github.com/operator-framework/api/pkg/apis/scorecard/v1alpha3" + operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1" log "github.com/sirupsen/logrus" admissionregv1 "k8s.io/api/admissionregistration/v1" appsv1 "k8s.io/api/apps/v1" @@ -39,6 +40,7 @@ import ( // Manifests holds a collector of all manifests relevant to CSV updates. type Manifests struct { + ClusterServiceVersions []operatorsv1alpha1.ClusterServiceVersion Roles []rbacv1.Role ClusterRoles []rbacv1.ClusterRole RoleBindings []rbacv1.RoleBinding @@ -57,6 +59,7 @@ type Manifests struct { } var ( + csvGK = operatorsv1alpha1.SchemeGroupVersion.WithKind("ClusterServiceVersion").GroupKind() roleGK = rbacv1.SchemeGroupVersion.WithKind("Role").GroupKind() clusterRoleGK = rbacv1.SchemeGroupVersion.WithKind("ClusterRole").GroupKind() roleBindingGK = rbacv1.SchemeGroupVersion.WithKind("RoleBinding").GroupKind() @@ -96,6 +99,8 @@ func (c *Manifests) UpdateFromDirs(deployDir, crdsDir string) error { gvk := typeMeta.GroupVersionKind() switch gvk.GroupKind() { + case csvGK: + err = c.addClusterServiceVersions(manifest) case roleGK: err = c.addRoles(manifest) case clusterRoleGK: @@ -166,6 +171,8 @@ func (c *Manifests) UpdateFromReader(r io.Reader) error { gvk := typeMeta.GroupVersionKind() switch gvk.GroupKind() { + case csvGK: + err = c.addClusterServiceVersions(manifest) case roleGK: err = c.addRoles(manifest) case clusterRoleGK: @@ -210,6 +217,19 @@ func (c *Manifests) UpdateFromReader(r io.Reader) error { return nil } +// addClusterServiceVersions assumes all manifest data in rawManifests are ClusterServiceVersions +// and adds them to the collector. +func (c *Manifests) addClusterServiceVersions(rawManifests ...[]byte) error { + for _, rawManifest := range rawManifests { + csv := operatorsv1alpha1.ClusterServiceVersion{} + if err := yaml.Unmarshal(rawManifest, &csv); err != nil { + return err + } + c.ClusterServiceVersions = append(c.ClusterServiceVersions, csv) + } + return nil +} + // addRoles assumes all manifest data in rawManifests are Roles and adds them // to the collector. func (c *Manifests) addRoles(rawManifests ...[]byte) error { diff --git a/internal/generate/testdata/clusterserviceversions/bases/memcached-operator.clusterserviceversion.yaml b/internal/generate/testdata/clusterserviceversions/bases/memcached-operator.clusterserviceversion.yaml index f33f7566618..5cc18dc3f03 100644 --- a/internal/generate/testdata/clusterserviceversions/bases/memcached-operator.clusterserviceversion.yaml +++ b/internal/generate/testdata/clusterserviceversions/bases/memcached-operator.clusterserviceversion.yaml @@ -1,24 +1,13 @@ apiVersion: operators.coreos.com/v1alpha1 kind: ClusterServiceVersion metadata: - annotations: - alm-examples: '[]' - capabilities: Basic Install name: memcached-operator.vX.Y.Z namespace: placeholder spec: apiservicedefinitions: {} - customresourcedefinitions: - owned: - - displayName: Memcached App - kind: Memcached - name: memcacheds.cache.example.com - version: v1alpha1 - description: Memcached Operator description. TODO. + customresourcedefinitions: {} + # displayName is a required field. displayName: Memcached Operator - icon: - - base64data: "" - mediatype: "" install: spec: deployments: null @@ -32,16 +21,4 @@ spec: type: MultiNamespace - supported: true type: AllNamespaces - keywords: - - memcached-operator - links: - - name: Memcached Operator - url: https://memcached-operator.domain - maintainers: - - email: your@email.com - name: Maintainer Name - maturity: alpha - provider: - name: Provider Name - url: https://your.domain version: 0.0.0 diff --git a/internal/generate/testdata/clusterserviceversions/output/memcached-operator.clusterserviceversion.yaml b/internal/generate/testdata/clusterserviceversions/output/memcached-operator.clusterserviceversion.yaml index 9cf1d1491cc..b6cdc473fd6 100644 --- a/internal/generate/testdata/clusterserviceversions/output/memcached-operator.clusterserviceversion.yaml +++ b/internal/generate/testdata/clusterserviceversions/output/memcached-operator.clusterserviceversion.yaml @@ -15,60 +15,16 @@ metadata: } } ] - capabilities: Basic Install name: memcached-operator.v0.0.1 namespace: placeholder spec: apiservicedefinitions: {} customresourcedefinitions: owned: - - description: Memcached is the Schema for the memcacheds API - displayName: Memcached App Display Name - kind: Memcached + - kind: Memcached name: memcacheds.cache.example.com - specDescriptors: - - description: List of Providers - displayName: Providers - path: providers - - description: Foo represents the Foo provider - displayName: Foo Provider - path: providers[0].foo - - description: CredentialsSecret is a reference to a secret containing authentication details for the Foo server - displayName: Secret Containing the Credentials - path: providers[0].foo.credentialsSecret - x-descriptors: - - urn:alm:descriptor:io.kubernetes:Secret - - description: Key represents the specific key to reference from the secret - displayName: Key within the secret - path: providers[0].foo.credentialsSecret.key - x-descriptors: - - urn:alm:descriptor:com.tectonic.ui:advanced - - urn:alm:descriptor:com.tectonic.ui:text - - description: Name represents the name of the secret - displayName: Name of the secret - path: providers[0].foo.credentialsSecret.name - x-descriptors: - - urn:alm:descriptor:com.tectonic.ui:advanced - - urn:alm:descriptor:com.tectonic.ui:text - - description: Namespace represents the namespace containing the secret - displayName: Namespace containing the secret - path: providers[0].foo.credentialsSecret.namespace - x-descriptors: - - urn:alm:descriptor:com.tectonic.ui:advanced - - urn:alm:descriptor:com.tectonic.ui:text - - description: Size is the size of the memcached deployment - displayName: Size - path: size - statusDescriptors: - - description: Nodes are the names of the memcached pods - displayName: Nodes - path: nodes version: v1alpha1 - description: Memcached Operator description. TODO. displayName: Memcached Operator - icon: - - base64data: "" - mediatype: "" install: spec: clusterPermissions: @@ -199,18 +155,6 @@ spec: type: MultiNamespace - supported: true type: AllNamespaces - keywords: - - memcached-operator - links: - - name: Memcached Operator - url: https://memcached-operator.domain - maintainers: - - email: your@email.com - name: Maintainer Name - maturity: alpha - provider: - name: Provider Name - url: https://your.domain version: 0.0.1 webhookdefinitions: - admissionReviewVersions: diff --git a/internal/generate/testdata/clusterserviceversions/output/with-ui-metadata.clusterserviceversion.yaml b/internal/generate/testdata/clusterserviceversions/output/with-ui-metadata.clusterserviceversion.yaml new file mode 100644 index 00000000000..9cf1d1491cc --- /dev/null +++ b/internal/generate/testdata/clusterserviceversions/output/with-ui-metadata.clusterserviceversion.yaml @@ -0,0 +1,255 @@ +apiVersion: operators.coreos.com/v1alpha1 +kind: ClusterServiceVersion +metadata: + annotations: + alm-examples: |- + [ + { + "apiVersion": "cache.example.com/v1alpha1", + "kind": "Memcached", + "metadata": { + "name": "memcached-sample" + }, + "spec": { + "foo": "bar" + } + } + ] + capabilities: Basic Install + name: memcached-operator.v0.0.1 + namespace: placeholder +spec: + apiservicedefinitions: {} + customresourcedefinitions: + owned: + - description: Memcached is the Schema for the memcacheds API + displayName: Memcached App Display Name + kind: Memcached + name: memcacheds.cache.example.com + specDescriptors: + - description: List of Providers + displayName: Providers + path: providers + - description: Foo represents the Foo provider + displayName: Foo Provider + path: providers[0].foo + - description: CredentialsSecret is a reference to a secret containing authentication details for the Foo server + displayName: Secret Containing the Credentials + path: providers[0].foo.credentialsSecret + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Secret + - description: Key represents the specific key to reference from the secret + displayName: Key within the secret + path: providers[0].foo.credentialsSecret.key + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:advanced + - urn:alm:descriptor:com.tectonic.ui:text + - description: Name represents the name of the secret + displayName: Name of the secret + path: providers[0].foo.credentialsSecret.name + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:advanced + - urn:alm:descriptor:com.tectonic.ui:text + - description: Namespace represents the namespace containing the secret + displayName: Namespace containing the secret + path: providers[0].foo.credentialsSecret.namespace + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:advanced + - urn:alm:descriptor:com.tectonic.ui:text + - description: Size is the size of the memcached deployment + displayName: Size + path: size + statusDescriptors: + - description: Nodes are the names of the memcached pods + displayName: Nodes + path: nodes + version: v1alpha1 + description: Memcached Operator description. TODO. + displayName: Memcached Operator + icon: + - base64data: "" + mediatype: "" + install: + spec: + clusterPermissions: + - rules: + - apiGroups: + - cache.example.com + resources: + - memcacheds + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - cache.example.com + resources: + - memcacheds/status + verbs: + - get + - patch + - update + - apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create + - apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create + serviceAccountName: default + deployments: + - name: memcached-operator-controller-manager + spec: + replicas: 1 + selector: + matchLabels: + control-plane: controller-manager + strategy: {} + template: + metadata: + labels: + control-plane: controller-manager + spec: + containers: + - args: + - --secure-listen-address=0.0.0.0:8443 + - --upstream=http://127.0.0.1:8080/ + - --logtostderr=true + - --v=10 + image: gcr.io/kubebuilder/kube-rbac-proxy:v0.5.0 + name: kube-rbac-proxy + ports: + - containerPort: 8443 + name: https + resources: {} + - args: + - --metrics-addr=127.0.0.1:8080 + - --enable-leader-election + command: + - /manager + image: controller:latest + name: manager + ports: + - containerPort: 9443 + name: webhook-server + protocol: TCP + resources: + limits: + cpu: 100m + memory: 30Mi + requests: + cpu: 100m + memory: 20Mi + volumeMounts: + - mountPath: /tmp/k8s-webhook-server/serving-certs + name: cert + readOnly: true + terminationGracePeriodSeconds: 10 + volumes: + - name: cert + secret: + defaultMode: 420 + secretName: webhook-server-cert + permissions: + - rules: + - apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete + - apiGroups: + - "" + resources: + - configmaps/status + verbs: + - get + - update + - patch + - apiGroups: + - "" + resources: + - events + verbs: + - create + - patch + serviceAccountName: default + strategy: deployment + installModes: + - supported: false + type: OwnNamespace + - supported: false + type: SingleNamespace + - supported: false + type: MultiNamespace + - supported: true + type: AllNamespaces + keywords: + - memcached-operator + links: + - name: Memcached Operator + url: https://memcached-operator.domain + maintainers: + - email: your@email.com + name: Maintainer Name + maturity: alpha + provider: + name: Provider Name + url: https://your.domain + version: 0.0.1 + webhookdefinitions: + - admissionReviewVersions: + - v1beta1 + containerPort: 443 + deploymentName: memcached-operator-controller-manager + failurePolicy: Fail + generateName: vmemcached.kb.io + rules: + - apiGroups: + - cache.example.com + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - memcacheds + sideEffects: None + targetPort: 9443 + type: ValidatingAdmissionWebhook + webhookPath: /validate-cache-my-domain-v1alpha1-memcached + - admissionReviewVersions: + - v1beta1 + containerPort: 443 + deploymentName: memcached-operator-controller-manager + failurePolicy: Fail + generateName: mmemcached.kb.io + rules: + - apiGroups: + - cache.example.com + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - memcacheds + sideEffects: None + targetPort: 9443 + type: MutatingAdmissionWebhook + webhookPath: /mutate-cache-my-domain-v1alpha1-memcached diff --git a/internal/util/projutil/project_util.go b/internal/util/projutil/project_util.go index 455bb405f67..a0a500b58a6 100644 --- a/internal/util/projutil/project_util.go +++ b/internal/util/projutil/project_util.go @@ -106,6 +106,15 @@ func PluginKeyToOperatorType(pluginKey string) OperatorType { return OperatorTypeUnknown } +// GetProjectLayout returns the `layout` field in PROJECT file that is v3. +// If not, it will return "go" because that was the only project type supported for project versions < v3. +func GetProjectLayout(cfg *config.Config) string { + if cfg == nil || !cfg.IsV3() || cfg.Layout == "" { + return "go" + } + return cfg.Layout +} + var flagRe = regexp.MustCompile("(.* )?-v(.* )?") // SetGoVerbose sets GOFLAGS="${GOFLAGS} -v" if GOFLAGS does not diff --git a/website/content/en/docs/cli/operator-sdk_generate_bundle.md b/website/content/en/docs/cli/operator-sdk_generate_bundle.md index 2758f4b4aa3..2d0b3bc6795 100644 --- a/website/content/en/docs/cli/operator-sdk_generate_bundle.md +++ b/website/content/en/docs/cli/operator-sdk_generate_bundle.md @@ -90,6 +90,7 @@ operator-sdk generate bundle [flags] --metadata Generate bundle metadata and Dockerfile --output-dir string Directory to write the bundle to --overwrite Overwrite the bundle's metadata and Dockerfile if they exist (default true) + --package string Bundle's package name -q, --quiet Run in quiet mode --stdout Write bundle manifest to stdout -v, --version string Semantic version of the operator in the generated bundle. Only set if creating a new bundle or upgrading your operator diff --git a/website/content/en/docs/cli/operator-sdk_generate_kustomize_manifests.md b/website/content/en/docs/cli/operator-sdk_generate_kustomize_manifests.md index adf9d5527e8..2f64a236432 100644 --- a/website/content/en/docs/cli/operator-sdk_generate_kustomize_manifests.md +++ b/website/content/en/docs/cli/operator-sdk_generate_kustomize_manifests.md @@ -50,8 +50,9 @@ operator-sdk generate kustomize manifests [flags] --apis-dir string Root directory for API type defintions -h, --help help for manifests --input-dir string Directory containing existing kustomize files - --interactive When set or no kustomize base exists, an interactive command prompt will be presented to accept non-inferrable metadata + --interactive When set to false, if no kustomize base exists, an interactive command prompt will be presented to accept non-inferrable metadata --output-dir string Directory to write kustomize files + --package string Package name -q, --quiet Run in quiet mode ``` diff --git a/website/content/en/docs/cli/operator-sdk_generate_packagemanifests.md b/website/content/en/docs/cli/operator-sdk_generate_packagemanifests.md index 52577819bb2..47b04ab334a 100644 --- a/website/content/en/docs/cli/operator-sdk_generate_packagemanifests.md +++ b/website/content/en/docs/cli/operator-sdk_generate_packagemanifests.md @@ -70,6 +70,7 @@ operator-sdk generate packagemanifests [flags] --input-dir string Directory to read existing package manifests from. This directory is the parent of individual versioned package directories, and different from --deploy-dir --kustomize-dir string Directory containing kustomize bases and a kustomization.yaml for operator-framework manifests (default "config/manifests") --output-dir string Directory in which to write package manifests + --package string Package name -q, --quiet Run in quiet mode --stdout Write package to stdout --update-objects Update non-CSV objects in this package, ex. CustomResoureDefinitions, Roles (default true) From 060cc7b5bb411a1b414321cf8eddf96527e34f88 Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Fri, 4 Dec 2020 10:24:11 -0800 Subject: [PATCH 229/376] generate: fix "invalid CSV name" bug (#4276) This commit fixes a bug caused by an invalid CSV name being generated. `operator-sdk generate kustomize manifests` will auto-migrate a base CSV's name to `.v` if it ends in `.vX.Y.Z`. `operator-sdk generate Signed-off-by: reinvantveer --- changelog/fragments/csv-base-name-bugfix.yaml | 6 ++ .../operator-sdk/generate/bundle/bundle.go | 23 ++---- .../cmd/operator-sdk/generate/bundle/cmd.go | 5 -- .../generate/kustomize/manifests.go | 13 ++-- .../packagemanifests/packagemanifests.go | 10 +-- .../bases/clusterserviceversion.go | 20 ++++-- .../bases/metadata_test.go | 2 +- .../clusterserviceversion.go | 71 +++---------------- .../clusterserviceversion_test.go | 30 ++++---- ...cached-operator.clusterserviceversion.yaml | 2 +- ...ith-ui-metadata.clusterserviceversion.yaml | 2 +- ...cached-operator.clusterserviceversion.yaml | 2 +- ...cached-operator.clusterserviceversion.yaml | 2 +- ...cached-operator.clusterserviceversion.yaml | 2 +- .../en/docs/olm-integration/generation.md | 38 +++++++--- 15 files changed, 104 insertions(+), 124 deletions(-) create mode 100644 changelog/fragments/csv-base-name-bugfix.yaml diff --git a/changelog/fragments/csv-base-name-bugfix.yaml b/changelog/fragments/csv-base-name-bugfix.yaml new file mode 100644 index 00000000000..e2edb1eb6e9 --- /dev/null +++ b/changelog/fragments/csv-base-name-bugfix.yaml @@ -0,0 +1,6 @@ +# entries is a list of entries to include in +# release notes and/or the migration guide +entries: + - description: > + `generate kustomize manifests` will (re)generate a base `ClusterServiceVersion` manifest with a valid name. + kind: bugfix diff --git a/internal/cmd/operator-sdk/generate/bundle/bundle.go b/internal/cmd/operator-sdk/generate/bundle/bundle.go index d2e06dceec9..20351c9d308 100644 --- a/internal/cmd/operator-sdk/generate/bundle/bundle.go +++ b/internal/cmd/operator-sdk/generate/bundle/bundle.go @@ -189,11 +189,13 @@ func (c bundleCmd) runManifests() (err error) { // If no CSV is passed via stdin, an on-disk base is expected at basePath. if len(col.ClusterServiceVersions) == 0 { basePath := filepath.Join(c.kustomizeDir, "bases", c.packageName+".clusterserviceversion.yaml") - base, err := bases.ClusterServiceVersion{BasePath: basePath}.GetBase() - if err != nil { - return fmt.Errorf("error reading CSV base: %v", err) + if genutil.IsExist(basePath) { + base, err := bases.ClusterServiceVersion{BasePath: basePath}.GetBase() + if err != nil { + return fmt.Errorf("error reading CSV base: %v", err) + } + col.ClusterServiceVersions = append(col.ClusterServiceVersions, *base) } - col.ClusterServiceVersions = append(col.ClusterServiceVersions, *base) } var opts []gencsv.Option @@ -257,11 +259,6 @@ func writeScorecardConfig(dir string, cfg v1alpha3.Configuration) error { return ioutil.WriteFile(scorecardConfigPath, b, 0666) } -// validateMetadata validates c for bundle metadata generation. -func (c bundleCmd) validateMetadata() (err error) { - return nil -} - // runMetadata generates a bundle.Dockerfile and bundle metadata. func (c bundleCmd) runMetadata() error { @@ -342,7 +339,7 @@ func updateMetadata(layout, bundleRoot string) error { // writeDockerfileCOPYScorecardConfig checks if bundle.Dockerfile and scorecard config exists in // the operator project. If it does, it injects the scorecard configuration into bundle image. func writeDockerfileCOPYScorecardConfig(dockerfileName, localConfigDir string) error { - if isExist(bundle.DockerFile) && isExist(localConfigDir) { + if genutil.IsExist(bundle.DockerFile) && genutil.IsExist(localConfigDir) { scorecardFileContent := fmt.Sprintf("COPY %s %s\n", localConfigDir, "/"+scorecard.DefaultConfigDir) return projutil.RewriteFileContents(dockerfileName, "COPY", scorecardFileContent) } @@ -402,9 +399,3 @@ func rewriteAnnotations(bundleRoot string, kvs map[string]string) error { } return ioutil.WriteFile(annotationsPath, b, mode) } - -// isExist returns true if path exists. -func isExist(path string) bool { - _, err := os.Stat(path) - return err == nil || os.IsExist(err) -} diff --git a/internal/cmd/operator-sdk/generate/bundle/cmd.go b/internal/cmd/operator-sdk/generate/bundle/cmd.go index d2178eb9994..8d87c04eb54 100644 --- a/internal/cmd/operator-sdk/generate/bundle/cmd.go +++ b/internal/cmd/operator-sdk/generate/bundle/cmd.go @@ -80,11 +80,6 @@ func NewCmd() *cobra.Command { return fmt.Errorf("invalid command options: %v", err) } } - if c.metadata { - if err := c.validateMetadata(); err != nil { - return fmt.Errorf("invalid command options: %v", err) - } - } // Run command logic. if c.manifests { diff --git a/internal/cmd/operator-sdk/generate/kustomize/manifests.go b/internal/cmd/operator-sdk/generate/kustomize/manifests.go index 954c3f99a51..cc510e48e1f 100644 --- a/internal/cmd/operator-sdk/generate/kustomize/manifests.go +++ b/internal/cmd/operator-sdk/generate/kustomize/manifests.go @@ -187,16 +187,15 @@ func (c manifestsCmd) run(cfg *config.Config) error { } } + relBasePath := filepath.Join("bases", c.packageName+".clusterserviceversion.yaml") + basePath := filepath.Join(c.inputDir, relBasePath) base := bases.ClusterServiceVersion{ OperatorName: c.packageName, OperatorType: projutil.PluginKeyToOperatorType(cfg.Layout), APIsDir: c.apisDir, - Interactive: isInteractive(c.interactiveLevel), + Interactive: requiresInteraction(basePath, c.interactiveLevel), GVKs: getGVKs(cfg), } - relBasePath := filepath.Join("bases", c.packageName+".clusterserviceversion.yaml") - basePath := filepath.Join(c.inputDir, relBasePath) - // Set BasePath only if it exists. If it doesn't, a new base will be generated // if BasePath is empty. if genutil.IsExist(basePath) { @@ -231,8 +230,10 @@ func (c manifestsCmd) run(cfg *config.Config) error { return nil } -func isInteractive(ilvl projutil.InteractiveLevel) bool { - return (ilvl == projutil.InteractiveSoftOff || ilvl == projutil.InteractiveOnAll) +// requiresInteraction checks if the combination of ilvl and basePath existence +// requires the generator prompt a user interactively. +func requiresInteraction(basePath string, ilvl projutil.InteractiveLevel) bool { + return (ilvl == projutil.InteractiveSoftOff && genutil.IsNotExist(basePath)) || ilvl == projutil.InteractiveOnAll } func getGVKs(cfg *config.Config) []schema.GroupVersionKind { diff --git a/internal/cmd/operator-sdk/generate/packagemanifests/packagemanifests.go b/internal/cmd/operator-sdk/generate/packagemanifests/packagemanifests.go index 103bed33597..7ef7b5bcf80 100644 --- a/internal/cmd/operator-sdk/generate/packagemanifests/packagemanifests.go +++ b/internal/cmd/operator-sdk/generate/packagemanifests/packagemanifests.go @@ -178,11 +178,13 @@ func (c packagemanifestsCmd) run() error { // If no CSV is passed via stdin, an on-disk base is expected at basePath. if len(col.ClusterServiceVersions) == 0 { basePath := filepath.Join(c.kustomizeDir, "bases", c.packageName+".clusterserviceversion.yaml") - base, err := bases.ClusterServiceVersion{BasePath: basePath}.GetBase() - if err != nil { - return fmt.Errorf("error reading CSV base: %v", err) + if genutil.IsExist(basePath) { + base, err := bases.ClusterServiceVersion{BasePath: basePath}.GetBase() + if err != nil { + return fmt.Errorf("error reading CSV base: %v", err) + } + col.ClusterServiceVersions = append(col.ClusterServiceVersions, *base) } - col.ClusterServiceVersions = append(col.ClusterServiceVersions, *base) } var opts []gencsv.Option diff --git a/internal/generate/clusterserviceversion/bases/clusterserviceversion.go b/internal/generate/clusterserviceversion/bases/clusterserviceversion.go index e7c7a92b7a6..cd302dacc5f 100644 --- a/internal/generate/clusterserviceversion/bases/clusterserviceversion.go +++ b/internal/generate/clusterserviceversion/bases/clusterserviceversion.go @@ -66,9 +66,14 @@ func (b ClusterServiceVersion) GetBase() (base *v1alpha1.ClusterServiceVersion, if base, err = readClusterServiceVersionBase(b.BasePath); err != nil { return nil, fmt.Errorf("error reading existing ClusterServiceVersion base %s: %v", b.BasePath, err) } + // Auto-migrate bases with names matching ".vX.Y.Z", which + // may cause problems with the CSV validator. + if base.GetName() == b.OperatorName+".vX.Y.Z" { + base.SetName(fmt.Sprintf("%s.v%s", b.OperatorName, base.Spec.Version.Version.String())) + } } else { b.setDefaults() - base = b.makeNewBase() + base = b.newBase() } // Interactively fill in UI metadata. @@ -92,6 +97,13 @@ func (b ClusterServiceVersion) GetBase() (base *v1alpha1.ClusterServiceVersion, return base, nil } +// New returns a base with default data with name opertorName. +func New(operatorName string) *v1alpha1.ClusterServiceVersion { + b := ClusterServiceVersion{OperatorName: operatorName} + b.setDefaults() + return b.newBase() +} + // setDefaults sets default values in b using b's existing values. func (b *ClusterServiceVersion) setDefaults() { if b.DisplayName == "" { @@ -136,15 +148,15 @@ func (b *ClusterServiceVersion) setDefaults() { } } -// makeNewBase returns a base v1alpha1.ClusterServiceVersion to modify. -func (b ClusterServiceVersion) makeNewBase() *v1alpha1.ClusterServiceVersion { +// newBase returns a base v1alpha1.ClusterServiceVersion to modify. +func (b ClusterServiceVersion) newBase() *v1alpha1.ClusterServiceVersion { return &v1alpha1.ClusterServiceVersion{ TypeMeta: metav1.TypeMeta{ APIVersion: v1alpha1.ClusterServiceVersionAPIVersion, Kind: v1alpha1.ClusterServiceVersionKind, }, ObjectMeta: metav1.ObjectMeta{ - Name: b.OperatorName + ".vX.Y.Z", + Name: b.OperatorName + ".v0.0.0", Namespace: "placeholder", Annotations: map[string]string{ "capabilities": b.Capabilities, diff --git a/internal/generate/clusterserviceversion/bases/metadata_test.go b/internal/generate/clusterserviceversion/bases/metadata_test.go index 2605ee2fddb..e7e2f91e1bd 100644 --- a/internal/generate/clusterserviceversion/bases/metadata_test.go +++ b/internal/generate/clusterserviceversion/bases/metadata_test.go @@ -55,7 +55,7 @@ var _ = Describe("Metadata", func() { It("populates a CSV with existing values", func() { b := ClusterServiceVersion{OperatorName: "test-operator"} b.setDefaults() - csv := b.makeNewBase() + csv := b.newBase() meta.apply(csv) diff --git a/internal/generate/clusterserviceversion/clusterserviceversion.go b/internal/generate/clusterserviceversion/clusterserviceversion.go index ba95f1ec066..d0225a7a214 100644 --- a/internal/generate/clusterserviceversion/clusterserviceversion.go +++ b/internal/generate/clusterserviceversion/clusterserviceversion.go @@ -45,7 +45,6 @@ var ( type Generator struct { // OperatorName is the operator's name, ex. app-operator. OperatorName string - OperatorType projutil.OperatorType // Version is the CSV current version. Version string // FromVersion is the version of a previous CSV to upgrade from. @@ -57,10 +56,6 @@ type Generator struct { // Func that returns the writer the generated CSV's bytes are written to. getWriter func() (io.Writer, error) - // If the CSV is destined for a bundle this will be the path of the updated - // CSV. Used to bring over data from an existing CSV that is not captured - // in a base. Not set if a non-file or base writer is returned by getWriter. - bundledPath string } // Option is a function that modifies a Generator. @@ -81,7 +76,6 @@ func WithWriter(w io.Writer) Option { func WithBundleWriter(dir string) Option { return func(g *Generator) error { fileName := makeCSVFileName(g.OperatorName) - g.bundledPath = filepath.Join(dir, bundle.ManifestsDir, fileName) g.getWriter = func() (io.Writer, error) { return genutil.Open(filepath.Join(dir, bundle.ManifestsDir), fileName) } @@ -94,9 +88,6 @@ func WithBundleWriter(dir string) Option { func WithPackageWriter(dir string) Option { return func(g *Generator) error { fileName := makeCSVFileName(g.OperatorName) - if g.FromVersion != "" { - g.bundledPath = filepath.Join(dir, g.FromVersion, fileName) - } g.getWriter = func() (io.Writer, error) { return genutil.Open(filepath.Join(dir, g.Version), fileName) } @@ -149,34 +140,28 @@ func (g *Generator) generate() (base *operatorsv1alpha1.ClusterServiceVersion, e return nil, fmt.Errorf("cannot generate CSV without a manifests collection") } - // Search for a CSV in the collector with a name matching the package name, - // but prefer an exact match ".vX.Y.Z" to preserve existing behavior. - var oldBase *operatorsv1alpha1.ClusterServiceVersion + // Search for a CSV in the collector with a name matching the package name. csvNamePrefix := g.OperatorName + "." - oldBaseCSVName := genutil.MakeCSVName(g.OperatorName, "X.Y.Z") for _, csv := range g.Collector.ClusterServiceVersions { - if csv.GetName() == oldBaseCSVName { - oldBase = csv.DeepCopy() - } else if base == nil && strings.HasPrefix(csv.GetName(), csvNamePrefix) { + if base == nil && strings.HasPrefix(csv.GetName(), csvNamePrefix) { base = csv.DeepCopy() } } - if base == nil && oldBase == nil { - return nil, fmt.Errorf("no CSV found with name prefix %q", csvNamePrefix) - } else if oldBase != nil { - // Only update versions in the old way to preserve existing behavior. - base = oldBase - if err := g.updateVersionsWithReplaces(base); err != nil { - return nil, err - } - } else if g.Version != "" { + // Use a default base if none was supplied. + if base == nil { + base = bases.New(g.OperatorName) + } + if g.Version != "" { // Use the existing version/name unless g.Version is set. base.SetName(genutil.MakeCSVName(g.OperatorName, g.Version)) if base.Spec.Version.Version, err = semver.Parse(g.Version); err != nil { return nil, err } } + if g.FromVersion != "" { + base.Spec.Replaces = genutil.MakeCSVName(g.OperatorName, g.Version) + } if err := ApplyTo(g.Collector, base); err != nil { return nil, err @@ -195,39 +180,3 @@ func makeCSVFileName(name string) string { func requiresInteraction(basePath string, ilvl projutil.InteractiveLevel) bool { return (ilvl == projutil.InteractiveSoftOff && genutil.IsNotExist(basePath)) || ilvl == projutil.InteractiveOnAll } - -// updateVersionsWithReplaces updates csv's version and data involving the version, -// ex. ObjectMeta.Name, and place the old version in the `replaces` object, -// if there is an old version to replace. -func (g Generator) updateVersionsWithReplaces(csv *operatorsv1alpha1.ClusterServiceVersion) (err error) { - - oldVer, newVer := csv.Spec.Version.String(), g.Version - newName := genutil.MakeCSVName(g.OperatorName, newVer) - oldName := csv.GetName() - - // A bundled CSV may not have a base containing the previous version to use, - // so use the current bundled CSV for version information. - if genutil.IsExist(g.bundledPath) { - existing, err := (bases.ClusterServiceVersion{BasePath: g.bundledPath}).GetBase() - if err != nil { - return fmt.Errorf("error reading existing ClusterServiceVersion: %v", err) - } - oldVer = existing.Spec.Version.String() - oldName = existing.GetName() - } - - // If the new version is empty, either because a CSV is only being updated or - // a base was generated, no update is needed. - if newVer == "0.0.0" || newVer == "" { - return nil - } - - // Set replaces by default. - if oldVer != "0.0.0" && newVer != oldVer { - csv.Spec.Replaces = oldName - } - - csv.SetName(newName) - csv.Spec.Version.Version, err = semver.Parse(newVer) - return err -} diff --git a/internal/generate/clusterserviceversion/clusterserviceversion_test.go b/internal/generate/clusterserviceversion/clusterserviceversion_test.go index ef6428c8d4c..13e5f95d260 100644 --- a/internal/generate/clusterserviceversion/clusterserviceversion_test.go +++ b/internal/generate/clusterserviceversion/clusterserviceversion_test.go @@ -30,6 +30,7 @@ import ( appsv1 "k8s.io/api/apps/v1" "sigs.k8s.io/yaml" + "github.com/operator-framework/operator-sdk/internal/generate/clusterserviceversion/bases" "github.com/operator-framework/operator-sdk/internal/generate/collector" genutil "github.com/operator-framework/operator-sdk/internal/generate/internal" "github.com/operator-framework/operator-sdk/internal/util/projutil" @@ -164,7 +165,22 @@ var _ = Describe("Generating a ClusterServiceVersion", func() { }) Context("to create a new ClusterServiceVersion", func() { - It("should return a valid object", func() { + It("should return a default object when no base is supplied", func() { + col.ClusterServiceVersions = nil + g = Generator{ + OperatorName: operatorName, + Version: zeroZeroOne, + Collector: col, + } + csv, err := g.generate() + Expect(err).ToNot(HaveOccurred()) + col.ClusterServiceVersions = []v1alpha1.ClusterServiceVersion{*(bases.New(operatorName))} + csvExp, err := g.generate() + Expect(err).ToNot(HaveOccurred()) + Expect(csv).To(Equal(csvExp)) + }) + + It("should return a default object", func() { col.ClusterServiceVersions = []v1alpha1.ClusterServiceVersion{*baseCSV} g = Generator{ OperatorName: operatorName, @@ -253,18 +269,6 @@ var _ = Describe("Generating a ClusterServiceVersion", func() { }) }) }) - - Context("with incorrect configuration", func() { - It("should return an error when a base CSV has an invalid name", func() { - col.ClusterServiceVersions = []v1alpha1.ClusterServiceVersion{*baseCSV} - g = Generator{ - OperatorName: operatorName, - Collector: col, - } - _, err := g.generate() - Expect(err).To(HaveOccurred()) - }) - }) }) var _ = Describe("Generation requires interaction", func() { diff --git a/internal/generate/testdata/clusterserviceversions/bases/memcached-operator.clusterserviceversion.yaml b/internal/generate/testdata/clusterserviceversions/bases/memcached-operator.clusterserviceversion.yaml index 5cc18dc3f03..f8a89d5cd56 100644 --- a/internal/generate/testdata/clusterserviceversions/bases/memcached-operator.clusterserviceversion.yaml +++ b/internal/generate/testdata/clusterserviceversions/bases/memcached-operator.clusterserviceversion.yaml @@ -1,7 +1,7 @@ apiVersion: operators.coreos.com/v1alpha1 kind: ClusterServiceVersion metadata: - name: memcached-operator.vX.Y.Z + name: memcached-operator.v0.0.0 namespace: placeholder spec: apiservicedefinitions: {} diff --git a/internal/generate/testdata/clusterserviceversions/bases/with-ui-metadata.clusterserviceversion.yaml b/internal/generate/testdata/clusterserviceversions/bases/with-ui-metadata.clusterserviceversion.yaml index d2c60cd35ad..c86b8c7fb24 100644 --- a/internal/generate/testdata/clusterserviceversions/bases/with-ui-metadata.clusterserviceversion.yaml +++ b/internal/generate/testdata/clusterserviceversions/bases/with-ui-metadata.clusterserviceversion.yaml @@ -4,7 +4,7 @@ metadata: annotations: alm-examples: '[]' capabilities: Basic Install - name: memcached-operator.vX.Y.Z + name: memcached-operator.v0.0.0 namespace: placeholder spec: apiservicedefinitions: {} diff --git a/testdata/ansible/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml b/testdata/ansible/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml index e0831a96a16..1f1eb4269d2 100644 --- a/testdata/ansible/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml +++ b/testdata/ansible/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml @@ -4,7 +4,7 @@ metadata: annotations: alm-examples: '[]' capabilities: Basic Install - name: memcached-operator.vX.Y.Z + name: memcached-operator.v0.0.0 namespace: placeholder spec: apiservicedefinitions: {} diff --git a/testdata/go/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml b/testdata/go/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml index 7171abf6739..bcfeaa4015d 100644 --- a/testdata/go/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml +++ b/testdata/go/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml @@ -4,7 +4,7 @@ metadata: annotations: alm-examples: '[]' capabilities: Basic Install - name: memcached-operator.vX.Y.Z + name: memcached-operator.v0.0.0 namespace: placeholder spec: apiservicedefinitions: {} diff --git a/testdata/helm/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml b/testdata/helm/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml index e0831a96a16..1f1eb4269d2 100644 --- a/testdata/helm/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml +++ b/testdata/helm/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml @@ -4,7 +4,7 @@ metadata: annotations: alm-examples: '[]' capabilities: Basic Install - name: memcached-operator.vX.Y.Z + name: memcached-operator.v0.0.0 namespace: placeholder spec: apiservicedefinitions: {} diff --git a/website/content/en/docs/olm-integration/generation.md b/website/content/en/docs/olm-integration/generation.md index 89b02c35268..8a67a52b295 100644 --- a/website/content/en/docs/olm-integration/generation.md +++ b/website/content/en/docs/olm-integration/generation.md @@ -43,6 +43,8 @@ Comma-separated list of keywords for your operator (required): ... ``` +Once this base is written, you may modify any of the fields labeled _user_ in the [fields section](#csv-fields) below. + **For Go Operators only:** the command parses [CSV markers][csv-markers] from Go API type definitions, located in `./api` for single group projects and `./apis` for multigroup projects, to populate certain CSV fields. You can set an alternative path to the API types root directory with `--apis-dir`. These markers are not available @@ -63,6 +65,12 @@ The following resource kinds are typically included in a CSV, which are addresse - `CustomResourceDefinition`: definitions of custom objects your Operator reconciles. - Custom resource examples: examples of objects adhering to the spec of a particular CRD. +You can optionally specify an input `ClusterServiceVersion` manifest to the set of manifests passed to +these `generate` subcommands instead of having them read from the [base path](#kustomize-files). +This is advantageous for those who would like to take full advantage of `kustomize` for their base. +All fields unlabeled or labeled with _marker_ [below](#csv-fields) will be overwritten by these command, +so make sure you do not `kustomize build` those fields! + ## Generate your first release You've recently run `operator-sdk init` and created your APIs with `operator-sdk create api`. Now you'd like to @@ -249,7 +257,16 @@ Let's say you're upgrading your Operator to version `v0.0.2`, you've already upd in your `Makefile` to `0.0.2`, and built a new operator image `quay.io//memcached-operator:v0.0.2`. You also want to add a new channel `beta`, and use it as the default channel. -If using a bundle format, a new version of your CSV can be created by running: +First, update `spec.replaces` in your [base CSV manifest](#kustomize-files) to the _current_ CSV name. +In this case, the change would look like: + +```yaml +spec: + ... + replaces: memcached-operator.v0.0.1 +``` + +Next, upgrade your bundle. If using a bundle format, a new version of your CSV can be created by running: ```console $ make bundle CHANNELS=beta DEFAULT_CHANNEL=beta IMG=quay.io//memcached-operator:v0.0.2 @@ -261,8 +278,9 @@ If using a package manifests format, run: $ make packagemanifests FROM_VERSION=0.0.1 CHANNEL=beta IS_CHANNEL_DEFAULT=1 IMG=quay.io//memcached-operator:v0.0.2 ``` -Running the command for either format will persist user-defined fields, updates `spec.version`, -and populates `spec.replaces` with the old CSV version's name. +Running the command for either format will persist user-defined fields, and updates `spec.version` and `metadata.name`. + +**For `packagemanifests` only** The command will also populate `spec.replaces` with the old CSV version's name. ## CSV fields @@ -273,9 +291,10 @@ Below are two lists of fields: the first is a list of all fields the SDK and OLM These markers are not available to Ansible or Helm project types. Required: -- `metadata.name`: a *unique* name for this CSV of the format `.vX.Y.Z`, ex. `app-operator.v0.0.1`. -- `spec.version`: semantic version of the Operator, ex. `0.0.1`. -- `spec.installModes`: what mode of [installation namespacing][install-modes] OLM should use. +- `metadata.name` _(user*)_: a *unique* name for this CSV of the format `.vX.Y.Z`, ex. `app-operator.v0.0.1`. +- `spec.displayName` _(user)_ : a name to display for the Operator in Operator Hub. +- `spec.version` _(user*)_: semantic version of the Operator, ex. `0.0.1`. +- `spec.installModes` _(user)_: what mode of [installation namespacing][install-modes] OLM should use. Currently all but `MultiNamespace` are supported by SDK Operators. - `spec.customresourcedefinitions`: any CRDs the Operator uses. Certain fields in elements of `owned` will be filled by the SDK. - `owned`: all CRDs the Operator deploys itself from it's bundle. @@ -293,7 +312,6 @@ Currently all but `MultiNamespace` are supported by SDK Operators. Optional: - `spec.description` _(user)_ : a thorough description of the Operator's functionality. -- `spec.displayName` _(user)_ : a name to display for the Operator in Operator Hub. - `spec.keywords` _(user)_ : a list of keywords describing the Operator. - `spec.maintainers` _(user)_ : a list of human or organizational entities maintaining the Operator, with a `name` and `email`. - `spec.provider` _(user)_ : the Operator provider, with a `name`; usually an organization. @@ -301,13 +319,15 @@ Optional: - `metadata.annotations.alm-examples`: CR examples, in JSON string literal format, for your CRD's. Ideally one per CRD. - `metadata.annotations.capabilities`: level of Operator capability. See the [Operator maturity model][olm-capabilities] for a list of valid values. -- `spec.replaces`: the name of the CSV being replaced by this CSV. +- `spec.replaces` _(user)_: the name of the CSV being replaced by this CSV. - `spec.links` _(user)_ : a list of URL's to websites, documentation, etc. pertaining to the Operator or application being managed, each with a `name` and `url`. - `spec.selector` _(user)_ : selectors by which the Operator can pair resources in a cluster. - `spec.icon` _(user)_ : a base64-encoded icon unique to the Operator, set in a `base64data` field with a `mediatype`. -- `spec.maturity`: the Operator's maturity, ex. `alpha`. +- `spec.maturity` _(user)_: the Operator's maturity, ex. `alpha`. +**\*** `metadata.name` and `spec.version` will only be automatically updated from the base CSV +when you set `--version` when running `generate `. [olm]:https://github.com/operator-framework/operator-lifecycle-manager [doc-csv]:https://github.com/operator-framework/operator-lifecycle-manager/blob/0.15.1/doc/design/building-your-csv.md From 636e3ab6d96e0fee02d9169a9dbf04fff26d3167 Mon Sep 17 00:00:00 2001 From: Camila Macedo Date: Sat, 5 Dec 2020 00:25:02 +0000 Subject: [PATCH 230/376] add olm bindata 0.17.0 (#4242) Signed-off-by: reinvantveer --- Makefile | 2 +- .../fragments/add-0.17.0-olm-bindata.yaml | 16 ++++++ hack/generate/olm_bindata.sh | 15 +++++- hack/tests/integration.sh | 4 +- hack/tests/subcommand-olm-install.sh | 2 +- internal/bindata/olm/manifests.go | 54 +++++++++++++++++-- internal/bindata/olm/versions.go | 1 + internal/olm/installer/client.go | 8 +-- internal/testutils/olm.go | 2 +- 9 files changed, 89 insertions(+), 15 deletions(-) create mode 100644 changelog/fragments/add-0.17.0-olm-bindata.yaml diff --git a/Makefile b/Makefile index ae2f7908244..774ac6d9dba 100644 --- a/Makefile +++ b/Makefile @@ -41,7 +41,7 @@ generate: build # Generate CLI docs and samples go run ./hack/generate/samples/generate_testdata.go .PHONY: bindata -OLM_VERSIONS = 0.16.1 0.15.1 +OLM_VERSIONS = 0.16.1 0.15.1 0.17.0 bindata: ## Update project bindata ./hack/generate/olm_bindata.sh $(OLM_VERSIONS) diff --git a/changelog/fragments/add-0.17.0-olm-bindata.yaml b/changelog/fragments/add-0.17.0-olm-bindata.yaml new file mode 100644 index 00000000000..fa1d6ea0295 --- /dev/null +++ b/changelog/fragments/add-0.17.0-olm-bindata.yaml @@ -0,0 +1,16 @@ +# entries is a list of entries to include in +# release notes and/or the migration guide +entries: + - description: > + Add OLM bindata for the 0.17.0 release version. + + # kind is one of: + # - addition + # - change + # - deprecation + # - removal + # - bugfix + kind: "addition" + + # Is this a breaking change? + breaking: false diff --git a/hack/generate/olm_bindata.sh b/hack/generate/olm_bindata.sh index e92e52ea035..7c6a012aa82 100755 --- a/hack/generate/olm_bindata.sh +++ b/hack/generate/olm_bindata.sh @@ -1,9 +1,20 @@ #!/usr/bin/env bash +base_version=0.16.1 + +function version_gt() { + test "$(printf '%s\n' "$@" | sort -V | head -n 1)" != "$1"; +} + function get_olm_manifests() { echo "downloading olm manifests for version ${1}" - curl -L -o olm-manifests/$1-olm.yaml "https://github.com/operator-framework/operator-lifecycle-manager/releases/download/${1}/olm.yaml" - curl -L -o olm-manifests/$1-crds.yaml "https://github.com/operator-framework/operator-lifecycle-manager/releases/download/${1}/crds.yaml" + tag=$1 + if version_gt ${1} $base_version; then + tag="v"$1 + fi + echo "using the olm tag ${tag}" + curl -L -o olm-manifests/$1-olm.yaml "https://github.com/operator-framework/operator-lifecycle-manager/releases/download/${tag}/olm.yaml" + curl -L -o olm-manifests/$1-crds.yaml "https://github.com/operator-framework/operator-lifecycle-manager/releases/download/${tag}/crds.yaml" } function remove_olm_manifests { diff --git a/hack/tests/integration.sh b/hack/tests/integration.sh index 91a76b247c5..673c5e0f02d 100755 --- a/hack/tests/integration.sh +++ b/hack/tests/integration.sh @@ -27,7 +27,7 @@ popd # Install OLM on the cluster if not installed. olm_latest_exists=0 if ! operator-sdk olm status > /dev/null 2>&1; then - operator-sdk olm install --version=0.15.1 + operator-sdk olm install --version=0.17.0 olm_latest_exists=1 fi @@ -40,5 +40,5 @@ header_text "Integration tests succeeded" # Uninstall OLM if it was installed for test purposes. if eval "(( $olm_latest_exists ))"; then - operator-sdk olm uninstall --version=0.15.1 + operator-sdk olm uninstall --version=0.17.0 fi diff --git a/hack/tests/subcommand-olm-install.sh b/hack/tests/subcommand-olm-install.sh index c043bb6106b..604461da64e 100755 --- a/hack/tests/subcommand-olm-install.sh +++ b/hack/tests/subcommand-olm-install.sh @@ -37,4 +37,4 @@ test_version() { } test_version "latest" -test_version "0.15.1" # Check installation of OLM for locally stored version of binaries +test_version "0.17.0" # Check installation of OLM for locally stored version of binaries diff --git a/internal/bindata/olm/manifests.go b/internal/bindata/olm/manifests.go index 20aa7101bd5..de5755f8d7c 100644 --- a/internal/bindata/olm/manifests.go +++ b/internal/bindata/olm/manifests.go @@ -5,6 +5,8 @@ // olm-manifests/0.15.1-olm.yaml // olm-manifests/0.16.1-crds.yaml // olm-manifests/0.16.1-olm.yaml +// olm-manifests/0.17.0-crds.yaml +// olm-manifests/0.17.0-olm.yaml package olm import ( @@ -96,7 +98,7 @@ func olmManifests0151CrdsYaml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "olm-manifests/0.15.1-crds.yaml", size: 814667, mode: os.FileMode(420), modTime: time.Unix(1605551831, 0)} + info := bindataFileInfo{name: "olm-manifests/0.15.1-crds.yaml", size: 814667, mode: os.FileMode(420), modTime: time.Unix(1607105035, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -116,7 +118,7 @@ func olmManifests0151OlmYaml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "olm-manifests/0.15.1-olm.yaml", size: 9184, mode: os.FileMode(420), modTime: time.Unix(1605551830, 0)} + info := bindataFileInfo{name: "olm-manifests/0.15.1-olm.yaml", size: 9184, mode: os.FileMode(420), modTime: time.Unix(1607105034, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -136,7 +138,7 @@ func olmManifests0161CrdsYaml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "olm-manifests/0.16.1-crds.yaml", size: 824806, mode: os.FileMode(420), modTime: time.Unix(1605551830, 0)} + info := bindataFileInfo{name: "olm-manifests/0.16.1-crds.yaml", size: 824806, mode: os.FileMode(420), modTime: time.Unix(1607105033, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -156,7 +158,47 @@ func olmManifests0161OlmYaml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "olm-manifests/0.16.1-olm.yaml", size: 9143, mode: os.FileMode(420), modTime: time.Unix(1605551829, 0)} + info := bindataFileInfo{name: "olm-manifests/0.16.1-olm.yaml", size: 9143, mode: os.FileMode(420), modTime: time.Unix(1607105032, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _olmManifests0170CrdsYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\xfd\x7d\x73\x23\xb9\x91\x27\x8e\xff\xef\x57\x91\xd1\xf6\x86\xa4\xb5\x48\x75\xdb\x6b\xff\x76\xfb\x7c\x37\xa1\xed\xee\x19\xeb\xe7\x7e\x50\xb4\x34\xe3\x73\x8c\x67\xe7\xc0\x2a\x90\xc4\xaa\x08\x94\x01\x14\xd5\xf4\xcd\xbd\xf7\x6f\x20\x81\x7a\x22\x8b\x22\x0b\x80\xdc\xea\x31\xd2\x11\x9e\x96\x44\x66\xa1\xf0\x90\x99\xc8\xfc\x64\xe6\x64\x32\xf9\x05\x29\xd9\x77\x54\x2a\x26\xf8\x4b\x20\x25\xa3\x9f\x34\xe5\xe6\x27\x35\xbd\xfb\x77\x35\x65\xe2\x62\xfd\xe2\x17\x77\x8c\xe7\x2f\xe1\x55\xa5\xb4\x58\x7d\xa4\x4a\x54\x32\xa3\xaf\xe9\x9c\x71\xa6\x99\xe0\xbf\x58\x51\x4d\x72\xa2\xc9\xcb\x5f\x00\x10\xce\x85\x26\xe6\xd7\xca\xfc\x08\x90\x09\xae\xa5\x28\x0a\x2a\x27\x0b\xca\xa7\x77\xd5\x8c\xce\x2a\x56\xe4\x54\x22\xf3\xfa\xd1\xeb\xe7\xd3\xdf\x4e\x9f\xff\x02\x20\x93\x14\xbf\x7e\xcb\x56\x54\x69\xb2\x2a\x5f\x02\xaf\x8a\xe2\x17\x00\x9c\xac\xe8\x4b\xc8\x88\x26\x85\x58\xd8\x41\xa8\xa9\x28\xa9\x24\x5a\x48\x35\xcd\x84\xa4\xc2\xfc\x67\xf5\x0b\x55\xd2\xcc\x3c\x7d\x21\x45\x55\xbe\x84\xc1\xcf\x58\x7e\xf5\x20\x89\xa6\x0b\x21\x59\xfd\xf3\x04\x44\xb1\xc2\x7f\xb9\x57\xb7\x0f\xbd\xc1\x87\xe2\xef\x0b\xa6\xf4\x9f\x76\xff\xf6\x96\x29\x8d\x7f\x2f\x8b\x4a\x92\x62\x7b\xb8\xf8\x27\xb5\x14\x52\xbf\x6f\x1f\x3e\x31\x1f\x52\x32\xb3\x7f\x64\x7c\x51\x15\x44\x6e\x7d\xf3\x17\x00\x2a\x13\x25\x7d\x09\xf8\xc5\x92\x64\x34\xff\x05\x80\x9b\x3e\x64\x34\x01\x92\xe7\xb8\x20\xa4\xb8\x96\x8c\x6b\x2a\x5f\x89\xa2\x5a\xf1\xe6\x31\x39\x55\x99\x64\xa5\xc6\x09\xbf\x5d\x52\x28\x25\xd5\x7a\x83\x13\x01\x62\x0e\x7a\x49\xeb\xa7\xe2\x37\x00\xfe\x5b\x09\x7e\x4d\xf4\xf2\x25\x4c\xcd\x9c\x4e\x73\xa6\xca\x82\x6c\xcc\x18\xdc\x27\xec\xa2\xbc\xb6\xbf\x77\xbf\xd3\x1b\x33\x50\xa5\x25\xe3\x8b\x7d\x8f\x36\x9f\x39\xee\x99\x76\x02\x6e\x37\x65\xff\x91\x9d\x5f\x1c\xf3\xbc\xb2\x9a\x15\x4c\x2d\xa9\x3c\xee\xa1\xcd\xc7\x7b\xcf\xbc\xde\xfa\xed\xc0\x83\x3b\x8c\xea\x63\x31\xdd\xd9\xd2\x3d\xa6\x97\x8b\xfe\x7b\xe4\x44\xdb\x5f\xd8\x3f\xaf\x5f\x90\xa2\x5c\x92\x17\x76\x77\x64\x4b\xba\x22\x2f\xdd\xe7\x45\x49\xf9\xe5\xf5\xd5\x77\xbf\xbd\xe9\xfd\x1a\xfa\x6f\xdf\xdb\x9f\xc0\x14\x10\x90\xb4\x14\x8a\x69\x21\x37\x66\x36\x5e\xdd\x7c\xa7\xce\xe1\xd5\xc7\xd7\xea\x1c\x08\xcf\x9b\xe3\x02\x25\xc9\xee\xc8\x82\xaa\x69\xc3\xd8\x8e\x50\xcc\xfe\x9b\x66\xba\xf9\xa5\xa4\x7f\xab\x98\xa4\x79\xfb\xfc\x09\xd4\xef\xde\xf9\x95\x99\xd7\xe6\xc7\x52\x9a\xa7\xe8\xe6\xc0\x59\xea\xc8\xa2\xce\x6f\xb7\xde\xe7\xc4\xbc\xb2\xfd\x14\xe4\x46\x08\x51\x85\x0b\xea\xce\x02\xcd\xdd\x2c\xd9\x85\x66\xca\xbc\xad\xa4\x8a\x72\x2b\x96\x7a\x8c\xc1\x7c\x88\x70\xf7\x46\x53\xb8\xa1\xd2\xb0\x31\x47\xb4\x2a\x72\x23\xbb\xd6\x54\x6a\x90\x34\x13\x0b\xce\xfe\xde\xf0\x56\xa0\x05\x3e\xb4\x20\x9a\x2a\xbd\xc5\x13\xcf\x1e\x27\x05\xac\x49\x51\x51\x3b\xa9\x2b\xb2\x01\x49\xcd\x53\xa0\xe2\x1d\x7e\xf8\x11\x35\x85\x77\x42\x52\x60\x7c\x2e\x5e\xc2\x52\xeb\x52\xbd\xbc\xb8\x58\x30\x5d\xcb\xe0\x4c\xac\x56\x15\x67\x7a\x73\x81\xe2\x94\xcd\x2a\x23\xce\x2e\x72\xba\xa6\xc5\x85\x62\x8b\x09\x91\xd9\x92\x69\x9a\xe9\x4a\xd2\x0b\x52\xb2\x09\x0e\x9d\xa3\x1c\x9e\xae\xf2\x5f\x4a\x27\xb5\xd5\x49\x6f\xac\x3b\x1b\xd8\x12\x0a\xbd\x07\x56\xc0\x08\x3e\xbb\x93\xec\x57\xed\x5b\xb4\x13\x6d\x7e\x65\x66\xe7\xe3\x9b\x9b\x5b\xa8\x1f\x8d\x8b\xb1\x3d\xfb\x38\xef\xed\x17\x55\xbb\x04\x66\xc2\x18\x9f\x53\x69\x17\x71\x2e\xc5\x0a\x79\x52\x9e\x97\x82\x71\x6d\x0f\x71\xc1\x28\xdf\x9e\x7e\x55\xcd\x56\x4c\x2b\xdc\x97\x54\x69\xb3\x56\x53\x78\x85\x8a\x09\x66\x14\xaa\xd2\x9c\xb0\x7c\x0a\x57\x1c\x5e\x91\x15\x2d\x5e\x11\x45\x1f\x7d\x01\xcc\x4c\xab\x89\x99\xd8\xe3\x96\xa0\xab\x53\xb7\x3f\xbc\x75\xfe\x00\x6a\x7d\x77\xf0\x83\x43\x87\x15\xec\xe9\xdc\x96\xb2\x96\x86\xcf\xa9\x21\x92\xe7\x92\xaa\x9d\x5f\xef\x1c\x56\xfb\x31\xbb\x5b\x96\x42\x99\x75\x23\x1a\x3e\xbc\x7d\x07\x19\xe1\x50\x29\x6a\x8e\x52\x26\x38\x37\x1b\x41\x0b\x20\x46\x2b\x4d\xe8\x27\xa6\x74\x7f\x46\xda\x37\x58\x30\xa5\xe5\x66\x0a\x5f\x0b\xb9\x22\xfa\x25\xfc\xa1\xfe\xd5\x04\x1f\x20\x24\xb0\xf2\x7f\xbd\xfc\x43\x29\xa4\xfe\x5f\xf0\x81\x17\x1b\xf3\x98\x1c\xee\x97\x94\xc3\xcd\xf0\x7b\x5a\xfa\x9f\x9d\x3f\x7f\x23\xcb\x6c\x0a\x57\x0b\x2e\x64\xfd\x5d\xb3\xe3\xae\x56\x64\x41\x61\xce\x68\x81\x27\x40\x51\x3d\x3d\xd9\xe1\xb4\x67\x4d\xc1\x9a\x43\x73\xb6\x78\x47\xca\x03\x13\xf7\xaa\xfe\x9c\x79\x8a\x79\x70\x57\x49\xb7\x7f\xd4\x02\xb7\xb4\x79\x3d\x2d\x06\xde\x68\x46\xb2\x3b\x20\xee\xa9\x2b\x52\x4e\x14\x1e\xaf\xce\x24\xee\x9d\x9f\xde\x6c\xbc\xaa\x19\x0c\x3c\x43\xc8\xce\x07\xaf\x9c\xec\x9b\x8e\x99\x94\xee\x9b\x8f\xfa\x5e\x6b\x8e\x1c\x98\xce\x77\xdb\xfa\xe8\x08\xee\x2c\xdb\x3f\x9c\x81\x93\x05\x7b\x4f\x17\xe0\x09\x9b\x11\x45\x7f\xff\x6f\x83\x83\x30\xfa\x32\x67\x44\x0f\xed\xca\xfd\x27\x10\x70\x7d\x6b\xa6\x43\x7f\x7d\xf0\xf5\x00\xa5\x8c\x7b\xec\xe8\x6f\x33\x73\x0e\x0e\x4c\xba\x3d\x2b\xe6\xe4\xf3\xc6\xa8\x98\xd4\x3b\x0f\x2f\x06\x84\x71\x2a\x2d\x2f\xb3\x95\x19\x57\x9a\x70\xcd\x6a\x0b\xa8\x4f\xa4\xd9\xb5\xf5\x2e\xbe\x67\x7a\x79\xec\x0e\xc6\xf3\x3c\xc0\xf5\x6a\x0e\x4e\xf9\x9c\xe3\xd9\x72\x72\xad\x3d\xe2\xcc\x8a\x80\x51\x1b\xba\x94\x4c\x48\xa6\x37\x87\xa4\xe3\xb5\xfb\x9c\x7b\x1a\x51\x8a\x2d\xb8\x91\x94\xf7\x94\x2d\x96\xba\xb6\x32\x9c\xad\x0a\xaa\xbd\x7f\x6c\x0d\x45\xd4\x8f\x64\x7f\x37\x8a\x96\xae\x40\x09\x2b\x69\x99\x46\x41\x3b\xa3\x66\xc2\x55\xb5\xa2\x39\xcc\x36\xc8\x35\xa7\x25\xe5\x39\xe5\xd9\x66\x50\xca\x2a\x51\xac\xa9\x9c\xc2\xb7\xca\xac\x34\xfc\x91\x2d\x8c\xf5\xec\x06\xc6\x78\xce\xcc\xa5\x49\xd9\x87\xa0\x8a\x3e\x38\x4a\xa6\xcc\x54\xcf\xa9\x34\x12\x55\x98\x05\x2c\xc4\x7d\xc3\x93\xe6\x5b\x1c\x14\xe4\x15\x5a\x17\x87\x07\x5a\x99\xf9\x9c\xa2\xa1\x2f\x09\x5f\x34\x82\xb2\x5e\x07\x67\xa0\x98\x89\x58\x08\x6b\x4b\xa0\x05\xcc\xd6\x7b\x66\x93\xd3\x05\x31\x7f\x05\x66\xc5\x7e\xc3\x95\x71\xfd\xdb\xdf\xd8\x27\xe5\x74\x4e\xaa\x42\x3b\xde\xa8\xba\xfa\x97\x8a\x2e\x39\x1b\xc8\xec\x58\xa8\xb8\x5d\x68\x9a\xb7\x03\xbc\x47\x83\x73\x46\xe1\xb9\x65\xde\x9f\x0a\xfc\xde\xd0\x48\x97\x14\x94\x51\x0c\xfd\x17\x55\x70\xcf\x8a\xc2\x70\x93\x84\xdf\xd1\x1c\x0a\xfa\x89\x65\x62\x21\x49\xb9\x64\x19\x29\x8a\x0d\x0a\x8e\x7c\x48\x98\x73\x30\xb6\x93\xd1\x36\x7b\x15\x9b\xb1\x6f\x17\xcd\x25\xa8\xa6\xe6\xca\x34\x4a\x84\x2b\x9a\x49\xaa\x0f\x99\x11\x37\xf6\x53\xad\xa1\x68\x14\xaf\x59\x0e\xf7\x75\xbb\x0b\xdd\x3e\xdf\xaf\x0d\x49\x96\x99\xa3\x8d\x47\x4a\x70\x6d\x0c\xce\xad\xeb\xe0\x14\xae\xb4\xd9\xa7\x33\xaa\xf0\xf4\xdd\x51\x5a\xda\xdd\x5d\xb0\x1d\x3b\x1f\xc7\xbf\x22\x45\x71\x6e\xae\xed\x19\x05\x4a\xb2\xa5\x9d\x7a\x4e\x71\x0c\x66\x38\x5a\x32\x9a\xc3\x5c\x48\xa0\x6b\x6a\xe4\x9e\x5b\x59\xca\x8d\xfe\xdd\x33\x57\x44\x4a\xb2\xbb\xdb\x99\xa6\xab\x41\x35\xf0\xd0\x04\x37\x12\xf0\xd0\x1c\xb7\x72\xd3\x99\x1c\xf5\x1d\x7d\xcf\x81\x7e\xe0\xa1\xd6\xc6\xbe\xd1\x92\x68\xba\x38\x24\x05\xbf\xed\x7d\xb8\xb9\xd3\x2d\xc5\x7d\x6d\xab\x6f\x9f\x06\x54\x18\xdb\x77\x09\x40\x3f\x0e\xee\x80\x9c\xa9\xcc\xc8\x17\x9a\x1b\x53\x49\x31\x65\xd7\x99\x70\x7b\x35\x5b\x93\xc2\x6e\x98\xfa\x51\xa5\x28\x0a\x14\x34\x95\x1c\xba\x23\x1a\x32\x77\x38\xc2\x81\xae\x66\x34\xcf\xcd\x3d\xb0\x1e\xee\xa0\xd2\x7e\xd0\x48\x78\x58\xa3\xd7\x3a\xee\x5a\x14\xc5\x43\x5a\x79\x0f\xf3\xc3\x0f\x80\xfa\x86\xba\x26\x7b\x1e\x00\x3b\x8a\xbc\x9e\x35\xa6\xea\xd3\x05\x39\xd5\x54\xae\x18\xa7\x76\xab\xb0\x15\x6d\xb8\xee\x65\x0a\x30\xa3\xfa\x9e\x52\x0e\xd9\x92\x66\x77\xcd\xe1\xb3\xb7\xe8\xed\x55\x76\x17\x7a\x94\x87\x0f\xb0\xac\xbf\xd5\xba\x2d\x44\x51\xe0\x05\x5d\x51\x0a\x6c\x0e\x04\x38\xbd\xaf\xb9\x0d\xbb\x7f\x86\x48\xb5\x0e\x93\x35\x61\x05\x99\x15\x74\x6a\xac\x85\xe6\xa7\xf3\xee\xd8\x59\x6d\xeb\x94\x55\x51\x0c\x4a\xd6\x9a\xcc\x4e\x5a\x7c\xbc\x7e\x05\x5a\x92\xf9\x9c\x65\xe6\x4b\x39\x93\x34\xd3\x76\x62\xf7\x4e\xc8\x90\xf5\x62\x69\xcf\x49\x54\x9a\xe8\x4a\x1d\x79\x31\xdc\xbf\x69\x9a\x2b\xcb\x47\xa3\xbb\x29\xcf\x06\x24\x89\xb7\x55\xcc\x5b\x57\xe2\xf6\xaf\xd1\xcb\x39\xf2\xf4\x14\x44\x69\x2b\x4f\x6e\xd9\xd0\xa5\x00\x0e\xdb\xc4\x60\x64\x35\xde\x2b\x0d\x9b\x89\xd9\xd9\x03\x9f\xe2\x83\x77\x8e\x23\xd8\x37\x6f\xe6\xf5\xed\xda\x99\x32\xe8\x26\x3b\x92\x47\xc5\x06\x56\x02\x76\xa4\xf2\xd5\x6b\x7b\x69\x47\x2d\x80\xe2\x72\x29\x8a\x5c\x41\xc5\xd9\xdf\x2a\x0a\x57\xaf\x9d\xad\x71\x0e\x8c\x67\x45\x95\xef\x9b\x4d\x80\x6f\xbf\xbd\x7a\xad\xa6\x00\xff\x49\x33\x62\x2e\xfc\xf7\x14\x72\xc1\x4f\x34\x7c\x78\xff\xf6\x2f\xe8\x02\xc0\x4f\x9c\x5b\x45\x6b\xef\x0b\xa4\x60\xe8\x65\xdb\xc3\xd2\xbe\x1c\xf2\x34\x82\xdb\x8d\x32\x23\xa5\xae\x24\x55\x28\x89\xb8\xc6\xa3\xb6\xa4\x45\xa9\x60\x45\xee\x28\xa8\x4a\xda\x37\xd9\x37\xce\xab\xd7\x0a\xbf\x83\x6b\x04\xb9\x00\x2e\x34\x2c\xa8\xc6\x23\x50\xa0\xd7\x68\xec\x84\x3b\xcf\x06\x13\xfc\x46\x13\x1d\xf3\xe4\x98\xad\xfe\x61\x86\x37\xa1\x1c\x79\x8f\x3c\x2a\x7b\x1d\x38\x07\xde\x08\xdc\x31\x7b\x65\xdf\xec\x11\xcf\xd8\xce\x1b\x8e\x7e\x96\x95\xa3\x78\x0f\xfd\xf8\xa0\x5e\xdd\x89\x17\x98\x67\x5b\xad\x86\x0e\x97\xbe\x0f\x1d\x65\x7d\x73\x91\x5d\x12\x63\x2f\xd2\x21\xab\xc1\xa8\x22\x2b\xd5\x29\x77\xbb\x8f\xb6\xaa\xa2\x2a\x27\x5a\x4c\xf2\xa1\xa5\x7b\x70\xfe\x0e\xcd\xdd\x8a\x2a\x75\xf8\x76\x7e\x09\xcb\x6a\x45\x38\x48\x4a\x72\xa3\xce\xea\xaf\xd5\x77\x3b\x7b\xf3\xd2\x84\x15\x0a\xc8\x4c\x54\x1a\xee\x97\x43\x17\xb0\x81\xf9\x51\xf6\xda\x64\xee\x84\x82\xdb\x98\xd4\xa8\xeb\xb3\xa4\x44\x0d\x09\xb7\xde\xf8\x3f\xe2\x87\x6a\x5b\xd5\x7e\x65\x60\x30\xf7\x46\x8c\x48\xc2\x15\x0e\x63\x50\x33\x6b\x81\x77\x9e\xac\x92\x12\xaf\x16\x66\xab\x8d\x1c\xaf\xdd\x0a\x37\x54\xae\xd9\x68\xf5\xf8\xf0\x31\xc5\xe0\x11\xcd\x2f\x1f\xf3\xa0\x95\x42\xfa\xb1\x2f\xa5\xd0\x22\x13\x0f\x1a\xaa\x7b\xbf\xac\xec\x6c\x0d\x7b\xef\xc6\x7d\x7f\x8c\x42\xb5\xf2\xe4\x25\x68\x59\xd9\xb9\x50\x5a\x48\x74\x71\xb4\xbf\xa9\x66\x4d\xc0\xa4\xe6\xea\x8c\x29\xf8\xbf\xff\xef\x17\xbf\xf8\x22\xe3\xe6\x45\xa5\x34\x95\x6e\xd2\xea\xc0\xf1\x3f\x2a\x7e\x6e\x1f\xee\xce\x87\x9b\x37\xfc\x7b\x27\x8e\x3e\xf4\x99\xdd\x78\xfa\xe0\x6b\xd8\x55\xdb\x8d\xab\xab\x75\xfb\x2f\xf7\xa1\x36\xbe\x3e\xc4\xe9\x71\xe2\xec\x3d\xdf\xfd\xcd\x77\x6e\x47\x3d\x5e\x70\x7d\xeb\xae\xb3\xff\x91\xeb\xce\x4a\xd4\x8f\xfb\xae\xf7\xbb\x63\x1e\x57\xbf\x1e\x31\x4f\xea\x38\x04\x05\xc7\x98\x60\x41\xb2\xe6\xb2\xbe\x3d\x80\xad\x3f\xdb\x11\x7c\xec\xff\xf2\xe1\x28\xbb\x3d\x97\xd3\x72\x49\x54\x7f\xda\xae\x3b\xbf\xd9\x61\x11\x2b\xb6\x3e\xb4\x67\xad\xd9\x6c\x4f\x3d\xd4\xc7\x1e\xd7\xc2\xd8\xa8\xff\x67\xf0\x3b\x37\x25\xcd\xfe\x4f\x8a\xb3\xa7\x38\x7b\x8a\xb3\x7f\x51\x71\xf6\xc3\xd2\xc0\x9c\x6c\xc8\x69\x56\x10\xeb\x5b\x54\xa0\x69\x51\x60\x00\x7c\x29\xee\x9b\xa8\x57\xb1\xed\x35\xeb\xc4\xcc\x5a\xef\xf6\x8a\x70\x63\xa1\x93\xb2\x54\xe8\x51\x26\xb0\x60\x6b\xca\x1b\x57\xd9\x71\xae\x9e\x7d\x18\x80\x5d\x05\x54\xff\x65\x68\x88\x0f\x40\x03\xb6\x6d\x99\xbd\x33\x76\xd9\x7e\xd2\xdd\xfb\x2b\xae\xb4\xac\x70\x79\x73\xb8\xa3\x75\xe4\x66\x45\x4a\xb4\xd3\x68\xbe\x2f\x14\x42\xba\x07\x80\x68\xdc\xd7\x33\x8a\x71\x82\xd9\x06\x8c\x79\x86\xa2\x42\x0b\xe1\x9c\x83\x86\x1b\x8a\x0c\x49\xb5\x64\x74\x30\x12\x44\xe4\x8c\x69\x49\xe4\xa6\xd9\x27\xfb\xee\x05\x7b\x6c\xfb\xae\xa9\xf0\x90\x95\xff\x80\xa9\x4b\x4a\xe6\x6c\x94\xbc\x31\x1d\x0f\xce\xeb\xf5\x95\xdb\x85\xad\xb9\xa9\xdc\x2e\xa4\x0a\x48\x51\xd4\xb6\x41\x63\xb7\xe2\x73\x06\x46\x66\xb7\x5c\x0e\x42\x36\xfb\xc6\x4c\x68\x77\x7b\xce\xd0\x07\x23\x09\x37\x7f\x18\x3c\x04\x23\x67\xed\xe1\x1b\x91\xb8\xe7\x43\x1e\x11\x38\x10\x3c\x81\x87\x02\x28\x0f\xce\x60\xf3\x6b\x33\xb0\x35\xcb\xa9\x6a\x2e\xc6\x5a\xe0\x49\xc6\xfb\xf1\x1e\xb6\x76\x05\xeb\xaf\xe6\xb0\x66\x04\xc8\x62\x21\x31\xc2\x38\x18\x6b\x38\x38\x3f\x96\xf6\x3b\x87\x2c\x4d\xac\xfd\xbe\xf7\xaf\x46\x48\xee\xfd\xe3\xa0\x5f\xb6\xfe\x63\xdf\x6c\xdc\xa6\xc3\xe1\x07\x00\x82\x2e\xb1\x7a\x6a\x85\x7c\xe0\xa3\x87\x57\xd5\xd2\x83\x6b\x6b\xa9\xbf\xc2\x5b\x43\x70\x7f\x9d\x99\xf3\xd1\x0a\xec\x41\xb1\xb0\xfb\x26\xbd\x00\x64\x49\xa5\xb9\x75\x9b\x43\xc3\x81\x40\x66\x2d\xc1\x46\x3c\x59\x94\xc3\x60\x84\x7c\xfb\x9d\x1f\x5c\x7f\x4b\x87\x76\x81\xa5\x09\x94\x64\x50\x6c\xb6\x74\xcc\xb2\x59\x7a\x10\xae\xb3\x4d\x07\x1d\x14\x1d\xbe\x0f\xc1\x79\x02\xf8\x9a\x57\x8f\xca\x10\x75\xd2\x61\x8e\x7d\x77\x15\xb9\x7f\x57\x3b\xd8\x10\x83\x4b\xee\x81\xf2\x4c\x18\x91\xf0\xff\xbf\xf9\xf0\xde\x32\xdd\x1f\xe3\x69\xe9\x4a\x03\x5b\x95\x05\x5d\x61\xfc\xfa\x1d\x91\x6a\x49\x0a\x2a\x51\x97\x7d\xcb\x57\xbd\x9f\x33\xb2\xef\x94\x76\xa9\x0d\x9a\x43\x4e\x0b\xb2\xb1\x03\xca\x69\x26\x72\x23\xd9\x85\x84\xd2\x98\xd2\xab\xb2\xd2\x14\x08\xfe\xf5\x08\xae\xf8\x76\x8c\x2f\x0e\xbf\xd3\x88\xa9\x6f\x1d\x5a\xb3\xcd\x20\x4a\xa8\x4b\x9f\x26\xf9\x71\x12\xa6\x3b\x8c\x43\x72\xc6\xd2\x11\xd2\xa6\xcb\xf4\xc0\xbb\x35\x58\xa8\xeb\xbd\x9e\xb8\x2e\xb7\x61\x00\x46\x97\xea\x49\x42\xb8\xca\xde\xcf\xe5\xb4\x2c\xc4\xc6\xec\xa3\x43\x67\xee\xa8\xb7\x38\x52\x2e\x1c\xc7\xeb\x38\x59\x70\x14\x2f\xeb\xc6\x0a\xe5\xb2\x7b\x59\xf3\x60\xb2\x3f\x6c\x38\x82\xc9\x8e\x6f\x72\x3f\xa7\xe8\x4a\xf3\xfa\xaa\xf6\x68\x34\xd1\x60\x2b\xcf\xfe\x54\xcd\xa8\xe4\x54\x53\xd5\x8c\xef\xc0\xe9\x40\x77\x08\xca\x1d\x63\x4f\x6e\xab\xc9\x7f\xac\x76\x7c\xc0\x16\xaa\x3f\xf2\x80\x45\x54\x7f\xe4\x61\xbb\xc8\xd2\xf1\x6a\xf6\xd0\x86\xb3\x34\x42\x76\x1e\xda\x7c\xa3\x19\xae\x1f\x8a\x42\x8f\xe6\x69\x6e\xd7\x9f\xd5\x22\xbc\xe9\x0d\xa0\x67\x0f\x3a\x34\xa8\x31\xe7\x7a\xfe\xb5\x61\x9a\x15\x22\xbb\x73\x1e\xd1\x8f\xaf\x1b\x28\x66\x0d\x7a\x77\x40\x4c\x60\x0f\xef\xdd\x64\x02\xc6\xe3\x9b\x4c\xc0\x03\x94\x4c\xc0\xce\x30\x3e\x87\x09\x68\xe3\x18\x9f\x57\xfe\x6d\x0d\x61\xaf\x04\xc4\xcf\x25\x19\x98\x64\x60\x92\x81\x87\xb9\x26\x19\x08\xc7\xbe\xdb\x11\xf6\xe4\x41\x7c\xe4\x43\x62\x20\xb9\x87\x3b\x94\xdc\xc3\xdb\x94\xdc\xc3\x0f\x50\xd2\x8b\x49\x2f\x26\xbd\x98\xdc\xc3\xfe\x6f\x91\xdc\xc3\xc9\x3d\x9c\xdc\xc3\xc9\x3d\xec\xc9\x33\xb9\x87\x87\x5e\x32\x99\x80\x31\xf8\x26\x13\xf0\x00\x25\x13\xb0\x33\x8c\xe4\x1e\x4e\xee\xe1\x24\x03\x93\x0c\x4c\x32\xf0\xd0\x67\x9f\x92\x7b\xd8\x5e\x20\xea\xfb\xc3\xf1\x58\xea\x67\xfb\xf2\xf7\x86\x01\xd5\xaf\x3e\xbe\x56\x35\x68\x7a\x60\xa0\x61\x30\x6a\xf8\xeb\xd0\x46\xbd\x6a\x9e\xec\x4a\x2c\x61\x85\x1c\x57\xb9\xe8\xc3\x3d\xa7\x39\xa6\xd9\x9d\x03\xc3\xda\x36\xe6\x58\xb0\x8c\xe9\x62\xd3\x0c\x65\xfa\x6c\x87\xed\x53\x07\x68\xbf\xfa\xf8\xfa\x68\xd7\xbb\x99\x88\xbd\x9b\xc6\x2c\xd8\x9e\x3f\x46\xf1\xb2\x27\x3f\x7a\xf2\xa3\x77\x28\x19\x10\xc9\x80\x48\x06\xc4\xe7\x31\x20\x9e\xaa\x07\x3a\xf9\x8e\x93\xef\x38\xf9\x8e\x7b\x94\x7c\xc7\xc3\x94\xfc\x26\x3d\x4a\x66\x4f\x32\x7b\x0e\x7d\xf2\x9f\xde\xec\x49\xbe\xe3\xfd\x2f\x9a\x64\x60\x0c\xbe\x49\x06\x1e\xa0\x24\x03\x3b\xc3\xf8\xf2\x7c\xc7\xf0\x0f\x84\x16\x27\xc7\x66\x72\x6c\x26\xc7\x66\x43\x49\xbb\x25\xed\x76\xe8\x93\xff\xf4\xda\x2d\x39\x36\x93\x63\x33\x39\x36\x93\x63\x33\x39\x36\x93\xd9\x13\x8d\x6f\x32\x7b\x0e\x50\x32\x7b\x3a\xc3\x48\x8e\xcd\xe4\xd8\x4c\x32\x30\xc9\xc0\x24\x03\x0f\x7d\xf6\x29\x39\x36\x1f\xa5\xf3\xee\x03\xdf\x7b\xa8\xa7\xae\x57\xcf\xc3\xbd\x62\xee\x21\xe1\xf6\x60\x33\xde\x87\xdb\xf1\x1e\x16\x76\x87\x5a\xf2\x1e\xb1\xae\x07\xda\xf2\x3e\x3c\xc3\xb6\x54\xf7\x01\x50\xb3\x59\xb8\xfc\xca\x7e\xb4\xe9\xbc\xd8\x96\x87\x47\xe4\x70\xab\x8d\xf8\x03\x0d\x3c\xfa\xd4\x38\x29\xef\x97\xb4\x6e\x77\x64\x9f\xd2\x76\x4c\x64\x0a\xef\x03\x6c\xce\xf6\x77\xd5\xf5\xe8\x87\x55\xf3\xdf\xf9\xd3\xc3\x0b\xb6\x5b\xd3\x7d\x70\xc2\xea\x49\x7a\x6d\xbd\xf0\xaf\x9b\xd4\xe8\xed\x59\x2b\x89\x34\xf2\xd0\x79\xeb\xf7\xac\x1f\xaa\xf8\x0e\x8f\xad\x95\x78\xa8\xcb\xd8\x03\x7a\xfd\x61\x7d\x3e\xe9\xe4\x73\x0f\x8f\xeb\xb0\x1a\x77\x3d\x53\xae\xa9\x5c\x31\xa5\x86\xc1\xf3\xfd\xe1\x3e\x2c\x12\x0f\x8a\xc2\x3d\x6b\x50\xbf\x47\x67\x20\x8d\xe1\xf5\x60\x4c\xc4\x90\x9c\x91\x0c\x64\x55\x50\xdb\xec\xcd\x15\x57\x07\x92\x65\xa2\xe2\x1a\x5b\xb7\xb6\x4d\x92\xb7\x77\xef\x41\x31\x7b\xd0\xee\x3a\xc6\xea\x9a\xd8\xf1\x3d\xf8\x09\x37\xee\x4b\x3b\xec\x9d\xa2\xfd\x7d\x3a\xd6\x42\xc3\xc7\x1e\xd2\x4d\xc7\x2b\xbb\x23\x55\x5d\x6f\x95\xaf\x45\xc1\xb2\xcd\xc7\xaa\xa0\xae\xe1\x20\xe3\x56\x6f\x37\x61\x92\xc6\xc4\x3e\x42\x87\x12\x28\x91\x1f\xbe\xd9\x39\xcc\x2a\x0d\xb9\xa0\x0a\x3b\xfb\xb9\xb2\x0a\xdd\x07\x1c\xc3\xd1\xf5\x42\xb3\x8d\x49\x0c\x5b\x20\x65\x59\x30\x8a\xa1\x39\x21\xe1\x7e\xc9\xb2\xe5\x03\x1d\x2c\x77\x69\x80\xd1\xb1\x96\xcf\x11\x66\x3e\x1c\x6d\xea\x43\xed\x91\x9b\x1d\x9e\xda\xe3\x6d\x7e\xb0\x35\x8e\xbe\x91\xa2\x2a\x8f\xfa\xf0\xae\xff\xd4\x7e\xb7\xee\xf5\xd6\x6d\xa7\x54\xff\xf1\x28\xb6\xe0\xc2\x6c\x76\xdd\xeb\xc6\x71\xce\x31\x3c\xc5\x44\x9a\x55\x55\x68\x56\x16\xc8\xf8\x48\x9e\x0b\x3b\x38\x22\x69\xab\xd7\xce\x81\xf0\x4d\x1d\xdb\x73\x0d\x52\x68\x0e\x64\x61\x9e\x7b\x78\xb9\x2c\x09\xde\xbc\x26\xe5\xd5\x8a\x4a\xec\x85\xdc\x0c\x18\x2f\x96\x7c\x63\x46\xfa\x60\x29\xa7\x6d\xaa\x7b\x83\x93\xa2\x10\xf7\xfb\x5a\x5a\x6e\xd3\x18\x03\x17\xc6\x18\xb9\x30\xd6\x88\x07\xe0\x82\xd7\x0e\xf5\x6f\x3f\xbe\xf5\xd9\x52\xef\xfb\x1c\x5c\x8f\x1d\xdb\x52\xbc\x24\x52\xb3\x07\x9b\x18\x77\xa9\x92\x85\xeb\x3e\x4e\xcc\x45\x48\xd6\x2d\x8d\x96\x64\x4d\x9b\x7e\xe3\x62\x0a\xf0\xaf\xc7\x48\x2b\xc0\x9e\x23\xcd\xd2\x58\x79\x25\x78\xb1\x01\x62\x77\xeb\xbc\x2a\x8a\x73\x98\x33\x4e\x8c\x4a\xa2\xc7\x2e\xb9\xcb\x05\x33\xb7\x59\xb8\xc1\x56\xe5\x5c\xf0\x49\x63\xac\xe1\x1c\x98\xe7\x72\x71\xec\xde\x6c\xc4\x5b\xee\xda\xb6\x3a\x5f\x87\x72\xc3\x35\x82\x2c\xc3\xb6\x92\x73\xf1\x50\x25\x9a\x2e\x39\x23\xf3\xa3\x28\x30\x20\xe2\x42\x25\xb9\xed\x49\x44\xba\x7f\xfe\x4f\xc6\x8f\xbb\x1e\x5a\xfa\x88\xca\x3e\x23\x1c\x28\xd3\x4b\x73\xbf\x2d\xcb\x62\x63\xc4\xb5\x39\x3b\xed\x81\x3a\x55\x55\xf6\xb0\xa7\xa3\x25\xa2\xe0\x59\x29\x72\xf5\xcc\x88\xfc\x67\xae\x0f\xfd\xb3\x33\xf3\xd3\xf6\xdc\x1e\xc9\xd1\xac\x8e\x1b\x03\x72\xbf\x20\x25\x7b\x76\x76\x0e\xb8\x09\xb0\xa9\x92\xd0\xcb\x2f\xef\xb4\xd6\x33\xd1\xe9\xcc\x77\x88\xb6\xfa\x7c\x76\xbe\xef\xba\x04\x89\xd2\x36\xd5\x31\xba\xf6\xe0\x55\xbe\xa6\x82\x29\x3c\xe0\xb6\xbb\xaf\x6b\x53\xb7\xab\x78\x01\x2e\x8f\x31\x03\x0c\xd1\x55\xa9\x37\x28\x37\x56\x94\x70\xc7\x13\xbb\xfc\xeb\x25\xe3\x0b\x1c\xec\x97\x2a\x64\x8f\x0a\x98\xb6\x34\xb8\x64\x4e\xb0\xd6\x13\xdf\xb0\x3c\x5a\x59\x33\x35\xb0\x3c\x35\xf7\xcb\xa2\xe8\x5c\xbe\x8e\x3d\xb6\xf8\xa5\x5a\xe5\x7f\x71\xab\x82\xb6\x99\xc7\x8a\x7c\x67\xbe\xd7\x5f\x0d\xfb\x2b\xab\xba\x8c\x38\x3c\x76\xc0\x02\x2e\xdf\xbe\xb5\x6d\xe7\xdc\x3c\xfe\x89\xf1\xdc\xde\xa5\x2e\xb5\xed\xd9\x46\x3f\x52\xf3\x4a\x68\xfe\x1c\xbb\x32\x75\x91\xb3\xbc\x69\x1e\x6c\x96\x7e\x0a\x38\x50\xef\xb5\xc6\x4e\x70\x5f\xd2\x3a\xef\x5e\xeb\x8e\xbb\x8e\x3d\xc8\xba\x73\xf3\xff\xbc\x17\x76\xec\x86\xd7\xb3\xbf\x8d\x34\x3e\x3f\x1c\x20\x36\xbb\xab\x20\x33\x5a\xd8\xc6\x77\xe6\x9b\xed\x4b\xc1\xe5\xdb\x77\x4d\x2f\x49\xec\x97\xfc\x8f\xba\xa6\x1f\x00\x38\x4c\x0e\xbd\xd8\xb1\xb7\x28\x7c\xf5\x31\xc1\x15\xb8\xa1\xda\x9e\xf7\x15\x29\xcd\x71\xb7\x1c\x6c\xa4\xa0\x1f\x07\x38\xb8\x83\xdf\xe2\xbc\x1f\x3a\x44\x23\xee\xa3\xc7\x76\xc5\x1b\x7a\xc0\x11\x47\xe8\x18\xcc\xc6\xf1\xe7\x71\xaf\x7f\xb0\xa5\xde\xc4\x6f\x6d\x76\x77\x67\x75\x37\xc3\xcc\xba\x31\xc4\xfc\xf0\xdb\xe2\x0e\x57\xb6\x50\x04\x5d\x92\x35\x13\xb2\xbe\x0d\xb6\x8f\x88\xb8\x28\xc7\xba\x08\x26\xa0\x68\x41\x33\x7d\xd0\xac\x9f\x80\xa6\xab\xb2\x78\xf8\x34\xc2\x48\x57\xc2\x8a\xf1\x8f\x94\xe4\x9b\x1b\x9a\x09\x9e\x1f\x25\x7e\x7b\xab\xf3\x8e\x71\xb6\xaa\x56\xc0\xab\xd5\x8c\xe2\x84\x2a\xcb\x09\xc5\x0a\xba\x6e\x8e\x92\xe8\x04\x38\xbd\x2f\x36\x75\x7b\x76\x28\x45\x5e\x4b\xa0\x19\x76\xa3\xcf\x37\xd8\xa9\x52\x54\xda\x5c\xd2\x8f\xe2\x29\xe6\xb6\x0f\x7d\x5d\xed\x13\x32\x49\x94\x31\x24\xcf\x71\x70\x4c\x1b\xe5\x3b\xa3\x18\x07\x66\x39\x95\x83\x05\x46\x06\x86\xba\x26\xac\x30\x57\xb1\x29\xbc\xa6\x73\x52\x15\xd8\xaa\x15\x9e\xc3\xa9\x19\x74\xed\x0d\xf0\x65\x6a\xae\x2a\x4a\x08\x6e\xfe\x6b\xeb\x8b\xe0\xcb\x9f\x1d\xe3\xf6\xc2\xcd\x79\xb8\x5a\x69\x4d\xc7\x55\x2d\xad\xa9\x24\x95\x3a\xc6\xe1\xb5\xb5\x41\xae\x78\x6e\x4e\x69\xf7\x86\xd0\x51\x34\x4c\x39\xbe\xc7\x98\x14\xf6\xfd\x66\x42\x14\xf4\x88\x58\x6a\x29\xc5\x42\x52\xa5\x5e\x53\x92\x17\x8c\x53\xdf\x1d\x7e\xbb\xa4\xb0\x22\x9f\x70\x97\x6b\xb6\xa2\xc6\x9c\xea\xee\x71\xd2\x79\x9f\xe3\xec\x22\x01\x2b\x72\x47\x9b\x01\xc2\x8c\xce\xb1\x89\x2f\x4e\x47\xbb\x6f\xec\xee\x3c\x8a\xe5\x9c\xb0\x82\xe6\x53\x1c\x6b\x67\x76\xdb\x9e\xf7\x76\x5b\x9a\x9f\x19\xaf\x8e\xe3\xa9\x85\x19\x21\x3a\x5c\x2c\xfb\xae\xd5\x83\xf6\x03\x31\x0c\xad\xe6\x39\x8a\xa3\x39\xbf\x40\xe0\x7a\x6b\x61\xde\x7c\xca\x6c\x88\x40\x52\xa2\x04\xaf\x4f\xd0\x51\x2c\x55\x25\xe7\x24\xab\x6d\xdc\xde\xcb\xbb\x46\xe6\xf0\x5e\x68\xd7\xc2\xb6\x9e\xf0\x23\x07\x5b\x14\xe0\x5a\x2f\x53\xa5\xd9\x0a\xc5\x52\x5e\xc9\xba\x49\x34\xee\x85\xd1\x8b\xdf\x6e\xf8\x9e\xf0\xf8\xfd\xf3\xe7\x47\x59\xd5\x8f\x7b\xc4\x25\x45\x2f\xd3\xf8\x33\xf2\xbe\x91\xfe\xb5\x8a\x2d\x45\xae\xcc\x7e\x64\xee\x96\x84\xbd\xaf\x8f\x1a\x32\xee\xbc\x9c\x29\xcd\xf8\xa2\x62\x6a\x09\x33\xaa\xef\x29\xe5\x40\x3f\xd9\x3a\x4b\xf0\x77\x2a\x05\x6e\x40\xb3\x3c\x0f\x84\x3e\x87\xa8\x3b\xe9\x2f\x9e\xc2\x8c\xaf\x99\x62\x82\xff\x91\x29\x2d\xe4\xe6\x2d\x5b\xb1\x07\x0b\x52\xd7\xb4\x23\xa1\x5a\xfd\x2b\x8a\x1c\x3b\xfe\xb3\x8c\xdc\x50\xfb\xa2\x92\x1a\x05\x78\xec\xdc\xa3\x8b\x05\x8c\xdc\x98\x91\xec\x6e\x60\x11\xb7\x16\xe8\x28\xbe\xc7\x2e\x62\xb3\x40\xc7\x8e\xf6\xc5\xf3\xcf\xbf\x8a\xb5\x01\x37\x7a\xe5\xf0\x26\xd0\x7c\x1d\xd5\x89\x3d\x38\x6f\x3e\xd9\xf9\xed\xae\xe4\x71\x62\x6b\x29\x14\x45\x26\x36\x80\x82\xac\xeb\xf0\x2b\x53\x8d\x79\x62\x24\x98\xe0\x47\xba\x8e\xc8\x7c\xde\xe7\xd2\x0a\x3d\xbc\xfb\xac\x2a\xa5\x61\x45\x74\xb6\x3c\x18\x2c\xae\xc9\x98\x4a\xb5\x39\x7b\xa2\xdc\x55\xf4\xf8\x95\x3c\x32\x4c\x37\x36\xac\x06\xf6\x2d\xde\x7c\x2a\x8d\x9e\x78\x38\x1e\xdf\xa7\xde\xb2\x6e\x33\xe9\x3b\x8a\xf0\x5d\x8f\x64\xdb\xee\xad\xfa\x3e\x81\xea\xd7\x6a\xfa\xee\x6f\xcc\x6a\x1f\xcd\xf3\xf2\xfd\xeb\x63\xe5\xe5\x78\x37\xce\x48\x47\xce\x76\x70\xd2\x4e\xcf\xe0\x6b\x1f\xcd\x11\xea\x00\x94\xe3\xd1\x8f\x52\xe2\x9d\x5d\x9d\x03\x81\x3b\xba\x39\x1f\xc1\x14\x6d\x9e\x4e\x81\x41\x64\x2b\x69\xe1\xac\x5b\x8a\xfd\xf5\xc9\x81\x24\x8e\x3e\xd9\xb1\x1c\xbb\x14\xa3\x77\xbf\xa5\xe3\x83\xd5\x35\x4d\xcc\xab\x8c\xf8\x74\x3d\x25\x47\x7f\x65\xec\xb1\xb4\x74\x47\x37\x63\x3e\xbe\xb5\xb5\xcc\xea\x38\xef\x81\xdd\x63\xe6\x17\x66\x0d\x47\xb1\xb4\x9e\x84\x66\x6b\x8d\x41\x18\xf4\x98\x8c\xf3\x53\xd7\x54\x4f\x74\xc0\x34\x34\xdb\xb7\x03\xb4\xc2\xa3\x70\x72\xac\x1f\xb8\x26\xdc\xfa\x46\xbe\x2d\x59\x89\x86\x43\x1d\xf2\x75\xbb\x1a\xbe\x23\x05\x1b\x73\x1a\xba\x6f\x68\xf5\xd7\x15\x3f\x37\x06\xbc\xf9\x0f\xaa\x44\x35\xf2\x7c\x19\x7a\x2d\xa8\x7a\x2f\x34\x7e\xff\x1f\xb2\x48\xf6\xf5\x03\x96\xc8\x32\x70\xb1\x39\x94\xbc\xe8\x58\x19\x3b\x8e\x76\x2c\xd3\xba\xa6\x69\xb3\xf8\x4c\xc1\x15\x07\x21\xdd\xec\x7a\x1c\x01\x37\x48\x3b\x3c\xb4\x00\x66\x36\x0c\x8e\x51\xbc\x71\x13\x0d\x43\xe3\x73\x0b\x2e\x64\x6f\x05\xa3\x0d\xd5\x0e\x13\xad\xdb\x91\x2c\x2d\x1f\xf4\xcc\x94\x05\xde\x3e\xdd\xb5\x90\xd4\xb0\x36\x76\x28\x3b\x6b\x9b\x56\x54\x2e\x10\x4f\x90\x1d\x19\x91\x6e\x5e\x6f\xb4\x76\xb6\x34\x52\x47\x77\x1f\x36\x62\x1f\xa2\x21\x64\xdd\xdd\xfe\x86\x94\xfd\x7e\xcf\xf9\xfe\x7f\x8d\xe6\xc6\x55\xfd\x7f\xc7\xab\x1c\xc2\xa4\x9a\xc2\x25\x28\xc6\x17\x05\xed\xf2\xa8\xbd\x07\x9d\xc7\x1d\xcd\xd6\x8c\x88\x29\x30\x2a\x76\x4d\x0a\xca\xd1\xa9\x48\x38\x50\x1b\x0d\x30\xa3\xdd\x36\x07\x8f\xdf\xc2\xd6\x9a\x37\x7a\xaa\x81\x83\x3c\xbb\xa3\x9b\x67\xe7\xdb\x87\xe5\x68\x8e\xcf\xae\xf8\xb3\x73\xb4\x64\x76\x0e\x46\x63\x20\x21\xe2\xe4\x19\xfe\xed\xd9\xf1\xbb\x71\xc8\x22\xf5\xb1\x34\x47\x19\x37\x7e\x91\x8f\xfe\x03\x8f\xdc\xcf\x35\x62\xd5\xeb\x7a\xde\xf3\x4b\x39\xdc\xb6\x16\x50\x29\x6a\xef\xe7\x28\x47\x8e\x1a\x37\xad\x6f\x86\x78\xc7\x43\x97\x1a\xa7\xf7\x78\x97\x7b\x02\xd7\x27\x29\x8a\x82\xf1\xc5\xb7\x65\x4e\xf4\x11\x69\x39\x96\x7a\xb3\x75\xf2\xd1\xb2\x80\x0a\x79\x98\x5d\x39\x67\x0b\x28\x89\x24\xab\x11\x86\xf2\xb5\xab\xda\x8d\x7b\x99\xcd\xbb\x51\x24\x37\xff\xb7\x9b\x92\xc2\xff\x84\x8f\xdd\x11\x1f\xcf\x7f\x32\x99\xc0\xed\x87\xd7\x1f\x5e\x82\xfd\xa6\xbd\x17\x6b\x01\x73\x81\xee\x13\x51\x49\x33\xf4\x35\xe5\x47\xbb\x47\xc1\xfa\x1d\xcc\x52\x7e\x98\x9f\xc3\xfd\x92\x68\xba\xa6\x12\xee\xcd\xf6\xc9\x58\x4e\x9b\x88\xc5\xf4\xe4\xf1\x4e\x94\x8f\x65\xbe\x22\x9f\x6e\x2a\xb9\x38\x7a\xc1\x61\x67\xd1\xbb\x4e\xf6\xd6\x95\x65\xb6\xf8\x38\x6d\xd8\xa9\xfa\xa2\xb2\x25\xcd\xab\x82\xe6\x40\x66\x62\x4d\xbb\x01\xc0\x51\x3c\xfb\xc3\x41\xa3\xb6\xa2\xf5\x43\x8c\x7d\x36\x53\xa2\xa8\x8e\x46\x4d\xf5\x98\x9e\xd2\x4f\x2f\xe1\x77\x08\x72\x23\x50\x52\x99\x51\xae\xc9\x82\x76\x1c\xa9\xa3\xb8\xa2\x48\x40\x9e\x2f\x9e\xff\xcb\x99\xf3\xdc\x99\x91\x3a\x3f\xf6\x73\x73\x12\xde\x91\x4f\xdf\xf2\x26\xdc\x34\xce\x68\x50\xf0\x7c\x0a\x97\xee\x85\xeb\x97\xc0\x67\x14\x59\x55\xa0\x87\x7c\x2e\xc5\x6a\xdc\xa0\xdb\xd7\x9e\x6d\x40\x8a\x0a\xa1\x88\x50\x95\x3d\x0f\xf9\x28\x96\xbf\xf9\xdd\xbf\x4c\xe1\xcd\x27\xb2\x2a\x0b\xfa\x12\xee\x97\xd4\x01\x60\x98\xc2\x1b\x8a\x16\xf0\xdb\xe7\xff\x32\xce\x90\x44\x68\x05\xbd\xef\xf8\xe3\xda\x7d\x46\xcc\x26\xab\x4a\x60\x2b\x9b\x68\x44\x8f\x06\xff\x58\x72\x03\xa4\xb5\xf4\xac\x45\x9f\xd2\x44\x6a\x75\x0e\x88\x60\x1c\x7d\x51\xc5\x18\x85\xd0\xa4\xd8\xf2\x0d\xa3\xcf\x95\xde\xdb\xcd\x92\x8f\x9b\x58\xb3\x8f\x28\x86\x6b\xe0\xc5\x6f\x9f\xff\xcb\xae\xc3\xff\xc3\xa1\x3a\x4a\xdb\x64\x46\x84\x23\x41\x80\xef\x8c\x52\x0e\x77\xac\x28\x68\x7e\xbe\x35\xdd\xa3\xb8\xee\x2c\xcd\xbc\x92\x7a\x49\xe5\x39\x50\xae\xea\x10\xce\xd8\xf9\xdc\x9a\x4b\x1c\xb5\xac\x38\x47\xcb\x1f\xa3\xd2\x18\x13\x1a\x77\xed\x6b\xe3\x49\x6e\xd1\x8d\x99\xab\x61\x25\x94\xde\x9e\xe2\xd1\xa2\xe0\x68\x35\x01\xe8\xdc\xda\x7c\x98\x8f\x11\xe0\x93\xd1\x4e\xf5\xed\x6f\x8e\xbe\xd0\x7e\x9a\xdc\x35\x15\x5e\x26\x8c\xeb\x89\x90\x13\xcb\xe4\x25\x68\x79\x64\x5c\x13\xac\xc2\xea\xc8\xc0\x27\xa5\xb6\xaa\x76\x5c\xbb\xbb\x63\xdc\xdd\x70\x9f\xa6\xda\xd2\x3e\xe3\xce\xeb\x5e\x4d\xb5\xad\x7d\x46\xb1\x3d\xac\x53\x3a\x0f\x1d\xc5\xb9\xab\x53\x72\x71\xcf\x87\xb5\xe2\x28\x96\xef\x9c\xb9\xe3\xf4\x61\x37\xa4\xd8\xd3\x3c\x3e\x4a\x60\x47\x4b\xd9\x9b\x5e\x2f\xa6\x17\x20\x0a\xcd\x0c\x18\xce\xff\xbf\x5d\xe1\x3d\xce\x12\x68\x55\xdd\x01\xf5\x35\x6e\x1f\x7c\xc0\x5c\x8a\x5a\x3b\x99\x1b\x24\xa2\x5f\xce\x23\xcf\x40\xa3\x0e\xac\xb5\x8e\x91\xad\x51\x3c\x0d\x33\xfb\xaa\x03\x96\x41\xab\x65\xc6\x4b\x81\x21\xad\x6d\xe7\xc2\xcb\x62\x33\x7a\xa9\x28\x50\x2f\xa9\xbd\xca\xa6\xa0\xe4\xe8\x1c\x2a\x4b\x03\xdb\x27\x29\x9b\x21\x7a\x28\xe9\x7c\x9b\xfa\x4e\x03\x73\x3b\xc5\x29\x6e\x23\xad\xaf\xec\x46\x7e\xf6\x91\x5a\x94\xdc\x6e\x93\xa9\x7d\x24\x24\x3c\xeb\x5d\x74\x9f\x35\x62\xcb\xec\x01\xaf\x3b\xf0\xa8\x69\xad\x43\xbd\xe3\x9d\x27\xee\x8b\x9d\x3a\x30\x98\x79\x65\x8e\x04\x1e\x98\x7b\x56\x1c\x17\x4c\x9d\xd1\x1a\x5c\xf8\x04\xfc\x24\x2b\xaa\xc9\x43\x25\x0d\xb6\xa9\x6f\x76\xdc\x68\xc2\x73\x22\x73\x37\xbe\x93\x13\xd5\x30\x9c\xc2\x3b\x31\x22\x12\xcc\xf8\x5c\xbc\x84\xa5\xd6\xa5\x7a\x79\x71\xb1\x60\x7a\x7a\xf7\xef\x6a\xca\xc4\x45\x26\x56\xab\x8a\x33\xbd\xb9\x40\x10\x19\x9b\x55\x5a\x48\x75\x91\xd3\x35\x2d\x2e\x14\x5b\x4c\x88\xcc\x96\x4c\xd3\x4c\x57\x92\x5e\x90\x92\x4d\x5a\x6f\x87\x9a\xae\xf2\x5f\xd6\x03\x7a\x44\x57\x45\xef\x84\x62\x2c\x4b\xae\xe9\xa4\xe2\x77\x5c\xdc\xf3\x09\x7a\x4c\xd5\x88\xb3\x7a\x0c\x32\xb9\xa6\xad\xf5\xd8\x02\x23\x0f\x82\x8d\x8f\x3f\xac\xf3\x7a\x8b\xdb\xc5\x7c\xc4\x45\x32\xaf\x3c\x21\x3c\x9f\x58\xb0\xdc\x23\xae\xd5\xd8\x18\xf4\xa4\x85\xed\x1e\x6b\x99\xf8\x78\xae\x48\xa6\xd9\x9a\x7a\x40\x44\x6b\xea\x6d\x84\x0f\x75\x1a\x5d\x5e\x49\xbb\x17\x5a\xac\xe8\xe8\xbb\x7b\x29\x72\x58\x91\x0d\xda\xee\x38\x4a\x10\xd6\xcc\xe2\x22\xa7\x2e\xf6\x7a\xb0\x1a\xf2\x16\x5b\x01\x37\xc6\x28\xbb\x65\x2b\x5a\xa3\x4e\x31\x9a\xbd\x51\x9a\xae\x2c\x36\xc8\x3e\x6b\xa4\x07\x43\xcb\x8d\x85\xb5\xca\x3b\x60\xba\xc6\x8b\x12\x9e\xe3\x65\x1e\x88\x52\x22\x33\xd6\xe2\xb8\x3b\x6c\xbb\x03\x6a\xaf\x5b\x1d\xbb\x23\x50\x0a\xc5\x70\x52\x9c\x45\x30\xc6\xcc\xf4\x35\x25\x3a\xa0\xb0\xdf\xff\xdb\xf1\x5b\x6c\x8e\x0d\x2e\x47\x21\x17\xfa\x08\xea\x79\x37\x0f\xde\x6d\x8d\x13\x55\x3b\x38\xc7\x9a\x99\x99\xe0\x4a\x4b\xc2\x8e\xcf\xfb\x02\x5f\xe0\x89\x2f\xce\x03\x70\x8f\x5f\x7a\x4c\x1c\xec\x66\x8f\xd4\x66\x03\x1e\x9b\x7a\x31\x46\xb2\x84\xce\x64\xbb\x52\x27\x75\xd6\x94\x11\xd3\x5e\x61\xd4\xd1\x73\x09\x01\xf3\x69\xbf\x4b\xe7\x54\x4a\x9a\xbf\xc6\x7b\xc0\x4d\xf3\x46\x57\x0b\x2e\x9a\x5f\xbf\xf9\x44\xb3\xea\xb8\x7a\x72\xbb\xb4\x13\xf7\xaa\x9d\xf0\xf2\x78\x3b\x6d\x78\xd8\x46\xbc\xd4\xcc\x9c\xf5\x27\x70\x49\xc7\x06\xef\x2d\xa1\xe9\xa8\x88\x66\x6a\x6e\xeb\xd2\xd4\x1b\x03\x68\x1b\xa7\xf5\xe2\xdc\x1c\xd5\x06\x2c\x89\x86\x88\x2d\x3d\x70\xa0\xd2\xe0\x3e\x32\x6a\x20\x5b\x0a\xa1\x8c\xe4\xc3\x7d\x8c\xe3\x5f\x33\x81\xd8\x33\x2f\x9e\x58\x0c\x43\xc2\xca\xe8\x80\xba\x28\x46\xfb\xea\x63\xb7\xb4\xa5\xdb\x5a\x3b\xe1\xf0\x98\xb2\x6e\xcc\x66\xdf\x79\xf1\x74\x88\x2d\x33\x5c\x0c\x76\x9a\x1f\x16\x68\xc7\x2b\x0d\xaa\x1a\x17\x6b\xa8\x49\xcc\xe1\x9e\xb2\xc5\x52\xab\x73\x60\x53\x3a\xc5\xd3\x4c\x49\xb6\xc4\xe1\xfb\xef\xa8\x15\xa5\xba\xd7\xbd\xd8\x53\x46\xd7\xd4\x8b\xa7\x9f\x36\x35\x10\x5c\x01\x94\xb1\x50\x98\x1e\xcf\x1d\x29\xe0\x2f\x1b\x01\xc3\xd2\x2d\xbc\x01\xa8\xce\xa6\x67\xe7\xd0\x94\x29\xf4\x3b\x48\xd5\xca\x1c\x21\xa6\xa9\xb1\xa5\xd0\x6f\x21\x45\xb5\xb0\x3b\x80\x1e\x9b\x6b\x39\x44\xb8\x36\x4d\x89\x0d\x44\x75\xe6\xe8\x1f\x7c\x66\x37\xc5\xf1\xf7\xea\x2e\x69\x5b\xc0\xc8\x0c\x9b\xcd\x5b\x43\x0d\xc1\x1f\xde\x52\x8a\x42\x26\xa4\xa4\xaa\x14\xd6\x83\xb9\x0d\x25\xf9\x1f\xde\x7c\xcd\xe0\x4e\xd5\x59\x7b\xa8\x96\x6c\xb1\x0c\x39\x53\xc4\x19\x93\xfd\x33\xef\x23\x48\x7c\x31\x4d\x96\xbc\x90\x4d\x96\xfa\x48\x64\xee\xea\x51\x84\xc9\xaf\x9e\xe9\xa0\xa9\x5c\xd5\x3b\xc2\x88\x09\x4f\x8e\xd6\x74\x70\xe8\x8f\xba\xfd\xb8\x93\x68\x9e\x2c\x9f\xc3\x29\x0a\x42\xa6\x4f\x14\x2a\x99\x89\x28\xcf\xa6\x70\x09\xbc\xf2\x1e\x66\x33\x71\xfb\xa6\xc0\x93\x2f\x17\xcd\x0c\xb8\x41\x9b\xc9\x54\xa2\x1d\xb7\xdf\xa9\xf0\x37\xcb\x2c\x8d\xc7\x59\x77\x69\xe2\xe6\x8b\x8e\x0d\xa1\xb6\x0c\x02\x76\x40\x88\x61\x59\x73\xa8\x47\xef\xcb\x61\x27\x15\x00\x05\xe8\x91\xd9\xd1\x0f\x91\xd9\x73\xe7\x9d\x5b\x68\x23\xf4\x02\x78\xf6\xe5\xb2\x9d\x79\xbf\x7d\x07\x31\xf6\x1e\x44\x59\x43\x08\xc8\x80\x19\xa6\xed\xe4\x0e\x9b\x03\x13\xc4\x12\xfa\xfb\xa2\x67\x24\x05\x32\x9e\x6d\x90\xf7\xa8\x84\xa4\xfd\x14\xa6\xc7\x5a\x0a\xd0\x68\x2d\x0d\x1c\xad\x40\x8e\xc3\xb9\x49\xc1\x4c\x77\x53\x77\x82\x59\xee\xa6\xfe\x04\xb3\xbc\xa3\x9b\xf3\xed\x84\xa0\x60\xa6\x43\x09\x45\xc1\x4c\xcd\x20\xc7\xa6\x19\xed\x19\x5e\x0c\x21\x65\x29\x4c\x55\xb6\x34\x2e\x51\x69\x1f\x8f\x48\x0b\x18\x47\xfe\x5a\x1a\x9d\xea\x34\x4c\xdb\x0e\x99\x08\x2c\x21\x2c\x7b\x6a\x98\x86\x72\xaa\xe2\x30\x1e\x99\x97\xb5\x87\x8b\x5f\x08\x79\x98\xfc\x72\xb8\x86\x69\xab\x4c\xdc\xc8\x82\x5e\x0f\x93\x4b\x0a\xeb\xa5\x79\x45\x5a\x93\x9d\x54\xb1\x28\x7c\x31\xdd\xac\x4d\x20\x8b\x33\x09\xbd\x24\xb4\x28\x2c\x6d\x5e\xd3\x79\x40\x5e\xda\x3e\xfa\x46\x5b\x9d\xf4\x36\x0a\xbf\xa8\x9b\xde\x27\x27\x6e\x98\xb6\x2e\xe9\x91\x56\x39\x24\xc7\x6e\x98\xfa\x99\x77\x51\x58\xf6\xb3\xf7\xe2\xb0\xac\x33\x00\xa3\x0d\x72\x27\xd9\x2e\x0a\xd7\x90\xdc\xc2\x61\xda\xca\x38\x8c\xc2\x33\x5a\xd6\xe2\x30\x6d\xa7\x6c\x45\x61\xda\xcf\x87\x7c\xca\x53\xfb\x8d\x36\xd3\xfa\x56\x3f\xf5\xbd\x6a\x6b\x55\xbb\x3c\xc3\x28\x1c\x9d\xbb\xfb\x7c\x44\x41\xb5\x43\x54\x17\x02\xc1\x8a\x2e\xa5\xa4\x63\x83\xf3\xfb\x88\x60\xd2\xb2\x47\x54\x7e\x3f\x21\x60\xb7\x4e\xba\x8d\xc2\x71\x2b\x71\x37\x92\xb9\xd4\x24\xff\xda\x74\xde\x28\x5c\x3d\x52\x82\x87\x29\x96\x33\xc2\x52\x14\x97\x44\x77\x60\xc1\x8a\x17\xdd\x56\x5f\x5b\xcc\xd7\x3f\xa5\xc7\xca\xe2\xdd\x92\xc7\xea\x41\x4a\x1e\xab\xe4\xb1\xf2\xa3\xe4\xb1\x3a\x40\xc9\x63\x95\x3c\x56\x47\x50\xf2\x58\x75\x28\x79\xac\x92\xc7\xca\x8f\x92\xc7\xea\xa9\x7b\x01\x92\xc7\x2a\x79\xac\x92\xc7\x2a\x79\xac\x92\xc7\xca\x93\x7e\xce\x1e\x2b\x8b\x17\x8b\x04\x94\xfb\x33\x32\xf3\xcd\xb2\xda\x1a\x18\xd3\x4b\xeb\x4b\xab\x53\xc5\x7b\x40\xb7\x00\xce\x5c\xe4\xf4\xc6\x5d\x98\x6e\x11\x90\x67\xab\xee\x05\xb0\x94\x84\x2f\x28\xbc\x98\xbc\x78\x7e\x54\x11\xf0\x61\xf2\xcd\x06\xeb\xd3\xb8\x82\xe1\xdb\xb4\x0f\x93\xff\x48\x99\x39\x4e\xdb\x35\x39\x2f\xc1\xfe\xc8\x3d\x49\x2f\x23\x7b\x60\xf6\x69\x45\x35\x10\xdd\x83\x0e\xb3\x15\x6d\x12\xe0\xbc\x78\x76\x9b\x3a\xb4\xf5\xc1\x04\xb7\xd8\x7d\x2f\x96\x66\x5b\x4f\xff\x71\x33\x9a\x51\xa2\x3c\x13\x54\xb0\xd7\x4d\x3d\xab\x62\x45\x6d\x39\xff\x10\x85\x52\x8a\x1c\x68\xbd\x2b\xe1\x94\x4e\x17\x53\xc8\x2b\x6a\x2b\x60\x7a\x71\xb4\x75\x29\xce\xce\xbb\x69\xa9\x2b\x73\xd1\x91\xe6\x3f\x9e\x0b\xa4\xeb\xfc\x54\xba\xa6\x5c\x57\xa4\x28\x36\x40\xd7\x2c\xd3\xde\x8b\x6e\x5e\x1c\x8b\xd2\x30\x6d\x13\x0b\xfd\xd3\x1c\xbc\x9d\x93\x21\x0e\xc9\xc9\x8e\x34\xf6\xd9\xa5\xa1\xde\xc3\x9d\x31\xf8\xea\xc3\x2d\x9f\x92\x9d\x97\xa9\x0b\xde\x78\x8b\x74\x31\xdf\x0a\xdb\x68\x33\xc6\x69\x90\x53\x12\x59\xa0\x58\xfc\xf0\xd1\x2f\x39\x06\xa2\x58\x46\x81\xd6\xd0\x76\x68\xa6\x2a\x0a\x73\x44\xf1\x42\x16\x68\x22\xf4\xa7\x3b\x30\x53\x04\x7a\xd9\x22\xbb\x5d\x13\x02\xd8\xda\x04\xbf\x55\xa7\xca\x2d\x72\xbf\x15\xa5\x28\xc4\x62\xd3\xdd\xd7\x01\x4f\x31\x2b\xdd\x69\x2d\x68\x4c\xf6\x6a\xa6\x46\x16\x40\x1a\x1a\x38\xbc\xdf\x3a\x7c\x29\x77\x61\x87\xbe\xd4\x48\x70\xca\x5d\x38\x82\x52\x24\x38\x45\x82\xfd\x28\x45\x82\x0f\x50\x8a\x04\xa7\x48\xf0\x11\x94\x22\xc1\x1d\x4a\x91\xe0\x14\x09\xf6\xa3\x14\x09\x7e\xea\xd1\xb5\x14\x09\x4e\x91\xe0\x14\x09\x4e\x91\xe0\x14\x09\xf6\xa4\x9f\x73\x24\x18\x52\xee\x42\xca\x5d\x38\x8a\x92\xc7\x2a\x79\xac\xfc\x28\x79\xac\x0e\x50\xf2\x58\x25\x8f\xd5\x11\x94\x3c\x56\x1d\x4a\x1e\xab\xe4\xb1\xf2\xa3\xe4\xb1\x7a\xea\x5e\x80\xe4\xb1\x4a\x1e\xab\xe4\xb1\x4a\x1e\xab\xe4\xb1\xf2\xa4\x9f\x9f\xc7\xaa\x14\x79\xe4\x86\x1c\xa5\xc8\x23\xf6\xe3\xb0\xe8\xe3\x4c\x4c\x0a\x91\xd5\xfd\xb8\x47\x73\x35\x43\xb2\x59\x09\xa0\xc8\xca\x16\x49\x3f\x87\xbf\x0b\x4e\x6d\x51\x7b\x20\xe3\x79\x22\xd4\x5a\xe8\x25\x95\x86\xfd\xa9\x3a\x1b\x5d\x9e\x3a\xf5\x0b\x19\x3f\xec\xd4\x2f\x24\xf5\x0b\x49\xfd\x42\x52\xbf\x90\x2f\xae\x5f\xc8\x92\xa8\xf1\xed\x78\x6b\x42\x83\xb5\x69\x30\x11\x27\x7b\xaf\xa3\xf8\x6f\xa9\x5c\xfd\x8f\x9d\xee\x21\x9e\xdb\xbf\xd7\x71\xe4\x67\xd7\x3d\xc4\x88\x36\x27\x32\xcc\xfe\x09\xe8\xf5\x61\xf7\x86\x5d\xd3\xdc\xe5\x7a\xd2\xfc\xba\xbf\x2a\x9e\xcc\x6d\xdc\x0d\x27\x9f\xe4\x39\xcd\xa1\xa4\x72\x62\x25\xb2\xf0\x66\xc9\xf3\x81\x95\xac\x77\x8c\xdf\x66\xf9\xec\x9d\x39\x22\xcc\xf6\xe7\x6e\xcf\xd1\x7f\x85\x48\xb9\x3f\xdd\x64\x2b\xdf\xa4\x4c\x4b\x8d\x41\xb5\xdd\xac\x23\x80\x67\x63\x00\x3c\xc1\x66\x1d\xe1\x31\xb9\x09\x68\x97\x6c\xf4\xa7\x80\xa8\x5c\x9c\x30\x1a\x06\xa9\xea\x74\xa2\xb8\x18\x06\x0c\x7f\xfd\xad\xa2\x32\xf4\x26\x2d\xd6\x54\xb6\xa1\x90\xda\x38\x52\xa1\xce\x42\xe6\xda\xf6\x67\x44\xd9\x9b\x46\x0c\x18\x43\x84\xb0\x6f\xbc\xf8\x68\xdc\xac\x2a\xd8\x5e\xe3\x6d\xf6\x31\x1c\x26\x0a\x48\x8d\x7e\xb1\x3b\x28\x02\xd3\x41\x08\x4c\x0c\x67\x51\xc4\xac\xc4\x9a\xda\xac\xc4\x70\x98\x44\x44\x57\x56\x34\x47\xd6\x90\x90\x88\xe2\x1f\x7b\x14\x90\x0d\x6c\x03\x6d\x22\xc5\x27\x88\x6e\xc0\x36\x11\x1d\xf4\xe7\x36\x16\x1d\x27\x88\x12\x1b\xb4\x03\x03\xc0\x9d\x28\x4c\xef\xe8\x26\x22\x78\x07\xe2\x02\x78\x20\x22\x88\x07\x22\x01\x79\x20\x26\x98\x07\x22\x03\x7a\x20\x1e\xa8\x07\xb6\xc5\x4d\x9c\xa9\xb3\xe4\xbc\x55\xf1\xe4\x17\xb8\xad\x8c\x67\x24\xd6\xd9\x80\xae\x60\x8c\x89\x17\x82\x68\x98\x21\x88\x0d\xa1\x80\xc8\xd8\x21\xd8\xde\x46\x51\x45\x22\xd8\x30\x5b\x4c\x40\x12\x3c\x26\x28\x09\xfa\xc0\xa4\x68\x3c\x6b\x18\x08\x82\x93\xa2\x71\x8d\x0b\x72\x82\xc7\x01\x3a\x41\x03\x76\x32\x7a\x2c\x1a\xcb\xf8\xb8\xa9\x47\x38\xa8\xf1\xf0\x4e\xb0\x7d\x4c\x2d\xeb\x98\x02\x9f\xf0\x88\x78\x12\xb0\x2e\xc2\x88\x73\x09\x3d\x34\x55\xbc\xd3\x1e\x1b\xa2\x02\x76\x36\xaf\x78\x8b\xaa\x8a\x3a\xd8\xc8\x0b\x1f\x19\xf5\x02\x8f\x82\xd2\x82\x47\x82\x13\x41\x17\xad\x15\x6f\xdf\x3f\x06\xea\x0b\xbe\xa4\xe5\x8f\xbc\xf4\x2d\xf4\x27\xe6\xaa\xd7\xf0\x9f\x68\x3c\x2d\x8c\xa8\x0b\x01\x8a\xc6\x1a\xa1\x44\xf1\x60\x40\x10\x1d\x0a\x04\x71\xe1\x40\x10\x57\x1b\xa3\x2b\xef\x2d\x96\x1f\x7a\x0c\x27\xa1\xe5\x1c\xcb\x3f\xb8\x22\xa5\x51\x9d\xff\xf7\x8e\x6e\xce\xf1\xb4\xff\xbf\x18\x97\x58\xc2\xa4\x9a\xc2\x65\x3c\x3c\x62\x67\x7c\xe1\x15\x53\x6b\xea\x4c\xa7\x99\x87\x38\x53\x4a\xff\x56\xb1\x35\x29\x28\xd7\xfe\xe1\xc3\x2e\x11\x5e\xc7\xed\xcd\x3a\x6d\xbb\x89\x63\x88\xfb\xfb\xa5\x50\x98\xf7\x65\x23\xa1\x71\xa6\xe1\xd9\x1d\xdd\x3c\x3b\x8f\xad\x44\x0d\xe3\x2b\xfe\xcc\xa6\x1c\xc4\xd9\x04\x3d\x3c\x6e\x44\x47\xa2\xe0\xc5\x06\x9e\x21\xf7\x67\x61\xe5\x12\x5b\xea\x21\x5b\x88\x8c\xc1\x32\xaa\x7f\x3c\x92\x9b\x8f\xe4\x39\x33\x02\x8f\x14\xd7\x51\xbd\x61\x91\x64\x3c\x27\x2b\xaa\x4a\x92\x85\x0e\xaa\x27\xda\x5b\xa6\x81\x2f\x5a\x43\xe9\x94\xc3\xc1\x44\x63\xdc\xb8\xe8\x6e\xe2\x3a\xc1\xb4\x80\xd3\x1a\xac\x43\x16\xe6\xf4\xe9\xb3\xff\x11\xc8\xb3\x57\x8b\xd3\xc6\xc0\x56\x94\x04\x9f\xeb\x67\x18\xe3\x2c\x45\x7e\xa2\xda\x79\xf5\x03\x3e\xd5\xf4\xa4\x12\xb6\x23\x1d\x90\x4e\x44\x3e\xe2\x09\xb9\x75\x73\x1f\x7a\x3e\x96\xa2\x2a\x72\x73\x6f\x68\x60\xd2\xa1\x2c\x4f\x6b\xd8\xc6\x99\xd9\x73\x5c\xe8\x98\xac\xb9\x66\x93\x96\xbf\x37\xd4\xac\x25\x57\x3a\x5c\xf5\x0a\xdc\x07\xf2\xec\xcb\x85\x28\x06\x5a\x0b\x09\x6e\x25\x58\xa8\xb5\x73\xbf\xa4\xb2\xbb\xee\xe1\xb9\x1d\x39\x9d\x33\x4e\x73\x20\x0a\x64\xc5\xb9\x99\x4d\x11\x9a\x25\xe7\xd0\xca\xd6\x2c\x43\x03\x22\xdc\x39\xdc\x08\x6f\x0b\x07\xc2\xe0\x48\x04\xdc\x8c\xa5\x16\x6a\x49\xd0\x48\x25\x3c\x94\x23\x4e\x80\xe0\x4e\x85\x11\xbe\x89\x33\x03\x36\x7c\x43\x73\xbb\xff\x83\x17\xdf\xad\xf8\x14\xde\xa0\x9a\x89\x37\xa1\x4c\xa1\x14\x21\x45\x21\xee\x43\xad\xb3\xa7\xd6\xa7\xe3\xfe\x8b\xe8\xd3\xb1\x05\x14\x4c\x6d\x3a\x5a\x4a\x6d\x3a\x76\x29\xb5\xe9\xf8\xa2\xdb\x74\x78\xaf\x91\x55\xa9\x7b\xfa\x75\x78\x71\xb4\x3d\x3e\x1e\xea\xd7\xe1\x37\xa1\x76\x23\x6e\xf5\xeb\x80\x3f\x2f\x29\xca\x35\x4f\x57\x82\x39\x32\xab\xaa\xd0\xac\x2c\xda\xec\x12\x3b\x0d\x85\x77\x90\xc3\x75\x9c\x50\x5b\x78\x65\x33\x13\xc4\x33\x11\x79\x4b\x9a\xe3\xb8\x31\x09\x59\xa1\x39\xe0\x67\x56\x62\x0a\x14\x29\x0a\xd7\xce\xa2\xce\x69\xb7\xf9\x71\xec\x4b\x4e\xdb\x78\x8d\x46\xad\x0a\x05\x26\xa0\x91\x75\x6a\xac\xf7\xc2\x88\x05\x63\xcd\xd6\xba\xda\x93\xe3\xae\x0b\xc2\x62\x32\xd6\x01\xa9\x1a\x98\x1a\xc7\xd6\x94\xb7\xf7\x8c\x53\x75\x76\x16\x52\x67\xa8\xf6\x12\xc4\xbc\x6b\x3e\xc2\x1d\x73\xe8\x6e\x79\x6e\xef\x48\x9e\x1c\x7b\x37\xab\x81\xbb\x91\x27\x5b\xc1\x87\xef\x44\x01\x16\xd9\xd6\x5d\xe8\x0f\x1d\xdb\xfd\x7f\x79\xb2\x1c\xb8\x05\xd5\xf7\x18\x5f\xbb\xdb\xde\x7e\x70\x2b\xd5\xa9\x91\x16\xb7\xef\x9d\x1b\x67\x63\x91\x01\xab\xf1\xd9\xb3\x90\x42\x6f\x59\xe1\x00\xcb\x48\x69\x1e\x8f\x92\xe2\xf1\x08\xe9\x1d\x11\x53\x3b\xfe\x39\x9a\xe4\x44\x4e\xe5\xd8\x4d\xe3\x88\x85\xa0\xef\xa5\x70\xc4\x4e\xc0\x88\x94\x7c\xf1\xa4\xfc\xe3\x8f\x92\x70\x91\x2a\x9a\xa6\x8a\xa6\x7e\x94\x2a\x9a\x1e\xa0\xc7\xa8\x68\x1a\x2b\xf1\xa1\x9b\xf4\x10\x8d\x69\x9d\xf0\x10\x37\xc7\xca\xc5\x79\xff\xa9\x0a\x9b\x46\x45\x7e\xb6\x49\x09\x75\x32\x41\x24\xb6\x6d\x42\x42\x1c\xb0\x11\xa4\x2a\xa9\x98\x38\x10\x1d\xf0\xff\x25\x14\x36\x8d\x08\xf6\xed\x00\xfc\x63\x25\xb6\xd8\xb9\x8b\xba\x2d\x1f\xa9\x66\x64\x74\x30\xfe\xa3\xd6\xe0\x4c\x25\x4e\xbf\x94\x12\xa7\xa9\x26\x65\x34\x41\xfc\x73\xaa\x49\xd9\xa7\x68\xe0\xf3\x47\x02\x9e\x3f\x0e\xe8\x7c\x0b\x70\x1e\x91\xb3\x2b\x84\x19\x17\x2a\xbe\x0d\x13\x07\x12\x8a\x19\x7a\x44\x88\xf8\x16\x3c\xbc\x05\x77\x47\x00\xe4\x74\xab\x8b\x23\xb0\x3b\xd4\xe9\xe4\xca\x6e\x45\x14\xe7\x8d\xdb\xa3\x07\xe8\x0e\x64\xba\xed\x6b\x8b\x00\xe6\x8e\xe6\x6b\x8b\xe0\x9a\x78\x0c\x00\x77\x04\xf9\x18\x03\xb8\xbd\x07\xb4\xdd\xc2\xae\x43\xe0\x4c\x5b\x80\xed\xdd\x78\x67\x00\xf3\xf6\x12\x1f\x17\x6e\xfd\x08\x50\xeb\xc8\x30\xeb\x18\x2a\x3f\x58\xd1\x47\xd8\xbe\x51\x60\xd5\x83\x90\x6a\x17\xa8\x0e\x78\xbd\x5e\x88\xbb\x13\xac\x0e\x09\x65\x6d\x87\xb9\xb7\x03\xd6\xa1\xc0\xc1\xd8\x40\xe8\x21\x10\x74\x8b\x8d\x0a\x39\x62\x2d\x00\x7a\x07\xc2\x1c\x12\xd8\x1b\x0a\xd1\x87\xc1\x97\x63\x87\xe9\x61\x37\x54\x1f\x07\x65\xbb\x2f\x58\x1f\xb2\x5f\xfb\x70\xe5\x1e\xe0\x38\x80\xad\x83\x2a\x3f\x0e\xd8\x38\x16\xd0\x38\xa8\xa0\x3e\xd7\xec\x31\x8a\xea\x77\x65\xc5\xe8\x17\xdb\x53\x59\x9f\xac\x05\xcb\xa1\xac\xb4\xf6\x11\xe3\x0d\x2e\xe8\xa1\xea\xfa\xa3\xb9\x12\x95\xaa\xeb\x3f\x40\x5f\x70\x75\xfd\xa0\x1d\x0c\xfd\xfa\xe2\xbb\x20\x5d\x2f\x8e\xbd\xb2\xfc\xbb\x25\xf6\xfd\x5f\xbc\x2e\xcb\x3f\x50\x62\x3f\xf4\xd5\xa7\x3b\x25\xf6\xbd\x38\x6e\x95\x72\xde\x2a\xb1\xef\xf9\xe6\xfd\xb2\xfc\x3b\x25\xf6\xfd\xd6\xa8\x5b\x96\x7f\xb7\xc4\xbe\xf7\x48\xbb\x32\x71\xb0\xc4\xbe\x37\x1e\x8c\x2a\x7d\xbe\x37\xaf\xc0\x8b\x6b\xef\xec\x0c\xd5\xd9\xf7\xe2\xda\xd4\xe6\xdf\x5b\x67\xdf\x7b\x72\x6b\xf4\xf4\x6e\x9d\x7d\xbf\xf7\xef\xd7\xe6\xef\xd7\xd9\xf7\x1e\x64\xaf\x36\x7f\xbf\xce\xbe\x37\xcf\x3e\xca\x7b\xbb\xce\x7e\xd0\x50\xeb\xda\xfc\xdb\x75\xf6\xfd\x66\x34\xd5\xe6\x1f\xa6\x54\x9b\xff\x09\xa0\x62\x53\x6d\xfe\x96\x52\x6d\xfe\x54\x9b\x7f\x87\x52\x6d\xfe\x54\x9b\x7f\x04\xa5\xda\xfc\x5d\x4a\xb5\xf9\x47\x53\xaa\xcd\x9f\x6a\xf3\xa7\xda\xfc\xde\x94\x6a\xf3\x8f\xa3\x54\x9b\x3f\xd5\xe6\x8f\x40\xa9\x36\x7f\x97\x52\x6d\xfe\x54\x9b\x3f\xd5\xe6\x8f\x40\xa9\x36\x7f\xaa\xcd\x9f\x6a\xf3\xa7\xda\xfc\xc1\x94\x6a\xf3\xa7\xda\xfc\x41\x94\x6a\xf3\xa7\xda\xfc\xa9\x36\x7f\xaa\xcd\x9f\x6a\xf3\x7b\x52\xaa\xcd\x1f\x40\xa9\x36\x7f\xaa\xcd\x1f\x36\x98\x54\x9b\x7f\x24\xa5\xda\xfc\xa9\x36\x7f\xaa\xcd\x9f\x6a\xf3\xa7\xda\xfc\xc3\x94\x6a\xf3\xa7\xda\xfc\x63\x68\xb0\x36\x7f\x70\xa2\x4a\xef\xf2\x14\x31\x53\xa5\x2e\xea\xbf\x5b\xa0\xdf\x8b\x67\xaf\xa8\xff\x70\x81\x7e\x2f\xbe\x75\x51\xff\xad\x02\xfd\x4f\x77\x5a\xb1\xb2\xff\x6e\x95\x7e\x2f\x8e\xdd\xca\xfe\x43\x55\xfa\xbd\x98\x76\x2b\xfb\x0f\x54\xe9\xf7\xe2\xd9\x56\xf6\x7f\xb0\x4a\xbf\x17\x6f\xac\xec\xff\x50\x95\x7e\xbf\xfd\x8a\x36\xd5\xfe\x2a\xfd\x5e\x4c\x0b\x5b\x89\x69\x5f\x95\x7e\xbf\xd7\x27\xd9\x32\x55\xe9\x3f\x48\xa9\x4a\x7f\xaa\xd2\x9f\xaa\xf4\xa7\x2a\xfd\x07\xe9\xb3\xe7\x23\xa5\x2a\xfd\x0f\x51\xaa\xd2\x7f\x24\xa5\x2a\xfd\xa9\x4a\xff\x68\x4a\x55\xfa\x53\x95\xfe\x54\xa5\x7f\x0f\x8f\x54\xa5\x7f\x14\xa5\x2a\xfd\xa9\x4a\x7f\x30\xdb\x54\xa5\x3f\x55\xe9\x0f\xa1\x54\xa5\x3f\x55\xe9\x4f\x55\xfa\x53\x95\xfe\x54\xa5\xdf\x8f\x52\x95\xfe\xb1\x94\xaa\xf4\xa7\x2a\xfd\x96\x52\x95\xfe\x54\xa5\x7f\xf4\xe0\x52\x95\x7e\x5f\x4a\x55\xfa\x53\x95\xfe\x54\xa5\xdf\x51\xaa\xd2\x9f\xaa\xf4\xa7\x2a\xfd\x9f\xb9\x4a\x3f\xa9\xb4\x58\x89\x8a\xeb\x1b\x2a\xd7\x2c\xa3\x97\x59\x66\x7e\xba\x15\x77\x74\x14\x80\xb4\x1f\x95\x7b\x80\xe9\xa8\xd7\x63\x3c\x67\x19\xc6\x90\xee\x97\x14\x0b\xe0\x13\x50\x96\x27\x10\xcb\x14\xf4\x68\xae\x2d\x22\x08\xdf\x9e\x68\x96\x91\xa2\xd8\x00\x0e\x79\xdc\x0a\xd8\x39\x9f\x09\x51\xd0\x11\xd7\x07\x67\xce\x52\x39\x4a\x9b\xf5\xa6\xf8\xad\x8b\x45\xb7\xac\x60\x46\x0b\xc1\x17\x63\x55\x9b\x83\xa6\x96\x22\x9f\xc2\xab\x96\x59\x46\x38\x0a\xfe\x4a\x4a\xca\xf5\x48\xd8\xe3\xac\x2e\xe7\x8b\x01\xd5\x95\x58\xd3\x1c\x43\xdb\x88\x54\xb4\x2e\x99\x91\xb1\xd0\x82\x12\xf3\xbe\x9c\xb6\x2f\x6c\x84\x3b\x81\x6b\x1c\xb7\x1d\xec\x6c\x9c\xe4\xb0\x88\x51\x8f\xe5\x1e\x6b\xc5\x78\xd8\x2d\x5b\x41\x6e\x77\xa3\x46\xf3\x31\xc3\x70\x43\x3b\x0f\x23\xe5\x05\x0a\xdb\x8d\xa8\xe0\x9e\xd8\x6b\xaf\xac\x38\x0a\x76\x9c\x4e\xb3\x0d\xc6\x6d\x1f\xdf\xeb\x8a\x5f\xdc\x74\x82\x7a\x78\xd4\x57\xfc\x63\x99\x44\x2e\x3c\xcc\xcd\xde\xd2\x9d\x5c\xca\x45\x65\x6f\x97\xee\xa0\x51\xae\xe5\x06\x41\xd1\x3e\x92\xde\xdc\x59\x73\x91\xdd\x99\xed\xbf\x22\x0b\x7a\x72\xa2\xe0\xd5\xbb\xd7\x46\x87\x54\xca\x4b\xc5\x31\x57\x90\xde\x69\xa1\x52\x8a\x35\xcb\xcd\x79\xfd\x8e\x48\x46\x66\x5e\x25\x04\xb0\xe8\x36\xe5\xe6\xf6\xf4\xab\xd3\xef\x2e\x3f\xfe\xf8\xfe\xf2\xdd\x9b\x33\x8c\x16\xd1\x4f\x25\xe1\xb9\xd7\x48\x2b\xd5\xa6\x9a\xb8\xbd\x6f\x5e\x9f\xf2\x35\x93\x82\x9b\x49\xf6\x99\xd1\xab\x39\x10\x58\xbb\x77\xad\xc5\xde\x8c\x22\x6c\xab\x58\xfb\xe1\x92\x35\x7a\x16\xdc\x1c\xd4\x46\x28\xe3\x65\xa5\xfd\x2f\x1f\x98\x8e\x30\xa3\x50\xf1\x6c\x49\xf8\xc2\x49\xd4\xee\xfc\x7a\x30\x55\x1b\xae\xc9\x27\xf3\xd6\xe8\x26\x57\x19\x29\x69\x6e\xcd\x3c\x02\xb9\xa8\xfc\x96\xff\x57\xbf\x3a\x07\x46\x5f\xc2\xaf\x3a\x83\x9b\xc2\x1b\xc7\xbd\xdd\x1c\xbe\xb3\xc0\xe9\x9a\x4a\x1c\xb0\xdb\x4c\xe7\x20\xe9\x82\xc8\xbc\xa0\xca\x87\xa9\x98\x37\xe6\x85\xf5\x5b\xb9\xcd\x40\xeb\x78\x87\x07\x4f\x2e\x74\x47\x2f\x35\xba\x06\xde\x09\x84\xbd\xcf\x85\xcf\xed\x71\xa9\x75\xa9\x5e\x5e\x5c\xdc\x55\x33\x2a\x39\xd5\x54\x4d\x99\xb8\xc8\x45\xa6\x2e\x34\x51\x77\xea\x82\x71\x23\x87\x27\x39\xd1\x64\xd2\x51\x16\x17\xf6\x8a\x31\xc9\xc4\x6a\x45\x78\x3e\x21\x4e\x28\x4d\x9a\x83\x74\xf1\x4b\x67\xda\x4e\x48\xf3\x29\xc6\x27\x64\xa2\x96\xb4\x28\x4e\x46\x8f\x35\xe4\xba\xef\x7d\xcd\x0f\xb8\xde\xbb\x77\x0e\x95\xf6\x6f\x1a\xe1\x6e\xdf\x7d\x0a\xef\x85\x8f\x17\xcf\xe6\xc8\xb8\xa3\x88\x8a\x19\xd7\x61\xda\x91\xff\x3e\xa2\xbe\xd6\x18\x6f\xde\xdf\x7e\xfc\xcb\xf5\x87\xab\xf7\xb7\xb5\xe2\xa8\xd5\x80\x0f\xd7\x7d\x8a\x23\xec\xa4\xef\x53\x1c\xad\x1a\xf0\x60\xba\x57\x71\xf4\xd5\x80\x0f\xe7\x5d\xc5\xd1\x57\x03\x3e\x33\xbb\xab\x38\x06\xd4\x80\xa7\x15\xd1\x9d\xdf\x41\x35\xe0\x25\x9d\x3b\x8a\x63\x58\x0d\x78\x70\xdd\x55\x1c\x7d\x35\xe0\x75\xbe\x76\x15\x47\x47\x0d\x78\xaa\xfc\x5d\xc5\xd1\x55\x03\x1e\x4c\x87\x15\x47\x52\x03\xc7\x3c\xd4\x4b\x0d\x50\xbe\x0e\x54\x01\xf5\xbd\xbc\x23\x5c\x9a\x7d\xe1\x23\x06\xb5\x40\x2c\x98\x13\x05\xcd\x42\xc5\xd9\x54\x5f\xc6\x7a\xf6\xe6\xf7\x0d\x5f\x7f\x47\x64\x0f\xcc\xe7\xe7\x2b\x1d\x5a\x20\x70\x4c\x81\xf9\xf1\x24\xad\x07\xc5\x3f\xf1\xd0\x3b\xf4\x17\x82\x44\xf6\xb8\x57\x5b\x0a\x45\x0a\x9b\xc7\xfa\x06\x52\x7a\x1b\xe3\x3d\x59\xd5\x7e\xee\xee\xda\x7a\x7b\x53\xeb\x3d\x31\x85\x77\xb5\xcb\x0a\x5e\xfd\x78\xf5\xfa\xcd\xfb\xdb\xab\xaf\xaf\xde\x7c\xf4\xf5\xd3\x06\xc7\xa0\xd0\xa3\x1f\x65\xca\x4e\xe2\x58\x6a\x96\x1e\xb6\xd7\xfc\x9d\xda\x4b\x3c\x95\x6b\x26\xaa\x36\x52\x12\x73\x7d\xd5\x8e\x6c\xf5\x66\x69\x93\x28\x36\x8d\x87\x3a\xea\x30\xa7\x83\x9e\x0a\x6f\xbe\x51\x0d\x55\x4b\x0f\x98\xab\xde\x3c\xa3\x7a\x3b\x2c\xed\xf7\x79\xf8\x2f\x7c\x6c\x93\xd7\xd2\x83\x86\x6f\xc8\xca\xef\x31\x7f\xbd\x59\x3e\xe0\x3d\xf1\xe6\x59\x1b\xcf\xaf\xe9\x9c\x54\x85\xf5\x9f\x3e\x7b\x36\x1d\x6f\x83\x5a\x8a\x23\x76\xbf\x96\xc2\xbb\x73\x5d\x4f\xf4\xde\x60\x4a\x28\xf6\x72\x0d\x09\xcc\x0e\x19\x31\x27\x2e\x39\xcc\x7f\xdf\x75\xdc\x56\xce\x35\x60\xa3\xc8\x01\x80\x57\xc3\x2f\x08\x85\x1b\x01\x16\x15\x23\xa9\x29\x13\x7c\xce\x16\xef\x48\xf9\x27\xba\xf9\x48\xe7\x21\x60\x94\xfe\x7e\xc0\x18\xb5\xcb\x4c\x09\x02\x69\x89\xb9\x35\x43\xed\x30\x43\xb0\x68\x91\x90\x68\x31\x12\xe4\x42\x93\xe3\x62\xe5\xb3\x45\xc8\x65\xdb\xe9\xd2\x1a\x23\xed\x0c\x6f\x89\x66\x07\xc5\x49\x8c\x8c\x90\x22\x13\x62\xd7\xd7\xd4\x37\x56\x9d\x81\x1f\x3e\x57\xad\xb1\xa3\xad\x5b\x25\x98\xe5\x41\xb7\x4c\x26\x78\x46\x4b\xad\x2e\xc4\xda\xd8\x86\xf4\xfe\xe2\x5e\xc8\x3b\xc6\x17\x13\x63\x77\x4c\xec\x19\x53\x17\x88\x31\xba\xf8\x25\xfe\x27\x78\x50\xb7\x1f\x5e\x7f\x78\x09\x97\x79\x0e\x02\x95\x73\xa5\xe8\xbc\x0a\xcf\x94\xb6\x2d\x7b\xa7\x40\x4a\xf6\x1d\x95\x8a\x89\x08\xf9\x35\x77\x8c\xe7\xe7\x50\xb1\xfc\x2b\x5f\xf5\x5e\x53\xb4\xfd\x2b\x4a\x8b\x9d\x8d\xba\x87\x6f\x10\x87\x16\x7e\xdc\xbb\xf6\x56\x23\xea\x83\xb9\x0a\x89\x45\xa9\xee\xe8\xa6\x46\x69\x04\xb3\x74\x17\xb6\x28\x8b\x3a\x16\x64\xb3\x4d\xb8\x71\x63\xea\xec\x93\x46\x69\x07\xbd\x9f\x05\xf4\x3b\xcf\x45\x29\xf2\x97\xa0\xaa\xb2\x14\x32\xb0\xf8\xc3\x8a\x6a\x92\x13\x4d\xa6\x46\x9a\x9c\xf7\x7f\x44\x1c\x63\xd8\xb1\x6d\xf8\x21\x32\x50\x75\x1e\x80\xc6\xa3\x4d\x89\x0d\x7b\x84\x2a\x69\x36\xe5\x22\xa7\xef\xf1\x0d\xf0\x47\xd5\x03\x94\xe1\x1f\xc2\x9e\xa1\x89\xae\xd4\x74\x29\x94\xbe\xba\x3e\xaf\x7f\x2c\x45\x7e\x75\x1d\x85\x31\x72\x52\xde\xb7\x16\x78\x6a\x66\x18\x6e\xd6\x6b\x12\x54\x09\x39\x96\x31\xd6\x6a\xa0\xa8\x42\xda\xf1\x0c\x17\xa7\x0e\x7d\x9a\x2d\xe9\x8a\x44\xe9\x98\xf0\x75\x3d\xf9\xc0\x14\xdc\x4b\xa6\xb5\x67\xe1\xc0\x2e\x31\xee\x6a\xe7\x89\xf9\xb9\x91\xd7\x78\xd9\x8e\x61\x90\x3e\x5b\xbf\x08\x4e\xd1\x89\xa6\xce\x9b\x7d\x1b\x75\xab\xe0\x5a\x44\x32\x49\xad\x1a\x68\x0c\xf9\x28\xeb\xda\x85\xbe\xc3\xe5\xf5\x55\x30\xd3\xb5\x3d\x1b\x4f\x62\x59\xeb\xba\x5a\x5f\x3f\x51\xbd\x5e\x8f\xaf\x16\x04\x8d\x7f\x39\x6c\x0b\x62\x06\x5c\x53\x53\x0c\x0a\xb6\x62\x81\xe7\x95\xf0\x1c\xb5\x03\x55\x5a\xc1\xa9\x65\x38\xcd\xca\x2a\x4c\x01\x3a\x3e\x2b\xba\x12\x72\x73\x5e\xff\x48\xcb\x25\x5d\x51\x49\x8a\x89\xd2\x42\x92\x45\xa0\xfa\xae\x87\x8d\xc3\x6d\x7f\xb2\x0f\x8d\x36\x29\xbb\xa3\x0e\x49\x7b\xb1\x55\x33\x1a\x60\x75\x6d\xed\xd1\xfc\xe7\x63\x25\xd4\xdb\xf3\x09\x18\x09\xcd\xa9\x7b\x1f\xdd\x21\xf1\x2a\x38\x60\x54\x13\x3a\x4b\x9a\xb9\x87\x79\x84\x92\x0d\x6b\x51\x54\x2b\xaa\xce\x9b\x8b\x6c\xf8\xc5\x5f\x48\xa0\x7c\x0d\x6b\x22\xd5\x93\xb9\xa6\xe7\x6c\xcd\x54\x78\xe5\xa1\x81\x5b\x7a\x8c\x16\xd3\x98\x5d\x5d\xe9\xb2\xd2\xae\xf0\x7b\x2c\xa3\x92\x7e\x2a\x85\xc2\xc8\x50\x84\xda\x92\x96\xf2\x6e\x9c\xe5\x45\x58\x67\x1d\x2c\x15\xa1\xa9\xe4\x2f\xe1\xbf\x4e\xff\xfa\xeb\x9f\x26\x67\x5f\x9d\x9e\x7e\xff\x7c\xf2\x1f\x3f\xfc\xfa\xf4\xaf\x53\xfc\xc7\xbf\x9e\x7d\x75\xf6\x53\xfd\xc3\xaf\xcf\xce\x4e\x4f\xbf\xff\xd3\xbb\x6f\x6e\xaf\xdf\xfc\xc0\xce\x7e\xfa\x9e\x57\xab\x3b\xfb\xd3\x4f\xa7\xdf\xd3\x37\x3f\x1c\xc9\xe4\xec\xec\xab\x5f\x05\x0e\x9c\xf0\xcd\x87\x20\x53\x02\x6c\x81\xd4\x28\xdd\x02\xfa\xdc\xa2\x14\x2e\xfa\x34\x69\xdd\x93\x13\xc6\xf5\x44\xc8\x89\x65\xfc\x12\xb4\xac\xc2\x2e\x29\xf5\x76\x8c\x2b\x67\x3f\x46\xaa\xb0\xd7\x31\xc9\x1a\x33\xfb\x49\x08\x32\x45\x33\x49\xf5\xd3\x8e\x28\xd9\x31\xd6\xb7\x0a\x4c\x0b\x0f\x8e\x0f\xa0\x1b\xea\xe7\x62\xf3\xa4\x00\xd5\x43\xd4\xa4\xe2\xe2\x2e\x8a\x77\xcb\x9d\x4b\xb1\x9a\x42\x07\xa2\xb5\x8e\xd2\x78\xdf\x8d\xf3\x8e\x06\x57\x8d\x4a\x01\x35\x1f\x4a\x01\xb5\x30\x4a\x01\xb5\x71\xd4\x0d\xa8\xdd\xe0\xd9\x4f\xd1\xb4\x21\xa2\x7c\xed\x07\x81\x1a\xc4\xc8\xd7\x3e\x2c\x2d\xa0\x14\x65\x55\x10\xed\x95\xcb\x31\x84\xb4\xdf\x05\xcc\x7b\x70\x76\xca\xaf\xc5\x9d\xb6\xd9\x58\xbe\xee\x8d\xd5\x30\x96\x18\x2e\x8b\x02\x18\xf7\x55\x5e\x38\xc8\x3a\x33\x48\x52\xeb\x4e\x02\x82\xf5\x3f\xb1\x73\x91\x07\xcf\xfb\x25\xdd\x9a\x42\x60\x0a\x94\x26\x52\x33\xee\xd5\xb6\xe9\xcf\x86\x23\x9a\xa3\x75\x82\x0c\xe3\x6d\xe7\xa2\x80\x8b\x6c\x53\x6c\xac\xd3\xda\xae\xad\x2e\x53\x10\xe5\xf3\xfe\xee\xa6\x80\xb3\xaa\xc9\x1d\xa2\x90\x33\x9a\x53\x9e\xd1\x29\x7c\xe7\x5b\xa5\xb5\xde\x49\xb3\x8d\x59\x9b\x37\x7c\xdd\xe4\x4c\x55\x36\x4d\xc7\x67\x53\x99\x19\x1d\x1e\xe7\x3f\x6f\x92\x88\x11\x53\x0e\x64\xd9\xe6\x8a\x78\x49\x4e\xb4\x5b\x1b\x4f\x7e\x53\x9a\xb9\xc1\x5d\x78\x65\xf5\x84\xdd\x5c\x42\x6f\x0b\x0d\x8a\x31\xe0\xc2\xb9\x73\x4d\x68\x26\x24\xa4\x0a\xb6\xbd\x16\xa0\x59\xef\xc9\xe3\x89\x00\x45\x43\xcd\xf5\x41\x53\x3d\x38\x8a\xdc\x37\xd3\x9f\x9e\x99\xfd\x08\x26\xf6\x80\x79\x6d\xcd\xe3\x20\xae\xa1\xa6\x75\x14\xb3\x3a\x86\x49\x3d\x64\x4e\x07\xa4\xc1\xb6\xd4\xc3\xa6\x45\x31\x81\xc3\xcd\xdf\x70\x20\x59\x29\xe9\x9c\x7d\x8a\x22\x33\x2f\x79\xb3\x80\xc0\x72\xca\x35\x9b\xb3\x80\x39\x37\x46\xb4\xa4\x25\xe5\x08\x22\xc0\x8e\x8b\xc6\x2e\xf0\xcc\x64\x84\xed\x15\x7c\x72\x69\x70\xd6\x45\x13\x53\x81\xdd\xc4\x72\x4e\x25\xed\x95\xb4\x57\xd2\x5e\x87\xe8\xc9\x6b\x2f\x27\x0f\xea\x2b\xfb\xe7\x55\x3f\x58\xbb\x25\xb4\x3c\xcd\xeb\x4e\xe5\x30\x3c\xe3\xde\xee\xda\xe3\xcf\x5e\x5b\xa0\xf0\x02\x9f\xeb\x73\xc4\xb0\x44\x6e\x53\xf8\xbc\xd1\x9a\x5a\xd8\xa2\x99\x1e\x1c\x97\x6c\x61\x4e\x68\x41\xd7\xb4\x70\xd7\x21\x58\x11\x4e\x16\xb6\x82\xbb\xd7\x0d\xc6\x45\xd0\x41\x48\xec\x00\x29\x59\xde\x73\x9e\xf8\xbe\x3c\xe3\x60\xc4\x56\x21\x48\x8e\xec\xa4\x28\x0a\x2a\x15\x14\xec\x8e\xc2\x6b\x5a\x16\x62\xe3\xdb\x2a\x90\xf0\x1c\x6e\x34\xd1\x46\x4c\xdd\x50\xed\x83\x53\x0e\x10\x05\x38\x23\xd7\x55\x51\x5c\x8b\x82\x65\x1e\x71\xab\xfe\xe6\xbe\xc2\x5d\x5d\x56\x45\x01\x25\x32\x9c\xc2\x07\xee\xb3\xb7\xc5\x1c\x2e\x8b\x7b\xb2\x51\xe7\xf0\x9e\xae\xa9\x3c\x87\xab\xf9\x7b\xa1\xaf\xad\x13\xc1\xc7\xe0\xe9\xe6\xb0\x5a\xd6\xc0\xe6\xf0\x12\xbb\xe3\x69\xd0\xc4\x47\x88\xb2\x4e\xcb\xf7\x73\xb3\xe7\xba\x83\xb4\x0a\xe8\x9e\x29\xaf\x2c\xd0\x07\xcb\x96\xf9\x1d\xfa\x5f\x22\x27\xa3\x7a\xed\xcf\xff\xd0\x8d\x56\xb0\x39\xcd\x36\x59\x11\x2a\x3f\x2f\x33\xcc\x6a\x68\x1b\xbc\xb5\x12\xc3\xc7\xc1\x68\xfb\xcd\xbb\x62\xb4\xe8\xba\x63\x1c\x6c\xb3\x75\xe5\xd9\x4b\xbb\x15\x37\xcd\x3b\x5b\x07\xb0\xfa\xac\xbe\x40\x4f\x7b\x36\xcc\x92\x2d\x85\xd2\x37\x9a\x48\x1d\xa1\x19\xfb\xc9\x75\xcd\x0c\xb0\x09\x6f\x51\x78\x1b\x02\x6c\xb5\xa2\x39\x23\x9a\x16\x1b\x20\x73\x8d\x25\x8d\x43\x4b\x4f\x98\x31\x49\x6a\x4f\xaa\xeb\xfd\xb4\x24\x3c\x2f\xa8\x84\x39\x61\x85\x37\x3a\x6c\xc7\xfd\xaf\xa9\x5c\x31\x1e\x50\xf2\xdc\xc2\x6a\x31\x8a\x40\x73\x2c\xe1\x2c\x73\x2c\xe7\x26\xc0\x1f\xc6\xec\x18\xb6\x62\x1f\xad\xef\xa0\xc3\x09\x2d\x66\xa1\x9d\x80\x59\x21\xb2\x3b\x05\x15\xd7\xcc\xd7\xaa\xc7\xa5\x11\xe2\x0e\x32\xb1\x2a\x0b\x14\x9e\x61\x25\x21\xe1\xe1\xb2\x90\x43\x12\xb9\xf9\xe7\xa4\x11\x12\x13\x33\x26\x75\xf1\xcb\xf6\x4f\xf8\x0b\xbf\x3b\x42\xf0\x1d\x36\xfc\x06\x4b\x3f\xd1\x2c\x52\x7b\x86\x0f\x9c\xe2\xae\x15\x7c\x64\x11\xec\x3e\x09\xde\x24\x02\xcc\x85\x31\x5a\xcd\xae\x8f\xd1\xf1\xa1\x31\x02\xa6\xf0\xe6\x13\xcd\xa2\xf4\x40\x31\xa3\x24\xa8\xec\xb0\x6a\x31\xb9\x0b\x28\x26\xf1\x84\xda\x8d\x7b\x17\xf9\xec\x52\x6f\x73\xbc\xb2\x1c\xc3\x5b\xc1\x59\x41\x63\x99\x15\x8c\x7b\xaa\xff\x2e\xb9\x12\xa2\xc0\xb8\x32\x17\x91\x9e\x24\x8b\xd1\x35\xca\xb9\x52\x20\x67\x12\x7b\x6d\x84\x82\x30\x5c\x29\x94\x66\x16\xc2\xe7\x54\x0a\xa1\xe1\xf4\xe4\xe2\xe4\x6c\x07\x0d\x10\xdc\xfb\x75\xce\x0a\x6a\x0d\x38\x5b\x98\xc8\x8d\x3a\x90\xab\xb1\xe9\xd9\xaa\x2c\x36\xb8\x7a\x27\xf9\x39\xb0\x50\x20\x8a\xab\xce\x2a\x2b\x5e\xef\x84\xd0\x8e\xe1\x58\x0a\xf2\x1c\x94\x00\x2d\x49\xdd\x62\x2a\x06\x4f\x33\x40\x2d\x2b\x67\x64\x9f\x9e\xfc\x74\x12\xba\x4f\xa9\xce\xce\xe0\x5e\xf0\x13\x8d\xdb\x75\x0a\xb7\xa1\xa7\xaa\x52\xb4\x2e\xc6\x7b\x8e\x55\xf4\x39\x0d\x07\xe4\x08\xa0\x9f\xca\x82\x65\x4c\x17\x1b\x34\x2e\x41\x54\xa1\xeb\x8e\xd5\xe6\x89\xae\xeb\x06\xbf\xf9\x14\xbc\x93\x6c\x46\xb3\x51\x62\xcf\xd1\x14\xb4\x06\x67\x20\x53\xa2\xa0\x60\x6b\x7a\xb1\xa4\xa4\xd0\xcb\x0d\x84\x9f\x21\x2e\xf8\xe4\xef\x54\x0a\xac\x6c\xcc\x1d\xdf\x18\x2d\xd9\xc2\xfb\xd8\x45\x69\x54\x19\xc1\xf7\x6a\xec\xc5\x6f\xa8\xe7\xbd\x08\xb6\x75\xe0\x1f\x6f\x6f\xaf\xbf\xa1\x3a\x9a\xe1\x61\x46\x57\xa7\xde\x61\x54\x8b\xca\xb9\x90\xab\xcf\x6c\x81\x84\x83\xc4\x27\x50\x0a\xf9\xb9\x4d\xa0\xa5\x50\x01\xeb\x0e\x3b\x6b\x2f\x94\xf6\xad\x1c\xda\x25\x2d\x8c\x6e\xe6\x34\x33\x2b\x1e\x2d\x0d\xbd\x6d\x6d\x03\x57\xd7\x53\xf8\x8b\xa8\xcc\x2c\xce\xc8\x2c\xc8\x92\x37\x54\xf7\x4e\x51\x54\xc3\x33\x33\x09\xcf\x42\x02\xad\x96\xcc\xbe\xff\x23\x25\x39\x95\x0a\x35\x21\x25\x51\x3a\x49\x06\x43\x77\x3b\xe3\x8a\x69\x39\x57\x4a\x8b\x15\x2c\x2d\xe3\xf0\x85\xee\x14\x49\x76\xb2\x23\x14\xb9\x6f\xe4\x9a\x8d\x2f\x28\x90\xb4\x8c\xa1\xed\xdc\xdb\xfe\x8c\xb4\xd1\x8e\x26\xb0\x3b\x25\x90\x6b\xcd\x77\x46\x15\x10\xc8\x70\xab\x04\xb3\xb4\x93\x6f\xf6\x8a\x2b\x6c\x18\xcc\x91\x71\xbb\x49\x8c\x50\x09\xce\x2f\x88\xd6\xf7\x35\x4e\x42\x13\x84\x14\x85\xee\x33\x41\x68\x6e\x20\x97\x58\xf9\x51\x10\x29\x93\x06\x06\x00\x24\x11\x58\x36\xbb\xd4\x06\x3b\x23\x4c\x3f\xc4\xcc\xe1\x80\xd0\xf2\xd3\x5d\x7a\xfc\xe9\x8b\xb1\xf1\x20\xde\xfc\x95\xc1\xe5\x67\x76\x8b\xcf\x68\x01\x24\xcb\xfc\xda\x1e\x75\x49\x58\xd5\x89\xe2\x4c\x51\xb9\xf6\x4b\x98\x68\x29\xd6\x94\x09\xdf\xf0\x4d\x4d\x03\x35\xe2\x25\xf0\x6a\x35\x0b\x56\x52\x4d\xc5\x36\xa9\x63\x2f\x43\xa7\xcd\xc3\xfb\x18\x43\xad\x21\x2c\xb5\x81\x44\xf8\x22\xf4\x5c\xbc\x30\xef\xfc\xfb\xdf\xfd\xee\xb7\xbf\x9b\xda\x69\x35\xcf\x08\xe4\x39\xa3\x40\x38\x5c\x5d\xbe\xbf\xfc\xf1\xe6\xbb\x57\x58\x3d\x3b\x6c\x17\x46\x48\xe6\x8f\x99\xca\x1f\x31\x91\xff\x11\xd3\xf8\xb1\x60\x59\xa0\x84\xef\xe3\xb2\x90\x61\xb8\x47\xbb\x52\xb6\x60\xb6\xbb\x29\xda\xb0\x61\x04\x4f\xb6\xb9\x13\xf7\xea\x8c\x47\xb8\x38\x7c\x76\xe9\xa9\xb3\xf2\x46\x64\x77\xd1\xbc\x3c\x27\xb7\xaf\xae\x2d\xc3\x28\x8e\x1e\xc2\xeb\x00\x13\xe3\x6b\x51\xac\xcd\x62\x12\xb8\x7d\x75\x1d\xa8\x2c\xa6\x86\x07\x46\x58\xad\xdf\x7b\x13\x94\xc9\xd9\x94\x66\x72\xd0\x4e\xb6\x2a\x8b\x90\x88\x32\x60\xaf\x00\x49\x49\xc1\x94\x66\x19\x8e\xb5\x89\xc1\x06\x79\x75\xc4\x9d\x3f\x9e\x33\xf9\xc7\x5a\x8a\xec\x1f\x3b\xf9\x10\x29\xeb\xb9\x71\xb4\x75\x5c\x65\xc1\x4e\x93\xf3\x5e\xd1\x9f\xf0\x0a\x95\xce\xd1\x16\x96\x72\xfe\x44\x2d\x47\x34\xc3\xfc\x5a\x81\x76\x89\x77\xba\x14\x39\xcb\x31\x34\x82\x82\x76\xe7\xae\xe5\x18\xc8\xd6\xbd\x70\xdf\x72\x0c\xf5\x4b\x18\xbb\x73\xc7\x72\x8c\x64\xdb\x26\xcb\xf1\x38\x7a\x04\xcb\xb1\x94\xf4\x46\x8b\x32\x0a\xce\xce\xb2\x8a\x8a\xb2\x9b\xd1\xb9\x90\x34\x0e\xcc\xae\x05\xc0\x41\x5e\xa1\x30\x26\x3c\xa0\xb2\x6a\x1d\xe6\x12\x5d\xb8\x9a\x77\xca\x3e\xa0\xc9\x92\x2d\xeb\xa8\x2a\xa7\x4a\x5d\x20\x34\xae\x2a\xad\x93\xd2\x93\xe9\x9c\xb0\xa2\x92\xf4\xdc\xac\x34\x5d\xe1\x5a\x9d\x87\x16\x79\x34\x8b\x41\xb9\x65\x45\x75\x66\x61\x14\x0e\xb5\xe8\xbf\x3e\xc6\xe6\xb3\x1b\xc7\x76\xb4\x0d\x6f\xeb\x95\x49\xa2\x96\x14\x9b\x79\xd2\x4f\x4c\x2b\x3b\x50\x49\x89\xf2\xae\x11\x8d\x50\x17\xb7\x91\xd0\x04\x56\x50\x12\xa5\x68\xee\xaf\x0d\x3a\x90\x4f\x3b\xc0\x6b\x91\x9f\x9c\xa8\xee\x63\x3c\x39\x2f\x24\xc9\x28\x94\x54\x32\x91\x03\x56\x5d\xcf\xc5\x3d\x87\x19\x5d\x30\xee\x7b\x03\x70\x27\xd2\x0c\xba\x3e\xf0\xc6\x84\xa5\x01\x40\xaa\xba\x63\xf2\x14\x3e\xf6\x3a\xba\xfa\x6b\x2d\x51\xe9\x4c\xb4\xda\xda\xcd\xee\x79\x00\xc7\x16\x49\x8a\xd5\x1a\xf0\x98\x57\xa4\x28\x36\xad\x58\xf1\xe4\xec\x0a\x93\xe8\xc7\x5a\xf8\x2f\x0c\x53\x6b\x0e\x6b\x28\xc7\xee\x01\xed\x4e\x85\xbf\x6c\x92\x94\x64\xcb\xb0\x64\x8a\x04\xdd\x3d\x40\x09\xba\x9b\xa0\xbb\x7b\x29\x41\x77\x13\x74\x37\x41\x77\x13\x74\x37\x41\x77\x13\x74\x77\x24\x25\xe8\xee\x21\x4a\xd0\xdd\xbd\xf4\x24\x43\x13\x09\xba\x9b\xa0\xbb\x47\x53\x82\xee\x26\xe8\xee\x38\xbe\x09\xba\xeb\x45\x09\xba\xfb\x20\x25\xe8\x6e\x08\x25\xe8\xae\x2f\x25\xe8\xee\x68\x4a\xd0\xdd\x04\xdd\x0d\xa0\x04\xc0\xf0\xa0\x04\xdd\x8d\x70\x71\xf8\xec\xd2\x33\x41\x77\x13\x74\xf7\x48\x4a\xfe\xb1\x96\x12\x74\x37\x80\x12\x74\xf7\x20\x25\xe8\x6e\x82\xee\x06\xf0\x7a\x7a\x96\x63\x0d\x11\xbd\x96\x62\x16\x5c\x5a\xfa\x1a\xc1\x51\x2c\xb3\x1e\x35\x73\x4e\x42\x80\x97\xf5\xd0\xa6\xf0\xaa\x8f\x99\xc3\xfe\x56\xae\x7c\xa4\x07\x5f\x87\x09\xb5\x63\xc4\xd2\x98\xd3\x81\x6a\xb7\x1e\x8c\x47\x42\xba\xea\x82\xce\xea\xa2\x14\xf6\xff\x5a\x40\x57\x07\xc9\x65\xbd\x93\xbe\xb5\x72\x3f\x4b\xd5\x55\x7f\xf8\xd6\x5e\xe8\x16\x08\xaf\x32\xce\xd0\x5e\xf4\xb7\x61\x5b\x7d\xf0\x95\x27\xef\x3e\x64\xab\x0f\xbc\xf2\xb5\xfc\xbd\xe1\x5a\x4f\x00\xb8\x17\x0c\xd1\xda\x03\xcf\x0a\xd4\x5e\x5b\xd0\xac\x1a\x5c\x15\xc0\x71\x10\x96\x15\x38\xca\x1d\x48\x56\x0d\xaa\x8a\xf0\xe6\x88\x3d\xed\x02\xaa\x02\xa3\xfc\x1d\x28\x56\x17\x4c\x15\xc0\xb5\x03\xc3\xda\x05\x52\x85\xac\x94\x1e\x02\x51\x39\x0c\x50\xc8\xe5\xb2\x07\xa0\x1a\x80\x40\x05\xf0\x46\xf0\x54\x64\xf8\xd3\x20\xf4\x29\xcc\x7e\x1d\x80\x3d\xd5\xc0\xa5\x90\x89\x6d\x21\x4f\x5d\xd0\x52\xc8\x16\x68\xe0\x4e\xdb\x80\xa5\x20\x17\x48\x1e\x1b\xac\x14\x23\x34\x1c\x1c\x16\x0e\xb4\x54\x5d\x9a\xd0\xed\x52\x52\xb5\x14\x85\xa7\x2a\xe8\xa9\x81\x77\x8c\xb3\x55\xb5\x32\x32\x47\x19\xb9\xcd\xd6\x81\x39\x4c\xaa\x41\xab\x5a\x23\x10\x63\xca\xde\x1a\x0f\x25\x8a\xa4\x39\x72\x37\x5b\x0c\x0b\xba\x2f\xc9\xda\xdf\xd4\x57\x55\x96\x51\x9a\xd3\xbc\xe7\xd7\x84\xdf\x4e\xeb\xb9\xf0\xe4\x6b\x1b\xa4\x32\x05\x2f\x42\x2c\x8c\x90\x1b\xd1\x5c\xc8\x15\xd1\xc8\xe3\xb7\xbf\xf1\xe0\x10\x84\x7d\x7b\x14\xdc\x5b\x74\xcc\x5b\xb0\x19\x17\xe6\xcb\x0b\xf0\xe3\x85\xdb\x8f\x61\xfe\xbb\x61\x6c\x5b\x98\x8e\x1b\xc2\xb5\x85\x71\x7c\x04\x4c\xdb\x20\x9e\xad\x8b\xfc\x0a\xb3\x74\xc3\xb0\x6c\x91\x10\xaf\xc1\x18\xb6\xc7\xc1\xaf\x0d\x63\xd7\x50\xba\x84\x18\x17\x7d\xdc\x5a\x38\xf2\xec\x49\x98\x16\x8f\x81\x36\xdb\x45\x9a\xb9\xc9\x0a\xf3\x62\x37\x28\xb3\x78\x28\xb1\x48\x08\xb1\x18\xe8\xb0\x60\x64\x58\x38\x2a\x2c\x16\x22\x2c\x06\x1a\x6c\xa7\x0b\x68\x84\x1d\x04\x75\xe3\xc6\x28\xf8\xea\x58\xde\xe3\x28\xe8\xaf\xc7\x9d\xae\x18\xa8\xaf\x08\xf3\x15\x86\xf6\x7a\x1c\xa4\x57\x4c\x94\x57\x8c\x29\x0a\x8a\xd1\x3d\x0e\xb2\x6b\x10\xd5\x05\xde\xf9\xef\xb0\xed\xee\x9a\x76\x23\x6b\x01\x4c\xb7\xd0\x5c\xdd\xa8\x5a\x00\xd7\x06\xc9\x15\x37\xa2\x16\x18\x4d\x8b\x15\x49\x8b\x14\x45\x7b\x24\xec\x55\x28\xee\x6a\x18\x73\x65\x6c\x90\x80\x0d\xb1\x83\xb7\x6a\x11\x53\x01\x5c\xbb\x3e\x89\x30\xb4\x54\xe0\x82\x32\xce\x34\x23\xc5\x6b\x5a\x90\xcd\x0d\xcd\x04\xcf\x3d\xad\x89\xad\x5e\xd5\x0e\x2d\x30\x07\x65\x99\x7a\xbe\x9f\xf5\x04\xf5\x6b\x5d\x2c\x89\x02\xff\xd8\x25\xb4\x85\x53\xea\xf0\xa8\x33\x4c\x81\x60\xf0\xd1\xcc\x87\x67\xf8\x12\x9e\x5c\x08\x13\x9e\x84\xcb\xc9\x96\xfc\x88\xb7\xbd\xfe\x28\xee\x41\xcc\x35\xe5\x70\xca\x78\xbd\xc3\xce\x7c\xbd\x4f\x8d\xb3\xa9\xf5\x67\x36\x4e\x43\x7f\x9e\x2f\x9e\xd7\x03\x6b\x5c\x8e\x41\x86\xd9\x97\xec\x72\x44\x67\xac\x52\x4f\xd3\xa3\xed\x06\xf7\x58\x2e\x6d\xc7\x7e\x5e\x15\x56\x98\xf9\xfa\x6f\xd0\x19\xee\x1c\xe4\x7d\x9f\xb6\xe7\xb6\x00\x78\xe7\xcc\x9c\x17\xf8\xe6\x8d\x34\x24\x3c\x07\x57\xee\xcc\x9b\x73\x77\xc3\x7f\xd1\x5b\x37\x10\x45\xfc\x58\x08\xe2\xbd\xe8\x61\x8b\x01\xf6\xe4\xba\x83\x1c\x6e\xf1\xbf\xbe\x1c\xfb\xa8\xe1\x2e\xf6\x37\x60\x8c\x6d\x57\x66\x7f\xdc\x6f\x8a\x11\xf8\x7d\x77\x2f\xbe\x17\xc3\x05\x01\x26\xf1\x16\xb6\x37\x56\x1a\x7c\x3f\x05\x3e\x14\x23\xfe\x64\x6e\xfb\x35\x1a\x37\xd4\x37\x96\x6e\xfb\xe9\xb6\x7f\x80\x1e\xe1\xb6\xaf\xd9\x8a\x8a\x4a\x3f\xd9\x0b\xe7\xfd\x92\x65\xcb\xae\x2d\xc8\x56\xde\xaa\x5a\x54\x7a\xcb\x5e\x73\x43\x8c\x08\x45\x48\xb7\xce\x2d\xf2\x8b\x69\x0c\x38\x54\xc3\xab\xdf\x36\x08\x59\x20\x0a\x08\xbc\x7e\x7f\xf3\xe3\xdb\xcb\xff\x7c\xf3\x76\x0a\x6f\x48\xb6\x0c\x62\xcd\x38\x10\xd4\x6c\x28\xc2\x96\x64\x4d\x81\x40\xc5\xd9\xdf\x2a\xea\xab\x17\x4e\x9b\xf1\x9d\x45\xc1\x74\x07\x48\x20\xa3\x93\x3c\x64\x43\x6f\x11\xdf\x32\xa5\xcd\x22\x22\x2f\x57\x67\x4c\x78\xf9\x03\xe7\x52\xac\xb6\x55\xdb\x1b\xc3\xcc\x9a\xde\x9e\xd6\xdc\x92\x4a\x0a\x0b\xb6\x76\xc8\x67\x8b\x01\x05\x92\x07\x54\x95\x33\x52\xc0\x1c\x1c\x73\x39\x20\x33\x04\x14\x2e\x29\x70\xaa\xcd\xa1\x6f\x5c\x99\x7e\xe8\xca\x4e\xf1\x6f\xa8\x14\x55\xe7\x30\xab\x10\x1c\x5a\x4a\xb6\x22\x92\x79\x41\x30\x3a\x03\x26\xc5\x14\xde\x8b\xfa\x7a\xb4\xc1\xa9\xf5\xf1\x37\x19\x6b\x06\xa7\xf6\xf5\x87\x37\x37\xf0\xfe\xc3\x2d\x94\x12\xeb\x04\xfb\x22\x2b\x91\x23\x6e\x81\x19\x35\xa3\xb2\xdb\x28\x9f\xc2\x25\xdf\xf8\xae\xbd\x55\x32\x4c\x81\xb9\x0f\x51\x6e\xd8\xba\xf0\x54\xee\xed\x7c\x7a\xf6\x7c\x8a\xff\x7b\x66\xf6\x90\x34\xa6\x5c\x03\xd7\x0d\x11\x34\x75\xd2\x88\x35\x0f\xd9\xac\xa0\xed\x79\x70\x3b\xcb\xc7\x5a\x8a\x26\x5f\xfc\x50\x19\xde\x68\x8c\x2d\x88\xbd\x9b\xd7\x6b\xb3\x47\x24\x2d\x25\x55\x94\x7b\xde\x59\x48\x73\x50\x71\xc7\xa1\x80\x37\x12\xa6\x08\x4c\x6c\x0b\xbc\xed\x86\xdc\x75\x27\xed\xc8\xaf\xfd\x0e\x4a\xe8\x85\xb7\xf7\x7c\x5f\xb3\x7c\xf0\xfa\x35\x0f\xcb\xd8\x6d\xf4\x51\x7d\xf0\x4b\x91\x9f\x28\xb8\xf2\xc7\x3d\xb9\x53\x3f\x85\xdb\x25\x53\xed\xcd\xc6\xd8\x8a\xcc\xbf\xdc\x13\xee\x45\x1b\x58\x3e\x87\xe7\xf0\x07\xf8\x04\x7f\xc0\xcb\xd7\xef\x7d\xef\x48\x31\x2e\x38\xa1\xae\x3d\xeb\x07\xb9\xba\x8e\xb2\x23\xfe\xbc\x24\x1a\xf9\xc1\xd5\x75\x08\xb8\x71\xc6\x78\x8e\x5b\x81\x7e\xd2\x54\x72\x52\xd4\x57\xf3\xb0\x99\x0e\xb8\x02\x9a\x97\x7a\xf2\x07\xc7\x56\xb0\xb8\x9a\x7b\x73\x6c\xac\xf4\x73\xd0\xbd\xa3\xe3\xcd\x11\x8f\xdc\xe0\xd1\xf1\x66\x69\x8f\x1c\x5c\xcd\xd1\xd7\xf6\xde\x69\x0a\xa6\x3a\xa3\xf7\x9f\xd2\xe6\xad\x57\x44\x67\xcb\xbe\x5a\xf3\x77\x85\xbc\x33\x47\xa2\x2d\xbd\x0f\xb9\x40\xdf\x72\x50\xd1\x60\x33\xd4\x2f\x5b\xf0\x84\x40\xee\x7a\xe7\xe9\x6a\xbe\xbd\x73\xbd\x67\x75\x9f\x1b\x2c\xa8\x22\xb1\xbb\x8c\x76\x1a\x6b\x94\x22\xb7\x37\x5f\x6f\x9e\x66\xf2\xf2\x8e\x7d\xd4\xbb\x00\xfb\x6b\xce\xee\xc5\xd9\x55\x74\x0a\x4d\x1e\xb4\xa2\xdb\x68\x86\x8c\x70\x9b\x74\x3d\xa7\x52\x86\x6c\x7d\x01\xb3\x0d\x22\xd7\x58\x46\x03\x0f\x41\x80\x4e\x28\xa5\xd0\x22\x13\xde\x45\x3d\xfa\xe0\x3e\xc7\x0c\xa7\x3b\x24\x7c\xd5\x46\x34\xbf\x7d\x7d\x7d\x0e\xb7\xaf\xae\xcf\x41\x48\xb8\x79\x15\x82\xaf\xe9\x7a\xee\x9e\xdd\xbe\xba\x7e\xf6\xd9\x26\x1d\xea\x7b\xe1\x4b\xaf\x32\x41\x3d\x37\xae\xb9\x72\x4e\x56\xa4\x9c\xdc\xd1\x8d\x87\x55\x1d\x6a\xd3\x4f\x9a\x1d\x14\xe1\x35\xec\xc4\xae\x48\x39\x92\x97\xa4\x24\x67\x4f\xb4\x72\x83\x3b\xe1\xed\x18\xb7\x4b\x38\x78\xf0\x44\xf9\xb3\x12\x6b\x9a\xdb\xcb\x7b\xfd\x0c\xca\xf3\x52\x30\xbf\x1b\x6b\xaa\x04\x71\x98\x52\x25\x88\xe3\x28\x55\x82\xe8\x53\xaa\x04\x11\xc0\x33\x55\x82\x48\x95\x20\x2c\xa5\x4a\x10\xa9\x12\x84\x27\xa5\x4a\x10\x87\x07\x97\x2a\x41\x7c\xb1\xd8\xd6\x54\x09\xe2\x30\x25\x94\x67\xaa\x04\x91\x2a\x41\xec\x50\xaa\x04\xf1\xb9\x4d\x8b\x54\x09\x22\x55\x82\xa8\x29\x55\x82\x18\x41\xa9\x12\xc4\x38\x4a\x95\x20\x0e\xd2\x13\xcb\x0d\x49\x95\x20\x52\x6e\xc8\xb1\x7c\x9e\x5e\x6e\x08\xa4\x4a\x10\x7e\x94\x2a\x41\x8c\xa7\x54\x09\x62\x1c\xa5\x4a\x10\xe3\x79\xa6\x4a\x10\x2d\xa5\x4a\x10\xa9\x12\xc4\x17\xba\x75\x53\x25\x88\x54\x09\x62\x98\x52\x8c\x20\x55\x82\x18\x47\xa9\x12\x84\x3f\xd3\x74\xdb\xf7\xe7\xf3\xf4\x6e\xfb\xa9\x12\x44\xaa\x04\x71\x90\x42\x4c\x37\x49\x95\xa8\x64\xe6\xa3\x22\xfb\xfb\xea\x95\x58\x95\x95\xa6\xf0\xb1\x66\xd8\xe8\x7d\x8f\x77\x9a\x6d\x6c\xc2\x55\x47\x3a\x7e\x0e\xd8\x74\x26\xf8\x9c\x2d\x2a\x89\xc9\xf7\x17\x2b\xc2\xc9\x82\x4e\x32\xfb\xa2\x93\x66\xe6\x26\xcd\x28\x2f\xbe\x28\xe8\x74\xc1\x56\xcc\xa7\x82\x04\xec\xac\xfd\x5b\xe4\xd4\xc6\x47\x03\xe0\x2d\x2b\xf2\x09\x2f\x44\x64\x25\x2a\xae\x6d\x9e\x00\xce\xb7\x27\xcf\x66\x95\x6c\x9c\xdb\x5c\x09\xdb\x4d\x10\x00\x11\x78\x02\x5b\x07\x62\x18\xe7\x6d\x2d\x8d\xeb\x60\x6b\xb9\x24\x5a\x53\xc9\x5f\xc2\x7f\x9d\xfe\xf5\xd7\x3f\x4d\xce\xbe\x3a\x3d\xfd\xfe\xf9\xe4\x3f\x7e\xf8\xf5\xe9\x5f\xa7\xf8\x8f\x7f\x3d\xfb\xea\xec\xa7\xfa\x87\x5f\x9f\x9d\x9d\x9e\x7e\xff\xa7\x77\xdf\xdc\x5e\xbf\xf9\x81\x9d\xfd\xf4\x3d\xaf\x56\x77\xf6\xa7\x9f\x4e\xbf\xa7\x6f\x7e\x38\x92\xc9\xd9\xd9\x57\xbf\xf2\xbe\x1c\x06\x98\x1f\x71\x8c\x8f\x28\xa6\xc7\x23\x18\x1e\x0e\x5d\x12\x45\x3c\x7c\x74\xbc\xe2\x08\x08\xe7\x31\x89\x2f\x20\x6a\x7d\x85\x19\xc4\xf5\x98\xfd\x9d\x90\x62\xc5\xb4\xa6\x39\xba\x8c\x3a\xe5\x45\x7c\x71\xe0\x4c\xf7\x9a\x71\x3b\x91\x8b\x09\x46\xde\x10\x68\xa6\xba\xb8\xea\x4e\xa6\xac\xd0\x4b\x2a\xef\x99\x77\x3c\xc8\x5c\x90\x78\xeb\xcd\x40\x21\x38\xc9\xe9\x9c\x71\x6f\x07\x09\x1a\x71\xa3\xed\xb7\x24\x86\x93\x18\x1e\xc3\xe5\x29\x89\x61\x45\xb3\x4a\x32\xbd\x79\x25\xb8\xa6\x9f\x3c\x1c\x22\x7d\x29\x7c\xe3\xd8\x81\xc0\xdf\xf8\xe6\x39\x95\x22\xaf\xb3\xda\x64\xc5\x31\x75\x3d\xd0\xa4\x3a\xe6\x1c\x97\xa2\x60\xd9\xe6\xa2\x9e\x12\x3c\xb0\xf4\x93\xbe\x78\xb4\x3b\x80\x26\xea\xae\x15\x1f\x74\x62\x6e\x7e\xad\x94\xd8\x19\xc7\x17\x65\xf8\xa3\x25\x7c\x2d\xd9\x9a\x15\x74\x41\xdf\xa8\x8c\x14\x28\x1f\x63\xe8\xfa\xcb\x3d\xbc\xfd\xe3\x43\x5a\x8a\x42\xc1\xfd\x92\x1a\x9d\x04\xc4\xbc\x3b\xba\xde\x32\xe2\xcb\x74\x41\x18\x87\x95\xd9\x06\x65\x3d\x50\x73\x1a\x8c\xc6\xf2\x56\xf8\x25\x91\x94\xeb\x7a\x70\xae\xc0\xd0\x4c\x88\xc2\xa5\xd8\x79\x63\xae\x9b\x19\x70\xb9\xc4\x5c\xfc\xc8\xe9\xfd\x8f\x66\xe4\xbe\x63\x9d\x17\x64\xd1\xd4\x2c\x53\x54\xd7\x60\xaf\x90\x8c\x6c\xb0\xbb\xd2\xbe\x7c\xe4\x4d\x80\x39\x55\x15\x05\x52\xdc\x93\x0d\x6e\x85\x38\xe3\x65\xea\x25\xbc\x38\x43\x31\x46\x14\x34\xe3\xcd\xe1\x37\xbe\x21\xf2\x25\x51\xf0\xea\xf2\xfa\xc7\x9b\xbf\xdc\xfc\x78\xf9\xfa\xdd\xd5\xfb\x10\x73\xc2\xec\x1e\xea\xb5\xc9\x33\x52\x92\x19\x2b\x98\xbf\x15\xb1\x83\xbb\xec\xb2\x0c\x30\x0a\xf3\xfc\x22\x97\xa2\xb4\x6b\x28\x2b\x8e\x65\xfd\xda\xfa\x37\xbe\x9e\xe4\xae\xd7\xb0\x53\x21\xd0\x6c\x6e\x5f\x67\xe4\xbc\xf7\xca\xb0\x90\x84\x1b\x6b\x1e\x3d\x53\x01\xd1\x6e\x07\xcd\x91\x15\xd7\x6c\xf5\xe5\x26\x5f\x93\x3c\x56\xe2\xf5\x65\x9e\xd3\x3c\xc6\xf6\x7a\x8a\x89\x07\xaf\xea\xd7\x0a\xc9\xb8\x81\xb6\x6a\x22\x5c\x7f\xb8\xb9\xfa\xdf\x71\x66\x0b\xdc\x8c\x85\x04\xb0\x22\xd4\x6c\x91\xa2\x8c\xb4\x93\x3e\xba\xea\x1d\x69\x2f\x3d\x44\x3f\xd3\xbd\xd4\x58\x72\x31\x30\x53\x1f\x2b\xde\x91\xd5\xde\x05\x0c\xda\x31\xc1\x4a\xe4\x74\x0a\xd7\xd6\x40\xa2\x2a\x0a\xcf\x4e\xd9\x38\x22\x29\x18\xc6\x5c\x33\x52\x78\x9b\x9a\xf4\x6f\x15\x5b\x93\x82\xda\x04\x3f\x2c\xe1\xd0\xad\x1f\x18\x41\x37\xcf\x49\xa1\x82\x94\x9e\xbf\x4d\x64\x8c\xd3\x77\xa2\xe2\x31\xf0\x49\x0d\x2f\xc8\x29\x17\x3a\xc8\x9f\x69\xde\x0b\x0b\x3e\x4a\x91\x81\xf5\x69\x06\x41\xb1\x6b\x6c\x5e\xc7\xa8\x42\x03\xce\xbf\x68\x32\x58\x13\xdc\xad\xe3\x75\xf3\xee\x36\xf6\x5b\xa9\xa0\xd7\xdf\x31\x89\x42\xa1\x2c\xe6\xfd\x25\x25\x39\x56\xf2\x29\x89\x5e\x5a\x9c\xde\x8a\xa8\x3b\x6f\xdf\x23\xb2\x71\x77\x3a\xe7\x25\xb6\x05\x78\x9a\xc9\xb8\xf5\x17\x7e\x73\x4a\x74\x25\xa9\xbd\x95\xd9\x64\x40\xca\xc9\xac\xf0\x45\x56\x07\x0a\x52\x33\x77\x1f\x78\xb1\xf9\x28\x84\xfe\xba\xa9\xb6\x12\xe1\xd0\xfc\xd9\xdd\xe0\xfb\x81\xdd\x80\x8b\x16\x42\xe4\xf2\x09\x2e\x34\x0a\xab\xf0\xe2\x30\x6e\x8f\x9b\xed\xfe\x19\x45\x95\xac\xf8\xa5\xfa\x46\x8a\xca\xd3\x32\xda\xb9\xbc\x7d\x73\xf5\x1a\x25\x7a\xc5\x03\x2e\x2f\x94\x6b\xb9\xc1\x4a\x68\x31\xda\x3e\x40\xd7\x5f\xf0\xad\x51\x89\x5b\xe7\xdf\x57\x50\xcd\xa1\xe2\x8a\xea\x29\xbc\x23\x1b\x20\x85\x12\xb5\x93\xc3\x5b\xe5\x5e\x23\x22\xbf\xeb\x8a\x9d\x02\x56\x16\xf5\xbe\x5c\x32\x0e\x33\xa1\x97\xb0\xc5\x36\xa0\x94\xe8\xee\x18\xb1\x42\x54\x10\x90\xbe\xed\xcc\xc1\xf8\xf6\x50\x7d\x25\x3e\xb9\xa3\x0a\x4a\x49\x33\x9a\x53\x9e\x05\x9d\xaf\x48\x88\x99\xdf\xff\x9b\xef\x09\x7d\x2f\xb8\x11\x92\x11\xce\xe8\x15\xcf\x59\x46\xb4\xf5\x42\xea\x28\x0e\x06\xc4\xea\x39\xcf\x16\xc1\xe2\x41\x46\x44\x7a\xb2\xad\x14\x95\x18\x15\xd5\xb2\xa2\x76\x63\xfd\xa9\x9a\xd1\x82\x6a\xdf\x62\x8b\x50\x57\x80\x26\xda\x56\x36\x63\x2b\xb2\xa0\x40\x74\x2d\x06\xfc\x7d\x4c\x94\x2b\xa3\x4e\x71\x26\x99\x86\x5c\xd0\xa6\x24\x97\xaf\xb3\x43\xc1\xb7\x57\xaf\xe1\x39\x9c\x9a\x39\x3c\x43\x7b\x62\x4e\x58\xe1\x5f\x9b\x03\xb3\x06\xb6\xec\x1f\x36\xaf\x87\xeb\xab\xbd\xae\x9c\xec\x03\x21\xad\xfa\x3a\x07\x2e\x40\x55\xd9\xb2\x9e\x6b\x7f\x1f\x6c\xed\x2e\x76\x19\x40\x88\xa3\x71\x02\xd6\x93\x63\x23\x96\xf7\x09\x58\xdf\xb9\xb5\x4c\x87\x04\xac\x77\x7c\x32\xdf\x27\x60\x83\x10\x89\x4f\x5c\xc0\x06\x1a\x30\xdf\x2a\x2a\x23\xd9\x2f\xdf\x3e\x71\xfb\xa5\x7b\xc5\x35\xb2\xb2\x5d\x59\x7f\x03\xc1\x0a\xc4\x15\xd5\x24\x27\x9a\x38\xbb\x26\xb4\x86\xe8\xae\x4d\x94\x0e\xdf\xd3\x3c\x7c\x9f\xd3\xba\x51\xf4\x2d\xe3\xd5\x27\x9b\xb0\x12\x2b\x80\x74\xf3\x06\x99\x42\x16\x36\xc5\xb8\x75\x49\x59\x16\x0c\x2b\x4a\x6e\xe5\x50\x04\x29\xce\x6e\xa3\x80\x70\xe1\x50\x5f\x67\x50\x71\x92\xa2\x10\xc6\xc0\x33\x77\x56\xc2\x73\xe1\x8b\x64\xdf\x9a\x44\x74\x76\xd0\x5e\x9b\xbc\x29\x1e\x72\xdf\xb3\x96\x44\xc3\x17\x20\x1a\x3e\x6b\xe0\xaf\xa0\x6b\xea\xdd\xd7\x60\xbb\xfb\xa0\xe1\x05\x4c\xd5\xdb\x3a\x20\x7a\x80\xc3\x82\x82\xcc\x68\x61\x2d\x7f\x2b\x22\x22\xe4\xc3\x05\x0b\x97\x28\x61\x32\x29\x8a\x58\xf5\x3e\x3e\x8a\x02\x93\x61\x48\x84\x69\x37\xc3\xfa\x19\xcf\x3a\xb2\x88\x33\xeb\xb7\x9b\x32\xda\xac\x63\xc8\xe0\xe7\x3b\xeb\x95\xf7\xc5\x01\xb6\x67\xdd\xdc\x41\x62\xcd\x3a\x1a\xf6\x3f\xcf\x59\xbf\x67\x3c\x17\xf7\x2a\xae\xc1\xf7\x67\xcb\xb4\xd6\xa6\xbe\x69\xec\x8a\x6a\xcd\xf8\x42\x75\x8d\x3e\x52\x14\x11\x40\x43\x43\x56\x9f\xc3\xc6\xfa\x86\x72\xea\xa6\x9f\xbb\x56\x49\xa0\xdb\xa5\x52\x2e\x2f\xa1\x63\x45\xf9\xda\x90\xbb\x4e\xe7\x21\x2b\x2a\x20\xa6\x97\xac\xa8\x43\xb4\x58\x29\xf2\x4a\x9a\x97\xd0\x8c\x14\x37\xa5\x6f\x0f\x13\xd8\x3e\x78\xdf\xbc\xbb\xb9\xec\x33\x0e\x90\x4f\x0c\xb1\x96\xd2\x3a\x68\x0d\x67\x20\xf9\x8a\x29\xe5\xef\x45\x34\x74\x4f\x67\x4b\x21\xee\xe0\xb4\x46\x5f\x2f\x98\x5e\x56\xb3\x69\x26\x56\x1d\x20\xf6\x44\xb1\x85\xba\x70\x82\x69\x62\xe6\xcb\x17\x93\x89\x6f\xc2\x0b\xc6\x5d\xcc\x16\xef\x4e\x5c\x2b\x10\xfe\xed\x10\xa1\x9d\x92\xac\x99\x6d\xdc\xf1\x01\x2c\x6d\xe3\x36\x0b\x30\x1c\x58\xc8\xf7\x61\xf5\x0b\xb0\xe2\xe5\x67\xd5\xeb\xbb\x9b\xfe\x7d\x50\x41\xd5\x03\x1b\x3f\x70\xbe\x6c\x23\x18\x5b\x6c\xc3\xf9\x0b\xcd\x33\x02\x38\x6e\xed\x14\xe7\x2c\xfc\xbc\xd7\x8a\xda\x51\x1b\x71\x25\xd0\x61\xeb\x58\x06\x1d\xd9\xc6\x82\x68\x5d\xbf\x1d\x27\x6e\x00\xeb\x6d\xf7\x6f\xe3\xc8\x0d\xe0\xb9\x8d\x40\x8e\xe2\x06\x86\x47\x74\x05\xc3\xd1\xee\xe0\x80\x07\xf4\x0d\x96\x48\x56\x00\xec\x77\xfd\x04\x0a\xf4\x47\x33\x5c\x20\x9a\xf1\x02\x61\x07\xdf\x95\x2b\x8b\xd2\xd2\xef\xa6\xc3\x0b\x58\x1d\xc2\xf6\x78\xab\x3a\xe8\x6d\x56\xd4\x16\xad\x6c\x4a\xc1\x15\x9b\xba\xf0\x26\xfb\xbb\xdf\x5e\xef\xb7\x80\xe5\xc2\xe6\xb6\x76\x2a\x59\x7a\xf0\x74\x3d\xbd\x72\xa8\xb8\x66\x45\x8d\x68\x5a\x95\x85\xb1\x5c\x7a\xa3\xf7\x1c\x31\x72\xec\x74\x0d\x3c\x6f\xa6\x27\xa4\xb9\xa1\xab\x05\x7a\x0e\xff\x5d\x29\x0d\xa4\x49\x29\xaa\x0b\xda\xe1\x4a\x7a\x30\xaf\x6b\xed\x21\x3e\xce\xb5\x72\xc5\x7a\xf6\x5a\x98\x97\x58\xb3\xdc\x87\x6b\xce\xe6\x73\x5a\x27\x55\xcd\x28\x94\x44\x92\x15\xd5\x08\x77\xf5\xc5\x48\xcc\xe8\x82\xd9\x9c\x13\x31\x07\x62\x26\xf4\xe4\x44\xb5\x55\xd2\x7c\xe4\x07\x66\xb2\x30\x0d\x2b\xb6\x58\x6a\x3c\xe4\x40\xa0\x10\x7c\x81\xb5\x70\xfc\x20\x02\x85\x20\x39\xa0\xac\x17\x12\xee\x89\x5c\x01\x81\x8c\x64\x4b\xc4\x5e\x78\x45\x64\xf3\x4a\x62\x3b\x42\x4d\x49\xbe\x99\x28\x4d\xb4\xb9\xeb\x52\x9b\x17\x6d\x57\xce\x83\x6b\xb6\x53\x93\xc5\xee\x01\xf4\xb8\xcc\xa8\xf6\xe9\x0e\x5e\xc3\x21\x1d\x06\xb2\xb6\x87\xbb\xc2\x26\x80\xeb\xbc\x20\x8b\xa7\x56\x04\x28\x75\xcf\x74\x94\xba\x67\x1e\x4b\xa9\x7b\xe6\xd1\x94\xba\x67\xa6\xee\x99\xa9\x7b\x66\xea\x9e\x99\xba\x67\x6e\x51\xea\x9e\x99\xba\x67\x3e\x40\xa9\x7b\xe6\x61\x86\xa9\x32\xb6\x27\xa5\xee\x99\xa9\x7b\xe6\x7e\x4a\xdd\x33\x3f\xb7\x69\x91\xba\x67\xa6\xee\x99\x35\xa5\xee\x99\x23\x28\x75\xcf\x1c\x47\xa9\x7b\xe6\x41\x7a\x62\xfd\x34\x52\xf7\xcc\xd4\x4f\xe3\x58\x3e\x4f\xaf\x9f\x06\xa4\xee\x99\x7e\x94\xba\x67\x8e\xa7\xd4\x3d\x73\x1c\xa5\xee\x99\xe3\x79\xa6\xee\x99\x2d\xa5\xee\x99\xa9\x7b\xe6\x17\xba\x75\x53\xf7\xcc\xd4\x3d\x73\x98\x52\x8c\x20\x75\xcf\x1c\x47\xa9\x7b\xa6\x3f\xd3\x74\xdb\xf7\xe7\xf3\xf4\x6e\xfb\xa9\x7b\x66\xea\x9e\x79\x90\x42\x4c\x37\xa5\x73\xe6\xd1\x36\xe5\x71\xea\xa2\x3a\xb4\x6c\xa7\xd6\xcc\xac\x9a\xcf\xa9\x44\xb3\x1b\x47\xea\xe5\xb8\x19\x2e\xd3\x3b\xad\xd3\x14\x7c\x78\x5a\xc3\x4f\x51\x7d\x8e\x25\x5c\x95\x4d\x9c\xc6\x21\xfa\x01\x1e\xfb\x43\x74\x25\x77\xb0\x59\x88\xa4\xca\xef\x7e\xcd\x38\xbc\xf9\xf0\xf5\x34\x42\x49\xd8\x90\x6a\x6a\x38\x27\x1f\x78\x16\x9a\xac\xd3\x6e\xb2\xb0\xca\x46\x75\x55\x23\xb7\xd7\xb2\x42\x28\x8b\xad\xb5\x8b\x97\x2d\x09\xe7\xd4\x27\x41\xc5\x0a\x44\xa6\xd1\xed\x36\xa3\x94\x83\x28\x29\xb7\xf8\x7f\x02\x8a\xf1\x45\xe1\xa3\x01\x88\xd6\x24\x5b\x4e\xcd\xfb\xf3\x7a\x83\xb9\x6e\x32\xcd\xa8\x7d\x8e\x9a\x96\x94\xac\xec\x46\x93\x74\x45\x98\x1d\x2e\x90\x4c\x0a\xa5\x60\x55\x15\x9a\x95\x01\x03\x06\x45\x31\xcd\x5a\xd9\x9c\xff\x7a\x13\x80\xd7\x71\x53\xd4\x82\x3d\xb1\x76\x67\x33\x07\x6e\x7a\xbd\x4c\xb0\xf6\xa8\xe1\x05\xfe\x1c\x1b\x09\xae\x4a\xbd\xb1\x09\x51\x9e\x07\x78\xce\xa4\xd2\x90\x15\x0c\x6f\x70\x38\x0f\x14\x35\x19\x8e\xd9\x07\x01\x4c\x78\x6e\x38\x73\xb7\x46\xca\x2d\x12\xcf\xd1\x00\x2d\xbd\x0c\x7e\x4c\xcb\xa9\xf3\xbe\x68\x3d\xdc\x9c\x29\x77\xa1\x50\x5e\x03\xad\xab\xa9\xdb\xc3\x55\xaf\x11\x1e\xaf\xdc\xb3\x2c\x70\xfd\xce\x8e\x49\x67\xc8\x01\xe7\x1f\x0b\xa0\x3b\xaf\x78\xa3\x02\x6c\xe9\xf2\x5a\x40\x7a\xbd\xff\x6e\x32\x6e\x5d\x0c\x17\x15\x84\x07\xcb\x8e\x4a\xc1\x63\xca\xe9\xda\x68\x2f\x9a\x51\xb6\x36\x46\xb8\x07\xcb\x41\x7d\xf0\x0f\x55\x07\x9a\xca\x15\xe3\x98\xb4\xf5\x8e\x2a\x45\x16\xf4\xda\x2b\xfa\xbd\xef\x6e\x8d\x01\xf0\x7a\x33\x7a\x1f\xe3\x02\x2f\xd8\xad\x71\xdb\xa6\x20\x9c\x78\xa5\x87\xb6\x2f\x0d\x2b\xfb\xd6\x4d\x5d\x94\x7b\xc9\xb4\xa6\x5e\x86\x8d\xb2\xdd\x16\x10\x38\xb4\x5d\x89\xc7\x6f\xa0\x9d\xf4\x0a\x78\x57\x0f\xd4\x0e\xd0\x3c\xce\x18\xa9\x3c\xf7\xf2\x71\x59\x94\xd3\x4c\x32\x3a\x87\x39\xc3\x2c\x06\xc4\xdb\x9f\xdb\xea\xbe\xc4\x67\xb4\x84\x03\x51\x8a\x4a\x9c\x57\x87\xb7\xae\xe7\x77\x0a\x7f\xf6\xce\x33\xd5\xb2\xe2\x19\x69\x7b\x65\x01\x17\x39\x05\x36\x87\x05\x22\xfb\x7d\xa4\x0e\xf6\xe6\xfb\xb7\xe7\xff\xf1\x7b\x98\x6d\xcc\x45\x03\xb1\x2c\x5a\x68\x52\xd4\x03\xf6\x60\x5a\x50\xbe\x30\xbb\xdd\xaa\xec\x7e\x49\xa1\x80\x34\x5b\xec\xaa\x6e\x73\x5f\x5f\xfc\xe6\x6e\xd6\xbb\x93\x79\x70\xbc\xc8\xe9\xfa\xa2\x73\x02\x26\x85\x58\x74\x9a\xe1\x7b\x70\xac\x53\x35\x7d\x13\x15\xbd\xae\xf9\x03\x82\x0b\x3b\x7a\x06\x8a\xae\xba\x70\x3a\x2c\xc5\xbd\xed\xa6\xd2\x3e\xc7\x63\x6a\x6a\xe9\xd2\xe6\x1d\x96\xa2\xac\x0a\x9b\xd9\xfa\x35\xf3\x32\xe8\x50\x52\x55\x8a\x6e\xd7\x9e\xd9\x23\xcb\xfd\x84\x43\x3d\xcc\xad\x8b\x90\x15\x12\x01\x13\x21\x5c\xe1\x06\x17\x5d\x6a\x2a\x9f\x57\xd2\x2b\xf3\xf1\x6b\x52\x14\x33\x92\xdd\xdd\x8a\xb7\x62\xa1\x3e\xf0\x37\x52\x0a\xd9\x9b\x21\x9f\x73\x4c\x8c\xd5\xb8\xac\xf8\x9d\x6d\x06\x5e\xbf\x7c\x21\x16\x20\x2a\x5d\x56\x5e\xb7\xbf\xf9\xf6\x76\x6a\xe6\x64\xee\xb7\x0f\x1a\x13\xd9\x19\xa5\x9d\x91\xd2\x4f\xcc\x2f\xf4\x71\xcf\x8c\x00\xe3\x40\xcd\x3c\x5a\xa9\xd8\xbe\xb5\xdf\x65\xa1\x23\xbe\x7e\xf3\xfc\xdf\xfe\xdd\x0a\x5c\x10\x12\xfe\xfd\x39\x26\x65\x7a\x99\xb7\x68\x0a\xa0\xfd\xc5\x14\xa8\x15\x29\x0a\x2a\x43\x05\xa3\x39\x8e\x1d\x41\xd8\x88\xb5\x7f\xa8\x54\xd3\xa1\x02\xec\x11\x9d\x3f\xb7\xb7\x7f\x41\xcf\x0f\xd3\x8a\x16\x73\x2f\xab\xbc\x50\xa2\xed\x77\x74\x82\xc6\xf4\x89\xb3\x45\xcc\x6d\xd2\x47\x04\x7c\x5e\x77\xca\x5a\x14\xd5\x8a\xbe\xa6\x6b\x96\xf9\x84\xb5\x7a\x4b\xd7\xe3\xe5\x9f\xf9\x5c\x30\x85\x05\xe9\x67\x85\xc8\xee\x20\x77\xec\x5a\x58\xbb\x8f\x15\xb2\x09\xad\x2b\x19\x92\x84\xe0\x9d\x7c\xb0\x77\x76\xdb\xd4\x01\x2f\x07\x2f\x81\x15\x29\xcb\xa6\xe8\x87\x24\xf7\xbd\xc9\xf6\xe2\x69\x24\x2f\xe3\xdd\x7b\xab\xcf\x61\x08\x0c\x0e\x87\x84\x86\x27\xee\xed\x3d\x6d\x0e\xef\xbc\x84\xd0\xa8\x72\x3b\x6a\xdf\xc0\x57\x6f\x9b\xb5\xec\x42\x6b\x17\x94\xc8\xc3\x26\xad\x47\xea\x2f\xd1\xa9\x8c\x64\xc7\xd9\x5c\x7b\xcd\x86\x0e\xa8\x2a\xa6\x85\x6f\xd0\x31\x38\xd2\x17\x92\x05\xd2\x5b\x39\xde\xc4\x54\x57\x44\x7b\x39\x2b\x2c\x75\x8b\xfc\x11\x28\xa9\x54\x4c\x19\x1b\xfd\x3b\x14\x40\xaf\x0a\xc2\x7c\x03\x67\x4d\xf0\xa4\x14\xbe\x4b\x15\x30\xdd\x56\x80\x62\x73\xc2\x50\x4d\x77\x2d\x72\xc7\x0e\x15\x13\xba\x4d\xbc\x22\x2a\x3b\x6e\x96\xd0\x92\x14\xd1\xcc\xbf\xcf\xa9\xea\xbe\x6b\x57\x2a\x5c\xd3\x19\x2e\x8d\xaa\xb3\x9c\x9d\xb2\xf2\xe4\xf8\xe5\x2a\x38\x9c\x8b\x2f\x4d\xbf\x35\x83\x8e\x22\x24\x51\xb1\x39\x5b\x25\x44\xb9\xb5\x77\xd5\x36\x52\xb1\xa4\x4e\x28\x78\x73\x6d\xdd\x2c\xce\x13\x3b\x75\x60\x51\xee\xdd\xa9\xae\x19\x2a\x9c\xbc\x3c\xf9\x6c\x4a\xce\x2e\xa2\x14\x25\x59\xa0\xef\x20\xca\x5a\x6e\x33\x0d\x40\x78\x59\xb7\x06\x55\xe8\x36\x43\xbe\xbe\x95\x10\x2d\x95\x6e\x54\x34\x6f\x4b\xa0\x2f\x05\x56\x58\x88\xb1\xe5\x9c\xc3\xc4\x16\x6e\xbc\x0f\xc8\x8b\x26\x52\x54\x3c\x77\xd1\xe0\x06\x82\xf0\x6e\x6b\x62\xdf\xfb\x57\x30\x43\x37\x8f\xad\xd5\x8e\x85\xf0\x6c\xa2\x24\x53\xbe\xc5\xf0\x1c\x4f\x0e\x2f\xa6\x2f\x9e\x7f\xf9\x36\x1b\xce\x49\x24\x9b\xed\x7d\x63\xb3\x59\x2d\xf7\xd9\x66\xa7\x6e\x98\x1c\x65\x86\xde\xb9\x90\x54\xd3\xd9\xd8\x7f\xd3\xd4\xdd\x3a\x91\xd5\xbd\x64\xda\x9d\xa0\x7b\x16\x90\xa8\x76\x8a\x4e\x1b\x10\xb2\x5b\x82\xf8\xac\xf5\xe5\x05\x5c\x49\x42\x3a\x2e\x87\xb7\x2c\x04\x50\xd5\xec\xc9\xe9\x5d\xab\x60\xad\x50\x1d\x8a\xa7\xfa\xcf\xb7\xe3\xbc\xab\x82\xbd\x39\x76\xb1\x87\xcf\x9e\xc1\xa9\x7d\xc2\x89\xad\x66\x77\xf6\xd9\x8e\xa7\x5b\xd6\x37\x9f\x4a\xef\xa6\x32\xbd\xa5\x7d\xf3\xa9\x24\x3c\xa7\xb9\xbd\xf0\x07\x98\xd6\x50\x17\x9d\x1e\x5a\xe3\x70\xb5\x79\xa2\xfa\x6b\xec\xcd\xb1\x6b\x9e\xfd\x27\x5d\x92\x35\xc5\x9a\x7f\xac\x20\x32\x40\x3c\x69\x01\x37\x76\x65\x60\x56\x69\xa0\x7c\xcd\xa4\xe0\x2b\x1a\x50\xd8\x7d\x4d\x24\x23\xb3\x82\x82\xa4\x58\x38\x38\xa3\x0a\x7e\x75\xfa\xdd\xe5\x47\x84\x59\xfb\xb7\x8f\x20\x92\x02\xad\x57\xbd\x52\x98\x9e\x1b\xe9\x14\x76\x5e\x7b\xba\x75\x80\xfc\x45\xf4\xd6\xc1\xab\xe7\xd9\x9c\x00\xff\x39\xe0\x79\xb3\x5e\x66\x3e\x56\x95\xae\x48\x81\x65\x1f\xb3\xa2\x52\x6c\xfd\x39\xf4\xaf\x2b\xc3\xf9\x9a\x79\x9c\xec\xad\xf2\xa5\xed\xa1\xd9\xa9\xed\xe9\x59\xc2\x1b\xcd\xcb\x78\x2d\x25\x1d\xf0\xf2\x44\xd5\xc9\x2a\xbd\xd6\x40\xde\x41\x39\x57\xb6\x7a\x86\x83\x9b\xb3\x45\x25\x6d\x21\x1d\x3f\x11\xd4\x69\x66\xbd\x42\x14\xc9\xe7\x0a\xcf\xe5\x5c\xbd\xc2\xf7\x19\xb3\x31\xfa\x79\xfd\xbd\x52\xc1\xaf\xdf\xdf\x74\xea\x8f\x8f\x7a\x07\xeb\x56\x14\xf9\x14\xae\xdb\x02\xe6\x6d\x8b\x01\xec\xaf\x33\x1a\x6d\x62\x64\x32\x95\x8b\xb6\x05\xea\x82\x72\x2a\xf1\x02\x66\x86\x5a\xaf\xe5\xf8\x7b\xe2\x8c\x28\x04\x85\x1a\x36\x16\xa1\x31\x66\xc5\x3c\xdd\x3d\xbe\x3e\x13\x73\x2f\xb1\xd5\x55\x46\x3b\x5b\x7a\x6b\x7d\xd9\x04\xe1\xcc\xe4\xa1\x33\xd8\xb2\x1d\xbd\x59\xaf\xae\x81\xe4\xb9\x44\xf8\xa2\xbb\x02\xd6\xc7\x94\x94\xa5\x1f\xfa\xcb\xad\xb0\x59\x99\xee\x1b\xb7\x4b\x3e\x9a\x23\x9a\x1a\xed\x02\xc3\xeb\xaa\x2c\x98\x85\x6c\x75\x1e\x30\x9a\x6d\xfd\xa6\x92\xae\xc4\x7a\xfc\x51\xf7\x77\xc4\x7a\xba\x61\xbd\x35\x8f\xf0\xeb\x93\xf7\xc0\x9e\x93\x54\x89\xc2\x67\xc3\xb9\xa1\x6c\xed\x35\x27\x1b\x8c\x71\x3a\x7e\x56\xea\xbd\xe6\x58\x77\x44\xcb\xd6\xbe\x19\xcd\xba\xb3\xcf\x28\xd7\xd2\x08\xd7\xc0\x3d\x03\xf0\xd1\xcc\x5c\x85\x00\x9d\x66\xc0\x6c\x4d\xb9\x51\x62\x1f\x3c\x9b\xf9\xe1\xa0\xc4\x9a\x4a\x69\x2b\x87\xdb\x1c\x07\xdb\xf2\x91\x12\xe9\x93\xa2\xd2\xcc\xaa\xf7\xf4\xfd\xc3\x8f\xc7\x76\x08\xe8\xf5\xfb\x1b\xab\x53\xed\xb4\x1a\x3b\x84\x71\xaf\x40\x45\x77\xc7\x37\xab\xd6\xe8\x49\xcf\x73\xfc\x59\xfa\x27\xf8\x7b\xc6\xfa\x2d\x79\x5d\x9c\x23\xa4\x7a\x81\xf7\x15\x39\xa0\xd2\x9c\xf7\x93\x15\x25\x32\x5b\x8e\x9f\xf3\x07\x44\xa8\x65\x09\xb9\xc0\xac\x87\xf1\x3a\x51\x48\x74\x59\x4f\x50\xfd\x17\x42\xdc\x55\x65\x5f\xaa\x8e\x66\x59\x6b\xfc\x9e\x06\x77\xc3\x2c\x89\x5e\x8e\x1f\xe4\x5e\x51\xdc\x11\xad\xa3\x99\x76\x47\xf4\xcf\xa1\xc3\x73\xae\xc6\xa3\x8f\xfb\xb7\x03\xaa\xed\x9d\x00\xd9\xb4\x15\x5d\xc6\x8a\xaf\xde\x95\xff\x55\x51\x29\x4d\xe5\xd7\x4c\x2a\xfd\x6c\x0a\xdf\x91\x82\xb9\x22\x8b\xe3\x76\x8a\xb9\x9f\x9f\x74\x99\xfd\x99\xe9\xe5\x1f\x85\xd2\xef\xa9\x3e\x39\xef\xff\xe9\x64\xdc\xcd\xf1\xc4\x0d\xf8\x04\x84\x84\x93\xf7\x82\xd3\x93\xe9\xd6\xe5\xc8\xaa\xdf\x51\x5c\x19\x5e\x37\xac\x72\x19\xb2\x61\xdc\xdc\x9a\xa9\x1e\x29\x65\x0a\x9a\xe9\x9a\x49\xe7\xb4\xdc\x0a\x58\x92\xb5\xbd\xd6\xf9\x74\xfc\x55\x54\x03\xc1\x1e\x4f\xc8\x79\x69\xe7\xf6\x5e\xc8\x3b\xdb\xb0\x01\x99\x8f\x8c\x7d\xd9\x2b\xe1\xa6\xbb\xad\x3a\x5d\x1b\xb4\xd8\xbf\xa4\xe3\x6f\x68\x23\xcf\x8b\x6d\xc5\x74\x43\xe5\x9a\x65\xf4\x2d\xe3\x77\xa3\x0e\x6a\x3f\xd7\xe8\xcd\x0e\x2f\xcf\xd6\x71\xf7\x0e\x39\xcb\xb8\x4d\xe0\x36\x26\x09\x99\x89\x4a\xe3\xdd\x0d\x41\x94\x1e\x8e\x4f\xac\xff\xf0\xdf\x76\xd7\x20\x5e\xa5\xb4\x2d\xc2\x3a\x8e\xba\xc6\xcf\x38\x12\x0a\x8d\x21\xaf\xda\x79\xa8\x36\x5c\x93\x4f\xa8\xbb\x44\x76\x47\x25\x14\x66\x2a\xa6\xd0\xa4\x62\x79\x8b\x11\x04\xe6\x8e\xc9\xed\xf0\x8b\x9c\xd0\x72\x49\x57\x54\x92\xa2\xf1\x9d\xf9\x6f\x8a\xb7\x4e\x8d\x37\x3c\x3b\x99\x38\xa3\xe6\xc1\xf6\x8d\x71\xdd\xf3\x44\x3e\x85\x37\xa1\x1c\x57\x64\x83\xea\xd0\x32\x26\x1c\xe8\x27\xa6\x10\x60\x53\x8a\xbc\x53\xd3\x6d\x14\xd3\x4a\x51\x39\x69\x2a\x00\xba\x0a\x4b\xaa\x4e\xe5\x82\x9c\xce\xaa\xc5\x82\xf1\xc5\x38\x5d\x82\xb6\x0a\x5a\x44\x6d\x5b\xb6\xd6\xcf\x84\x6d\xea\x32\x49\x89\x1e\x6b\xab\xa1\x55\x7e\x8e\x1e\x60\xd6\xe5\xbd\x12\xb9\x65\x3d\xdb\x58\xef\xde\x58\xc6\x75\xbd\x1c\x33\xc8\x29\x5c\x71\x10\x32\xa7\x12\xcb\xc3\xe4\x39\xce\x75\xbd\x7a\xa3\xd8\xb6\x4e\x48\xc3\xa9\xbf\x62\xe7\x5e\x79\x26\x46\x06\xa8\x76\x34\x9d\x34\x31\x55\xcd\xcc\x45\xa6\x92\x63\xdb\x79\xf6\xd1\x01\xa4\x28\x97\x64\x52\xd0\x35\x2d\xc0\x75\x55\x1a\x1d\xfb\x5d\x0a\x2e\xa4\x5d\x8d\xda\x43\x84\x77\x56\x2b\xbc\x71\xb2\xdf\xec\x9e\xd9\x51\x8f\x70\x4d\xf4\xc6\xeb\x9b\xb1\x06\xa1\x87\x31\xd8\xbf\x19\xf0\x81\x77\x1d\x9f\x0f\xd3\xcd\x4a\xc6\xb9\x74\xd2\x80\xe4\x68\xd5\xd3\x55\x29\x24\x91\x6c\x74\x14\x6c\x77\x5f\xa2\x05\xd9\x17\x0b\x63\xc7\x9a\x69\xb6\x66\xe6\x1e\x3b\x20\x47\xda\xd9\x18\xc9\xb5\xb3\xd5\xd1\xa6\xe1\x02\xea\xfd\x6e\x2c\x40\x95\x2d\x69\x5e\x15\xe3\xef\x9d\x8b\x8a\x48\xc2\x35\xa5\xea\xbc\x86\xf7\x6c\x5c\x9a\xb6\x15\x2e\x4d\x92\xf9\xd8\x90\x90\x11\x73\xc8\x8d\x7e\x62\x1a\xdb\x67\x9a\xdf\xa0\x0c\xb3\xc9\xeb\x78\xaf\x19\xc9\x55\xc8\xad\xac\xf7\xae\x70\xf2\x0e\xeb\x64\xa4\x52\xd8\x0d\xc1\xa9\x12\xfa\x29\xa3\xc6\xec\xd0\xaa\x99\xe4\xb1\x9b\xc0\x66\xff\x30\xc1\xcf\x1b\xe9\xea\xf6\x2c\x5d\xb3\xcc\x23\xfe\x32\xa4\x40\x91\xa5\x5b\x27\x3c\x0a\x23\x79\xce\x36\x2e\xb8\x56\xb4\x8a\x63\x4b\x19\xdc\x2e\xe9\xd8\x43\xd5\x94\xd7\xc2\xc3\xb9\x66\xa4\x66\x39\x2c\xba\x47\x72\xef\x08\xfa\xed\x1d\xeb\xeb\x14\xec\xbe\x31\x08\x9e\xb9\xa1\x77\x5a\xa8\x8e\xe5\x88\x6a\x64\x5f\x03\xd5\x50\xe1\xbf\xd5\x43\x75\x9c\xa6\xf7\xf5\xd0\xf9\x01\x80\x3d\xc0\xbb\xfe\x6e\x40\x22\x17\xa1\xce\xd5\x93\x4b\xb9\xa8\x56\x98\x17\xec\x5c\x45\x6d\x9b\x7b\x1f\x97\xe0\xed\x92\x42\x6e\xaf\x15\x18\x87\x35\x17\x98\x57\xef\x5e\xd7\xd8\x44\x0f\x8e\xcc\x15\xfa\x70\x95\x9b\x5c\x53\xe7\x7c\x0a\xdf\xb9\xbb\x90\x4f\x44\x7b\x10\xa5\xd1\x43\x5b\x78\x70\x1d\xc2\x67\xf4\xef\x6f\x9e\xf1\x7c\xd2\xe2\x4b\x5a\x1b\xd8\x79\xb1\xbd\xe2\xef\xb6\x0b\x91\x9b\x83\x3a\x55\x84\xf1\xd2\xdc\x60\x7d\x7d\xb9\x0d\x26\x80\x67\x4b\xc2\x17\x56\x9a\xd0\x40\x14\x8c\xbb\xab\xba\xc6\xde\x54\x65\xa4\xac\x7d\x2a\x04\x72\x51\xf9\x2d\xff\xaf\x7e\x75\x0e\x8c\xbe\x84\x5f\x75\x06\x37\x85\x37\x8e\x7b\xbb\x39\x7c\x67\xc1\xd6\x7b\x99\xb5\x9b\xe9\x1c\x24\x5d\x10\x99\x17\x7e\xad\x3d\xc4\xbc\x71\x39\x20\x6a\xab\xde\x0c\x68\xc6\x29\x10\x3e\xa0\x0e\x2e\xf4\x10\x46\xa2\x53\x66\xcf\x83\xe9\x03\x85\xf9\x34\x51\x77\xea\xc2\x3a\x38\x26\x39\xd1\x64\x42\x4a\xeb\x37\x66\x82\x5f\xd8\x80\xce\xc4\xb5\x76\x9d\x10\x27\x94\x26\xcd\x41\xba\xf8\xa5\xac\xb0\x7b\xfa\x84\x34\x9f\x62\x7c\x42\x26\xd8\x08\xd4\xb7\x9e\xc4\x3f\x38\xf5\x26\x20\x5a\xe2\xdd\x33\x79\xdb\x05\x56\x0b\x77\xfb\xee\x53\x78\xef\x95\xef\xe0\x7a\x23\xe7\x6d\x32\xaa\x6b\xc8\xda\xca\x7f\x1f\x51\x5f\x6b\x8c\x37\xef\x6f\x3f\xfe\xe5\xfa\xc3\xd5\xfb\xdb\x5a\x71\xd4\x6a\xc0\x87\xeb\x3e\xc5\x11\x76\xd2\xf7\x29\x8e\x56\x0d\x84\xa0\x98\xb6\x15\x47\x5f\x0d\xf8\x70\xde\x55\x1c\x7d\x35\xe0\x33\xb3\xbb\x8a\x63\x40\x0d\x78\x5a\x11\xdd\xf9\x1d\x54\x03\x5e\xd2\xb9\xa3\x38\x86\xd5\x80\x07\xd7\x5d\xc5\xd1\x57\x03\x5e\xe7\x6b\x57\x71\x74\xd4\x80\xa7\xca\xdf\x55\x1c\x5d\x35\xe0\xc1\x74\x58\x71\x24\x35\x70\xcc\x43\xbd\xd4\x00\xe5\xeb\x40\x15\xd0\x38\xbc\x87\xa2\x0a\x3e\x2f\xd3\x6b\x6d\xd9\x29\x8a\x1d\x63\x53\x7d\x19\xeb\xd9\xc7\xe8\xf3\xf5\x77\x44\x82\xa4\xa5\xa4\x0a\xef\x55\x9e\x39\x21\x43\x0b\x04\x8e\xa9\x6f\x6b\x7e\xd2\xc2\x8d\xbf\xb8\x94\xda\xcf\x94\x14\x1b\x2d\x01\xad\x4e\x1a\xb3\x77\xec\x78\x29\x07\xd3\xa6\xc9\x09\x81\x57\x3f\x5e\xbd\x7e\xf3\xfe\xf6\xea\xeb\xab\x37\x1f\x3f\x5b\xd6\x4b\x50\xfb\xc8\xbe\xb9\x1a\xc7\x52\xb3\xf4\xb0\xbd\xe6\xcd\xd6\x56\x50\xa7\x6b\x26\x2a\xe5\x70\x69\x79\xd4\xf5\x55\x3b\xb2\xd5\x9b\x25\x56\x9f\xe5\x9b\x3a\x4a\x1d\x77\x98\xd3\x41\x4f\x85\x37\xdf\xa8\x86\xaa\xa5\x07\xcc\x55\x6f\x9e\x51\xbd\x1d\x96\xf6\xfb\x3c\xfc\x17\x3e\xb6\xc9\x6b\xe9\x41\xc3\x37\x64\xe5\xf7\x98\xbf\xde\x2c\x1f\xf0\x9e\x78\xf3\xac\x8d\xe7\x7e\xea\x94\x77\xfb\x95\x38\x62\xf7\x6b\x29\x56\x51\x44\xef\x8d\x0d\xb4\x39\x74\x99\xf7\x24\x0d\x19\x31\x27\xca\x8e\xd5\x7f\xdf\x75\xdc\x56\xce\x35\x50\x37\x8a\xf0\x66\x69\xf8\x61\x8d\xc4\x30\xb5\x19\xd4\xb8\x3b\x46\xb7\x6b\x9b\x7e\xf3\x8e\x94\x7f\xa2\x9b\x8f\x34\xa0\x43\xcb\x0e\xea\xb0\xa0\x99\x31\x66\xe1\x6e\x74\x78\xac\x4f\x08\xb6\x7e\x55\x0f\x33\xa4\xb5\xcd\x93\xea\x95\x1e\x36\x2d\xb1\x1a\x9d\xdf\x51\xef\x5a\x00\x35\xed\x34\xee\x0e\x5d\x70\xa8\x6f\x89\x66\x07\x85\xac\x37\xc4\x6c\x72\x1e\xbd\x25\xfc\x89\x33\xf0\xc3\xe7\xaa\x35\x76\xb4\x75\xab\x04\xb3\x3c\xbe\x6d\x8e\x58\x1b\xdb\x90\xde\x5f\xb8\x5c\xd4\x89\xb1\x3b\x26\xf6\x8c\xa9\x0b\x4c\xd1\xba\xf8\x25\xfe\x27\x78\x50\xb6\x71\xde\x65\x9e\xbb\xea\x2a\x95\xa2\xf3\xca\xa7\xf2\x75\x9f\x10\xd9\xa4\xa6\x40\x4a\xf6\x1d\x95\x8a\x09\xaf\xf6\x0d\x7d\xba\x63\x3c\x3f\x87\x8a\xe5\x5f\xf9\x77\x57\xb3\x14\x6d\xff\x0a\x2f\xb4\xe6\x2e\x0d\x64\x9e\x86\x1f\xf7\xae\xbd\xd5\x88\xfa\x60\xae\xb6\xa0\xac\x91\x47\x35\xe2\x22\x98\xa5\xbb\xb0\x45\x59\xd4\x90\x02\x20\x50\x6f\xdc\x98\x3a\xfb\xa4\x51\xda\x41\xef\x67\xa1\x82\x4d\x17\xbd\xfc\x65\xdd\x32\x33\x4c\x04\xac\xa8\x26\x39\xd1\x64\x6a\xa4\xc9\x79\xff\x47\x55\x92\xcc\xab\x99\xc7\x00\xfb\x82\xcc\x68\xa1\x3a\x0f\x40\xe3\x11\xfd\xcd\x5e\x05\xa5\x5b\x42\xbc\x10\x17\x39\x7d\x8f\x6f\x80\x3f\xba\xab\xf5\x65\x96\x89\x8a\x6b\xfc\x43\xd8\x33\xb0\x8c\xfa\x74\x29\x94\xbe\xba\x3e\xaf\x7f\x2c\x45\x7e\x75\x1d\x85\x31\x72\x52\x01\x4d\x23\x9f\x98\x19\x86\x9b\xd5\xb3\xf0\x5e\x4d\xb1\x8c\xb1\x56\x03\x45\x15\xd2\x8e\x67\xb8\x38\xb5\x27\x5a\x65\x4b\xba\x22\x41\xb7\xbc\x9a\xbe\xae\x27\x1f\x98\x0a\x68\x8f\xd2\x27\xc6\xb1\x14\xbe\xb9\xff\x47\xe9\x96\x6a\xc9\x5c\xd6\xd7\x2f\x9e\x3d\x19\x73\xb4\xd9\xb7\x51\xb7\x0a\xae\x45\x24\x93\xd4\xaa\x81\xc6\x90\x8f\xb2\xae\xcb\x6e\x9a\xc0\xe5\xf5\x55\x30\xd3\xb5\x3d\x1b\x4f\x62\x59\x6b\xd0\xe6\xd7\x4f\x54\xaf\xb7\x68\xea\xad\x92\xd1\x61\x5b\x50\xf0\x62\xd3\xf0\x56\xb6\xa9\x43\xd8\x79\x25\x3c\x47\xed\x40\x95\x56\x70\x6a\x19\x4e\xb3\xb2\x0a\x53\x80\x8e\xcf\x8a\xae\x84\xdc\x9c\xd7\x3f\x36\x70\xdd\x89\xd2\x42\x92\x45\xa0\xfa\xae\x87\x8d\xc3\x6d\x7f\xb2\x0f\x8d\x36\x29\xbb\xa3\xf6\xf7\x3e\x83\xcb\xe2\xcc\x2a\x69\x2e\xa0\xc5\xa6\x6d\x90\xfe\xf3\xb1\x12\x3c\x31\xee\x5d\x8a\x65\x24\x34\xa7\xee\x7d\x74\x87\xc4\xab\xe0\x80\x51\x4d\xe8\x2c\x69\xe6\x1e\xe6\x5e\x88\xc3\x3e\xb9\xa2\xde\xe7\xcd\x45\x36\xfc\xe2\x2f\x24\x50\xbe\x86\x35\x91\x9e\x0d\x7d\x5b\x8a\xa6\xd7\x73\xb6\x66\x4a\x04\x8a\xd4\x7d\xf5\xa1\xa2\xe8\x75\xd7\xb1\xc7\x66\xb2\xc6\x32\x2a\xe9\xa7\x12\x3b\x3f\x36\x7a\x20\xdc\x07\x93\x77\xe3\x2c\x2f\xfc\x6b\xd4\x59\x2a\x89\xd6\x54\xf2\x97\xf0\x5f\xa7\x7f\xfd\xf5\x4f\x93\xb3\xaf\x4e\x4f\xbf\x7f\x3e\xf9\x8f\x1f\x7e\x7d\xfa\xd7\x29\xfe\xe3\x5f\xcf\xbe\x3a\xfb\xa9\xfe\xe1\xd7\x67\x67\xa7\xa7\xdf\xff\xe9\xdd\x37\xb7\xd7\x6f\x7e\x60\x67\x3f\x7d\xcf\xab\xd5\x9d\xfd\xe9\xa7\xd3\xef\xe9\x9b\x1f\x8e\x64\x72\x76\xf6\xd5\xaf\x02\x07\x1e\xd8\x78\xdd\x52\xac\xf6\xeb\x7d\x6e\x11\x8e\xcb\xa3\xb4\x62\x6f\xa9\xde\x8e\x71\xe5\xec\xc7\x08\x3a\xa9\x3f\xbe\xd6\xcc\x7e\x12\x82\x4c\xd1\x4c\x52\xfd\xb4\x23\x4a\x76\x8c\x9d\xb6\x17\x01\xa5\x31\xa1\x2e\xf0\x56\x92\x20\x1b\xe1\x49\xd9\x3c\x29\x40\xf5\x10\xd5\xce\x10\xbb\x8b\xe2\xdd\x72\xe7\x52\xac\xea\xd6\x02\x08\xd1\x5a\x93\x82\x85\xfa\x9b\xeb\x13\x69\xde\xfc\x49\x5c\x75\x21\x05\xd4\x52\x40\x6d\x0c\xa5\x80\xda\x38\xea\x06\xd4\x6e\xf0\xec\xa7\x68\xda\x10\x51\xbe\xf6\x83\x40\x0d\x62\xe4\x6b\x1f\x56\xa7\xcb\xad\xc7\xbb\x0d\x22\xed\x77\x01\xf3\x1e\x9c\x9d\xf2\x6b\x71\xa7\x6d\x36\x96\xaf\x7b\x63\x35\x8c\x25\x86\xcb\xa2\x00\xc6\x7d\x95\x17\x0e\xb2\xad\xef\x66\xdd\x49\x40\x14\x16\x33\x58\xfb\xc1\x4f\xeb\x72\x0b\xdd\xca\xcf\x0a\xb0\x52\xc2\xe8\xfa\x35\x96\xfe\x6c\xcb\x35\xdc\xd9\x0a\x0e\x4a\xe3\x22\xad\xaa\x42\xb3\xb2\xa0\x10\x70\x91\xb5\xb0\xc3\xa2\xa2\x40\x94\x12\x99\x2d\xbd\xd3\x54\x17\x2b\x88\xf2\x79\x7f\x77\x53\xc0\x59\xd5\xe4\x0e\x51\xc8\x19\xcd\x29\xcf\x28\x16\x70\x1b\x5b\xba\xcd\x52\xbd\x93\x66\x1b\xb3\x36\x6f\xf8\xba\xc9\x99\xaa\xab\xfc\xf9\x2d\xff\x9e\x71\xfe\xf3\x26\x89\x18\x31\xe5\x40\x96\x6d\xae\x88\x97\xe4\x44\xbb\xb5\xf1\xe4\x13\x4c\xc7\x11\xf3\x16\x77\xe1\x95\xd5\x13\x76\x73\x09\xbd\x2d\x34\x28\xc6\x80\x0b\xe7\xce\x35\xa1\x99\x90\x90\xd6\x50\xf6\x5a\x80\x66\xbd\x27\x8f\x27\x02\x14\x0d\x35\xd7\x07\x4d\xf5\xe0\x28\x72\xdf\x4c\x7f\x7a\x66\xf6\x23\x98\xd8\x03\xe6\xb5\x35\x8f\x83\xb8\x86\x9a\xd6\x51\xcc\xea\x18\x26\xf5\x90\x39\x1d\x90\x06\xdb\x52\x0f\x9b\x16\xc5\x04\x0e\x37\x7f\xc3\x81\x64\xa5\xa4\x73\xf6\x29\x8a\xcc\xbc\xe4\xcd\x02\x02\xcb\x29\xd7\x6c\xce\x42\xfa\x09\x0b\x33\xb8\x92\x72\x5b\x70\x8a\x64\x4b\xb4\x0b\x02\x3b\x18\xb5\x40\xf2\xa7\x96\x06\x67\x5d\x34\x31\x15\xd8\x4d\x2c\xe7\x54\xd2\x5e\x49\x7b\x25\xed\x75\x88\x9e\xbc\xf6\x72\xf2\xa0\xbe\xb2\x7f\x5e\xf5\x83\xb5\x5b\x42\xcb\xd3\xbc\xee\x54\x0e\xc3\x33\xee\xed\xae\x3d\xfe\xec\xb5\x75\xf9\x2e\xf0\xb9\x1e\xd8\x81\x80\xed\x86\x8f\xbc\xae\x8a\x62\x7c\x55\x78\x4b\xfd\x09\xbc\xc2\x99\x2b\xab\xa2\x70\x85\xbc\xa7\xf0\xc1\xab\xa3\xac\x98\xc3\x65\x71\x4f\x36\xea\x1c\xde\xd3\x35\x95\xe7\x70\x35\x7f\x2f\xf4\xb5\xbd\xa8\xfa\x28\xd5\x6e\x9e\xa4\x65\x0d\x6c\x0e\x2f\x0b\xa2\xa9\xd2\xa0\x89\xcf\x41\x65\xaa\xdb\xe7\x4c\xc8\xde\x20\xdb\x96\xa3\x71\xda\xbb\x8f\x15\xea\x3b\x1b\xeb\x97\x75\xc5\xc9\xc9\x67\xd8\x68\x05\x9b\xd3\x6c\x93\x15\xa1\x67\xf4\x6d\xcd\xa7\xae\xab\x44\x8a\x42\xdc\x7b\x89\x1d\x04\xec\x0c\x14\xf9\xfc\xa2\xda\xb0\x94\x42\xe9\x1b\x4d\xa4\x8e\xd0\x8b\xe5\xe4\xba\x66\x66\x26\x37\x23\x45\xe1\x2d\xce\xd9\x6a\x45\x73\x46\x34\x2d\x36\x40\xe6\x9a\xca\x6e\x45\x61\x5f\x9e\xca\x56\xf1\x76\x85\x68\xb1\xd3\x36\xe1\x79\x41\x25\xcc\x09\x2b\xbc\x31\x3e\x3b\x4e\x5c\xdb\x23\xdc\xab\xa3\x88\x25\x0b\x8e\x74\x55\x73\x81\x64\x99\x90\x39\x16\xe5\x12\xe0\x0f\x46\x75\x0c\x5b\xc1\x8a\x36\xd4\x8a\x70\xb2\xa0\x01\x25\x14\xb6\xd1\xb7\x30\x2b\x44\x76\xa7\xa0\xe2\x9a\xf9\xda\x66\xb6\x09\xba\xb8\x83\x4c\xac\xca\x02\xc5\x53\x58\x61\x3f\x78\xb8\xb8\xdf\x90\xcc\x6b\xfe\x39\x69\x44\xcf\xc4\x8c\x49\x5d\xfc\xb2\xfd\x13\xfe\xc2\xcf\xd2\x0b\xbe\x89\x84\xdf\x43\xe8\x27\x9a\xf9\x5b\x87\xbd\xa3\xff\x81\x53\xdc\xb5\x41\x7d\xb7\x01\x04\x6f\xe0\xdc\x73\x61\x04\xb3\xd9\xf5\x81\x4d\x78\xa1\x57\xcd\x7f\x0a\x6f\x3e\xd1\xac\xf9\x39\xe4\x42\x62\x46\x69\x1b\x10\x60\xed\x59\x72\x17\x50\x12\x20\x0a\xd4\x26\x0e\xc8\xc5\xbb\x54\x63\x97\xb6\x7a\xc4\x22\xc7\x90\xfa\x06\x96\xac\xa0\xb1\xcc\x0a\xc6\x47\x37\x8a\xd9\x25\x57\x08\x12\x18\x57\xb6\x61\x5d\x47\x92\x85\xc2\x04\x0c\xb3\x9d\x96\xb8\x81\x3c\xeb\x76\x49\xf5\x2c\x84\xcf\xa9\x14\x42\xc3\xe9\xc9\xc5\xc9\xd9\x4e\x4c\x37\x10\x82\x66\x6e\xd7\x05\x55\x1b\xa5\xe9\xca\x96\x97\x71\xa3\x0e\xe4\xca\xb0\x89\x76\x89\x1d\x94\x69\x76\x92\x9f\x03\x0b\x85\x13\x38\x5b\xd0\xf6\x2a\xc1\x9d\x10\x96\x9b\x02\xb6\x9e\xe8\x39\x28\x01\x5a\x92\x9c\x45\xc1\x88\x23\x4f\x33\x40\x2d\x2b\xd7\xf8\xe4\xf4\xe4\xa7\x91\x7d\xa8\x76\x89\xea\xec\x0c\xee\x05\x3f\xd1\xb8\x5d\xa7\x70\x1b\x7a\xaa\x2a\x45\xeb\x92\xaa\xb6\xab\x13\xa7\xe1\xb0\x0a\xd1\x6d\xea\x64\x8c\x4b\x10\x55\xe8\xba\x63\xcd\x70\xa2\xeb\xea\xaf\x6f\x3e\x05\xef\x24\x9b\x97\x6a\x94\xd8\x73\x34\x05\xad\xc1\x19\xc8\x94\x28\x28\xd8\x9a\x5e\x2c\x29\x29\xf4\x72\x03\xe1\x67\x88\x0b\x3e\xf9\x3b\x95\x02\xeb\xd3\x72\xc7\x37\x0c\x8b\x17\x12\x96\xee\x92\x77\x88\x7a\x77\x30\x41\x1e\x34\x63\x2f\x7e\x43\x3d\xef\x45\xb0\xad\x03\xff\x78\x7b\x7b\xfd\x0d\xd5\xd1\x0c\x0f\x33\xba\x3a\x81\xaa\xd3\x4c\xe9\x33\x5b\x20\xe1\x50\xdf\x09\x94\x42\x7e\x6e\x13\x68\x29\x54\xc0\xba\xc3\xce\xda\x0b\xa5\x7d\xeb\x3f\x76\x49\x0b\xa3\x9b\x39\xcd\xcc\x8a\x47\x4b\x26\x76\x7d\x13\x4a\x91\xc3\xd5\xf5\x14\xfe\x22\x2a\x33\x8b\x33\x32\x0b\xb2\xe4\x0d\xdd\x13\xae\xeb\x02\xab\xcf\xcc\x24\x3c\x0b\x09\x97\x59\x32\xfb\xfe\x8f\x94\xe4\x54\x2a\xd4\x84\x94\x78\xb6\x7e\xad\x29\x12\x00\xb3\x33\xae\x98\x96\x73\xa5\xb4\x58\xc1\xd2\x32\x0e\x5f\xe8\x4e\xa9\x5b\x27\x3b\x42\xf1\xd7\x46\xae\x59\x1f\x9a\x02\x49\xcb\x18\xda\xce\xbd\xed\xcf\x48\x1b\xed\x68\x02\xbb\x53\x02\xb9\xd6\x7c\x67\xd8\x09\x29\xc3\xad\x12\xcc\xd2\x4e\xbe\xd9\x2b\xae\x3c\x5d\x30\x47\xc6\xed\x26\x31\x42\x25\x18\x25\x1e\x29\x25\x05\x22\xa5\xa5\x40\x48\x69\xdf\x3e\x13\x04\x58\x06\x72\x89\x95\xe5\x02\x91\xf2\x21\x60\x00\x06\x10\x81\x65\xb3\x4b\x6d\x4d\x87\x08\xd3\x0f\x31\x91\xf8\x10\x5a\x44\xb8\x4b\x8f\x3f\x7d\x31\x36\x1e\xc4\x9b\xbf\x32\xb8\x88\xc8\x6e\x09\x11\x2d\x80\x64\x99\x5f\xf3\x9a\x2e\x09\xab\x3a\x51\x9c\xd9\x4e\x91\x4f\xc2\xf6\x30\x16\x73\xc4\x29\xb3\x70\x12\x09\xbc\x5a\xcd\x82\x95\x54\x53\x77\x4b\xea\xd8\xcb\xd0\x29\xd6\xff\x3e\xc6\x50\x6b\x20\x42\x6d\x20\x11\xbe\x08\x3d\x17\x2f\xcc\x3b\xff\xfe\x77\xbf\xfb\xed\xef\xa6\x76\x5a\xcd\x33\x02\x79\xce\x28\x10\x0e\x57\x97\xef\x2f\x7f\xbc\xf9\xee\x15\xd6\x40\x0e\xdb\x85\x11\x52\xb2\x63\x26\x64\x47\x4c\xc7\x7e\xc4\x64\x6c\x2c\x3b\x15\x28\xe1\xfb\xe8\x1a\x64\x18\xee\xd1\xae\x94\x2d\x7b\xec\x6e\x8a\x36\x6c\x18\xc1\x93\x6d\xee\xc4\xbd\x6a\xd1\x11\x2e\x0e\x9f\x5d\x7a\xea\xac\xbc\x11\xd9\x5d\x34\x2f\xcf\xc9\xed\xab\x6b\xcb\x30\x8a\xa3\x87\xf0\x3a\xc0\xc4\xf8\x5a\x14\x6b\xb3\x98\x04\x6e\x5f\x5d\x07\x2a\x8b\xa9\xe1\x81\x11\x56\xeb\xf7\xde\x04\xe5\xe3\x35\x05\x76\x1c\x40\x8f\xad\xca\x22\x24\xa2\x0c\x58\xf1\x5d\x52\x52\x30\xa5\x59\x86\x63\x6d\x62\xb0\x41\x5e\x1d\x71\xe7\x8f\xca\x4b\xfe\xb1\x96\x22\xfb\xc7\x4e\xfc\x5a\xf7\xef\x52\xe3\x68\xeb\xb8\xca\x82\x9d\x26\xe7\xbd\xd2\x2d\xe1\x75\x06\x9d\xa3\x2d\x2c\x71\xf8\x89\x5a\x8e\x68\x86\xf9\x35\x74\xec\x12\xef\xf4\x9a\x71\x96\x63\x68\x04\x05\xed\xce\x5d\xcb\x31\x90\xad\x7b\xe1\xbe\xe5\x18\xea\x97\x30\x76\xe7\x8e\xe5\x18\xc9\xb6\x4d\x96\xe3\x71\xf4\x08\x96\x63\x29\xe9\x8d\x16\x65\x14\x9c\x9d\x65\x15\x15\x65\x37\xa3\x73\x21\x69\x1c\x98\x5d\x0b\x80\x83\xbc\xa2\xae\x69\xbf\x7f\x7d\xcc\x3a\xcc\x25\xba\x70\x35\xef\xc4\x6b\x40\x93\xc5\xf6\xf9\x2f\xd8\x9a\x72\xaa\xd4\x05\x42\xe3\xaa\xd2\x3a\x29\x3d\x99\xce\x09\x2b\x2a\x49\xcf\xcd\x4a\xd3\x55\x69\x7b\xc9\x07\x96\xea\x33\x8b\x41\xb9\x65\x45\xb5\x6d\xef\x5e\xa3\x16\xfd\xd7\xc7\xd8\x7c\x76\xe3\xd8\xbe\xa4\xe1\xcd\x99\x32\x49\xd4\x92\x62\x4b\x46\xfa\x89\x69\x65\x07\x2a\x29\x51\xde\x95\x7e\x11\xea\xe2\x36\x12\x9a\xc0\x0a\x4a\xa2\x14\xcd\xfd\xb5\x41\x07\xf2\x69\x07\x78\x2d\xf2\x93\x13\xd5\x7d\x8c\x27\xe7\x85\x24\x19\x85\x92\x4a\x26\x72\xc0\xda\xd9\xb9\xb8\xe7\x30\xa3\x0b\xc6\x7d\x6f\x00\xee\x44\x9a\x41\xd7\x07\xde\x98\xb0\x34\x00\x48\x55\xf7\xbd\x9d\xc2\xc7\x5e\x5f\x4e\x7f\xad\x25\x2a\x9d\x89\x56\x5b\xbb\xd9\x3d\x0f\xe0\xd8\x22\x49\x31\xe7\x1e\x8f\x79\x45\x8a\x62\xd3\x8a\x15\x4f\xce\xae\xbc\x84\x7e\xac\x85\xff\xc2\x30\xb5\xe6\xb0\x86\x72\xec\x1e\xd0\xee\x54\xf8\xcb\x26\x49\x49\xb6\x0c\x4b\x57\x48\xd0\xdd\x03\x94\xa0\xbb\x09\xba\xbb\x97\x12\x74\x37\x41\x77\x13\x74\x37\x41\x77\x13\x74\x37\x41\x77\x47\x52\x82\xee\x1e\xa2\x04\xdd\xdd\x4b\x4f\x32\x34\x91\xa0\xbb\x09\xba\x7b\x34\x25\xe8\x6e\x82\xee\x8e\xe3\x9b\xa0\xbb\x5e\x94\xa0\xbb\x0f\x52\x82\xee\x86\x50\x82\xee\xfa\x52\x82\xee\x8e\xa6\x04\xdd\x4d\xd0\xdd\x00\x4a\x00\x0c\x0f\x4a\xd0\xdd\x08\x17\x87\xcf\x2e\x3d\x13\x74\x37\x41\x77\x8f\xa4\xe4\x1f\x6b\x29\x41\x77\x03\x28\x41\x77\x0f\x52\x82\xee\x26\xe8\x6e\x00\xaf\xa7\x67\x39\xd6\x10\xd1\x6b\x29\x66\xa1\xc5\x47\x91\x87\xc2\xfe\xd4\xa9\xf4\x68\x00\x86\x69\x2f\x7e\x09\x84\x57\xb5\x60\x68\x6f\xbb\xdb\xd8\xa5\x3e\x02\xc9\x93\x77\x1f\xb7\xd4\x47\x1f\xf9\x9a\xbf\xde\x98\xa5\x27\x80\x5e\x0b\xc6\x29\xed\xc1\x28\x05\x8a\xf0\x2d\x7c\x52\x8d\x30\x0a\xe0\x38\x88\x4d\x0a\x1c\xe5\x0e\x2e\xa9\x46\x16\x45\x78\x73\x04\x60\x76\x51\x45\x81\xa1\xee\x0e\x1e\xa9\x8b\x28\x0a\xe0\xda\xc1\x22\xed\xa2\x89\x42\x56\x4a\x0f\x21\x89\x1c\x10\x26\xe4\x86\xd5\x43\x11\x0d\xe0\x80\x02\x78\x23\x82\x28\x32\x06\x68\x10\xff\x13\x66\xc4\x0d\x60\x7f\x6a\xf4\x4e\xc8\xc4\xb6\xb8\x9f\x2e\x72\x27\x64\x0b\x34\x98\x9f\x6d\xd4\x4e\x90\x1f\x20\x8f\x8d\xd8\x89\x11\x1f\x0d\x8e\x8d\x06\x9a\x6b\x2e\x57\xe6\x76\x29\xa9\x5a\x8a\xc2\x53\x15\xf4\xd4\xc0\x3b\xc6\xd9\xaa\x5a\x19\x99\xa3\x8c\xdc\x66\xeb\xc0\x44\x1e\xd5\x40\x36\x31\xfe\x69\x03\xab\xde\x1a\x0f\x25\x8a\xa4\x39\x72\x37\x5b\x0c\xab\x9a\x2f\xc9\xda\xdf\xde\x55\x55\x96\x51\x9a\xd3\xbc\xe7\xdc\x83\xdf\x4e\xeb\xb9\xf0\xe4\x6b\x7b\x3d\x32\x05\x2f\x42\x2c\x8c\x90\x6b\xc1\x5c\xc8\x15\xd1\xc8\xe3\xb7\xbf\xf1\xe0\x10\x04\x00\x7b\x14\xf0\x57\x74\xe0\x57\xb0\x19\x17\xe6\xd0\x0a\x70\x66\x85\xdb\x8f\x61\x4e\xac\x61\x80\x57\x98\x8e\x1b\x02\x77\x85\x71\x7c\x04\x60\xd7\x20\xa8\xab\x0b\x7f\x0a\xb3\x74\xc3\x00\x5d\x91\x60\x9f\xc1\x40\xae\xc7\x01\x71\x0d\x03\xb8\x50\xba\x84\x18\x17\x7d\xf0\x56\x38\xfc\xea\x49\x98\x16\x8f\x01\xb9\xda\x85\x5b\xb9\xc9\x0a\x73\xe5\x36\x50\xab\x78\x50\xa9\x48\x30\xa9\x18\x10\xa9\x60\x78\x54\x38\x34\x2a\x16\x2c\x2a\x06\x24\x6a\xa7\xa1\x61\x84\x1d\x04\x75\x0f\xba\x28\x20\xe3\x58\x2e\xd4\x28\x10\xa8\xc7\x9d\xae\x18\xd0\xa7\x08\xf3\x15\x06\x79\x7a\x1c\xb8\x53\x4c\xa8\x53\x8c\x29\x0a\x0a\x54\x3d\x0e\xbc\x69\x10\xda\x04\xde\x49\xe0\xb0\xed\xee\x9a\x76\xc3\x4b\x01\x4c\xb7\x20\x4d\xdd\xd0\x52\x00\xd7\x06\xce\x14\x37\xac\x14\x18\x52\x8a\x15\x4e\x8a\x14\x4a\x7a\x24\x00\x52\x28\xf8\x68\x18\x78\x64\x6c\x90\x80\x0d\xb1\x03\x3a\x6a\x61\x43\x01\x5c\xbb\x3e\x89\x30\xc8\x50\xe0\x82\x32\xce\x34\x23\xc5\x6b\x5a\x90\xcd\x0d\xcd\x04\xcf\x3d\xad\x89\xad\xb6\xbb\x2e\x64\x3e\x07\x65\x99\x7a\xbe\x9f\xf5\x04\xf5\x0b\x3e\x2c\x89\x02\xd7\xff\xcd\x93\xab\xab\x1e\x52\x87\x2f\x9d\x61\x8a\xb1\x47\x3b\x1f\xda\x3f\x9e\x35\xb2\x34\xc3\xbd\x90\x77\x85\x20\xb9\xba\x28\x85\xfd\xbf\xb6\x30\x43\xa7\x22\x83\x1d\x61\x48\x49\x86\xcf\xe9\x72\xb2\x75\x2f\xe2\x6d\xaf\x3f\x8a\x7b\x10\x73\x4d\x39\x9c\x32\x5e\xef\xb0\x33\x5f\xef\x53\xe3\x6c\x6a\xfd\x99\x8d\xd3\xd0\x9f\xe7\x8b\xe7\xf5\xc0\x1a\x97\x63\x90\x61\xf6\x25\xbb\x1c\xd1\x19\xab\xd4\xd3\xf4\x68\xbb\xc1\x3d\x96\x4b\xdb\xb1\x9f\x57\x85\x15\x66\xbe\xfe\x1b\x74\x86\x3b\x07\x79\xdf\xa7\xed\xb9\x2d\xa0\xe9\xaa\xff\x02\xdf\xbc\x91\x86\x84\xe7\xe0\x6a\x7e\x79\x73\xee\x6e\xf8\x2f\x7a\xeb\x06\x42\x69\x1f\x0b\x46\xbb\x17\x42\x6b\x81\xb0\x9e\x5c\x77\xe0\xb3\x2d\x08\xd6\x97\x63\x1f\x3a\xdb\x05\xc0\x06\x8c\xb1\xd1\x90\x01\xe0\xd7\x14\x23\xf0\xfb\xee\x5e\x90\x2b\x86\x0b\x02\x4c\xe2\x2d\x80\x6b\xac\x5c\xf0\x7e\x1e\x78\x28\x50\xfa\xc9\xdc\xf6\x6b\x48\x6a\xa8\x6f\x2c\xdd\xf6\xd3\x6d\xff\x00\x3d\xc2\x6d\x5f\xb3\x15\x15\x95\x7e\xb2\x17\xce\xfb\x25\xcb\x96\x5d\x5b\x90\xad\xbc\x55\xb5\xa8\xf4\x96\xbd\xe6\x86\x18\x11\x8a\x90\x6e\x9d\x5b\xe4\x17\xd3\x18\x70\xa8\x5a\xf1\xd8\xe0\x89\x3d\x5e\xa4\x75\x5c\x34\x58\x59\x20\x0a\x08\xbc\x7e\x7f\xf3\xe3\xdb\xcb\xff\x7c\xf3\xd6\x47\xd0\xdc\x2e\x99\xb2\x2a\xb3\x16\x5f\x15\x67\x7f\xab\x28\x90\x95\x30\xb6\x60\x11\x34\x54\x75\x8e\x8e\x90\xce\x2f\x3c\x8b\x33\xc5\x04\x62\x7b\x89\x31\xa3\xd8\x3c\x04\x4c\x3f\xfa\x60\x78\x3c\x41\x64\xba\x5f\x2c\xda\x3b\x06\xbd\x05\x2c\x76\xa3\x37\x93\x03\x92\x96\x92\x2a\xca\x3d\x2d\x35\x02\x9c\x6a\x23\x93\xac\x1d\xc2\x38\x10\x50\x8c\x2f\x8a\xc0\x9c\x96\x40\x1b\x3f\xc4\xc2\x9f\xb4\x23\xbf\xf6\x33\xf4\x43\xcd\xfc\xde\xf3\x7d\x8d\x91\x41\xa3\x73\x1e\x96\xac\x67\x4b\xde\x09\x45\xeb\x68\x5c\x29\xf2\x13\x05\x57\xfe\x68\x0f\x92\xe7\x92\x2a\x2c\xac\xcd\x54\x6b\xcf\x19\x0d\xc9\xfc\x2b\xbd\xe0\x5e\xb4\xe1\xb4\x73\x78\x0e\x7f\x80\x4f\xf0\x07\x34\x39\x7f\xef\x6b\x19\xc6\x30\xeb\x42\x1d\x1a\xf6\xf6\x77\x75\x1d\x65\x47\xfc\x79\x49\x34\xf2\x83\xab\xeb\x10\x48\xd7\x8c\xf1\xdc\x2a\xda\x4f\x9a\x4a\x4e\x8a\xfa\x42\x12\x36\xd3\x01\x86\xaf\x79\xa9\x27\x7f\x70\x6c\xf2\xfa\xd5\xdc\x9b\x63\x63\x91\x9c\x83\xee\x1d\x1d\x6f\x8e\x78\xe4\x06\x8f\x8e\x37\x4b\x7b\xe4\xe0\x6a\x8e\x1e\x86\xf7\x4e\x53\x30\xd5\x19\xbd\xff\x94\x36\x6f\xbd\x22\x3a\x5b\xf6\xd5\x9a\xff\x05\xf0\x9d\x39\x12\x1d\xe3\x29\x17\x68\x3a\x04\xd5\x0b\x35\x43\xfd\xb2\x05\x4f\x08\xd0\xa8\x77\x9e\xae\xe6\xdb\x3b\xd7\x7b\x56\xf7\x5d\xfe\x83\x8a\x91\x3a\x53\xbc\x53\x53\xbf\x14\xf9\x14\xde\x90\x6c\xe9\xcd\xd3\x4c\x5e\xde\xb1\x8f\x4a\x91\xdb\xc1\x2f\x89\x77\xe8\xc3\x58\x5e\x6e\xac\x86\xbd\x2b\xe6\x12\x9a\x32\x65\x45\xb7\xd1\x0c\x19\xe1\x66\x6e\x25\x9d\x53\x29\x43\xb6\xbe\x80\xd9\x06\xf1\x3a\x2c\xa3\x81\x87\x20\x40\x27\x94\x52\x68\x91\x09\xef\x7c\xfe\xed\x7c\x57\x64\x86\xd3\x1d\xe2\xb4\x6f\xe3\x38\xdf\xbe\xbe\x3e\x87\xdb\x57\xd7\xe7\x20\x24\xdc\xbc\x0a\x41\x15\x74\xfd\x15\xcf\x6e\x5f\x5d\x3f\xfb\x0c\x93\x2e\x29\xc9\x59\x4a\x2f\x1e\xa6\x94\x5e\x7c\x1c\xa5\xf4\xe2\x3e\xa5\xf4\xe2\x00\x9e\x29\xbd\x38\xa5\x17\x5b\x4a\xe9\xc5\x29\xbd\xd8\x93\x52\x7a\xf1\xe1\xc1\xa5\xf4\xe2\x2f\x16\x30\x95\xd2\x8b\x0f\x53\x82\x0e\xa5\xf4\xe2\x94\x5e\xbc\x43\x29\xbd\xf8\x73\x9b\x16\x29\xbd\x38\xa5\x17\xd7\x94\xd2\x8b\x47\x50\x4a\x2f\x1e\x47\x29\xbd\xf8\x20\x3d\x31\xc0\x71\x4a\x2f\x4e\x80\xe3\x63\xf9\x3c\x3d\xc0\x31\xa4\xf4\x62\x3f\x4a\xe9\xc5\xe3\x29\xa5\x17\x8f\xa3\x94\x5e\x3c\x9e\x67\x4a\x2f\x6e\x29\xa5\x17\xa7\xf4\xe2\x2f\x74\xeb\xa6\xf4\xe2\x94\x5e\x3c\x4c\x29\x46\x90\xd2\x8b\xc7\x51\x4a\x2f\xf6\x67\x9a\x6e\xfb\xfe\x7c\x9e\xde\x6d\x3f\xa5\x17\xa7\xf4\xe2\x83\x14\x62\xba\x49\xaa\x44\x25\x33\x1f\x15\xd9\xdb\x57\x1f\x6b\x3e\x8f\x09\x4c\x86\x37\x31\xb2\x97\x15\xe2\xd3\x54\x69\x06\x2a\xdb\x61\x17\x92\x92\xdc\x27\x62\x69\x5e\x34\xc3\xd0\x69\xab\x42\xbf\x28\x0c\x75\xc1\x56\xcc\x27\xb5\x18\x76\x84\xcb\x5b\xe4\xd4\x06\x4a\x03\x70\x2e\x2b\xf2\x09\x6f\x46\x64\x25\x2a\xae\x8d\xbc\xca\xc4\xaa\xf4\x47\xd2\x76\x57\x1a\x37\x66\x57\x16\x04\x60\x05\x0e\x49\x90\x4c\xf0\x39\x5b\x54\x92\x98\x29\xba\x58\x11\x4e\x16\x74\xe2\x5e\x65\xd2\x0c\x6a\xd2\xec\xce\x8b\xcf\x64\xa5\x93\xbc\xc6\x97\x5e\x07\x9b\xcd\x25\xd1\x9a\x4a\xfe\x12\xfe\xeb\xf4\xaf\xbf\xfe\x69\x72\xf6\xd5\xe9\xe9\xf7\xcf\x27\xff\xf1\xc3\xaf\x4f\xff\x3a\xc5\x7f\xfc\xeb\xd9\x57\x67\x3f\xd5\x3f\xfc\xfa\xec\xec\xf4\xf4\xfb\x3f\xbd\xfb\xe6\xf6\xfa\xcd\x0f\xec\xec\xa7\xef\x79\xb5\xba\xb3\x3f\xfd\x74\xfa\x3d\x7d\xf3\xc3\x91\x4c\xce\xce\xbe\xfa\x95\xf7\x2d\x31\xc0\x0e\x89\x63\x85\x44\xb1\x41\x1e\xc1\x02\x71\x30\x93\x28\xe2\xe1\xa3\xe3\x15\x47\x40\x38\xd7\x49\x7c\x01\x51\x5f\x58\x31\x53\xb3\x1e\xb3\xbf\x37\x52\xac\x98\x36\xda\xc1\xa8\x35\xd2\x81\xf0\xfb\x72\xd4\xbd\x7e\xa7\x4e\xe4\xb2\x79\x08\x16\x9a\xa9\x2e\xc0\xba\x93\x91\x28\xf4\x92\xca\x7b\xe6\x1d\x18\x32\x37\x25\xde\xba\x35\x50\x08\x4e\x72\x3a\x67\xdc\xdb\x53\x82\xd6\xdc\x68\x43\x2e\x89\xe1\x24\x86\xc7\x70\x79\x4a\x62\x58\xd1\xac\x92\x4c\x6f\x5e\x09\xae\xe9\x27\x0f\xcf\x48\x3f\xde\xdb\xe7\xe6\x32\x56\x3c\xed\xde\x7b\x27\xd7\xbe\xf8\x3c\x42\x7c\x99\x6b\xc9\xd6\xac\xa0\x0b\xfa\x46\x65\xa4\x40\x51\x11\x43\xed\x5d\xee\xe1\xed\x1f\x33\xd1\x52\x14\x0a\xee\x97\xd4\x88\x67\x20\xe6\xdd\xd1\x1d\x95\x11\x5f\xa6\x0b\xc2\x38\xac\x8c\x4c\x2d\xeb\x81\x2a\xa3\x51\x38\x30\x6f\xdd\x67\x6e\x58\x5c\xd7\x83\x73\x35\x4d\x66\x42\x14\x2e\xed\xcc\x1b\x87\xdc\xcc\x00\xb3\x4e\x39\x2e\x7e\xe4\xf4\xfe\x47\x33\x72\xdf\xb1\xce\x0b\xb2\x80\x7b\x56\x14\x98\xab\x49\xf5\x4e\x27\x6a\xdf\x39\xa8\x5f\x3e\xf2\x26\xc0\x3c\xa3\x8a\x02\x29\xee\xc9\x06\xb7\x42\x9c\xf1\x32\xf5\x12\x5e\x9c\x61\xfe\x1a\x51\xd0\x8c\x37\x87\xdf\xf8\x86\x8d\x97\x44\xc1\xab\xcb\xeb\x1f\x6f\xfe\x72\xf3\xe3\xe5\xeb\x77\x57\xef\x43\x34\xab\xd9\x3d\xd4\x6b\x93\x67\xa4\x24\x33\x56\x30\x7f\x85\xba\x83\x45\xec\xb2\x0c\xb0\x8f\xf2\xfc\x22\x97\xa2\xb4\x6b\x28\x2b\xce\x19\x5f\x04\x89\x51\x4b\xaf\xfb\x4d\xf1\x6b\xa3\xd1\x6c\x6e\x5f\x07\xdd\xbc\xf7\xca\xb0\x90\x84\x1b\xc3\x76\xb6\x09\xc8\x1c\x6d\xe1\x2a\xb2\xe2\x9a\xad\xbe\xdc\x84\x64\x92\xc7\x4a\x46\xbe\xcc\x73\x9a\xc7\xd8\x5e\x4f\x11\x8c\xff\xaa\x7e\xad\x90\x2c\x14\x68\x0b\xb5\xc1\xf5\x87\x9b\xab\xff\x1d\x67\xb6\xc0\xcd\x58\x48\x50\x27\xdc\x7c\x34\xd2\x20\xd2\x4e\xfa\x48\x57\x62\x9d\xf6\xd2\x01\xfa\x99\xee\xa5\xc6\x92\x8b\x81\x23\xfa\x58\xf1\x8e\xac\xf6\x4e\xea\x6f\xc7\x04\x2b\x91\xd3\x29\x5c\x5b\x03\x89\xaa\x28\x3c\xbb\x65\x3e\x25\x05\xc3\x98\x6b\x46\x0a\x6f\x53\x93\xfe\xad\x62\x6b\x52\x50\x9b\xf4\x86\x65\x0d\xba\x25\xcb\x22\xe8\xe6\x39\x29\x54\x90\xd2\xf3\xb7\x89\x8c\x71\xfa\x4e\x54\x3c\x06\x66\xa7\xe1\x05\x39\xe5\x42\x07\xb9\xf6\xcc\x7b\xfd\x7f\xec\xbd\x0b\x73\x1c\xb7\xb5\x2e\xfa\x57\x50\x4a\x4e\x91\x4c\x38\x43\xc9\xc9\x71\x12\x9d\x54\x5c\x0c\x49\x39\xac\x48\x14\xaf\x48\xd9\x77\x5f\xc7\x3b\x85\xe9\xc6\xcc\x60\xb3\x1b\xe8\x00\xe8\x21\x27\xd7\xf7\xbf\xdf\xc2\x02\xd0\x8f\x99\xa1\xa5\x5e\x00\x45\xd2\x69\x9c\xaa\x63\x4b\xd9\x5e\x83\xc6\x63\xbd\xf0\xad\x6f\x01\xc7\x9c\x92\x19\x71\xe9\xbd\x28\x78\x72\xc0\xab\x75\x9f\x92\xae\x5b\x97\x08\xef\x82\xfb\x7d\xbc\x6c\xbe\xdd\xbd\x87\xd6\x3a\xea\xf3\xb7\x5c\xa2\x58\x78\x87\xfd\x7e\xc5\x68\x0e\xec\x36\x15\x35\x4b\x87\x5d\x2b\xa9\xbe\x41\xa7\xe1\x40\x8c\x8f\xe9\x7c\xc2\xd4\x91\xd2\x34\x8b\x71\x8d\x57\x7e\x73\x46\x4d\xad\x98\x8b\xca\x5c\x81\x1c\x13\x74\x56\x60\xd1\xc6\x91\x8a\xd4\xae\xdd\x7b\x51\xac\x3f\x48\x69\xde\x34\x0c\x24\x09\x2e\xcd\xf7\x3e\x82\x07\xf2\xbe\xd8\xd0\x6d\x09\x5c\xcc\x76\xae\x13\xd8\x68\x50\x56\xf1\x84\x29\xfe\x8c\xdb\xe3\xfe\x88\xaa\x4a\xd5\xe2\x58\x7f\xab\x64\x8d\xf4\x8c\xb6\x82\xb7\x6f\xcf\x4f\x41\xa3\xd7\x22\x22\x78\x61\xc2\xa8\x75\x25\xb9\x7b\x7f\x48\x9a\x2f\xf8\x68\x4d\xe2\xc6\xfd\xc7\x2a\xaa\x39\xa9\x85\x66\x66\x4a\xde\xd1\x35\xa1\x85\x96\x21\xc9\x81\x36\xb9\x97\x80\x52\xef\xe6\x11\xa7\x04\xc8\x0c\xd1\xc1\x25\x17\x64\x26\xcd\x72\x2b\x3d\x89\x67\x2f\xdc\x9e\x23\xb0\x26\x45\x81\xcb\x5b\xe2\x73\x2e\x36\xa7\x8a\xd5\xf8\xf4\x86\x69\x52\x29\x96\xb1\x9c\x89\x2c\xea\x7e\x25\x42\x91\x7c\xfd\x7b\xec\x0d\xbd\x90\xc2\x2a\xc9\x04\x77\xf4\x5c\xe4\x3c\xa3\xc6\x65\x21\x4d\x92\x04\x03\xe0\xd7\x7c\x66\x8b\x02\xa1\x8e\x55\x91\x48\xb1\xb5\x66\x0a\x1e\x08\x8d\xaa\x99\x3b\x58\x7f\xaf\x67\xac\x60\x06\xd2\x88\xf8\xc7\x2d\x9e\x53\xe3\xd8\xbe\x78\x49\x17\x8c\x50\x13\xd4\x00\x3e\xc7\xc4\x84\xb6\xe6\x14\x56\x92\x1b\x92\x4b\xd6\xd0\x54\x61\x93\x1d\x9a\x7c\x3c\x3f\x25\x2f\xc9\xbe\x5d\xc3\x03\xf0\x27\xe6\x94\x17\x78\xbe\x0a\x40\xd2\x6f\xf8\x3f\x7c\x1e\xa6\x8b\xb5\x5e\xe7\x5e\xf7\x11\xa9\x9c\xf9\x3a\x24\x42\x12\x5d\x67\xcb\xb0\xd6\xf8\x1c\x6c\x48\x17\xfb\xaa\x18\x80\x94\x78\x05\x8b\x94\xd8\xa8\xe5\xfb\x14\x2c\x76\x6d\x9d\xd0\x5d\x0a\x16\xfd\x54\x97\xdf\xa7\x60\xa3\x50\x7a\x4f\x5c\xc1\x46\x3a\x30\x1f\x35\x53\x89\xfc\x97\x8f\x4f\xdc\x7f\xe9\x86\xb8\x56\x57\xb6\x3b\x8b\x77\x10\x9c\x42\x2c\x99\xa1\x39\x35\xd4\xfb\x35\xb1\xbc\x9a\xdb\x3e\xd1\x78\xf9\x9e\xe6\xe5\x7b\x4c\xef\x46\xb3\xb7\x5c\xd4\x77\xae\x88\x23\xd5\x03\xd2\xd5\x19\x08\x85\x4b\x17\xb1\xc4\x70\x74\x69\x55\x15\xbc\xc5\xa0\x46\x75\x1b\x21\x8d\xe1\xec\x72\x93\xc7\x2b\x87\x10\xce\x80\xe1\x0c\xb0\x59\x1b\xb3\x52\x91\x4b\x2c\xba\x7b\x63\x11\x1d\x1c\x81\x66\xcb\x6e\x69\x85\xbd\xe4\xd8\xbb\x36\xaa\x86\x67\xa0\x1a\x1e\xf5\xe1\xaf\x60\x2b\x86\xa6\x52\xdf\x50\x0b\x6f\xad\x2c\xc2\x75\x38\xd6\x11\xaf\x07\x30\x2d\x52\xd0\x19\x2b\x9c\xe7\xef\x54\x44\x82\x1a\xb1\x68\xe5\x92\xe4\x99\x4c\xc9\x22\x15\x07\xc6\x07\x59\x40\x81\x08\x4d\xb0\xec\x76\x5a\xbf\xe0\x55\x07\x11\x69\x56\xfd\x7a\x5d\x25\x5b\x75\x78\x32\xf8\xe5\xae\x7a\x8d\x0e\x1c\xc8\xe6\xaa\xdb\x18\x24\xd5\xaa\x83\x63\xff\xcb\x5c\xf5\x5b\x2e\x72\x79\xab\xd3\x3a\x7c\xdf\x3b\xa1\xc1\x9a\x62\x4b\xbb\x35\x33\x86\x8b\x85\xee\x3a\x7d\xb4\x88\xc3\x5e\xba\xb1\xcb\xeb\x93\x55\x0c\xc7\xf8\x5c\x49\xc7\x17\xb2\xed\x95\x44\xa6\x5d\x6a\xed\x21\xfa\x1d\x2f\x0a\xeb\x43\x6e\x27\x9d\x77\x79\x51\x11\x6f\x7a\xa3\x17\xf5\xa9\xb1\x28\x35\x3d\x51\xf6\x23\x0c\xa7\xc5\x55\x85\xed\xeb\x41\x36\x2f\xde\xb7\xef\xae\x8e\xfb\x82\x23\xf4\x13\x07\xac\xa5\x72\x09\x5a\x2b\x99\xd0\xbc\xe4\x5a\xe3\xb3\x88\x76\xdc\xb2\xd9\x52\xca\x1b\xb2\x1f\x4a\x19\x16\xdc\x2c\xeb\xd9\x34\x93\x65\xa7\xaa\x61\xa2\xf9\x42\x1f\x79\xc5\x34\xb1\xeb\x85\xc5\x64\xc2\x97\x88\x82\x0b\xff\x66\x0b\xb1\x93\x30\x9a\x48\x7c\x07\x36\xd2\x2e\x49\xd6\xac\x36\x9c\xf8\x08\x91\xae\x57\x94\x03\x18\xee\xd8\xc8\x8b\xb8\x9a\x7e\x60\x81\x7c\x54\xbb\xbe\x7d\xe8\x2f\xa2\x48\x46\x3f\x71\xf0\x23\xd7\xcb\x35\x47\x71\x04\x14\x3e\x5f\x68\x7f\x23\x42\xe2\xc6\x49\xf1\xc9\xc2\xc7\x0d\x2b\x42\xa2\x36\xe1\x4e\x40\xc2\xd6\x8b\x8c\xba\xb2\x8d\x07\xd1\xa6\x7e\x3b\x49\xdc\x08\xd1\x9b\xe9\xdf\x26\x91\x1b\x21\x73\x13\x81\x9c\x24\x0d\x4c\x1e\x30\x15\x4c\x3e\x3b\x1d\x1c\xf1\x03\x7d\x87\x25\x91\x17\x40\xee\x4f\xfd\x44\x2a\xf4\x07\x73\x5c\x48\x32\xe7\x85\xc4\x5d\x7c\x4f\xe1\x35\xf6\x66\xdb\x1e\x63\x6f\xb6\xcf\x1b\x63\x6f\xb6\xfe\x18\x7b\xb3\xc5\x04\x03\x63\x6f\xb6\xb1\x37\x1b\x8c\xb1\x37\xdb\xd8\x9b\x0d\x39\xc6\xde\x6c\x9f\x9e\xdc\xd8\x9b\xed\xd9\xb2\xcd\x8e\xbd\xd9\x3e\x3d\x46\xde\xd5\xb1\x37\xdb\xd8\x9b\x6d\x6b\x8c\xbd\xd9\x1e\xdb\xb5\x18\x7b\xb3\x8d\xbd\xd9\xc2\x18\x7b\xb3\x0d\x18\x63\x6f\xb6\x61\x63\xec\xcd\xf6\xc9\xf1\xc4\xd8\xda\xc7\xde\x6c\x23\x5b\xfb\xe7\xca\x79\x7a\x6c\xed\x64\xec\xcd\x86\x1b\x63\x6f\xb6\xe1\x63\xec\xcd\x36\x6c\x8c\xbd\xd9\x86\xcb\x1c\x7b\xb3\xb5\x63\xec\xcd\x36\xf6\x66\x7b\xa6\x47\x77\xec\xcd\x36\xf6\x66\xdb\x3d\xc6\x37\x82\xb1\x37\xdb\xb0\x31\xf6\x66\xc3\x0b\x1d\xa3\x7d\xbc\x9c\xa7\x17\xed\x8f\xbd\xd9\xc6\xde\x6c\x9f\x1c\x31\xae\x9b\x36\x39\x47\x34\x20\x78\x18\x86\x41\x8f\x96\xed\xb0\x36\xcc\xea\xf9\x9c\x29\x70\xbb\x61\xa6\xa8\xc4\xcd\x6e\xc2\x4b\x47\xac\xb5\xe4\x98\xe3\xea\x51\x7e\x9a\x99\x43\x20\x43\xd4\xae\x04\x11\xa6\x88\x03\x3c\xf6\xa7\xe8\xc9\x2b\x80\x76\x5f\x31\x8d\x8b\xaf\xb9\x20\x67\xef\xdf\x4c\x13\x90\x2b\xc6\xf0\x12\xc1\x9a\xbc\x17\x59\x2c\xec\xbd\x3d\x64\x71\x1c\x21\x81\x1f\xc4\x9f\xb5\xac\x90\xda\x61\x6b\xdd\xe6\x65\x4b\x2a\x04\xc3\x50\xab\x39\x85\xc8\x0d\xa4\xdd\x66\x8c\x09\x22\x2b\x26\x5c\x65\x19\x25\x9a\x8b\x45\x81\xb1\x00\xd4\x18\x9a\x2d\xa7\xf6\xfb\x45\x38\x60\xbe\x2f\x43\x33\x6b\xcc\x55\x33\x8a\xd1\xd2\x1d\x34\xc5\x4a\xca\xdd\x74\x09\xcd\x94\xd4\x9a\x94\x75\x61\x78\x15\x31\x61\xa2\x19\x14\x2c\x6a\x57\x3d\x1b\x0e\x01\x41\x5d\x37\xcd\x1c\xd8\x13\x58\xf0\x9a\x35\xf0\xcb\x8b\x72\xc1\xda\xab\x06\x01\xfc\x21\x74\xa7\x2a\x2b\xb3\x26\xf6\x78\x60\xb6\x1f\x70\xff\x5c\x69\x43\xb2\x82\x43\x04\x07\xeb\xc0\xc0\x92\xc1\x9c\x31\x08\x60\x2a\x72\x2b\x59\xf8\x3d\xd2\x7e\x93\x44\x0e\x0e\x68\x85\x72\xf8\xa1\x98\x09\x3e\xd3\x5d\x26\x37\xdd\x9c\x6b\x1f\x50\x68\xd4\x44\x03\x2f\xb1\xbb\x5c\x61\x8f\xe0\x7a\xe5\x48\x82\xcd\xf0\xcd\x5e\x48\x67\xca\x11\xf7\x1f\xa8\x84\x7d\x56\xbc\x31\x01\x8e\x04\x38\x28\x48\xd4\xf7\x6f\x97\xb5\x05\x5a\x49\x30\x10\x08\x91\x1d\x93\x02\xd7\x54\xb0\x95\xb5\x5e\x2c\x63\x7c\x65\x9d\x70\x84\xc8\x9d\xf6\xe0\x8b\x9a\x03\x43\xd5\x82\x99\x93\xb0\x56\xb8\xfa\xc7\x3e\x89\xe7\xdc\xd9\xe1\x8d\xaa\xd1\x28\xa5\x00\x4b\x7f\x29\xf3\x2b\xa8\x17\x75\xdc\xa0\x28\xcd\xb5\xa3\xbe\xca\x2f\x81\xa3\x07\x4f\x24\x32\xd0\x15\xe0\xb8\x36\xbd\x87\x64\x17\x4f\x57\x34\x63\x9a\xec\x9f\x5f\x9e\x1c\x92\xcb\xf3\x53\x57\x19\x80\x90\x29\xe7\x1b\xee\x20\xdc\x35\xef\x34\x81\x4a\x43\xea\xd8\x5d\x9f\xcf\xb5\x2f\xb8\x40\xc8\xbc\x5d\x52\x03\x17\xab\xf3\xf9\x54\x59\xff\x80\x2a\xd7\x78\x0c\x39\xd1\x4a\xe6\x53\x72\x21\x0d\x6b\xc8\x65\x93\xf8\x2d\x10\x84\xfb\x6c\xa3\xd7\x5d\x8e\xc8\x1c\xeb\xd6\xa1\x82\x5e\xc3\x54\xc9\x05\x10\x9b\xbe\x63\x5a\xd3\x05\xbb\x44\x81\x58\xee\x4b\x91\x01\x8e\x25\xd8\x14\xb4\x35\x2e\x20\x4f\xd6\xc6\xa8\x6d\x25\xd1\x1e\xe6\x32\x77\x3e\x9a\x94\xee\xab\x9b\x9b\x77\xab\xb8\x31\xa8\x43\xcd\xb5\x6b\x3f\x00\xf8\xbf\x4d\x6a\x1a\xdc\x44\x3b\x55\x52\xe4\x5d\x98\xa8\x9b\xa0\xfd\x39\x1b\x6b\x8a\x1c\x95\xaa\x76\x60\xc5\x99\xe2\x6c\x4e\xe6\x1c\x8a\x91\xa0\x6c\xe6\xd0\xd1\xdd\x52\xcc\x6c\xa9\x20\x54\x6b\xa6\x60\x5d\x7d\xd9\x44\x58\xdf\x29\xf9\x1e\x47\x74\x3c\x63\xd6\x5d\x14\xae\x67\xb6\xe7\x76\x10\x32\x67\x84\xcf\xc9\x02\x0a\x74\x70\xf7\x9a\x0a\xf2\xfb\x97\x7f\xfa\x9a\xcc\xd6\x86\xf9\x0e\x0f\x46\x1a\x5a\x84\x09\x23\x84\x16\x4c\x2c\xec\x69\x77\x9e\x77\x9f\x63\x07\xcb\xf3\x3c\x63\xae\xe3\xb6\xe3\xed\x79\xf5\xd5\xcd\xac\x97\x5a\x41\x48\x3c\xca\xd9\xea\xa8\x73\x03\x26\x85\x5c\x4c\xc9\x09\x15\x56\xa7\xa3\xde\xff\xea\x2a\x07\xfc\xc0\xf0\xb4\x49\x5a\xc5\x25\x0b\x9e\xad\x63\x9d\x10\xcf\x24\x4e\x96\xf2\xd6\xb5\x17\x69\x7f\x07\xb1\x34\x41\xbb\xb4\xe5\xc3\x95\xac\xea\x02\x96\x8b\xbc\xe1\xa8\xb8\x0c\x34\x55\xad\xd9\x26\x19\xcb\x3d\xba\x1c\xa7\x1c\xc2\x34\x37\xf2\x19\x4e\x49\x44\x2c\x84\xf4\x4c\x06\xfe\x91\xb8\xa1\x02\x47\xd9\x3d\x42\xde\xd0\xa2\x98\xd1\xec\xe6\x5a\xbe\x95\x0b\xfd\x5e\x9c\x29\x25\x55\x6f\x85\x30\xf7\x98\xda\xe0\x6f\x59\x8b\x1b\xd7\x28\x3a\x7c\x7c\x21\x17\x44\xd6\xa6\xaa\x51\x49\x9c\xf9\xe6\x71\x6a\xd6\x64\x8e\x3b\x07\x4d\xa4\xeb\x63\xcb\xce\x4c\xd9\x1d\xc7\xbd\x60\xde\x72\xab\xc0\x04\x61\x76\x1d\x9d\x56\x6c\xbf\x1a\x17\xf3\x77\xd4\xd7\x57\x2f\x7f\xff\x47\xa7\x70\x89\x54\xe4\x8f\x2f\xa1\xb6\x1a\x15\xa5\x82\x2b\x00\xde\x1e\xd7\x44\x97\xb4\x28\xac\x63\x1a\xa7\x18\xed\x75\xec\x28\xc2\x46\xad\x7d\x51\xad\x66\x62\x15\xd8\x03\xe6\x70\xaf\xaf\xff\x0b\x12\xb8\xdc\x68\x56\xcc\x51\xc1\x75\xa1\x65\xdb\x00\x68\x0f\x62\xe2\x3d\xef\x8b\x18\x55\xa3\x54\xc0\xe3\x66\x45\x57\xb2\xa8\x4b\x76\xca\x56\x3c\xc3\xbc\x4e\xf7\xb6\xae\x27\x0b\x4f\x60\x50\x70\x0d\x0c\xed\xb3\x42\x66\x37\x24\xf7\xe2\xda\xea\x14\x8c\x17\xb2\x8e\x25\x5a\x8c\xa9\x25\x42\xd7\x10\xdd\xbb\xba\x6d\x05\x10\xea\x9d\x86\x92\x92\x56\x15\x17\x0b\xbb\xcc\x94\x28\x7a\xdb\x5b\x6c\x94\x4c\xab\x79\xb9\xe8\xa6\x9f\x30\x97\x21\x12\xe3\x11\x83\xf0\x98\xf8\xaf\x47\xfa\x1c\xe8\xf2\xa2\x58\x70\x48\x3b\x6b\xec\xfb\x75\xef\x98\xb5\xe2\x62\x29\x48\x2a\x90\xe1\xb8\x27\x12\x35\x5c\x20\x6d\x0a\xc3\xcd\xb3\x09\x7b\xed\x81\x8e\xa0\xd9\x32\x12\x8b\x1d\x88\x7e\xb0\x8f\x29\xe6\xea\xed\x9c\x68\xa0\x11\x25\x35\xa8\x64\x85\x1b\xdd\xfc\x25\x25\x15\x53\x9a\x6b\xeb\xa3\x7f\x07\x0a\xe8\xa4\xa0\x1c\xfb\xfe\xdd\x64\xf8\x2a\x89\xdd\xaa\x88\xe5\x76\x0a\x14\xba\xf5\xc5\x5a\xba\x4b\x99\x7b\x71\x60\x98\x20\x6d\x82\xca\x77\x6e\xa5\x59\x62\x99\x65\x92\xb9\x7f\x8f\x69\xea\xbe\x6b\x77\x2a\xde\xd2\x59\x29\x8d\xa9\x73\x92\xbd\xb1\x42\x4a\x7c\xbe\x06\x0e\xd6\xe2\xb9\xd9\xb7\x66\xd2\x49\x94\x24\x18\x36\xef\xab\xc4\x18\xb7\x36\x56\x6d\x1f\x1c\x97\xcc\x2b\x05\xb4\xd4\x36\xcd\xe2\x33\xb1\x53\x8f\xf9\x16\xe8\xd6\x6d\xcd\x54\xc9\xde\xeb\xbd\x47\x33\x72\x6e\x13\x95\xac\xe8\x02\x72\x07\x49\xf6\x72\x53\x28\x7a\x85\x72\xe6\xd2\x1a\x4c\x43\xda\x0c\xe4\xc2\xe3\x0b\xde\xf7\xf1\xb3\x62\x79\xcb\x09\xbe\x94\x40\x94\x92\xe2\xc8\xf9\x84\x89\x84\x48\xf9\x36\x82\xde\x80\x2a\x59\x8b\xdc\x83\x3a\x1a\x24\xd1\xbb\x8d\x85\xbd\xc0\x13\x11\x42\x9a\xc7\x91\x97\x43\xf7\x5c\x57\xef\xcc\x35\x99\x31\x43\x63\xdc\x88\x57\xd3\x57\x2f\x9f\xbf\xcf\x06\x6b\x92\xc8\x67\xbb\x68\x7c\x36\x67\xe5\x1e\x6d\x75\x42\x07\xe1\x24\x2b\xf4\xce\x3f\x49\x35\xad\x7e\xf1\x87\x26\xb4\xaf\x04\x51\xb7\x8a\x1b\x7f\x83\x6e\x79\x44\xbd\xe9\x3e\x24\x6d\x88\x54\x5d\x4e\xde\x83\x36\x97\x17\x11\x92\xc4\xb4\x20\x8e\xef\xe1\x47\x88\xae\x67\x4f\xce\xee\x3a\x03\xeb\x94\xea\xae\xf7\x54\xfc\x7a\x7b\xc9\xdb\x26\x18\x2d\xb1\x0b\x21\x7e\xf1\x82\xec\xbb\x5f\xd8\x73\xa4\x94\x07\x8f\x76\x3d\xfd\xb6\x9e\xdd\x55\xe8\x2e\x2b\xbd\xad\x3d\xbb\xab\xa8\xc8\x59\xee\x02\xfe\x08\xd7\x9a\x04\x16\xe6\x5d\x7b\x1c\x6f\x36\xf7\x74\x7f\x8f\xd1\x12\xbb\xee\xd9\x5f\xd9\x92\xae\x18\x50\x77\xf2\x82\xaa\x08\xf5\x64\x24\xb9\x72\x3b\x43\x66\xb5\x21\x4c\xac\xb8\x92\xa2\x64\x11\x4c\xe7\x2b\xaa\x38\x9d\x15\x8c\x28\x36\x67\x8a\x89\x8c\x69\xf2\xeb\xfd\xef\x8e\x3f\x40\xb5\x04\xbe\x9f\x02\x55\x8c\xb0\xb0\xeb\xb5\x86\x2a\xfb\x44\xb7\xb0\xf3\xd9\xd3\x8d\x0b\x84\x57\xd1\x1b\x17\x2f\xac\xb3\xbd\x01\xf8\x35\x10\x79\xb3\x5f\x76\x3d\xca\xda\xd4\xb4\x00\xf6\xd6\xac\xa8\x35\x5f\x3d\x86\xfd\xf5\x6c\xba\xa7\x1c\x71\xb3\x37\x58\x88\xdb\x4b\xb3\x45\xd1\x8b\xf9\xb0\x80\xb9\x4a\xd7\x63\xd1\xe3\x90\xf6\x74\xa8\x39\xeb\xf5\xca\x41\x3f\xca\x91\x92\x2f\x96\x90\x40\xc9\xa4\x98\xf3\x45\xad\x1c\x1f\x56\x2c\x92\x0f\x38\xfc\x1f\xef\x79\xce\x06\x1f\xc7\x05\xa7\x7a\x58\x18\xbe\xc5\x2e\xe8\x65\x40\x4f\x2d\xe1\xbb\x25\xd1\x61\xc0\x90\xf0\xbe\x63\xa7\xe4\x1e\xd0\xcf\x2f\x3d\x42\x35\xec\x20\x17\xff\xc3\xb2\xa1\x2f\xc0\x4d\x36\xad\x92\xf9\x9e\xf6\xe2\x01\x7b\xc5\xe7\x58\xd6\x73\xf0\xcf\xb9\x76\x74\xec\xd0\x43\x1b\x5e\x10\x85\x14\x13\x2b\xff\x82\x19\x7b\x3b\x06\x89\xac\x64\x3e\x88\xd3\x0e\x97\x8e\x43\x24\xe2\x76\xef\x35\x59\xca\x22\x77\x2c\xef\xfe\xd1\x68\xe0\x81\x9d\x31\x73\xcb\x98\x20\xe7\x97\xb0\xd7\x76\xd9\x00\xe1\xd8\xdb\xf1\x81\x32\xc3\xf9\x80\xe6\xf6\xc2\x35\x05\xe9\xe4\x96\xc3\xee\x0f\x94\x6a\xcf\xca\xb0\xe3\x81\xce\xe6\xe1\x93\x62\xcd\xfa\x45\x6a\xf8\xbf\x35\xfb\x10\x48\x14\xe8\x4c\xa2\x28\x19\xec\xc6\xe6\xb9\x42\xf5\x4f\x79\x94\x5c\x73\x84\x81\xe5\x55\x2c\x3e\xab\x59\xac\xf0\x26\xb6\xc4\x15\x61\x83\x62\x83\x83\xff\x05\x2d\xc8\xf9\xe5\x09\xda\x7a\xec\x7d\xf4\x90\x2f\x2b\x68\x6f\x4f\x13\x5e\x65\x2d\xd6\x79\xd8\x47\xb4\xf8\xdc\x80\x9e\x68\xa2\xe5\x21\x20\x3e\x5c\x88\xdc\x51\xfc\x51\xa6\x94\x08\x27\xc4\xfa\x56\x9e\x43\x15\x81\xf3\x06\x9c\x0c\x40\xbc\x7b\xeb\xab\x83\x74\xec\x12\x87\x82\x14\x67\xe2\x01\xa6\x14\x8a\x1b\x2a\xa9\x8c\x1e\xce\x78\xdf\x75\xcf\x9a\x12\xee\xd6\x2e\xa3\x08\x7c\x30\x49\x12\xfc\xae\x5f\x9e\x9f\xa6\x3b\xfe\x15\xcf\x9f\xed\xf1\x1f\x9a\xff\xec\xf3\xbc\xf5\x5a\xc7\x04\x71\x98\x6a\x99\x4b\x99\xdf\x13\x58\xb4\x4e\xc0\xe0\x57\xab\x70\x4c\x7d\xad\x1f\x25\xee\x31\x76\x92\xb3\x39\x17\xcc\x73\x75\x0e\x3f\x6f\x03\xb5\x2d\x84\x0b\x97\x75\x51\x5c\xb1\x4c\xb1\x61\x0f\xd6\xfd\x73\x77\xbe\x21\x29\x85\xeb\xde\xc9\x27\x00\x17\xb4\x17\xec\x1c\x30\x3d\x74\xc5\x9b\x5b\xe0\xb9\xff\xc0\x23\xa9\xea\xa2\x00\x8e\x1c\xb1\xc6\x1c\x0d\x58\x3f\xf7\xf2\xe0\xd0\x5f\x5c\x87\x3a\x2a\x57\x08\xda\x9c\x97\x81\xda\x96\x69\xd6\x7c\x70\x38\x2a\x15\xd5\xda\x21\x44\xb9\xc8\xf9\x8a\xe7\xf5\xc0\x75\xb5\x1f\x0b\x31\xa2\x67\xdd\x81\x57\x97\xc6\x33\x2b\x51\x9d\x02\xdf\x48\x45\xd8\x1d\xb5\x22\x0f\x9b\xda\x73\xaa\xe1\xa2\xe5\x32\xbb\x61\xea\x90\x0c\xce\xa7\x9f\xc2\x7f\x78\x02\x91\xb1\x6b\x43\x1d\xd6\x82\x2a\x7b\x97\x85\x54\x43\x43\xac\x81\x44\x08\x6d\x49\xc2\x91\xdb\xe3\x5f\xb9\xad\x5c\x73\xb1\x98\xc0\xdf\xd8\xc5\xf4\xb3\x9a\x48\x31\xa1\x13\xab\x0c\x9e\x7c\xc0\xf5\x56\x66\xb4\x78\x0f\x91\xc4\x87\x70\xbb\x42\xfa\x60\x68\x20\xc3\x84\xac\x17\x4b\x58\x54\x55\x52\xdf\x9a\x8b\x14\xcc\x40\x0f\x1c\x87\x87\x1d\x28\xd2\x11\xbd\xfb\x79\xe5\x3e\xe4\xe9\x76\x84\x1a\x7c\xeb\x09\xd6\xfa\x3d\x42\xd0\x85\x7b\xef\xdb\xe0\x3b\xe9\x34\x12\xf5\x2b\x89\xa2\xfd\x1a\x78\x5f\xe4\x8a\xa9\x15\x67\xb7\x47\xde\xd5\x9c\xdc\x72\xb3\x9c\xb8\xd5\xd3\x47\xb0\x05\x47\xbf\x82\x7f\x20\xe6\xe2\xc8\xc2\x8e\xf3\xdc\x3f\x45\xd7\x9a\xcd\xeb\xc2\x3d\xf2\xea\x29\xa1\x15\xff\x8e\x29\xcd\x25\xaa\xe4\xfc\x86\x8b\xfc\x90\xd4\x3c\xff\xe6\x0b\x15\xe6\x70\xc1\xdb\x82\xe0\x08\x8b\xfb\xd6\x5b\x49\xcf\xd4\xca\xff\xed\xae\x60\xab\xb9\x06\x7d\xce\x8c\x15\x52\x2c\x3a\x4c\xb6\xe0\xec\x9f\x0b\x6e\xb0\x12\x5d\xfa\x1e\xba\xc1\x41\x6a\x53\xaa\x1c\x8a\xc5\xb9\x35\x37\x12\x3f\x4f\xe8\x33\xd8\x29\x68\xb7\xa6\x9b\xf7\xe6\x09\xa5\x32\x03\x0b\x26\x02\x17\x98\x2b\x07\x08\x24\x8d\x46\x92\x25\x5d\xb1\xa6\xff\xd0\xc0\xba\x7e\xae\xc9\x92\x8a\x1c\xfe\xd3\x2c\x93\x2a\xf7\xeb\xcb\x4d\x53\x95\xef\xca\xb1\x86\xa6\x0b\x3d\x74\xd2\x5a\x6e\x2a\x36\xbf\x1e\x32\x87\xaa\x1c\xe8\x1c\xb4\xff\x7d\x08\x9a\x6a\xc1\xff\x55\x33\x42\x4b\x69\x1d\xa4\x88\x5e\xf8\x1b\xa7\x88\x94\x74\x0d\xde\x34\x2c\xed\xdb\xc0\x2f\x34\xec\x70\xb9\x46\x70\x87\xe4\x03\xa3\x39\xef\x90\xf5\x1e\x92\xb7\x7d\xf6\xde\x61\xc7\x40\x2a\x72\xe5\x28\x2e\xfd\x7f\xee\xaa\x7b\x14\xd3\xb2\x56\x19\xfb\xe0\x80\x71\xd6\x79\x1a\x76\x6c\xe5\x7c\xc7\x46\xd9\x1b\x62\xe8\x0d\x13\x2e\xa9\x6c\x8f\xc8\x50\x84\x67\x5e\x2b\xb8\x0f\xd9\x92\xe5\x35\x78\xb2\xb3\x35\x99\x5b\xff\xd0\xbf\x96\x2d\xf9\x62\xc9\x06\xa6\x7e\x7c\x9a\xe0\x08\x6a\x92\x5c\xdf\x54\x9a\x2d\x9b\x45\x00\xb5\x37\x6c\x59\x1b\x5e\x8f\xf6\x19\xaf\xa4\x77\x76\x55\xc0\x54\x51\x83\xa0\xc0\xf5\xf9\x44\x5d\x97\xc1\xde\xb9\x53\xdf\x3d\xa6\xe4\xad\xfd\x84\xe1\x7a\x8b\x56\x55\xc1\x83\xaf\xdd\x3f\xbc\x50\x7d\xe0\xdf\x61\x07\xc9\x9d\x53\xbd\xe4\x52\x6c\x29\x55\x92\xb9\xc7\x9a\xac\x56\xd6\x58\x0f\x74\x95\x67\x8c\xd0\x3c\xb7\xbe\x92\x22\x8a\x95\x72\x65\xb5\x62\xe4\xf3\x4f\x1c\x69\x98\x5d\xb0\x49\xc7\x7f\x7e\xfa\x4e\xf1\xb1\xa7\x2b\x72\xdb\x9e\x6d\xd8\xd1\xc1\x2e\x2c\x75\x0e\x70\xe8\x1c\xa5\x6a\xd1\x96\xad\x58\xab\xfa\x65\xdc\x50\x1c\x86\x17\x81\xbf\xc5\xfb\xbb\x54\x2d\x62\xdf\x17\xf6\x8e\xd5\xa2\x06\x75\x1c\xfc\x96\xb6\x75\x3b\xc6\xed\xb5\xca\xde\x85\xad\x2e\xb6\xdf\xdb\xd3\xe4\xe4\xdd\x69\x80\x17\x22\x24\x72\x9f\xe1\xf4\x1c\x6a\x95\x92\x2b\x0e\xed\x07\xbf\xf3\xb0\x09\xcc\xa3\xf4\x4e\xa0\x45\x0f\x30\x81\x90\xba\x0b\x62\xb1\xa7\x7b\x58\x09\xdc\x93\x3c\x6d\x21\x22\x59\xa3\x99\xac\x35\x29\x56\xb8\x27\xf4\x5e\x98\x18\xb2\x0e\x5c\x54\xb5\xc1\x23\x96\x9a\xbc\xb1\xc8\x96\x54\x2c\x1c\x94\x94\x45\x02\x59\xf4\x5a\x18\x7a\x67\xbf\xda\x8a\x66\x3a\xa3\x15\xcb\x7d\xf9\x30\xc9\x65\x8d\xdb\xfe\x5f\xff\xfa\x90\x70\xf6\x9a\xfc\xba\x33\xb9\x29\x39\xf3\xd2\xdb\xc3\x81\x5d\x05\xc7\xbc\x34\x6b\x0f\xd3\x21\x51\x6c\x41\x55\x5e\xe0\x9a\xec\xc8\x39\xb9\xed\xd0\xd9\x35\x87\x81\xdd\x71\x6d\x34\x41\x51\xce\x08\x69\x76\xd9\xb9\x8e\xed\x42\x08\xfd\x19\x6b\x67\xa8\xbe\xb1\xb6\xcd\xea\xe1\x49\x4e\x0d\x9d\x74\x8c\xc5\x91\xcb\xda\x4e\x7c\x93\xe5\x09\xf5\x4a\xa9\x35\x83\x47\xbf\x52\xb5\x10\x36\x30\xa6\xcd\xff\x15\x17\x13\x3a\x81\x96\xbc\xd8\xc8\xf3\xf9\xbc\x68\xa2\xbb\x97\xf7\xb5\xfd\x59\xa3\xdc\xdd\xb7\x03\xe3\x10\xe2\x4b\x9a\xb8\xb4\x31\xcc\xbe\x35\x72\xab\xff\x31\xaa\x3e\x58\x8c\xb3\x8b\xeb\x0f\xff\x75\xf9\xfe\xfc\xe2\x3a\x18\x8e\x60\x06\x30\x52\xef\x33\x1c\x71\x37\xfd\x3e\xc3\xd1\x9a\x81\x18\x20\xd2\xa6\xe1\xe8\x9b\x01\x8c\xe4\x6d\xc3\xd1\x37\x03\x98\x95\xdd\x36\x1c\x3b\xcc\x00\xd2\x8b\xe8\xae\xef\x4e\x33\x80\xd2\xce\x1d\xc3\xb1\xdb\x0c\x20\xa4\x6e\x1b\x8e\xbe\x19\x40\xdd\xaf\x6d\xc3\xd1\x31\x03\x48\x93\xbf\x6d\x38\xba\x66\x00\x21\x74\xb7\xe1\x18\xcd\xc0\xe7\xfc\x28\xca\x0c\x30\xb1\x8a\x34\x01\x21\xeb\xd9\x51\x2e\xcd\xb9\x40\x91\x9c\xf5\x9a\xcc\x76\xe8\xfb\x52\x1c\xaa\xe7\xb1\x9f\x7d\x98\xbd\x58\x7d\x47\x15\x51\xac\x52\x4c\x43\x5c\x85\x2c\xeb\xd8\xb5\x41\xc4\x0b\xc5\x51\x17\x12\x42\x5b\xc4\xf0\xb3\xab\x8a\x7d\xa4\xba\xd6\x64\x35\x64\xdd\x87\xa5\x94\x55\x03\xd3\xa6\xdd\x10\x25\x27\xff\x3c\x3f\x3d\xbb\xb8\x3e\x7f\x73\x7e\xf6\xe1\xd1\x0a\x57\xa2\x1a\xb9\xf6\xdd\xd5\x34\x9e\x9a\x1b\x3f\xef\xaf\xa1\xc5\xba\x5e\x06\x6c\xc5\x65\x0d\x10\x77\x00\x9f\xa4\xdc\x5f\xbd\xa5\x5b\xd1\x22\x81\x07\x5a\xac\xa1\x41\x2b\xcf\xd2\x1e\x43\x3d\xdd\x99\xa9\x40\xcb\x4d\xea\xa8\xba\xf1\x33\xee\x2a\x5a\x66\xd2\x6c\x87\x1b\xf7\xe7\x3c\xf0\x1b\x9f\xda\xe5\x75\xe3\x67\x1d\xdf\x98\x9d\xbf\xc7\xfd\x45\x8b\xfc\x99\xec\x09\x5a\x66\x70\x9e\xfb\xd5\x4f\xe8\x46\x48\x69\xd4\xee\x1b\x25\xcb\x24\xaa\xf7\xca\xbd\x54\x79\x68\x13\x7a\x91\x76\x39\x31\x7b\x7a\x38\x38\xaf\x3f\x3a\x69\x2b\x9f\x1a\x08\x2d\x5b\xd0\x22\xad\x3c\xa0\x39\x8c\x33\x9b\x51\x2d\xf4\x53\xf4\x9d\x77\xd5\x50\xef\x68\xf5\x77\xb6\xfe\xc0\x22\x7a\x25\x6d\x9e\x07\x56\xb0\xcc\x3a\xb3\xe4\x86\xe1\x8b\x27\x89\x7f\xc9\x25\x27\x61\x9a\x31\x4d\xa6\x12\x2c\x39\x89\xee\x37\xe7\xc6\x24\x72\x59\x52\x6c\xbd\x1d\x37\x0c\x5d\xce\x1f\xc6\x56\x0b\xfd\xd8\x0d\x27\x21\x4a\xb4\x27\x28\x66\xbf\x49\x9a\x6e\x71\x6e\xc4\xf8\xf5\x61\xec\x44\x8e\xc5\xaf\x55\x17\x79\x06\x69\x95\x68\x91\x4f\x04\x87\xd6\x1f\xbb\x51\x69\xd1\x62\xd3\xa0\xda\xfa\x23\x06\xe3\xd6\x1f\xc9\xce\x6f\x00\x86\x27\x3d\xc3\x0e\xf3\x1f\x7f\xdd\xbb\xfe\x56\xa3\xea\xa3\xa5\x3a\x4e\x58\xab\x8f\x02\xc4\x2a\x5a\xa4\x0f\xd8\x92\x6c\x6a\x0c\x87\x07\x09\x07\x37\xa5\xcd\xde\x6b\x8c\x76\xd4\xf7\x39\x2e\xa0\xa6\x9f\x65\xfe\x3a\xb4\x93\x88\x53\x01\x25\x33\x34\xa7\x86\x4e\xad\x36\x39\xec\xff\x11\xe0\xc6\x71\xd7\xb6\x91\x57\xd0\x19\x2b\x74\xe7\x07\xc0\x79\x74\xd0\xfd\xb8\x9f\xd0\x15\xcb\xa6\x42\xe6\xec\x02\xbe\x00\xfe\xe8\x43\xeb\x63\x07\x45\x83\xff\x21\xee\x37\x80\x09\x7d\xea\xaa\xfa\x0e\xc3\x1f\x2b\x99\x9f\x5f\x26\x11\x0c\x92\x74\x44\xfb\xd6\x27\xe6\x86\xc1\x61\x45\x72\xe7\x85\x91\xca\x19\x6b\x2d\x50\x52\x25\xed\x65\xc6\xab\x53\x77\xa3\x75\xb6\x64\x25\x8d\x8a\xf2\xc2\x78\x13\x16\x9f\x70\x1d\xd1\xe1\xa4\x3f\xb8\x00\x36\x7b\x1b\xff\x27\xe9\x5b\xec\x86\x0d\xd6\x57\xaf\x5e\x3c\x19\x77\xb4\x39\xb7\x49\x8f\x0a\xec\x45\x22\x97\xd4\x99\x81\xc6\x91\x4f\xb2\xaf\xcb\x4e\x65\x29\x39\xbe\x3c\x8f\x16\xba\x72\x77\xe3\x49\x6c\x6b\x80\xfb\xbe\x79\xa2\x76\xbd\x81\x23\x6f\xb2\x3e\xc7\x1d\x41\xe0\xe0\x08\xb2\xb5\xeb\xcb\x10\x77\x5f\xa9\xc8\x03\xa4\x5a\x93\x7d\x27\x70\x9a\x55\x75\x9c\x01\xf4\x72\x4a\x56\x4a\xb5\x3e\x0c\x7f\x6c\xda\x85\x4d\xb4\x91\x8a\x2e\x22\xcd\x77\x98\x36\x4c\xb7\xfd\x93\xfb\xd1\x64\x8b\xb2\x3d\x6b\x7c\xf6\x99\x78\x04\x77\x83\xa6\x0e\xde\x1e\xaa\xf3\x4e\x3b\x9e\x94\x97\x10\x8e\xe7\x13\x70\x12\xb2\xb8\xd6\x86\xfd\xd1\x57\x13\x27\xd1\x0f\x46\x61\x40\xb2\xa4\x59\x7b\x64\x93\xbb\xfe\xf0\xbc\xdc\x87\xb8\x0a\xe7\x5d\x03\xea\x2c\xc4\x8a\xac\xa8\x42\xb6\xd6\x6e\x47\x32\xbb\x9e\xf3\x15\xd7\x32\x52\xa5\xde\x57\x99\x9f\xc4\xae\xfb\xa6\x3b\xae\x06\x35\x95\x53\xc9\xee\x2a\xe8\xc1\xda\xd8\x81\xf8\x1c\x4c\xde\x7d\x67\x79\x85\xa7\x99\x73\xa3\xa2\xc6\x30\x25\x5e\x93\xff\xde\xff\xc7\x6f\x7f\x9a\x1c\x7c\xb3\xbf\xff\xc3\xcb\xc9\x9f\x7e\xfc\xed\xfe\x3f\xa6\xf0\x2f\xbf\x39\xf8\xe6\xe0\xa7\xf0\x87\xdf\x1e\x1c\xec\xef\xff\xf0\xf7\x77\xdf\x5e\x5f\x9e\xfd\xc8\x0f\x7e\xfa\x41\xd4\xe5\x8d\xfb\xd3\x4f\xfb\x3f\xb0\xb3\x1f\x3f\x53\xc8\xc1\xc1\x37\xbf\x8e\x9c\x38\x15\xeb\xf7\x51\xae\x04\x01\x0d\x18\xdf\x45\x7e\x5b\x5a\x82\xeb\x42\xc8\xdd\xa4\x4d\x4f\x4e\xb8\x30\x13\xa9\x26\x4e\xf0\x6b\xe0\x85\x4d\xe2\xf2\xa4\xd5\xb3\x1f\x12\xd8\xa4\xfe\xfc\x5a\x37\xfb\x49\x28\x32\x57\xa6\xff\xb4\x5f\x94\xdc\x1c\x7b\xec\x62\xd1\xef\x03\x90\x86\xfa\xa5\xf8\x3c\xe3\x03\xd5\xcf\x8d\x90\x0c\x71\xa7\x28\x5d\x94\x3b\x57\xb2\x0c\xdd\x01\x00\xa2\x05\xec\x84\xd1\x62\xfd\x3c\x6f\x18\xfa\xbd\x3a\x8c\xf1\x41\x0d\x33\xc6\x07\xb5\xb8\x31\x3e\xa8\x0d\x1b\xdd\x07\x35\x47\x10\x35\xbe\xa6\xed\x1a\x4c\xac\x70\x10\xa8\x9d\x18\xf9\x90\xc3\xea\x34\xaa\x45\x7c\xdb\x4e\xa4\xfd\x36\x60\x1e\x21\xd9\x1b\xbf\x16\x77\xda\x56\x63\x61\xd3\x1b\xe5\x6e\x2c\x31\x39\x2e\x0a\xc2\x05\xd6\x78\xc1\x24\x43\x65\x90\x62\x2e\x9d\x14\x58\x61\x57\x38\xf8\xe9\xed\x92\x6d\x2c\x21\xb0\x1f\x1a\xaa\x0c\x17\x0b\xcc\x72\x42\x77\x15\x70\x47\x43\x81\x0c\x17\xa4\xac\x0b\xc3\xab\x82\x91\x88\x40\xd6\xc1\x0e\x8b\x9a\x11\xaa\xb5\xcc\x38\x0d\x95\x73\xf0\xbf\x14\x14\xc5\x2c\xea\x23\x05\x58\x55\x43\x6f\x00\x85\x9c\xb1\x9c\x89\x8c\x4d\xc9\x77\xf6\xd7\x30\x16\x25\x9c\xa4\xd9\xda\xee\xcd\x99\x58\x35\x35\x53\xb5\x2b\xd3\xc1\x1c\x2a\xbb\xa2\xbb\xe7\xf9\x9f\x5b\x24\x62\xd5\x94\x07\x59\xb6\xb5\x22\x28\xcd\x09\x7e\x6b\x93\xc9\xa7\x50\x8e\x23\xe7\x2d\xee\x02\x55\xd5\x13\x17\xb9\xc4\x46\x0b\x0d\x8a\x31\x22\xe0\xdc\x0a\x13\x9a\x05\x89\xe9\xee\xe4\xc2\x02\x70\xeb\x91\x32\x9e\x08\x50\x34\xd6\x5d\xbf\x97\x35\x2d\x32\x41\xd3\x75\xd3\x9f\x9e\x9b\xfd\x00\x2e\xf6\x0e\xf7\xda\xb9\xc7\x51\x52\x63\x5d\xeb\x24\x6e\x75\x0a\x97\x7a\x97\x3b\x1d\x51\x06\xdb\x8e\x1e\x36\x2d\x89\x0b\x1c\xef\xfe\xc6\x03\xc9\x2a\xc5\xe6\xfc\x2e\x89\xce\x3c\x6e\xd9\x67\x09\xcf\x99\x30\x7c\xce\x63\x5a\x02\x4b\x3b\xb9\x8a\x09\x00\x11\x00\x21\x96\xf5\x0b\x22\x9b\x10\xb5\x40\xf2\xa7\x56\x06\xe7\x52\x34\x29\x0d\xd8\x55\xaa\xe4\xd4\x68\xbd\x46\xeb\x35\x5a\xaf\x4f\x8d\x27\x6f\xbd\xbc\x3e\x08\x21\xfb\xe3\x9a\x1f\xe0\x6e\x89\xa5\xa7\x39\xed\x30\x87\xc1\x1d\x47\xa7\x6b\x23\x98\xaa\x51\x89\x98\x6e\xcf\xd4\xc6\x6a\x1a\x49\x68\x51\xc8\x5b\x84\x44\xa0\x9d\x54\xa4\x60\x2b\x56\xf8\x70\x88\x94\x54\xd0\x05\x70\x67\xe2\x22\x98\xd0\x80\x4b\x2a\x62\x15\x8e\xe2\x39\xdb\xec\x7c\x85\xe2\xd7\x11\x24\x30\x18\x82\x38\x25\x8b\x82\x29\x4d\x0a\x7e\xc3\xc8\x29\xab\x0a\xb9\x1e\xce\xf7\xe9\x06\x74\x6f\x33\xd4\x58\x35\x75\xc5\x0c\x06\xa7\x1c\xd3\x45\x26\x50\xf2\x3b\x8e\xd9\xd8\xc3\x0d\x0c\xff\xc0\x21\x4f\x2a\x47\x5a\x4b\xde\xa3\x1a\xf6\xca\x39\x39\x2e\x6e\xe9\x5a\x1f\x92\x0b\xb6\x62\xea\x90\x9c\xcf\x2f\xa4\xb9\x74\x49\x04\x8c\xc3\xd3\xad\x61\x75\xa2\x09\x9f\x93\xd7\x05\x35\x4c\x1b\x62\x28\x46\x89\x72\xdd\xed\xf6\x20\x55\x6f\x92\x6d\x47\xd7\x34\xdd\xf3\xe3\xe9\xe9\x41\x52\x43\x4e\x8f\x00\x10\x45\x1c\xb4\x22\x50\xf8\x46\x1e\xb1\x63\x47\xea\xeb\x28\x34\x1d\x47\x6c\xd0\x18\x98\x04\x23\x34\xd4\x08\x9d\x56\x21\x75\xc7\x05\x51\x4c\x57\x52\x68\x86\x53\x41\xad\xba\x69\xbe\xd9\x25\x80\xf5\xa3\xe6\x02\x91\xfe\x6c\x9c\x27\x5b\x49\x6d\x80\x2b\x19\xe7\x60\xf4\x95\xcb\x65\x10\x06\x04\xdc\xb4\x28\xd0\x8e\x00\x2f\x4b\x96\x73\x6a\x58\xb1\x26\x74\x6e\x98\x22\x34\x9a\x7a\xc2\xce\x49\x31\x1a\x18\xc7\x81\x57\x19\x78\xbd\x51\x54\xe3\xed\xd8\x4a\xff\xbb\x06\xf1\x74\x68\x4f\xc2\x76\x38\x58\xad\xa7\x47\xdf\x22\x1d\x47\x0a\xf5\x02\x5b\xb5\x0f\xde\x77\xd4\xe5\x24\x2d\x66\xa1\x5d\x80\x59\x21\xb3\x1b\x4d\x6a\x61\x38\xd6\xab\x77\xbd\x7e\xe4\x0d\xc9\x64\x59\x15\xa0\x3c\xe3\x28\x21\xc9\xcf\xd3\x42\xee\xd2\xc8\xcd\xbf\x4e\x1a\x25\x31\xb1\x73\xd2\x47\xbf\x6a\xff\x27\xf8\x0b\x5c\x8c\x10\x1d\xc3\xc6\x47\xb0\xec\x8e\x65\xf8\xb8\xa2\x77\xf5\xdf\x0b\x06\xa7\x36\xaa\xe9\x3a\x21\x52\x34\x85\x00\x73\x69\x9d\x56\xa0\x45\x8f\xeb\xc0\x4c\x36\x5a\x87\x9d\xdd\xb1\xac\xf9\x73\x4c\x28\x0b\x7d\x10\xb3\xd0\x31\xc5\x9a\x26\x3c\x0c\x26\x09\x48\x2b\x0d\x3c\x0a\x4d\xf2\xd9\x1d\x1b\x0d\x82\x41\x62\x0c\x33\x86\x1b\x4e\xd1\x38\x61\x05\x17\x48\xf3\xdf\x1d\x9e\x42\xb4\xdb\x9c\xa6\xb9\xdd\xb1\x00\x13\x2b\x6c\xab\x1f\x72\xa4\xcc\xd0\x7f\x33\xac\x42\xfc\x9a\x2a\x29\x0d\xd9\xdf\x3b\xda\x3b\xd8\x42\x03\x44\x82\x17\x5d\xdf\x49\xe7\xc0\x39\x62\x22\x3f\xeb\x48\xa9\x1c\x3a\xa8\x57\xd0\x3e\x9b\x65\x7b\xf9\x21\xe1\xb1\x40\x14\xcf\xce\xaa\x6a\x11\x4e\x42\x5c\x55\x13\x71\x4c\xb4\x87\x44\x4b\x62\x14\xcd\x79\x92\xea\x02\x90\x69\x27\x68\x54\xed\x9d\xec\xfd\xbd\x9f\xf6\x62\xcf\x29\x33\xd9\x01\xb9\x95\x62\xcf\xc0\x71\x9d\x92\xeb\xd8\x5b\x55\x6b\x16\xc8\x78\x0f\x81\x45\x5f\xb0\x78\x40\x8e\x24\xec\xae\x2a\x78\xc6\x4d\xb1\x06\xe7\x92\xc8\x3a\x76\xdf\x81\x6d\x9e\x9a\xc0\x1b\x7c\x76\x17\x7d\x92\x5c\x45\xb3\x35\x62\x2f\xc1\x15\x74\x0e\x67\xa4\x50\xaa\x49\xc1\x57\xec\x68\xc9\x68\x61\x96\xeb\xc1\x1d\x6c\xb6\x87\x90\x62\xf2\x6f\xa6\x24\x30\x1b\x0b\x2f\x37\x0e\xc5\x19\x03\x68\xe8\x0e\x34\xb8\x61\x7b\x32\x51\xb9\x57\xeb\x2f\x7e\xcb\x90\x71\x11\xd9\x6a\xe2\x7a\x7d\x7d\xf9\x2d\x33\xc9\x1c\x0f\x3b\xbb\x50\x7a\x07\xaf\x5a\x4c\xcd\xa5\x2a\x1f\xd9\x03\x89\x07\x89\x4f\xa0\x63\xec\x23\xbb\x40\x4b\xa9\x23\xf6\x9d\xec\x6e\xe0\x8b\x63\x0e\xed\x0e\xd7\x6f\x4b\xb0\xcc\xee\x78\xb2\x32\xf4\xb6\x53\x18\x39\xbf\x9c\x92\xff\x92\x35\x34\x4d\xa2\xb3\x28\x4f\xde\x8e\xd0\x3b\x45\x33\x43\x5e\xd8\x45\x78\x11\xf3\xd0\xea\x86\x3d\xf7\x7f\x63\x34\x77\x4d\x7c\xb4\x61\x14\xc5\xed\xdd\x8e\x44\xd0\xdd\xce\xbc\x52\x7a\xce\xb5\x36\xb2\x24\x4b\x27\x38\x7e\xa3\x3b\x24\xc9\x5e\x77\xc4\x22\xf7\xad\x5e\x73\xef\x0b\x9a\x28\x56\xa5\xb0\x76\xfe\x6b\x7f\x41\xd6\x68\xcb\x12\xb8\x93\x12\x29\x35\xc8\x9d\x31\x4d\x28\xc9\xe0\xa8\x44\x8b\x74\x8b\x6f\xcf\x8a\x27\x36\x8c\x96\xc8\x85\x3b\x24\xae\x13\x5b\x12\xbb\x1e\x5d\xcc\x44\x12\x15\x34\x91\x18\x52\xe8\xbe\x90\xe1\xad\xd3\xb6\x47\xaa\xfa\x28\x92\xa8\x92\x86\xec\x00\x90\x24\x10\xd9\x9c\x52\xf7\xd8\x99\x60\xf9\x49\xca\x1a\x0e\x12\x4b\x3f\xdd\x1d\x0f\xbf\x7c\x29\x0e\x1e\x49\xb7\x7e\x55\x34\xfd\xcc\x36\xf9\x8c\x6b\xcb\x88\x6b\x7b\xd4\x1d\xd2\x99\x4e\x50\x67\x9a\xa9\x15\xae\x60\xa2\x1d\xa9\x96\x4c\x62\x9f\x6f\xc2\xd8\xc1\x11\xaf\x88\xa8\xcb\x59\xb4\x91\x6a\x18\xdb\x94\x49\xbd\x0d\x9d\x36\x0f\x17\x29\xa6\x1a\x20\x2c\xc1\x41\xa2\x62\x11\x7b\x2f\x5e\xd9\x6f\xfe\xfa\x7f\xff\xef\xdf\xfd\xef\xa9\x5b\x56\xfb\x1b\x91\x32\x67\x8c\x50\x41\xce\x8f\x2f\x8e\xff\x79\xf5\xdd\x09\xb0\x67\xc7\x9d\xc2\x04\xc5\xfc\x29\x4b\xf9\x13\x16\xf2\x3f\x60\x19\x3f\x10\x96\x45\x6a\xf8\x3e\x2e\x0b\x04\xc6\x67\xb4\x6b\xed\x08\xb3\x7d\xa4\xe8\x9e\x0d\x13\x64\xb2\x6d\x4c\xdc\xe3\x19\x4f\x10\x38\x3c\xba\xf6\x34\x59\x75\x25\xb3\x9b\x64\x59\x9e\xbd\xeb\x93\x4b\x27\x30\x49\xa2\x87\x8a\xf0\xc0\xc4\xc5\x4a\x16\x2b\xbb\x99\x94\x5c\x9f\x5c\x46\x1a\x8b\xa9\x95\x01\x2f\xac\x2e\xef\xbd\x8e\xaa\xe4\x6c\xa8\x99\x3c\xb4\x93\x97\x55\x11\xf3\xa2\x4c\xa0\x57\x80\x62\xb4\xe0\xda\xf0\x0c\xe6\x5a\xa0\xfa\x4b\xf7\x87\xfd\x5e\x3c\x9e\x73\xcc\x8f\xb5\x23\x71\x7e\x6c\xef\x7d\xa2\xaa\xe7\x26\xd1\xd6\x49\x95\x45\x27\x4d\x0e\x7b\xa4\x3f\xf1\x0c\x95\x3e\xd1\x16\x57\x72\xfe\x44\x3d\x47\x70\xc3\x70\xad\x40\xbb\x43\x74\xba\x14\x79\xcf\x31\xf6\x05\x05\xfc\xce\x6d\xcf\x31\x52\xac\xff\xe0\xbe\xe7\x18\x9b\x97\xb0\x7e\xe7\x96\xe7\x98\xc8\xb7\x1d\x3d\xc7\xcf\x1b\x0f\xe0\x39\x56\x8a\x5d\x19\x59\x25\xc1\xd9\x39\x51\x49\x51\x76\x33\x36\x97\x8a\xa5\x81\xd9\xb5\x00\x38\x92\xd7\xa0\x8c\xa9\x88\x60\x56\x0d\xcf\x5c\xb2\x0b\x57\x43\x97\xec\x13\x70\x59\xb2\x65\x78\x55\x15\x4c\xeb\x23\x80\xc6\xd5\x95\x4b\x52\x22\x85\xce\x29\x2f\x6a\xc5\x0e\xed\x4e\xb3\x12\xf6\xea\x30\x96\xe4\xd1\x6e\x06\x13\x4e\x14\x33\x99\x83\x51\x78\xd4\x22\x7e\x7f\xac\xcf\xe7\x0e\x8e\xeb\x68\x1b\xdf\xd6\x2b\x53\x54\x2f\x19\x34\xf3\x64\x77\xdc\x68\x37\x51\xc5\xa8\x46\x73\x44\x03\xd4\xc5\x1f\x24\x70\x81\x35\xa9\xa8\xd6\x2c\xc7\x5b\x83\x0e\xe4\xd3\x4d\xf0\x52\xe6\x7b\x7b\xba\xfb\x33\x48\xc9\x0b\x45\x33\x46\x2a\xa6\xb8\xcc\x09\xb0\xae\xe7\xf2\x56\x90\x19\x5b\x70\x81\x8d\x00\xfc\x8d\xb4\x93\x0e\x17\xde\xba\xb0\x2c\x02\x48\x15\x3a\x26\x4f\xc9\x87\x5e\x47\x57\xbc\xd5\x92\xb5\xc9\x64\x6b\xad\xfd\xea\x1e\x46\x48\x6c\x91\xa4\xc0\xd6\x00\xd7\xbc\xa6\x45\xb1\x6e\xd5\x0a\x52\xb2\x27\x26\x31\x0f\xb5\xf1\xcf\x0c\x53\x6b\x2f\x6b\xac\xc4\xee\x05\xed\x2e\x05\x5e\x37\x29\x46\xb3\x65\x5c\x31\xc5\x08\xdd\xfd\xc4\x18\xa1\xbb\x23\x74\xf7\xde\x31\x42\x77\x47\xe8\xee\x08\xdd\x1d\xa1\xbb\x23\x74\x77\x84\xee\x0e\x1c\x23\x74\xf7\x53\x63\x84\xee\xde\x3b\x9e\xe4\xd3\xc4\x08\xdd\x1d\xa1\xbb\x9f\x3d\x46\xe8\xee\x08\xdd\x1d\x26\x77\x84\xee\xa2\xc6\x08\xdd\xfd\xd9\x31\x42\x77\x63\xc6\x08\xdd\xc5\x8e\x11\xba\x3b\x78\x8c\xd0\xdd\x11\xba\x1b\x31\x46\x00\x06\x62\x8c\xd0\xdd\x04\x81\xc3\xa3\x6b\xcf\x11\xba\x3b\x42\x77\x3f\x73\x8c\xf9\xb1\x76\x8c\xd0\xdd\x88\x31\x42\x77\x3f\x39\x46\xe8\xee\x08\xdd\x8d\x90\xf5\xf4\x3c\xc7\x00\x11\xbd\x54\x72\x16\x4d\x2d\x7d\x09\xe0\x28\x9e\xb9\x8c\x9a\xbd\x27\x31\xc0\xcb\x30\xb5\x29\x39\xe9\x63\xe6\xa0\xbf\x95\xa7\x8f\x44\xc8\xf5\x98\x50\x37\x47\xa0\xc6\x9c\xee\x60\xbb\x45\x08\x1e\x08\xe9\x0a\x84\xce\xfa\xa8\x92\xee\xff\x6b\x01\x5d\x1d\x24\x97\xcb\x4e\x62\xb9\x72\x1f\x85\x75\x15\x0f\xdf\xba\x17\xba\x45\x24\x8a\xc6\x99\xb4\x81\xfe\x26\x6c\xab\x0f\xbe\x42\xca\xee\x43\xb6\xfa\xc0\x2b\xac\xe7\x8f\x86\x6b\x3d\x01\xe0\x5e\x34\x44\xeb\x1e\x78\x56\xa4\xf5\xda\x80\x66\x05\x70\x55\x84\xc4\x9d\xb0\xac\xc8\x59\x6e\x41\xb2\x02\xa8\x2a\xc1\x97\x03\xf6\xb4\x0b\xa8\x8a\x7c\xe5\xef\x40\xb1\xba\x60\xaa\x08\xa9\x1d\x18\xd6\x36\x90\x2a\x66\xa7\xcc\x2e\x10\x95\xc7\x00\xc5\x04\x97\x3d\x00\xd5\x0e\x08\x54\x84\x6c\x00\x4f\x25\x86\x3f\xed\x84\x3e\xc5\xf9\xaf\x3b\x60\x4f\x01\xb8\x14\xb3\xb0\x2d\xe4\xa9\x0b\x5a\x8a\x39\x02\x0d\xdc\x69\x13\xb0\x14\x95\x02\xc9\x53\x83\x95\x52\x3c\x0d\x47\x3f\x0b\x47\x7a\xaa\xbe\x4c\xe8\x7a\xa9\x98\x5e\xca\x02\x69\x0a\x7a\x66\xe0\x1d\x17\xbc\xac\x4b\xab\x73\xb4\xd5\xdb\x7c\x15\x59\xc3\xa4\x1b\xb4\xaa\x73\x02\xe1\x4d\x19\x6d\xf1\x40\xa3\x28\x96\x83\x74\x7b\xc4\x80\xd0\x7d\x49\x57\x78\x57\x5f\xd7\x59\xc6\x58\xce\xf2\x5e\x5e\x93\xfc\x6e\x1a\xd6\x02\x29\xd7\x35\x48\xe5\x9a\xbc\x8a\xf1\x30\x62\x22\xa2\xb9\x54\x25\x35\x20\xe3\x77\x5f\x21\x24\x44\x61\xdf\x1e\x04\xf7\x96\x1c\xf3\x16\xed\xc6\xc5\xe5\xf2\x22\xf2\x78\xf1\xfe\x63\x5c\xfe\x6e\x37\xb6\x2d\xce\xc6\xed\xc2\xb5\xc5\x49\x7c\x00\x4c\xdb\x4e\x3c\x5b\x17\xf9\x15\xe7\xe9\xc6\x61\xd9\x12\x21\x5e\xa3\x31\x6c\x0f\x83\x5f\xdb\x8d\x5d\x03\xed\x12\xe3\x5c\xf4\x71\x6b\xf1\xc8\xb3\x27\xe1\x5a\x3c\x04\xda\x6c\x1b\x69\xe6\x17\x2b\x2e\x8b\xdd\xa0\xcc\xd2\xa1\xc4\x12\x21\xc4\x52\xa0\xc3\xa2\x91\x61\xf1\xa8\xb0\x54\x88\xb0\x14\x68\xb0\xad\x2e\xa0\x09\x4e\x10\x09\x8d\x1b\x93\xe0\xab\x53\x65\x8f\x93\xa0\xbf\x1e\x76\xb9\x52\xa0\xbe\x12\xac\x57\x1c\xda\xeb\x61\x90\x5e\x29\x51\x5e\x29\x96\x28\xea\x8d\xee\x61\x90\x5d\x3b\x51\x5d\x04\x5d\xff\x4e\x36\xd3\x5d\xd3\xee\xcb\x5a\x84\xd0\x0d\x34\x57\xf7\x55\x2d\x42\x6a\x83\xe4\x4a\xfb\xa2\x16\xf9\x9a\x96\xea\x25\x2d\xd1\x2b\xda\x03\x61\xaf\x62\x71\x57\xbb\x31\x57\xd6\x07\x89\x38\x10\x5b\x78\xab\x16\x31\x15\x21\xb5\x9b\x93\x88\x43\x4b\x45\x6e\x28\x17\xdc\x70\x5a\x9c\xb2\x82\xae\xaf\x58\x26\x45\x8e\xf4\x26\x36\x7a\x55\x7b\xb4\xc0\x9c\x68\x27\x14\xf9\x7d\x2e\x13\xd4\xe7\xba\x58\x52\x4d\xf0\x6f\x97\xa4\x25\x4e\x09\xcf\xa3\xde\x31\x25\x14\x1e\x1f\xed\x7a\x20\x9f\x2f\xc9\x93\x7b\xc2\x24\x4f\x22\xe5\xe4\x28\x3f\xd2\x1d\xaf\xbf\xc9\x5b\x22\xe7\x86\x09\xb2\xcf\x45\x38\x61\x07\xd8\xec\x53\x93\x6c\x6a\xf3\x99\x4d\xd2\x10\x2f\xf3\xd5\xcb\x30\xb1\x26\xe5\x18\xe5\x98\x3d\xe7\x94\x23\x24\x63\xb5\x7e\x9a\x19\x6d\x3f\xb9\x87\x4a\x69\x7b\xf1\xf3\xba\x70\xca\x0c\x9b\xbf\x81\x64\xb8\x4f\x90\xf7\x73\xda\xc8\x63\x41\xc8\x3b\xef\xe6\xbc\x82\x2f\x6f\xb4\x21\x15\x39\xf1\x74\x67\x68\xc9\xdd\x03\xff\xac\x8f\x6e\x24\x8a\xf8\xa1\x10\xc4\xf7\xa2\x87\x1d\x06\x18\x29\x75\x0b\x39\xdc\xe2\x7f\xb1\x12\xfb\xa8\xe1\x2e\xf6\x37\x62\x8e\x6d\x57\x66\x3c\xee\x77\x7c\x23\xc0\xfd\xb7\xf7\xe2\x7b\xe1\xb9\x20\xc2\x25\xde\xc0\xf6\xa6\x2a\x83\xef\x97\xc0\xc7\x62\xc4\x9f\x4c\xb4\x1f\xd0\xb8\xb1\xb9\xb1\x31\xda\x1f\xa3\xfd\x4f\x8c\x07\x88\xf6\x0d\x2f\x99\xac\xcd\x93\x0d\x38\x6f\x97\x3c\x5b\x76\x7d\x41\x5e\xa2\x4d\xb5\xac\xcd\x86\xbf\xe6\xa7\x98\x10\x8a\x30\x46\x9d\x1b\x03\xf7\xa6\xb1\x23\xa1\x1a\xcf\x7e\xdb\x20\x64\x09\xd5\x84\x92\xd3\x8b\xab\x7f\xbe\x3d\xfe\xeb\xd9\xdb\x29\x39\xa3\xd9\x32\x4a\x34\x17\x84\x82\x65\x03\x15\xb6\xa4\x2b\x46\x28\xa9\x05\xff\x57\xcd\xb0\x76\x61\xbf\x99\xdf\x41\x12\x4c\x77\x84\x06\xb2\x36\x09\xa1\x1b\x7a\x9b\xf8\x96\x6b\x63\x37\x11\x64\x79\x9e\x31\x89\xca\x07\xce\x95\x2c\x37\x4d\xdb\x99\x15\xe6\x5c\x6f\xa4\x37\xb7\x64\x8a\x91\x05\x5f\x79\xe4\xb3\xc3\x80\x12\x9a\x47\xb0\xca\x59\x2d\x60\x2f\x8e\x0d\x0e\xe8\x0c\x00\x85\x4b\x46\x04\x33\xf6\xd2\x37\xa9\x4c\x1c\xba\xb2\x43\xfe\x4d\x6a\xcd\xf4\x21\x99\xd5\x00\x0e\xad\x14\x2f\xa9\xe2\x28\x08\x46\x67\xc2\xb4\x98\x92\x0b\x19\xc2\xa3\x35\x2c\x2d\x26\xdf\x64\xbd\x19\x58\xda\xd3\xf7\x67\x57\xe4\xe2\xfd\x35\xa9\x14\xf0\x04\x63\x91\x95\x20\x11\x8e\xc0\x8c\xd9\x59\xb9\x63\x94\x4f\xc9\xb1\x58\x63\xf7\xde\x19\x19\xae\x89\x8d\x87\x98\xb0\x62\xfd\xf3\x54\x8e\x4e\x3e\xbd\x78\x39\x85\xff\xf7\xc2\x9e\x21\x65\x5d\xb9\x06\xae\x1b\xa3\x68\x42\xd1\x88\x73\x0f\xf9\xac\x60\xed\x7d\xf0\x27\x0b\xe3\x2d\x25\xd3\x2f\x38\x54\x06\x1a\x8d\xb1\x01\xb1\xf7\xeb\x7a\x69\xcf\x88\x62\x95\x62\x9a\x09\x64\xcc\x42\x9b\x8b\x0a\x27\x0e\x14\xbc\xd5\x30\x45\x64\x61\x5b\x64\xb4\x1b\x13\xeb\x4e\xda\x99\x5f\xe2\x2e\x4a\x6c\xc0\xdb\xfb\x7d\xac\x5b\xbe\x33\xfc\x9a\xc7\x55\xec\x36\xf6\x28\x5c\xfc\x4a\xe6\x7b\x9a\x9c\xe3\x71\x4f\xfe\xd6\x4f\xc9\xf5\x92\xeb\x36\xb2\xb1\xbe\x22\xc7\xd3\x3d\xc1\x59\x74\x0f\xcb\x87\xe4\x25\xf9\x33\xb9\x23\x7f\x86\xe0\xeb\x6b\x6c\x8c\x94\x22\xc0\x89\x4d\xed\xb9\x3c\xc8\xf9\x65\x92\x13\xf1\xfd\x92\x1a\x90\x47\xce\x2f\x63\xc0\x8d\x33\x2e\x72\x38\x0a\xec\xce\x30\x25\x68\x11\x42\xf3\xb8\x95\x8e\x08\x01\xed\x47\x3d\xf9\x8b\xe3\x18\x2c\xce\xe7\x68\x89\x8d\x97\x7e\x48\x4c\xef\xea\xa0\x25\xc2\x95\xdb\x79\x75\xd0\x22\xdd\x95\x23\xe7\x73\xc8\xb5\x5d\x78\x4b\xc1\x75\x67\xf6\xf8\x25\x6d\xbe\xba\xa4\x26\x5b\xf6\xcd\x1a\x3e\x15\xf2\xce\x5e\x89\x96\x7a\x9f\xe4\x12\x72\xcb\x51\xa4\xc1\x76\xaa\xcf\x5b\xf1\xc4\x40\xee\x7a\xf7\xe9\x7c\xbe\x79\x72\xd1\xab\x7a\x5f\x1a\x2c\x8a\x91\xd8\x07\xa3\x9d\xc6\x1a\x95\xcc\x5d\xe4\x8b\x96\x69\x17\x2f\xef\xf8\x47\xbd\x00\x18\x6f\x39\xbb\x81\xb3\x67\x74\x8a\x2d\x1e\x74\xaa\xdb\x5a\x86\x8c\x0a\x57\x74\x3d\x67\x4a\xc5\x1c\x7d\x49\x66\x6b\x40\xae\xf1\x8c\x45\x5e\x82\x08\x9b\x50\x29\x69\x64\x26\xd1\xa4\x1e\x7d\x70\x9f\x17\x06\xcb\x1d\xf3\x7c\xd5\xbe\x68\x7e\x3c\xbd\x3c\x24\xd7\x27\x97\x87\x44\x2a\x72\x75\x12\x83\xaf\xe9\x66\xee\x5e\x5c\x9f\x5c\xbe\x78\xb4\x45\x27\x21\x2e\x7c\x8d\xa2\x09\xea\xa5\x71\x6d\xc8\x39\x29\x69\x35\xb9\x61\x6b\x84\x57\x1d\xeb\xd3\x4f\x9a\x13\x94\xe0\x33\xdc\xc2\x96\xb4\x1a\x28\x4b\x31\x9a\xf3\x27\xca\xdc\xe0\x6f\x78\x3b\xc7\x4d\x0a\x07\x84\x4c\xd0\x3f\xa5\x5c\xb1\xdc\x05\xef\xe1\x37\x98\xc8\x2b\xc9\x71\x11\xeb\xc8\x04\xf1\xe9\x31\x32\x41\x7c\xde\x18\x99\x20\xfa\x63\x64\x82\x88\x90\x39\x32\x41\x8c\x4c\x10\x6e\x8c\x4c\x10\x23\x13\x04\x72\x8c\x4c\x10\x9f\x9e\xdc\xc8\x04\xf1\x6c\xb1\xad\x23\x13\xc4\xa7\xc7\x88\xf2\x1c\x99\x20\x46\x26\x88\xad\x31\x32\x41\x3c\xb6\x6b\x31\x32\x41\x8c\x4c\x10\x61\x8c\x4c\x10\x03\xc6\xc8\x04\x31\x6c\x8c\x4c\x10\x9f\x1c\x4f\xac\x36\x64\x64\x82\x18\x6b\x43\x3e\x57\xce\xd3\xab\x0d\x21\x23\x13\x04\x6e\x8c\x4c\x10\xc3\xc7\xc8\x04\x31\x6c\x8c\x4c\x10\xc3\x65\x8e\x4c\x10\xed\x18\x99\x20\x46\x26\x88\x67\x7a\x74\x47\x26\x88\x91\x09\x62\xf7\x18\xdf\x08\x46\x26\x88\x61\x63\x64\x82\xc0\x0b\x1d\xa3\x7d\xbc\x9c\xa7\x17\xed\x8f\x4c\x10\x23\x13\xc4\x27\x47\x8c\xeb\xa6\x98\x96\xb5\xca\x30\x26\xb2\x7f\xae\x4e\x64\x59\xd5\x86\x91\x0f\x41\x60\x63\xf7\x11\xdf\x34\x5b\xbb\x82\xab\x8e\x76\x7c\x0c\xd8\x74\x26\xc5\x9c\x2f\x6a\x05\xc5\xf7\x47\x25\x15\x74\xc1\x26\x99\xfb\xd0\x49\xb3\x72\x93\x66\x96\x47\xcf\x0a\x3a\x5d\xf0\x92\x63\x18\x24\xc8\xd6\xde\xbf\x05\x49\xed\xfb\x68\x04\xbc\xa5\xa4\x77\x10\x10\xd1\x52\xd6\xc2\xb8\x3a\x01\x58\x6f\xa4\xcc\x66\x97\xdc\x3b\xb7\x0d\x09\xdb\x43\x10\x01\x11\x78\x02\x47\x87\xa4\x70\xce\x5b\x2e\x8d\xcb\x68\x6f\xb9\xa2\xc6\x30\x25\x5e\x93\xff\xde\xff\xc7\x6f\x7f\x9a\x1c\x7c\xb3\xbf\xff\xc3\xcb\xc9\x9f\x7e\xfc\xed\xfe\x3f\xa6\xf0\x2f\xbf\x39\xf8\xe6\xe0\xa7\xf0\x87\xdf\x1e\x1c\xec\xef\xff\xf0\xf7\x77\xdf\x5e\x5f\x9e\xfd\xc8\x0f\x7e\xfa\x41\xd4\xe5\x8d\xfb\xd3\x4f\xfb\x3f\xb0\xb3\x1f\x3f\x53\xc8\xc1\xc1\x37\xbf\x46\x07\x87\x11\xee\x47\x1a\xe7\x23\x89\xeb\xf1\x00\x8e\x87\x47\x97\x24\x51\x0f\x1f\xbc\xac\x34\x0a\xc2\x67\x4c\xd2\x2b\x88\x60\xaf\xa0\x82\x38\xcc\x19\x9f\x84\x94\x25\x37\x86\xe5\x90\x32\xea\xd0\x8b\x60\x71\xe0\xdc\xf4\x9a\x71\x7b\x95\x0b\x05\x46\x68\x08\x34\xd7\x5d\x5c\x75\xa7\x52\x56\x9a\x25\x53\xb7\x1c\xfd\x1e\x64\x03\x24\xd1\x66\x33\x40\x09\x4e\x72\x36\xe7\x02\x9d\x20\x01\x27\x6e\xb0\xff\x36\xaa\xe1\x51\x0d\x0f\x91\xf2\x94\xd4\xb0\x66\x59\xad\xb8\x59\x9f\x48\x61\xd8\x1d\x22\x21\xd2\xd7\xc2\x57\x5e\x1c\x91\xf0\x37\xd8\x3a\xa7\x4a\xe6\xa1\xaa\x4d\xd5\x02\x4a\xd7\x23\x5d\xaa\xcf\xb9\xc7\x95\x2c\x78\xb6\x3e\x0a\x4b\x02\x17\x96\xdd\x99\xa3\x07\x8b\x01\x0c\xd5\x37\xad\xfa\x60\x13\x1b\xf9\xb5\x5a\x62\x6b\x1e\xcf\xca\xf1\x07\x4f\xf8\x52\xf1\x15\x2f\xd8\x82\x9d\xe9\x8c\x16\xa0\x1f\x53\xd8\xfa\xe3\x7b\x64\xe3\xdf\x87\x8c\x92\x85\x26\xb7\x4b\x66\x6d\x12\xa1\xf6\xdb\x21\xf5\x96\x51\xac\xd0\x05\xe5\x82\x94\xf6\x18\x54\x61\xa2\xf6\x36\x58\x8b\x85\x36\xf8\x15\x55\x4c\x98\x30\x39\x4f\x30\x34\x93\xb2\xf0\x25\x76\x68\xcc\x75\xb3\x02\xbe\x96\x58\xc8\x7f\x0a\x76\xfb\x4f\x3b\x73\xec\x5c\xe7\x05\x5d\x34\x9c\x65\x9a\x99\x00\xf6\x8a\xa9\xc8\x26\xee\x54\xba\x8f\x4f\x7c\x08\xa0\xa6\xaa\x66\x84\x16\xb7\x74\x0d\x47\x21\xcd\x7c\xb9\x7e\x4d\x5e\x1d\x80\x1a\xa3\x9a\x34\xf3\xcd\xc9\x57\xd8\x27\xf2\x25\xd5\xe4\xe4\xf8\xf2\x9f\x57\xff\x75\xf5\xcf\xe3\xd3\x77\xe7\x17\x31\xee\x84\x3d\x3d\x0c\x75\xc8\x33\x5a\xd1\x19\x2f\x38\xde\x8b\xd8\xc2\x5d\x76\x45\x46\x38\x85\x79\x7e\x94\x2b\x59\xb9\x3d\x54\xb5\x00\x5a\xbf\x96\xff\x06\x9b\x49\xee\x66\x0d\x3b\x0c\x81\xf6\x70\x63\x93\x91\xf3\xde\x27\x93\x85\xa2\xc2\x7a\xf3\x90\x99\x8a\x78\xed\xf6\xd0\x1c\x55\x0b\xc3\xcb\xe7\x5b\x7c\x4d\xf3\x54\x85\xd7\xc7\x79\xce\xf2\x14\xc7\xeb\x29\x16\x1e\x9c\x84\xcf\x8a\xa9\xb8\x21\x2d\x6b\x22\xb9\x7c\x7f\x75\xfe\x7f\xa7\x59\x2d\xe2\x57\x2c\xe6\x01\x2b\x01\x67\x8b\x92\x55\xa2\x93\xf4\xc1\xb3\x77\x8c\x67\xe9\xe7\xc6\x2f\xf4\x2c\x35\x9e\x5c\x0a\xcc\xd4\x87\x5a\x74\x74\x35\x9a\xc0\xa0\x9d\x13\x29\x65\xce\xa6\xe4\xd2\x39\x48\x4c\x27\x91\xd9\xa1\x8d\xa3\x8a\x11\x2b\x58\x18\x4e\x0b\xb4\xab\xc9\xfe\x55\xf3\x15\x2d\x98\x2b\xf0\x03\x0a\x87\x2e\x7f\x60\x02\xdb\x3c\xa7\x85\x8e\x32\x7a\x78\x9f\xc8\x3a\xa7\xef\x64\x2d\x52\xe0\x93\x1a\x59\x24\x67\x42\x9a\xa8\x7c\xa6\xfd\x2e\x20\x7c\x54\x32\x23\x2e\xa7\x19\x05\xc5\x0e\xd8\xbc\x8e\x53\x05\x0e\x1c\x9e\x34\x99\x38\x17\xdc\xef\xe3\x65\xf3\xed\xee\xed\xb7\xd6\x51\x9f\xbf\xe5\x12\xc5\x42\x59\xec\xf7\x2b\x46\x73\x60\xf2\xa9\xa8\x59\x3a\x9c\x5e\x49\xf5\x0d\x3a\xf7\x08\x62\x7c\x4c\xe7\xb3\xc4\x8e\x80\xa7\x59\x8c\x6b\xbc\xf2\x9b\x33\x6a\x6a\xc5\x5c\x54\xe6\x8a\x01\x99\xa0\xb3\x02\x8b\xac\x8e\x54\xa4\x76\xed\xde\x8b\x62\xfd\x41\x4a\xf3\xa6\x61\x5b\x49\x70\x69\xbe\xf7\x11\x7c\xff\x61\x37\x22\xd0\x02\x88\x5c\x3e\x81\x8d\x06\x65\x15\x4f\x0e\xe3\xcf\xb8\x3d\xee\x8f\xa8\xaa\x54\x2d\x8e\xf5\xb7\x4a\xd6\x48\xcf\x68\x2b\x78\xfb\xf6\xfc\x14\x34\x7a\x2d\x22\x82\x17\x26\x8c\x5a\x03\x13\x5a\x8a\xb6\x0f\xa4\x9b\x2f\xf8\x68\x4d\xe2\xc6\xfd\xc7\x2a\xaa\x39\xa9\x85\x66\x66\x4a\xde\xd1\x35\xa1\x85\x96\x21\xc9\x81\x36\xb9\x97\x80\xc8\xef\xa6\x62\xa7\x04\x98\x45\xd1\xc1\x25\x17\x64\x26\xcd\x92\x6c\x88\x8d\xa0\x12\xdd\x9e\x23\x30\x44\x45\x01\xe9\xdb\xce\x1c\x5c\x6c\x4e\x15\xab\xf1\xe9\x0d\xd3\xa4\x52\x2c\x63\x39\x13\x59\xd4\xfd\x4a\x84\x98\xf9\xfa\xf7\xd8\x1b\x7a\x21\x85\x55\x92\x09\xee\xe8\xb9\xc8\x79\x46\x8d\xcb\x42\x9a\x24\x09\x06\xc0\xea\xf9\xcc\x16\x05\xf2\x20\xab\x22\x91\x62\x6b\xcd\x14\xbc\x8a\x1a\x55\x33\x77\xb0\xfe\x5e\xcf\x58\xc1\x0c\x96\x6c\x91\x04\x06\x68\x6a\x1c\xb3\x19\x2f\xe9\x82\x11\x6a\x82\x1a\xc0\xe7\x98\x98\xd0\xd6\x9c\xc2\x4a\x72\x43\x72\xc9\x1a\x4a\x2e\x6c\xb2\x43\x93\x8f\xe7\xa7\xe4\x25\xd9\xb7\x6b\x78\x00\xfe\xc4\x9c\xf2\x02\xcf\xcd\x01\x55\x03\x1b\xfe\x0f\x9f\x87\xe9\x62\xad\xd7\xb9\xd7\x7d\x44\x2a\x67\xbe\x0e\x89\x90\x44\xd7\xd9\x32\xac\x35\x3e\x07\x1b\xd2\xc5\xbe\x02\x08\x70\x34\x5e\xc1\x22\x25\x36\x6a\xf9\x3e\x05\x8b\x5d\x5b\x27\x74\x97\x82\x45\xbf\x4f\xe6\xf7\x29\xd8\x28\x44\xe2\x13\x57\xb0\x91\x0e\xcc\x47\xcd\x54\x22\xff\xe5\xe3\x13\xf7\x5f\xba\x21\xae\xd5\x95\xed\xce\xe2\x1d\x04\xa7\x10\x4b\x66\x68\x4e\x0d\xf5\x7e\x4d\x2c\x87\xe8\xb6\x4f\x34\x5e\xbe\xa7\x79\xf9\x1e\xd3\xbb\xd1\xec\x2d\x17\xf5\x9d\x2b\x58\x49\xf5\x80\x74\x75\x06\x42\x49\x16\xb7\xc4\x70\x74\x69\x55\x15\x1c\x18\x25\x37\x6a\x28\xa2\x0c\x67\xb7\x51\x40\xbc\x72\x08\xe1\x0c\x18\x4e\x5a\x14\xd2\x3a\x78\x36\x66\xa5\x22\x97\x58\x24\xfb\xc6\x22\x42\xb2\x83\xf5\xda\xe4\x4d\xe1\x92\x63\xef\xda\xa8\x1a\x9e\x81\x6a\x78\xd4\x87\xbf\x82\xad\x18\xba\xaf\xc1\x66\xf7\x41\x2b\x8b\x70\x1d\x8e\x75\xc4\xeb\x01\x4c\x8b\x14\x74\xc6\x0a\xe7\xf9\x3b\x15\x91\xa0\x1e\x2e\x5a\xb9\x24\x79\x26\x53\xb2\x48\xc5\xf7\xf1\x41\x16\x50\x0c\x43\x13\x2c\xbb\x9d\xd6\x2f\x78\xd5\x41\x44\x9a\x55\xbf\x5e\x57\xc9\x56\x1d\x9e\x0c\x7e\xb9\xab\x5e\xa3\x03\x07\xb2\xb9\xea\x36\x06\x49\xb5\xea\xe0\xd8\xff\x32\x57\xfd\x96\x8b\x5c\xde\xea\xb4\x0e\xdf\xf7\x4e\x68\xb0\xa6\xd8\x32\x76\xcd\x8c\xe1\x62\xa1\xbb\x4e\x1f\x2d\x8a\x04\xa0\xa1\x5d\x5e\x9f\xc7\xc6\x62\x9f\x72\x42\xd3\xcf\x6d\xaf\x24\x32\xed\x52\x6b\x5f\x97\xd0\xf1\xa2\xb0\x3e\xe4\x76\xd2\x79\x97\x17\x15\xf1\xa6\x37\x7a\x51\x9f\x1a\x8b\x52\xd3\x13\x65\x3f\xc2\x70\x5a\x5c\x55\xd8\x1e\x26\x64\xf3\xe2\x7d\xfb\xee\xea\xb8\x2f\x38\x42\x3f\x71\xc0\x5a\x2a\x97\xa0\xb5\x92\x09\xcd\x4b\xae\x35\x3e\x8b\x68\xc7\x2d\x9b\x2d\xa5\xbc\x21\xfb\x01\x7d\xbd\xe0\x66\x59\xcf\xa6\x99\x2c\x3b\x40\xec\x89\xe6\x0b\x7d\xe4\x15\xd3\xc4\xae\x17\x16\x93\x09\x5f\x22\x0a\x2e\xfc\x9b\x2d\xc4\x4e\xc2\x68\x22\xf1\xed\x10\x49\xbb\x24\x59\xb3\xda\x70\xe2\x23\x44\xba\xc6\x6d\x0e\x60\xb8\x63\x23\x2f\xe2\xf8\x0b\x80\xf1\xf2\x51\xed\xfa\xf6\xa1\xbf\x88\x22\x54\xfd\xc4\xc1\x8f\x5c\x2f\xd7\x08\xc6\x91\x6d\xf8\x7c\xa1\xfd\x8d\x08\x89\x1b\x27\xc5\x27\x0b\x1f\x37\xac\x08\x89\xda\x84\x3b\x01\x09\x5b\x2f\x32\xea\xca\x36\x1e\x44\x9b\xfa\xed\x24\x71\x23\x44\x6f\xa6\x7f\x9b\x44\x6e\x84\xcc\x4d\x04\x72\x92\x34\x30\x79\xc0\x54\x30\xf9\xec\x74\x70\xc4\x0f\xf4\x1d\x96\x44\x5e\x00\xb9\x3f\xf5\x13\xa9\xd0\x1f\xcc\x71\x21\xc9\x9c\x17\x12\x77\xf1\x3d\x5d\x59\x92\x96\x7e\x57\x1d\x59\x84\x87\x27\x6c\xc4\x57\x85\x47\x6f\xbb\xa3\x8e\xb4\xb2\xa1\x82\x2b\xd6\x81\x78\x93\xff\x1b\x77\xd6\xfb\x2d\x60\x85\x74\xb5\xad\x1d\x26\x4b\x84\x4c\xdf\xd3\x2b\x27\xb5\x30\xbc\x08\x88\xa6\xb2\x2a\xac\xe7\xd2\x9b\x3d\x72\xc6\x20\xb1\xd3\x35\xf0\xb0\x59\x9e\x98\xe6\x86\x9e\x0b\xf4\x90\xfc\x4f\xad\x0d\xa1\x4d\x49\x51\x20\xb4\x83\x9d\x44\x08\x0f\x5c\x7b\x80\x8f\xf3\xad\x5c\x81\xcf\xde\x48\xfb\x11\x2b\x9e\x63\xa4\xe6\x7c\x3e\x67\xa1\xa8\x6a\xc6\x48\x45\x15\x2d\x99\x01\xb8\x2b\x16\x23\x31\x63\x0b\xee\x6a\x4e\xe4\x9c\x50\xbb\xa0\x7b\x7b\xba\x65\x49\xc3\xe8\x0f\xa8\x64\xe1\x86\x94\x7c\xb1\x34\x70\xc9\x09\x25\x85\x14\x0b\xe0\xc2\xc1\x41\x04\x0a\x49\x73\x02\xba\x5e\x2a\x72\x4b\x55\x49\x28\xc9\x68\xb6\x04\xec\x05\xea\x45\x36\xaf\x15\xb4\x23\x34\x8c\xe6\xeb\x89\x36\xd4\xd8\x58\x97\xb9\xba\x68\xb7\x73\x08\xa9\xd9\x16\x27\x8b\x3b\x03\x90\x71\x99\x31\x83\xe9\x0e\x1e\xe0\x90\x1e\x03\x19\xfc\xe1\xae\xb2\x89\x90\x3a\x2f\xe8\xe2\xa9\x91\x00\x8d\xdd\x33\xfd\x18\xbb\x67\x7e\xee\x18\xbb\x67\x7e\xf6\x18\xbb\x67\x8e\xdd\x33\xc7\xee\x99\x63\xf7\xcc\xb1\x7b\xe6\xc6\x18\xbb\x67\x8e\xdd\x33\x7f\x66\x8c\xdd\x33\x3f\x2d\x70\x64\xc6\x46\x8e\xb1\x7b\xe6\xd8\x3d\xf3\xfe\x31\x76\xcf\x7c\x6c\xd7\x62\xec\x9e\x39\x76\xcf\x0c\x63\xec\x9e\x39\x60\x8c\xdd\x33\x87\x8d\xb1\x7b\xe6\x27\xc7\x13\xeb\xa7\x31\x76\xcf\x1c\xfb\x69\x7c\xae\x9c\xa7\xd7\x4f\x83\x8c\xdd\x33\x71\x63\xec\x9e\x39\x7c\x8c\xdd\x33\x87\x8d\xb1\x7b\xe6\x70\x99\x63\xf7\xcc\x76\x8c\xdd\x33\xc7\xee\x99\xcf\xf4\xe8\x8e\xdd\x33\xc7\xee\x99\xbb\xc7\xf8\x46\x30\x76\xcf\x1c\x36\xc6\xee\x99\x78\xa1\x63\xb4\x8f\x97\xf3\xf4\xa2\xfd\xb1\x7b\xe6\xd8\x3d\xf3\x93\x23\xc6\x75\xd3\x26\xe7\x88\xb6\x29\x0f\xc3\x8b\xea\xd1\xb2\x1d\xae\x99\x59\x3d\x9f\x33\x05\x6e\x37\xcc\x14\x95\xb8\xd9\x4d\xd3\x3b\x0d\x65\x0a\x18\x99\xce\xf1\xd3\xcc\x1c\x02\x85\xab\x76\x85\xd3\x30\x45\x1c\xe0\xb1\x3f\x45\x4f\xb9\x03\xcd\x42\x14\xd3\xb8\xf8\x9a\x0b\x72\xf6\xfe\xcd\x34\x01\x25\x6c\x0c\x9b\x1a\xac\xc9\x7b\x91\xc5\x16\xeb\xb4\x87\x2c\x8e\xd9\x28\xb0\x1a\xf9\xb3\x96\x15\x52\x3b\x6c\xad\xdb\xbc\x6c\x49\x85\x60\x98\x02\x15\xa7\x10\xb9\x81\xb4\xdb\x8c\x31\x41\x64\xc5\x84\xc3\xff\x53\xa2\xb9\x58\x14\x18\x0b\x40\x8d\xa1\xd9\x72\x6a\xbf\x5f\x84\x03\xe6\xbb\xc9\x34\xb3\xc6\x5c\x35\xa3\x18\x2d\xdd\x41\x53\xac\xa4\xdc\x4d\x97\xd0\x4c\x49\xad\x49\x59\x17\x86\x57\x11\x13\x26\x9a\x41\x99\xb5\x76\x35\xff\xe1\x10\x10\xd4\x75\xd3\xcc\x81\x3d\x81\xbb\xb3\x59\x03\xbf\xbc\x28\x17\xac\xbd\x6a\x10\xc0\x1f\x42\x23\xc1\xb2\x32\x6b\x57\x10\x85\xbc\xc0\x73\xae\xb4\x21\x59\xc1\x21\x82\x83\x75\x60\x60\xc9\x60\xce\x18\x04\x30\x15\xb9\x95\x2c\xfc\x1e\x69\xbf\x49\x22\x07\x07\xb4\x42\x39\xfc\x50\x96\x13\xea\xbe\x58\x98\x6e\xce\xb5\x0f\x28\x34\x6a\xa2\x81\x4d\xdd\x5d\xae\xb0\x47\x70\xbd\x72\x24\x2d\x70\xf8\x66\x2f\xa4\x33\xe5\x88\xfb\x0f\x04\xe8\x3e\x2b\xde\x98\x00\x47\x5d\x1e\x14\x24\xea\xfb\xb7\x8b\x71\x03\x19\x2e\x18\x08\x84\xc8\x8e\x49\x81\x6b\x2a\xd8\xca\x5a\x2f\x96\x31\xbe\xb2\x4e\x38\x42\xe4\x4e\x7b\xf0\x45\xcd\x81\x61\xaa\xe4\x02\x8a\xb6\xde\x31\xad\xe9\x82\x5d\xa2\x5e\xbf\xef\x8b\xad\xe1\x01\x3c\x1c\x46\xf4\x35\x2e\x20\xc0\x6e\x9d\xdb\xb6\x04\x61\x0f\x55\x1e\xda\x7e\x34\x29\xdd\x57\x37\xbc\x28\xb7\x8a\x1b\xc3\x50\x8e\x8d\x76\xdd\x16\x00\x38\xb4\xc9\xc4\x83\x9b\x68\xa7\xbc\x82\xbc\x0b\x13\x75\x13\xb4\x3f\x67\x9d\x54\x91\xa3\x72\x5c\x0e\xe5\x34\x53\x9c\xcd\xc9\x9c\x43\x15\x03\xe0\xed\x0f\x1d\xbb\x2f\xc5\xcc\x96\x0a\x42\xb5\x66\x0a\xd6\xd5\xe3\xad\xc3\xfa\x4e\xc9\xf7\xe8\x3a\x53\xa3\x6a\x91\xd1\xb6\x57\x16\x11\x32\x67\x84\xcf\xc9\x02\x90\xfd\x18\xad\x03\xbd\xf9\x7e\xff\xf2\x4f\x5f\x93\xd9\xda\x06\x1a\x80\x65\x31\xd2\xd0\x22\x4c\x18\x21\xb4\x60\x62\x61\x4f\xbb\x33\xd9\x7d\x4a\xa1\x88\x32\x5b\xe8\xaa\xee\x6a\x5f\x5f\x7d\x75\x33\xeb\xc5\x64\x08\x89\x47\x39\x5b\x1d\x75\x6e\xc0\xa4\x90\x8b\x4e\x33\x7c\x84\xc4\x50\xaa\x89\x2d\x54\x44\x85\xf9\x3b\x14\x17\x74\xf4\x8c\x54\x5d\x81\x38\x9d\x2c\xe5\xad\xeb\xa6\xd2\xfe\x0e\x62\x69\x82\x76\x69\xeb\x0e\x2b\x59\xd5\x85\xab\x6c\x7d\xc3\x51\x0e\x1d\x68\xaa\x5a\xb3\x4d\xee\x99\x7b\x74\x39\x4e\x39\x84\x69\x6e\x04\x42\x4e\x49\x44\x2c\x84\xf4\xc4\x0d\xfe\x75\xa9\x61\x3e\xaf\x15\xaa\xf2\xf1\x0d\x2d\x8a\x19\xcd\x6e\xae\xe5\x5b\xb9\xd0\xef\xc5\x99\x52\x52\xf5\x56\x08\x73\x8f\xa9\xf5\x1a\x97\xb5\xb8\x71\xcd\xc0\xc3\xc7\x17\x72\x41\x64\x6d\xaa\x1a\x15\xfd\xcd\x37\x8f\x53\xb3\x26\x73\xdc\x39\x68\x5c\x64\xef\x94\x76\x66\xca\xee\x38\xee\xe9\xe3\x96\x5b\x05\x26\x08\xb3\xeb\xe8\xb4\x62\xfb\xd5\xb8\x60\xa1\xa3\xbe\xbe\x7a\xf9\xfb\x3f\x3a\x85\x4b\xa4\x22\x7f\x7c\x09\x45\x99\x28\xf7\x16\x5c\x01\xf0\xbf\xb8\x26\xba\xa4\x45\xc1\x54\xac\x62\xb4\xd7\xb1\xa3\x08\x1b\xb5\xf6\x45\xb5\x9a\x89\x55\x60\x0f\x98\xfc\xb9\xbe\xfe\x2f\xc8\xfc\x70\xa3\x59\x31\x47\x79\xe5\x85\x96\x6d\xbf\xa3\x3d\x70\xa6\xf7\xbc\x2f\x62\xa3\x49\x8c\x0a\x78\xdc\x74\xca\x4a\x16\x75\xc9\x4e\xd9\x8a\x67\x98\x67\xad\xde\xd6\xf5\x64\xe1\x2b\x9f\x0b\xae\x81\x90\x7e\x56\xc8\xec\x86\xe4\x5e\x5c\x0b\x6b\xc7\x78\x21\xeb\x58\x5e\xc9\x98\x22\x04\x74\xf1\xc1\xbd\xab\xdb\x96\x0e\xa0\x12\xbc\x94\x94\xb4\xaa\x1a\xd2\x0f\x45\x6f\x7b\x8b\x8d\x92\x69\x35\x2f\x17\xdd\xb8\x15\x73\x19\x22\x1f\x87\x63\x9e\x86\x27\xfe\xeb\x91\x3e\x07\xba\x2e\x21\xf6\x55\xb9\x9d\x35\xf6\xe1\xab\x77\xcc\x5a\x71\xb1\xdc\x05\x15\xc8\x70\x45\xeb\x89\xfa\x4b\x74\x98\x91\xdc\x3c\x9b\xb0\xd7\x1e\xe8\x08\x56\x31\x23\xb1\x8f\x8e\xd1\x2f\x7d\x31\x55\x20\xbd\x9d\x13\xcd\x9b\x6a\x49\x0d\x2a\x59\xe1\x46\x97\xe4\x8f\x92\x8a\x29\xcd\xb5\xf5\xd1\xbf\x03\x05\x74\x52\x50\x8e\x7d\x38\x6b\x1e\x4f\x2a\x89\xdd\xaa\x88\xe5\x76\x0a\x14\x9a\x13\xc6\x5a\xba\x4b\x99\x7b\x71\x60\x98\x20\x6d\x82\x7a\x51\xd9\x4a\xb3\xc4\x52\x52\x24\x73\xff\x1e\xd3\xd4\x7d\xd7\xee\x54\xbc\xa5\xb3\x52\x1a\x53\xe7\x24\x7b\x63\x85\x94\xf8\x7c\x0d\x1c\xac\xc5\x73\xb3\x6f\xcd\xa4\x93\x28\x49\x30\x6c\xde\x57\x89\x31\x6e\x6d\xac\xda\xbe\x54\x2c\x99\x57\x0a\x68\xa9\x6d\x9a\xc5\x67\x62\xa7\x1e\x2c\x2a\xd0\x9d\xea\x9a\xa9\x92\xbd\xd7\x7b\x8f\x66\xe4\xdc\x26\x2a\x59\xd1\x05\xe4\x0e\x92\xec\xe5\xa6\xd0\x08\x84\x97\x4b\x6b\x30\x0d\x69\x33\x90\x8b\x65\x42\x74\xa3\xf2\xb3\x62\x79\x4b\x81\xbe\x94\xc0\xb0\x90\xe2\xc8\xf9\x84\x89\x23\x6e\xbc\x8d\xa8\x8b\xa6\x4a\xd6\x22\xf7\xaf\xc1\x0d\x04\xe1\xdd\xc6\xc2\x5e\xe0\x19\xcc\x20\xcd\xe3\xb8\xda\x81\x08\xcf\x15\x4a\x72\x8d\x25\xc3\xf3\x32\x05\x79\x35\x7d\xf5\xf2\xf9\xfb\x6c\xb0\x26\x89\x7c\xb6\x8b\xc6\x67\x73\x56\xee\xd1\x56\x27\x34\x4c\x4e\xb2\x42\xef\xfc\x93\x54\xd3\xd9\x18\x7f\x68\x42\xb7\x4e\x10\x75\xab\xb8\xf1\x37\xe8\x96\x47\x14\xaa\xed\x43\xd2\x86\x48\xd5\xa5\x20\x3e\x68\x73\x79\x11\x21\x49\x4c\xc7\xe5\xf8\x96\x85\x84\xe8\x7a\xf6\xe4\xec\xae\x33\xb0\x4e\xa9\xee\x7a\x4f\xc5\xaf\xb7\x97\xbc\x6d\x82\xd1\x12\xbb\xd8\xc3\x17\x2f\xc8\xbe\xfb\x85\x3d\xc7\x66\x77\xf0\x68\xd7\xd3\x6f\xeb\xd9\x5d\x85\x6e\x2a\xd3\xdb\xda\xb3\xbb\x8a\x8a\x9c\xe5\x2e\xe0\x8f\x70\xad\x49\x20\x9d\xde\xb5\xc7\xf1\x66\x73\x4f\xf7\xf7\x18\x2d\xb1\xeb\x9e\xfd\x95\x2d\xe9\x8a\x01\xe7\x1f\x2f\xa8\x8a\x50\x4f\x46\x92\x2b\xb7\x33\x64\x56\x1b\xc2\xc4\x8a\x2b\x29\x4a\x16\x41\xec\xbe\xa2\x8a\xd3\x59\xc1\x88\x62\x40\x1c\x9c\x31\x4d\x7e\xbd\xff\xdd\xf1\x07\x80\x59\xe3\xdb\x47\x50\xc5\x08\x0b\xbb\x5e\x6b\x28\xcf\x4d\x74\x0b\x3b\x9f\x3d\xdd\xb8\x40\x78\x15\xbd\x71\xf1\xc2\x3a\xdb\x1b\x80\x5f\x03\x91\x37\xfb\x65\xd7\xa3\xac\x4d\x4d\x0b\xa0\x7d\xcc\x8a\x5a\xf3\xd5\x63\xd8\x5f\x4f\xc3\x79\xca\x11\x37\x7b\x83\xbe\xb4\xbd\x34\x5b\xdc\x9e\x48\x0a\x6f\x70\x2f\xd3\xb5\x94\xf4\xc0\xcb\x3d\x1d\x8a\x55\x7a\xad\x81\xd0\x8f\x72\x9e\xb6\x7a\x06\x93\x9b\xf3\x45\xad\x1c\x91\x0e\x4e\x05\x75\x9a\x59\x97\x80\x22\x79\xac\xe7\x39\x21\x73\x36\xb4\xa5\x45\xbf\xf0\xc5\x0b\x70\x54\xd6\x1d\xc2\x38\x9d\x2d\x59\x5e\x0f\x7c\x01\x76\x74\xee\x32\x27\x52\x18\x49\x68\xd3\x12\x0b\xe6\x09\x30\x3a\x3e\xf8\xb9\x56\x48\x31\x81\x07\x65\x77\xb6\xc2\xbc\x54\xe0\x63\x0d\x7f\x31\x4c\x6a\x7f\xa6\x90\x7e\xb6\x73\x3c\x24\x54\xeb\xba\x74\xaa\x6f\x20\x67\x28\x37\x64\xce\x0d\xe0\x06\x65\xad\x32\x16\xb2\x3a\x56\xe9\x0d\xe2\xc9\x42\x9f\x84\x2b\x56\xc0\x55\x46\x9f\x86\xbd\x8b\x8e\x14\x77\x24\xb4\xff\xd3\xa0\xa5\xf0\x57\xce\x17\x02\x01\x0a\xb9\x29\x06\x96\xf0\xe6\x3e\xe7\xc3\x16\x57\x0a\xe8\xee\x6f\x4f\x51\x33\xbf\xce\xaf\x40\x98\x45\x86\x45\x9e\x56\x1a\xb0\xe2\xd3\x19\x2b\xf4\xe6\x04\x67\xed\x51\x1b\xe6\x52\x00\x25\x8e\x3f\x4e\x83\x0b\x49\x82\x72\x82\xf8\xfc\x88\x6a\xcd\x17\x62\x52\xc9\x7c\x62\xa5\x1d\x0d\x41\x32\x21\x33\x92\x34\x0f\xfc\xc1\x97\xc8\x04\x1f\xea\xf4\xca\x15\x53\x4b\x46\x07\x25\x40\x37\xb0\x9d\x5e\x02\x51\xac\x52\x4c\x03\xf8\xc8\xf1\xdf\xb9\xdb\x38\x6c\x0f\x83\x30\xaa\xb5\xcc\x80\xbf\xc2\x61\x50\x54\xed\xba\x2a\xd0\xc1\x6f\x1d\xf6\x78\x51\xb2\xe0\x2b\x26\xc8\x07\x67\xe3\x4e\x0a\xaa\x75\x2f\x81\x32\x18\x8d\x37\x63\x84\xd6\x46\x36\xe8\x2d\x42\x4d\xdb\xbb\xcc\x81\xac\x67\xc3\x7c\x57\xbb\x66\xdd\xf9\x75\xc4\x59\xab\xa7\x24\x60\x5a\x06\x89\x3c\x9f\x7f\x9e\xd4\x61\xda\x56\x87\xce\x09\x87\xed\x76\x95\x3e\xa9\xda\xf6\xf9\x19\x24\xf3\x52\xe6\x24\x03\xf0\x66\xb0\x84\x1e\x82\xd9\x9d\xfa\x20\x89\xbb\x3e\x33\x54\x53\xd8\x9b\xd9\xf9\xc9\x41\x72\xc3\xf4\xbc\x0e\xb4\xc1\x8a\x4b\x1d\x36\x07\xb7\x50\x8c\xe6\xc3\xb6\x5e\x33\x03\x36\xba\xb7\x51\x0e\xae\x13\x3c\xa6\xa1\x08\x7d\x67\x3d\x1a\x57\x0b\x5a\x19\x55\x2c\x3b\x24\xcd\x75\xc5\x1c\xf9\x50\xe8\xd1\x74\x32\xca\xd9\x9c\x8b\xf6\x57\x32\xa9\x14\xd3\x95\x14\xf9\x50\x5f\xbb\xfb\xe9\x87\x6d\x1a\xc9\xda\xf6\x4e\x0d\xcc\x20\x91\xb5\xb0\xd3\x85\xdc\x6e\xcb\xf8\xfd\x6f\xa6\x64\xd7\x38\x0c\x92\xd8\xe9\x27\x38\xbd\xf9\x23\x58\x11\x26\x96\x54\x64\xce\xd5\x38\xba\x61\x95\x3e\xd2\x7c\xe1\x8c\xc6\x57\x2f\x5f\xfd\xe9\xe5\x57\x5f\x7d\x0d\x66\x24\x9c\x8f\x69\x39\x6c\x1f\xfb\x49\x5e\x5a\x54\x4b\x3a\x71\xad\xa8\x29\x60\x3c\xff\xde\xd8\xb4\x41\x62\x57\xaf\xa6\xaf\xbe\x3e\x24\x9e\x60\x1f\xba\x6a\x2c\xa5\x90\xca\x61\xaa\x1d\xa1\xdc\x50\xbf\x8e\x1a\xaf\x18\xc2\x81\x6b\x8e\x9a\xef\x8d\x32\x08\x10\xfc\x68\x66\xb4\xa2\xc6\x30\x25\x5e\x93\xff\xde\xff\xc7\x6f\x7f\x9a\x1c\x7c\xb3\xbf\xff\xc3\xcb\xc9\x9f\x7e\xfc\xed\xfe\x3f\xa6\xf0\x2f\xbf\x39\xf8\xe6\xe0\xa7\xf0\x87\xdf\x1e\x1c\xec\xef\xff\xf0\xf7\x77\xdf\x5e\x5f\x9e\xfd\xc8\x0f\x7e\xfa\x41\xd4\xe5\x8d\xfb\xd3\x4f\xfb\x3f\xb0\xb3\x1f\x3f\x53\xc8\xc1\xc1\x37\xbf\x1e\xa6\xe0\x86\x97\x66\xc7\x94\x63\x47\x94\x60\x27\x2b\xbb\xae\x14\xb3\xf1\x08\x97\x62\x38\xb4\xbb\x9f\x3c\xdd\x10\x14\x5a\x31\xba\x3f\x0d\xf6\x2e\xc2\xbc\xc4\xc2\x3a\x27\xda\x39\x2c\x85\xbc\x85\x52\x23\x2e\x15\x37\x03\x43\xfc\xf7\x02\x1e\x1e\x2e\xd8\x8a\xa9\xc3\x30\xdb\xb7\x56\xe0\x65\x90\x87\xcb\x87\x1b\xb9\x53\x9a\x6f\xf8\x67\xad\xd0\xe0\x3e\x4d\xbb\x75\xd3\xb6\x5e\x19\x66\x6a\x1a\x1d\xb4\xa5\x57\x2e\xa4\xb8\x6c\xd6\x3b\x7c\xc0\xb0\x19\x7b\x6d\xf4\xd0\x81\x61\xd8\x7b\xf4\x31\xbd\x86\xb2\x7d\xbf\x45\x60\x6f\xa7\xe4\x3b\xaa\xb8\x1c\x88\xb8\x77\xe8\x17\xe8\x1f\x27\x05\xf8\xe7\x0e\x0b\xdf\x58\x16\x08\x0b\x07\x3a\x18\xa6\x3b\xb9\x86\x7c\x23\x3c\x7d\xa2\x36\xe6\xb8\xf1\xd9\x4e\x5a\x9f\xad\xeb\x6e\x72\x63\xef\xda\xca\x7e\xc2\x30\x4f\x40\xdb\x93\xe4\xea\xf5\x5c\xb3\xef\xce\xd7\x3b\x47\x13\xd7\x77\xb8\xe3\x5b\x86\x48\x40\x77\x17\x16\x7e\x32\xac\x05\xf8\x36\x17\x74\xe8\x43\x22\xb0\xea\xf2\x45\xa8\xad\x86\x73\xe0\x32\x32\x9d\xbf\xc5\xe8\x19\xac\x31\xc0\xd1\x19\x54\x9b\xab\x80\xbe\x16\xfd\x7e\x8b\x4d\x5b\xc8\xc1\x19\xc5\x4a\xe6\x7b\xba\x5d\x39\xf2\xc2\xdd\x13\x70\xde\x26\x99\xe2\x86\x67\xb4\x18\x96\x25\xb7\x7a\x2f\x88\xc9\x8a\x5a\x1b\xa6\x5a\x49\x90\xd6\x36\xb7\xc3\x00\x0b\xf0\xa5\xb4\x20\x37\x6c\x7d\x2b\x55\x1e\xe2\x8e\xf0\xd5\xed\x39\x18\x48\x4a\xe3\x3f\x9b\x33\x6f\xae\x5c\x5b\x34\x55\x32\x45\x66\x2c\x3c\x40\x44\x08\x5e\x4f\xc9\xb1\x58\x7b\x44\x85\xe8\xb2\xd3\xf8\x90\x61\xa8\x3d\x80\x58\xcd\x65\x00\x7a\x17\xca\xbb\x88\xf0\x15\xc3\x1d\x56\x3b\xb3\xe9\x3d\xc9\xf4\x4a\xe6\xcd\xd7\x0c\x4b\xc2\xf9\xbc\x79\xc8\xa3\x4b\x45\x5c\x67\x20\xd0\x92\x8a\x39\x7a\x8a\x41\x22\xbd\xa8\x07\xb7\x59\x36\x76\xe5\x82\x69\xfd\xad\xbd\x52\xf8\xa4\x50\xff\x8e\x52\x08\xe0\xbc\xe4\x41\xdf\xbd\x80\x9b\x1d\x16\x94\x59\xe5\xe7\x40\x40\xd6\xed\x92\x79\x2b\x75\x98\x4e\x3d\x86\xff\x18\x4a\xcd\x69\xbe\x76\x1d\x36\xed\x24\xb9\xe9\xd4\xc8\x0c\x4c\x38\x28\xe6\xa5\x1d\x5f\x9c\x86\x62\x4f\x17\x8b\x68\x64\x9b\xe6\xa6\x91\x84\xff\x46\xbf\x1a\x90\x73\xf0\xdd\xb0\xd8\xbf\x6a\x3a\x2c\x8a\x37\x92\xbc\xb8\x56\x35\x7b\xb1\x2b\x43\xfa\xe9\xc0\x96\x99\x5b\xa9\x6e\x8e\x5e\xbe\x7c\xf9\x07\x88\x6b\xe1\x93\xff\xd7\x57\x7f\xfd\x5f\x5f\xfd\x75\x5a\xe6\xc3\x03\xbc\xa1\xb0\x58\x04\x20\x76\x13\x69\xfc\xa1\x7b\xc6\xc3\x76\x0f\x7d\x61\x75\x1b\xe3\x5f\x81\x81\x70\x0c\x8e\x54\xb3\xe7\x88\xcc\x2d\x02\xc4\x8a\x83\xaf\x4e\xda\x69\x5e\xaf\xab\x81\x46\x13\x8d\x3e\xed\xfd\x66\xfc\x73\x6a\x2b\xcb\xed\x03\xaa\xee\x5f\x3a\xf8\xb1\x93\xd5\x01\xd3\xef\x69\xe4\x4e\xba\x01\x15\x57\x60\x56\xe1\x79\x04\xcc\xe9\xba\x42\x57\xa2\x0d\xd6\xe1\x40\x9f\x11\x19\x23\xef\x7d\x70\x62\x48\xe5\x42\x64\x48\xa3\xf7\x4a\xd8\x07\xda\xc4\x00\x55\x72\x51\x82\x0f\x71\x8f\x81\x43\xe9\x90\xbc\x17\x6f\x5c\xd1\xef\xb0\x77\x66\x88\x90\x5b\xc6\x0c\x23\xbd\xc0\xa4\x3c\x62\x47\xbf\xf2\x2b\x3a\x71\x4b\x31\x5c\xc9\x0d\xdd\xc0\x4e\x2e\x34\xca\x53\xde\xfb\xb0\x21\xc9\x5f\x95\xa1\xa8\x59\xda\xcf\x4c\x7b\x8f\xcb\x6f\x27\x3c\xb7\x39\xa3\x31\xcc\xb4\x2b\x59\x57\x87\xde\x9f\x6d\x51\x62\xa1\xad\xb7\xaa\xc5\x70\xf6\x2f\x38\x5a\xce\x9d\xeb\x4f\xb9\x79\x1a\x86\x0b\x39\xf8\xc9\xda\x15\xf0\xe4\x24\x73\xe9\xe9\xe0\x1d\x3a\xda\x17\xf7\xea\xa1\x6a\x31\xf8\x71\xc6\x65\xa8\xa5\x22\x9d\x67\xf6\x17\x05\x5b\xd0\x6c\xfd\x02\xff\xf4\xd1\x83\x6d\x84\x78\x41\x13\x2a\x80\xbe\x96\x67\xdc\xb8\xef\x18\x7c\x7f\xa1\x10\x1c\x2a\xcc\xc1\x87\x77\x4a\x13\xdc\xe8\x5a\x23\xe2\xaf\xe0\x1e\x07\xc6\xaf\x25\x15\x39\x94\x6d\xa3\x1c\x13\x99\xb3\x23\x2f\x69\x02\x9f\x87\xca\xb4\x37\x7d\xc5\x9b\x7e\xde\xd1\x69\xf6\xdf\x23\xd2\xde\x03\x15\x46\x03\xcd\x48\x18\x57\x77\xcf\xf8\xd0\x67\xa2\x9c\xeb\x0a\xee\x99\x7b\x4d\x08\x42\xdb\x79\x0e\xbe\x29\xf7\x84\x67\x4d\xa4\xd5\xfc\xe0\xd0\xb0\x32\x1c\x42\xd4\xd4\x70\x9b\xc5\xb2\x1a\xa2\x57\x29\x0c\xbb\x1b\xc4\xa3\xdb\x57\xee\x57\x7d\x41\x64\x29\x8b\x1c\xa0\x35\x2e\x09\x3b\xf0\xb9\xd0\xc9\x22\xd4\x18\xc5\x67\xb5\x8d\x33\xa8\xc8\xa1\x0b\xb3\x7f\x43\x1d\x8e\x2b\xf3\xb9\x36\x3d\x25\x2d\xff\x53\x17\x82\x08\xba\x64\x4a\xc8\x15\x1b\x08\x76\xb2\x4e\x5f\x67\x2d\xc0\x37\x09\x1b\x09\xf9\x31\x7b\x67\x07\x89\x64\x34\x5b\xfa\x74\xe0\x17\x78\xa4\xc2\x3a\xd1\x73\xfd\xad\x35\x9a\x43\x9d\xe7\xde\xb1\x79\x71\xdc\xe4\x94\x74\x5d\x79\x3a\xf3\x81\x31\x24\x09\xe6\xdb\x69\x7f\x5a\x55\x05\x77\x95\x9b\x11\x1e\x22\x71\x11\x2f\x75\x46\xfc\x4a\x96\x0d\x70\xd9\xae\xb2\x76\x7d\x10\x87\x7b\xd0\x4b\x06\xca\xbb\x70\x2f\xd7\xd9\x12\x48\x97\xe1\xc5\xfe\xd6\x4e\x71\xc9\xab\xc1\x32\x21\xdb\x4d\x4d\x33\x3d\xc0\x2c\x59\x71\x81\x90\x6a\xb0\xc4\x4a\xe6\xaf\xc9\x3f\x04\x79\xe5\x92\xd1\xf2\x16\xb0\x2e\xdf\x9e\x9f\x06\x0d\x87\xfa\xee\x37\x57\x70\x5c\xc8\x57\x4e\xaa\x66\x66\xc1\x73\x32\x73\x5d\xd0\x35\x1b\x8e\x83\xde\x17\xec\xd6\xd5\xd3\x7a\xe8\x44\xf3\xf0\xbf\x0a\x75\xa0\x08\x52\xab\xee\xe2\xf9\x29\x1f\x90\xdf\xb9\x39\x57\x4c\x61\xf2\xf2\x20\x96\xbb\x9a\x33\xf2\xfe\xc3\x5e\x00\x11\xdd\x4e\xd4\xed\x64\x32\x99\xd8\xb5\x3e\x1f\xa6\x21\x48\x40\x14\x1c\xf6\xce\x54\xe3\x02\x96\x32\xe7\xf3\xe1\x68\xf5\xde\x49\x04\x95\xdb\x7e\x32\x78\x1e\x54\x0c\x17\xea\x76\x63\x3a\x14\xe1\x1d\xc3\x74\xdc\x79\x14\xf8\xfa\xf7\x18\xa5\x76\x02\x37\x13\xc7\xd9\xd5\xb7\x8b\x3b\x04\xfa\xa4\xf3\x70\x85\x34\x63\x4b\xba\xe2\x12\xf8\xb8\x41\x77\x40\xe5\x73\x77\xbf\x86\xdf\xf5\x66\x7f\xc3\xb3\x99\xbf\x3c\xbe\x99\x13\xa4\xdf\x07\x4b\x65\x77\x95\x74\x2d\x4a\x81\x1f\xe2\x52\xe6\x71\xf8\x36\x02\x80\xca\x62\x0d\xca\x7d\x6d\x75\x5c\x4f\x19\xfb\xa8\xcd\x35\xd5\x18\x2c\xd8\xef\x10\x99\x51\x3b\xe5\x66\x39\xf7\x37\x8e\x3f\xa2\xa4\xe7\xdc\xdf\x48\xc8\x91\x0a\x49\xd8\x7c\x6e\x43\x55\x29\x08\xab\x96\xac\x64\x0a\x61\xe9\x7a\x1f\xee\xd9\x10\x5f\x5b\x8f\x49\x59\x65\xe0\x30\x5a\x25\xad\x86\x1f\x2e\xfb\xb9\xe0\x03\xe5\x5c\x4d\xc9\x77\xb4\xe0\x79\x70\x5f\xac\xde\x7a\xf1\x5e\x7c\x90\xd2\xbc\xe3\x1a\x82\xd6\xe1\xf5\x1a\xf0\x1a\xe5\x12\x22\x2f\xb6\x1f\x39\xf0\x3d\x29\x8c\x6c\xc5\x0e\xe5\xf8\x43\xa3\x48\x54\x2d\x8e\x13\xb8\x3f\xd6\xa8\x58\xbb\xda\x64\x18\x18\x61\xc2\xa8\x75\x25\x39\xa2\x30\x68\x93\x86\x25\x50\xcb\x4e\xc9\x47\x1b\x11\xfb\x78\x14\x91\xeb\xf4\x14\x56\x0d\x2c\xe3\x1d\x5d\x3b\xb2\x2c\x07\xc2\xc3\x38\x56\x1b\xe1\x82\xcb\x93\xf8\x7e\xd5\x33\x89\xe0\x30\xd8\x8c\x3f\xec\x71\xbb\x84\xee\x68\xdd\xbf\x1e\x5e\x38\xd2\xa2\x0b\xdb\xb3\xba\x3d\xff\xe1\x62\xe9\x0d\xd3\xa4\x52\x2c\x63\x39\x24\xed\x1d\xee\x9c\x1a\x3c\x01\xc5\xe3\x18\x4c\xb8\x09\x17\x12\x94\x43\xd4\x5d\x38\xef\x3c\x9d\x7b\x16\x20\x7c\x01\x11\x3c\xef\xda\x2b\x45\x35\x14\x0c\x88\x89\x92\x12\x32\x43\xca\xd1\x38\xab\x1a\x41\xdc\xbc\xe5\x6a\xad\xac\x96\x0c\x0f\xdf\x50\x03\x34\x5c\x2d\xb6\x29\x27\x1b\x84\x0a\x5d\x2b\xe6\x56\x80\x1b\x92\x4b\x84\x97\x60\xf5\xaa\xff\xf4\x8f\xe7\xa7\xe4\x25\xd9\x87\xc2\xb8\x86\xcc\x12\xc3\x52\xe0\x92\xef\x7d\xed\xc2\xe7\x61\x8a\x53\xb4\xfb\x4a\xa4\xf2\x2c\xda\xd6\x3e\x82\x39\xf3\x6b\x8a\x71\xb2\x43\x02\xc6\x37\x1e\x64\xf9\xa8\xaa\x1e\x40\x55\xe1\xf4\x12\xa6\x54\x1d\x74\xcb\x47\xcd\x06\xd7\x3b\x6e\x19\xd9\x8f\x5f\xc0\xc8\xa2\x39\x01\x5c\x33\x5d\xd5\xdf\x35\xd0\x26\xa4\x64\x86\xe6\x14\xc1\xa5\xe1\x8c\x75\x10\xb8\x75\x0f\x30\x6d\x47\x3e\x75\x0f\xa2\x0f\xda\x3d\xf7\xa0\x3d\xd7\xc3\xd5\xd6\xcf\xdc\x03\x77\xae\x87\x07\x4c\xcf\xdf\x64\x6b\xf6\x96\x8b\xfa\xce\xa5\x41\x07\xbf\x9c\x6f\xdd\xad\xab\x33\x10\xe7\xc8\x9e\xef\x50\x24\x38\x33\xe6\xd3\x76\xf9\x76\xda\x6e\xea\xdf\xa6\x9a\x7c\x3b\x4a\x2f\x6e\x35\xf4\x09\x5d\x73\x1c\x7f\xec\xf0\xb3\x4a\x14\x15\xb9\x2c\xb7\xbe\xde\x1e\x0a\x46\x11\x64\x2f\x9d\xde\x6e\x3b\x6e\xeb\xce\xdb\x37\xfc\x3e\xdc\x7f\x5b\x9f\x9b\x15\x4a\x76\xfb\x50\x6c\x6d\x31\xb4\x67\xf0\x1e\x12\xcd\xa2\xf7\x16\xa0\xed\x5c\x37\x07\x70\xf8\x33\x4b\x33\x21\x3a\x63\xc5\x56\xf2\x3c\x92\x52\x37\x92\xca\x44\xc9\x02\xc5\xc1\xd4\x5b\xa3\x0f\xb2\xf0\x15\xed\x61\x91\xac\xd8\x5f\xcc\x1a\x19\x14\x74\x69\x53\x83\xaf\xab\x8d\x35\x32\x43\x51\x58\x61\x3c\xc5\x35\xaa\x11\xde\x23\xd9\x5c\x23\xeb\x82\xf6\xd7\xc8\x8a\xfd\x45\xac\x51\xf7\xd5\x0d\xf2\x59\x71\xfe\xc0\x71\xc3\xef\x0d\x2f\x72\x3a\x98\x75\x8c\x4f\xdc\xf6\xc8\xf2\x2e\x36\xb8\xef\x5c\xb8\xe7\xd1\x66\xb9\x86\x5b\x28\x2e\x9a\xc2\xbc\xad\xc5\x77\x18\xfc\x92\xaa\xe1\xef\x1c\xdf\x9e\x9f\x4e\xc9\xa6\xb3\x62\xc3\x5a\xbf\x14\xd8\xe7\x28\x9a\xe7\xde\x2f\x12\xeb\x58\x63\x87\xe1\x7d\x45\xb2\xbe\xc6\x75\xaa\x8c\xf0\x6e\xd7\x3a\x33\x45\xdc\x31\xbe\x72\x32\x00\xc4\x40\x68\x38\xd3\xc3\x33\x31\xb4\x64\xba\xa2\x19\xcb\xc3\xac\x1c\xa0\xac\xc3\x31\x31\xfc\xb2\x5f\x36\x45\x7d\xb5\x68\xfa\x88\x37\xf2\xf7\x07\xd6\xf9\x93\xfb\xfc\xe3\x03\x4f\x95\x33\xa7\x88\x06\x77\x46\x92\x82\xd6\x22\x5b\x3e\xf9\x53\xba\x63\xdb\xc3\xf3\x1c\xa1\xe4\x86\x29\x5c\x7b\xc7\x8a\x2a\x5a\x32\xc3\x54\xe0\x10\x41\xa4\x9e\xa2\xc8\x84\xf1\x54\xc2\x48\x2a\xe0\x09\x32\x44\x8f\x23\x10\xc6\x53\x75\xf6\xe9\x8f\x5a\x42\x74\x37\x1d\x2c\xd1\x9b\x91\xa8\xad\x26\xf1\xcc\x7f\xb0\xfa\x09\x96\xe2\x3b\x08\xdd\x9e\xeb\x5a\xdc\x72\x91\xcb\x5b\x9d\x2a\xb5\xf1\xbd\x13\xd7\x12\x58\x05\x10\xd9\xf0\x7c\xc1\xc3\xa6\x37\xa4\xfb\xe0\x1d\x7d\x3a\xf6\x74\x74\xe8\xdd\x85\xf0\x4e\xff\xc3\x93\x7e\xcf\x24\xc7\xb0\x28\x35\x3d\x51\x76\xca\x86\xd3\xe2\xaa\x62\x59\x74\x10\xf4\xed\xbb\xab\xe3\xbe\x48\xd4\xd5\xe6\x9a\xdc\x42\xd9\xa1\xdd\x60\x2b\xb3\x43\x8e\x73\xcb\x66\x4b\x29\x6f\x50\x72\xf7\x3b\xe0\xec\x65\x3d\x9b\x66\xb2\xec\xd4\x58\x4c\x34\x5f\xe8\x23\xaf\x1d\x26\x76\x75\x70\xfc\x98\x5c\x40\x53\xb0\xed\xe6\x76\xfe\x63\x50\x42\xb3\x66\x55\xe1\xec\x7a\x74\xbf\xef\x6a\xb4\xbd\xec\x17\x38\xa6\x7e\x4f\x8e\xf0\xc5\x23\xf0\xed\xa3\x38\x14\x17\x1e\xc6\x27\x8e\x23\x7a\x5d\x3c\xdf\x46\xe8\x8a\xd2\x1c\xcc\x76\x5f\x50\x62\x61\x2f\xdd\xdb\xce\x97\x4f\x9f\x85\x97\xb3\x24\x6b\x0d\x2f\x68\x5e\x98\x55\xaa\xde\x2c\xe2\x4c\xfb\xae\x57\xb8\x34\x1d\x84\xb6\x5e\xe2\x42\x74\x8f\xce\xd6\xfc\xcc\x8b\x1c\xe1\xc3\xe3\x41\xe2\x9e\xbd\x93\xbe\xca\x11\x17\x12\x6e\x3d\x0f\x34\x66\x1a\x25\xf1\x41\x5f\x08\xc8\xc3\xbd\x12\x90\x04\xef\xd5\x04\x5f\x4b\xa1\x56\x3c\x63\xc7\x59\x26\x6b\x11\x51\x4a\x71\xca\xec\xe4\xa9\x61\xf9\x55\x4f\xe2\x50\xca\x54\x4a\x72\x90\xe4\x88\x0b\x69\xc1\xa9\xa3\xb7\xec\x4b\x1d\xce\x01\xd2\xce\x0f\x52\xa3\x1b\xdf\xed\x95\x84\x36\x8c\x62\xca\x17\xa2\xd6\x3c\xae\x3e\x71\x7b\x5d\x30\x4d\xd2\xba\x66\x64\x63\xff\x9c\x31\xf0\x2a\x70\x90\xd0\xc0\x53\xfb\xb9\xa5\xa4\x86\xea\x9b\x96\x46\x94\x41\x71\x7c\xa3\x5c\x3b\x7f\xef\x97\x6f\x42\xdd\x0c\x11\xd4\xa2\x43\xf7\x6b\x49\x15\xbb\x74\x8a\xfa\x22\xa4\xc7\x22\xb6\xcc\x8a\x23\x94\x68\x2e\x16\x05\x6b\x12\xc5\x4d\xe2\x6d\xd0\x22\xcf\x98\xb9\x65\x9e\x7b\x61\xd3\x20\xe9\xb6\x1a\x64\x90\x4c\xe0\x1f\x32\xbe\x98\xcf\x2a\xe4\x8d\xa6\xdb\x90\xe0\x9d\x0d\xe5\x57\x96\x64\xc5\xd9\x2d\x28\x64\xcd\x17\x82\x16\xe1\xcb\x99\x27\x16\x02\xa6\x93\x41\x32\xfb\x5f\x0a\x14\xcb\xf6\x20\x57\x32\x3f\x6c\x3a\xd2\x40\x36\x7e\x90\xd4\xb0\x21\x5b\x59\xfb\x6e\xb5\xea\x30\xa5\x06\x64\xb8\x2c\x27\x97\xe7\xa7\xe4\xd5\x94\xfc\x4d\x6a\x63\xff\x15\x18\xdb\x77\x1d\xae\x61\xab\xe0\x09\xbc\xad\xf9\x73\x36\x79\x47\xb9\xd8\xd0\xbd\x72\x8d\x3e\x86\x5f\xad\xa1\x90\x29\x5d\xcf\x72\x59\x52\x3e\xa8\xff\xd2\x27\x8a\x2e\xe7\x75\x51\xac\xc9\xbf\x6a\x5a\x0c\x67\x0c\xb9\x94\x39\xb4\x45\x02\x8d\x18\x0e\xfb\x8b\x3f\x87\xbf\xfa\xcb\xf4\xcf\xcd\x8c\xff\x32\xfd\xf3\x50\x26\xdd\xe6\x8e\xff\x65\xaa\x57\xd9\xf4\xcf\x9e\xe1\x88\x78\x81\x0d\xc6\x7c\xd8\xe3\xc1\x3d\x55\x9d\xf6\x50\x00\x8a\x9f\x7a\xf9\x83\x73\xa4\xd4\x58\xbd\xf2\xe0\xf5\x9c\x9d\x0e\xde\xdf\x2a\x9a\xb1\x4b\xa6\x38\xb8\x6c\x52\xe4\x78\x06\x9d\x70\x05\x48\xee\x39\xa9\xed\x85\xd6\x4e\xe8\x40\x3b\xe6\x16\x55\x30\x96\x3b\xf7\xdc\xcf\x97\x91\x85\x9d\x2e\x1c\xb7\x61\x1a\xd6\xfa\xd0\x40\x6f\x94\x29\x46\x5d\xd1\x09\xc9\x59\xc1\x5a\xf6\xde\xa9\x4b\x6a\x0e\x92\x1a\xf8\xa1\x84\x14\x13\xc1\x16\xd4\xf0\x15\x0b\x8f\x59\xae\x18\x6c\x78\x72\xca\xd1\x2e\x35\x30\x67\x3f\x49\x5e\x96\x2c\xb7\x2e\x5a\xb1\x1e\x8c\xa3\x05\xc3\xe2\xdc\x68\xae\x89\xe0\xc5\xa1\xef\x9e\xea\x10\xfb\xb0\xa4\xa4\x82\x23\x30\x30\x8d\xda\x66\xfc\x1a\x5f\x0e\xbe\x1a\x2d\xd2\x07\xd9\x3b\x0e\x10\xa1\x73\xd3\x10\xc7\x79\x2b\x36\x48\x74\x60\xe3\x6e\x19\x3d\xa0\x62\x45\x33\x61\x08\xed\xde\x88\x61\xaa\xc0\x19\xd6\x60\xfb\x1c\x66\xcc\x59\x73\xec\x44\xed\xac\xe6\x52\x65\x7c\x56\xac\xc9\x92\x16\x0d\x9f\x38\x25\x37\x76\xc5\xdd\x4f\x0e\x3b\xfe\x57\xcc\x74\x8f\x41\x21\xc5\x02\x16\x93\xfa\x18\xfb\xae\x02\xe6\xe5\x61\x56\xd0\x9a\x9d\xba\x72\xdf\x6c\x23\x86\xb5\xac\x63\x81\xae\x46\x92\xdf\xbd\x0c\x5b\xfe\x85\x89\x01\x07\xbc\x20\x1b\x59\x30\x77\x42\xf1\xda\x72\x27\x75\xc1\x9e\xee\xca\x1e\xbe\x00\x5f\x9a\x9a\xea\x3a\xf4\x40\xb0\x67\xeb\xba\x99\xf9\xd0\x18\xd4\x1a\x3e\x43\x81\x7c\xc1\x6a\x7b\x27\x07\xca\xf9\xd7\xc4\x7a\x82\x66\x78\x83\x0d\x12\x68\x53\xdc\xbd\x54\xbc\x2a\x18\xf9\xf3\x0d\x5b\x1f\x3a\x36\x4a\x57\x65\xf7\x97\x81\x32\xdb\x46\x47\x0d\x4b\x92\xac\xec\x64\xa5\x22\x7f\x0e\xff\xf6\x97\x61\x77\x13\x9d\xfc\xc7\xa7\xfe\xdd\xc7\x47\xbe\x83\x9f\xb9\x3a\x45\x3c\x99\xa5\x1b\x6e\x7f\x7d\xd1\xa3\x91\x6e\x61\xa7\xe4\x0c\x48\x5b\x4a\x46\x07\xd3\x9c\x91\xb0\xf7\x10\xa2\x75\xc5\x6b\xcf\xf4\x1a\xf1\x8c\x46\x5c\x4d\x3f\xeb\x55\x3d\x5e\xc8\x2b\x4f\xc5\x01\xcc\xc7\x73\xa6\xda\xbf\xc1\xfc\x82\xc8\xc9\x85\x3c\xbb\x63\x59\x6d\xbe\x14\x01\x97\x1b\x37\x0c\xd1\xb0\xb1\x77\x28\xfe\xce\x1a\x66\x6a\xb7\xf2\x37\x0c\xf3\x32\xdc\x14\x77\xb5\xda\xb0\x83\x84\xc3\xe4\xea\x3a\xe7\x69\xeb\x74\xdc\xb0\xf5\x40\x32\x46\x37\x7c\xaf\x8a\x1b\xf7\xcd\x9e\x10\xa9\xd1\x07\xd6\x39\x44\x08\x9d\x31\x72\x76\xc7\xb5\xd1\xff\xc7\x69\xd5\x4c\x96\x33\xef\x99\xa0\xaf\x43\xb8\x56\xf0\xcd\xe1\xe0\x8a\x1c\xfe\x88\xfb\xf8\x88\x43\x16\x16\x28\xf2\xa4\xbd\x0f\xeb\xdc\xe9\xe1\x82\xe9\x26\x7b\xc3\xd6\x7b\x9a\x28\x56\x38\x9b\xbb\xe4\x55\xaf\x5d\x04\xe6\x5c\xb8\xb2\xe8\xf0\x9d\x4e\x47\xb8\x3d\x85\x55\x3f\xb3\x81\x32\x46\x6e\xf7\xc5\xc2\x09\x09\x62\x39\xd0\x6a\xf2\x15\x2d\x70\xbd\x02\x8d\xb4\xde\x7c\x9e\x51\xe5\x70\x67\x9e\xb1\x59\xfb\x6e\x57\x98\x75\x05\x6a\x49\xeb\x5f\x7a\x6b\xde\xde\x37\xc7\x11\x81\xc3\x4b\x19\x9e\xd5\x05\x55\xc4\x5a\x9c\x05\xaa\x0f\x5d\xc4\xc9\x6d\x95\x11\x22\x54\x76\xa3\xef\x3d\x6d\xca\xeb\x9c\x65\x94\xd2\x0c\x31\x17\x24\x26\xa1\x58\xb4\xa7\x42\x11\x32\xf7\xfb\xdd\xb9\xe4\x3c\x58\xea\xc6\x40\x61\x6c\x68\xdb\x2b\xc5\xf4\x7a\x85\xf0\x05\xf0\xee\x63\x5e\xdd\x5b\xa7\xb1\xb1\x3d\x53\xf2\xd7\x86\x2c\x0b\x33\x4b\x47\x3a\xd3\x74\xc4\xf6\x2b\x01\x16\x24\xfc\x1a\x72\x97\x9c\xd9\x99\x4b\xc5\x56\x4c\x91\xfd\x5c\xc2\xaf\xb0\x15\xcf\x70\x3d\x61\xff\x1f\xa6\x24\xa8\x96\x26\x09\xe1\x95\x3c\x96\x8a\x87\x74\xfb\xcf\xbc\x24\xfb\x30\xb5\x6e\x12\x02\xb3\x45\x1e\xab\xe0\xb8\xc6\xb1\x17\xf7\xcb\x43\x85\xd1\xa8\xb9\x1d\x88\xb9\x9e\x6b\x84\x03\x2e\x91\x4d\xbf\xa8\x89\x73\xe4\xd4\x7b\x24\x98\x1b\x19\xac\x29\xd7\xde\xa6\x1c\x76\x5f\x5f\xb1\xcd\x72\x67\xac\x71\x8b\x9a\x2b\xff\x3f\x56\x97\x50\xa2\xd8\xc2\x6a\x72\x84\x50\xa7\xbb\xbf\x90\xe6\x37\xb2\x92\x85\x5c\xac\xaf\x2a\xc5\x68\x7e\x22\x85\x36\x0a\x8c\x18\xbe\x45\xc6\x7d\x12\xfd\xff\xd9\x6c\x60\xbe\x68\x29\x6f\x09\xf5\xdc\x66\x72\xee\xda\xb9\xc8\x7a\xb1\x74\x9d\x39\xe1\x47\x08\xcd\x94\x1c\xc8\x9e\x19\x3e\xdc\xa7\xb2\xf5\x94\x5c\x35\xdd\x34\x41\xad\xa0\x9a\x7e\xc2\xec\xe0\x91\xec\x96\xae\xbd\x4a\xa5\x33\x9e\x33\x1d\xd4\x43\xd6\x2e\xc8\xd0\xa6\x13\x5d\x53\xb2\xd9\x1f\xca\x27\xfe\xe3\x1a\x44\x9d\xad\x98\xb8\x94\xb9\x76\x5b\x87\xe9\xca\x42\xc8\xb1\x75\x83\xee\x3d\x02\xd6\x55\x3c\xbe\x38\x1d\xd6\x13\xf6\x91\x72\x3f\xf7\x7c\xc4\xc0\x7b\x19\x82\x71\x0d\x07\xb9\x3d\xb2\x4d\x82\xc5\x1e\x99\xa1\xd9\xa4\x52\xfa\x34\x8d\xeb\xa1\x18\xd6\xfb\x0b\x25\x66\xb0\x14\xe7\x25\xbd\xbb\xba\x61\xc3\x08\x03\x27\xcd\xc7\xfd\x7d\x60\xa4\x3d\x81\x44\xf5\x47\xa1\xa9\xe1\x7a\xce\x07\xbf\x2f\xe3\xd3\x4f\x50\xde\x86\xe9\x3f\xeb\x46\xbf\xc2\xb5\x2b\xcb\x5e\xfc\x5a\x23\x0a\xc9\x48\xe8\x27\xd4\x3f\x76\x53\x57\x47\x83\x48\x3e\x92\x26\x09\x05\x1e\xae\x2b\xe8\x0b\xed\x71\xe1\x96\x67\xae\x7d\x3c\x6e\xaa\x39\x73\x0f\x16\x4e\x2d\x89\xba\x9c\x31\x15\x94\x3f\xc6\xd3\x85\x67\x00\xae\xfa\xcd\x10\x9b\x93\x85\x90\xe8\x8c\x06\xd6\x46\x23\xcb\x59\xe2\xaa\x44\x60\xbb\xce\xee\x6c\x00\xa6\x31\x75\x01\x6e\xf4\x0e\xe7\xa6\x48\x94\x44\xe2\x8a\x4a\x43\xc9\x64\xff\x28\x21\x25\xf6\xba\x4d\x43\x16\xbf\xfb\x37\x48\xa1\x28\xdb\xd5\x0e\x7c\x55\x97\x1b\xc8\xda\x2e\x37\x36\xeb\x53\x53\x2c\x72\x6f\x99\x23\x1a\x64\x77\x47\x97\xcb\xc0\xbf\xe6\xe9\x43\xa8\x41\x5b\xe3\x20\x96\xc4\x27\x9c\xa9\x68\x63\x00\xf8\x11\xc8\x88\x21\xaa\x20\xda\x99\xba\xcc\xa8\x15\xee\xe6\x89\x3b\x16\x91\x3a\xc1\x0d\x7c\xa1\x9b\x1b\x13\x64\x1e\xdb\xfd\xb7\x61\x61\x91\x02\xe2\xd4\x9a\x1b\xa8\xcc\x7e\x3b\x7a\xd7\xe3\xa6\xc9\xf1\x47\x48\x0c\x45\xee\x56\x58\x93\xed\x8f\xbe\x1e\xa4\x29\xa2\xc2\xbe\x13\x84\x11\x59\x68\xe7\x06\x3e\xd5\xdd\x8e\xde\xd2\xcb\xed\xa4\x77\xdc\x5a\xed\x4e\x7f\x47\xca\x04\xca\xb6\x79\xb8\xf5\x2e\x1d\x1e\x25\xb2\x9f\x4a\x3f\x17\x87\xe4\x42\x9a\x73\x81\xd7\x78\x76\x74\x32\xf2\xa7\x92\xe9\x0b\x69\xe0\x6f\x1e\xfd\xd0\xb8\x65\x4b\x76\x64\x7c\x26\x10\xba\x69\xc4\xed\xab\xb5\xcc\x76\x5f\xdd\xf7\x45\x2a\x75\x37\xfc\x0b\x5a\x37\xfb\x74\x1e\x37\x4b\xa9\xfc\xd9\x68\xd3\x57\x3a\xc2\xa9\x08\xa3\x8b\xf4\xf2\x3d\x00\x10\xcc\x4a\xdd\xb1\xf9\xdd\xee\x38\xc6\x7e\x7b\xf7\x24\x77\x97\x20\xc1\xce\x87\x25\xf0\x9f\x3f\xb8\xeb\xee\x6e\xa9\xd0\xd0\xae\x2a\x80\xfe\x20\xaf\xa3\x2e\x0e\x71\xca\xc7\x28\x6a\xd8\x82\x67\xa4\x64\x6a\xc1\x08\x34\xd9\x88\xbf\xd4\xb1\x47\x28\xca\x3b\xed\x4e\x04\xad\x5d\x20\x18\x81\x70\x39\x59\x68\xe3\xa4\x81\x6e\x41\x7e\x59\x49\x21\x69\xf9\xff\x36\xc0\x9c\xff\x8f\x54\x94\x2b\x3d\x25\xb8\x2a\x49\x12\x40\xfe\x5d\x89\x1e\xf2\xd7\x99\x72\xc4\x6c\x7b\x4f\xad\x8e\x70\x85\x30\x47\x8e\x83\x94\x2a\xe7\x5b\x81\xe2\x21\xb9\x5d\x4a\xcd\x22\xbc\xce\x26\x11\xfa\xe2\x86\xad\x5f\x1c\xf6\xd4\x0d\x3e\x0c\x7d\x71\x2e\x5e\xb4\x48\xff\x04\xda\xb5\x09\x65\x20\x5f\xfb\x02\x24\xbe\x78\x5a\x11\x69\x44\xe0\x11\xdf\xd9\x7f\x73\x32\xa8\xdb\xef\xf3\x8a\x91\x99\xb6\xbd\x77\x4e\x4c\xfb\x4c\x81\x0c\x01\x72\xb6\x50\x0c\x0a\x9c\x5c\xfe\x1f\xde\x04\x4a\x07\xd0\xae\x05\x5b\x31\x51\xa0\x52\x4e\x5c\xfb\x3e\x40\xf9\x94\x9c\x9b\xbd\x3d\xed\x6f\xfd\x1d\x2f\xeb\xd2\x91\xf4\x1b\x5c\xc6\x2d\xe7\xf3\xd0\x36\x33\x94\xff\xf4\xf2\x6e\x58\x6d\xdc\xb4\xdf\xe7\xc2\x61\x1d\x6f\x65\x7c\xd2\xcd\xc1\x2b\x36\x32\xdf\xc8\x66\x8e\x84\xbc\x91\x8a\xb0\x3b\x5a\x56\x05\x3b\x74\x0f\x37\xbf\x9b\xfc\x5b\x0a\x16\x1e\x54\x30\x3e\x78\x38\x48\xbe\xd8\xc9\x48\xf2\xca\x29\x95\x2a\xb0\x16\x21\x5f\x45\xa1\x18\xa9\x97\x5d\x6e\x1e\xc0\x30\x2a\xe4\xd5\xd1\xab\xa3\x97\xaf\xc9\x4f\xc4\x7e\xf0\x2b\xff\xcf\xaf\xfc\x3f\x7f\x47\x7e\x42\x88\xfc\x89\x10\x72\xb9\xf1\x4f\xf7\xf7\x13\xc2\xe7\x61\x65\x30\x29\x5c\x6d\x17\x91\x8b\x4c\x96\xfe\x54\x01\xfa\x06\xd4\xea\x8c\x35\x8f\x75\xc8\x7c\xb3\xfb\x60\x60\x29\xca\x64\xc9\x60\x65\x5e\xfd\x9f\x20\x15\xe7\x8f\x70\x43\xa4\xf0\xb2\x5f\xed\xc3\xd2\x1e\x90\x5b\xe8\xa9\x58\xd2\x1b\xec\xc3\xf8\x71\x66\x6a\x5a\xd8\x45\xdc\xff\x6a\xf2\xf2\x80\x48\xd1\xfb\x01\x84\xd4\x15\x97\x05\x35\x2c\xec\xcd\xfe\xab\x83\x69\x82\xcd\xfa\x6a\xc7\x66\x45\xee\x13\xac\xa6\x55\x23\xf6\x53\x83\x0a\xa4\x4d\xee\x0b\x21\xd1\x71\x41\x34\xbd\x4a\x9b\x1a\x92\x57\x70\x5b\x5f\xe2\xbe\x5c\x48\x13\x40\xb4\x83\x5b\x71\x24\x44\x81\xfc\xee\xab\xc1\xe8\xaf\xe6\x9d\x2d\x1a\xf7\xd5\x48\x0a\x88\x10\x9c\xa3\x27\xe7\xd0\xca\xd4\xa9\x3c\x3d\x25\x17\x32\x0f\x9d\x11\x96\x74\x85\xc2\x1e\xfb\xb4\x9c\x6f\xb0\xcf\x75\x93\xc3\xe5\xc0\x72\x91\xa1\x68\x2e\x3a\x58\xe9\x4c\x42\xb7\x1f\xe5\xa0\xfe\x33\xe6\x9d\x73\x0c\x0c\x84\x42\x37\x04\xff\xb2\x4b\xbe\x6f\x65\xe3\xa8\x95\x89\x2b\x0f\x70\x93\xfd\x8b\xeb\x09\xf1\x62\x56\x67\x37\xcc\x38\x9f\x17\x85\xa2\x82\x3e\x44\x55\x6d\xc8\x8c\x16\x54\xd8\x28\x37\xc1\x6b\x9d\x91\xae\x50\xd6\xcd\x0e\xae\x7a\x92\x9b\xfe\x65\x20\x35\x6e\x6c\x3d\x3e\xc7\xba\xa7\xdf\x6f\x0a\x6c\x4b\x13\x10\x0b\xe2\xc1\x08\x39\xa3\x45\xa8\xbe\x82\xfe\xfb\x4d\x3b\x0b\xb1\xb7\x87\x09\x0a\xdc\xfc\x3c\x12\xce\xf9\x26\x2d\xe2\x65\x4a\x26\x08\x91\xa7\xf2\x42\x9a\x00\xce\x21\xfb\x1e\xf1\x78\x40\x0c\x2b\x0a\xac\x8f\xde\xf4\x16\x05\x75\x6d\x64\xf3\x17\xf6\xf3\x27\x0d\x14\xe8\x58\xac\x6f\x51\xb1\x5f\x33\xb7\xce\x2f\xd9\x5f\x31\x68\x64\x91\x1b\xdc\x78\xbb\xd7\xd1\x33\x54\x93\x17\xbd\x83\x31\xbc\x2d\x15\xb4\x4a\xb0\x5a\x10\xfc\x29\x3e\x27\x55\x41\x33\x57\x4d\xe8\x6c\x38\x42\xa2\x3d\x4e\xd2\xfb\xfd\xc1\x4b\xf7\xbe\x86\x26\x2f\xbc\x73\xf1\x62\xf4\xd9\x87\x8d\xdf\x59\xcf\x34\xb5\xcf\x7e\x09\xff\x6f\xdb\x77\x3f\x9f\x93\x2d\xad\x83\x73\x8a\xfc\x9a\xf6\xae\xf2\x61\xec\xe9\xda\x19\x00\x04\x77\xfe\x2b\xf0\x88\x7f\x87\xc3\x5a\x87\x38\xe0\x77\x47\x5f\x1d\xbd\xda\xb7\x6b\xfe\xd5\x81\xbd\x67\x3d\xef\xfb\x15\x46\xb6\xf7\xd7\xc3\xec\xbc\xbe\xe4\x4c\x77\xfd\x6f\x84\xdc\x73\xe1\x20\xa8\xe4\x56\xaa\xdc\x83\x5b\x03\x19\x40\x86\x7a\x19\x71\xba\xca\x7a\x30\x65\xb0\xed\x87\x64\x56\x77\xfa\x32\x23\x84\xde\x4a\x6b\x57\x20\x00\xb2\xba\xec\x37\xa5\x54\xec\x37\x9d\x5f\x40\x7d\xfa\x46\x20\x80\x68\x1a\xec\x06\xd2\xda\xdf\x4d\x3a\x14\x7b\x05\xd7\x66\x52\xd2\x6a\x72\xc3\xd6\x83\x72\x61\x58\xa0\x5b\x1c\xcc\x6d\x7b\xee\x6e\x11\x4a\xfa\xf9\x3d\x78\x5d\x33\x46\x3c\x60\x78\xef\xad\x87\xfe\x78\x41\x1e\x04\x02\x01\xe3\xa0\x3d\x2c\x1d\xe4\x0c\xe0\xb0\x2d\x91\xcb\x8c\x15\xd2\x35\x09\x75\x75\x4f\x83\x44\x0e\x60\x1b\xca\xa4\xc8\x58\x65\xf4\x91\x36\x52\xd1\x05\x3b\xf2\x9f\x33\x9c\xf2\xe4\x4b\x23\x5d\xbf\x73\xdd\x34\xbb\x85\x66\x8e\x7e\x71\xe0\x0d\xf2\x5d\x39\x03\x47\x90\xdb\x47\x9f\xf8\xa4\x19\x50\x05\x0c\x15\x39\x5b\xf7\x09\xdf\x3b\xf4\x06\x4f\x1c\xec\x3a\x98\x1b\x05\x0f\x83\xa1\xb7\xfa\xac\xa0\xda\xf0\xec\xaf\x85\xcc\x6e\xae\x8c\x54\xd1\xd1\xc6\xf1\xf7\x57\x5b\x32\x11\xba\xb9\x7b\xa6\x04\x39\xfe\xfe\x8a\x9c\x72\x7d\x43\x14\xd3\xb2\x56\x03\x69\x89\xdc\x70\x5d\x01\x75\xaf\xa2\x9e\x92\x1b\xd7\x90\x70\x6f\x0f\x17\x0b\x69\x7b\x4e\xb3\x25\x17\x2c\x3c\xfe\x88\xa6\x7d\x2f\x0a\x2e\x12\xce\x68\xa4\xee\xf8\x15\xbd\xd5\xcc\x6d\xc3\xcc\x6e\x83\xfd\x9f\x19\xd6\xb0\x3d\x02\x89\xba\xfb\x8c\xf3\xd3\xc1\xff\x69\x1c\x26\x6c\xae\xaf\x91\x5d\x61\x36\xaf\xc1\x1b\x5e\x30\x57\xd0\x85\xef\x08\x43\x36\x9a\x4a\xc3\x09\x5e\xcb\x9a\xdc\x52\xf4\x9b\xaa\x91\xce\xda\x4d\xc9\x35\xaf\x5e\x93\xb3\x4e\xc7\x4c\x3c\x6e\x6d\xde\xff\x58\xf0\xdb\x43\x6f\x05\xa4\x48\x5f\xf4\x02\x37\xcc\x3d\xcf\x5a\x43\x8c\x2d\x91\x73\xe3\xcc\x85\x7e\xfa\x35\x79\xc1\xee\xcc\xef\x5f\x1c\x92\x17\x77\x73\x6d\xff\x21\xcc\x5c\xa3\x22\x4a\x3b\xce\xcb\xaa\xe0\x19\x37\x36\x00\x16\x73\xa6\xda\x14\x9e\xfb\x19\xec\xab\xf2\x66\x0f\xc2\xf4\x0a\x01\x39\xb3\xeb\xf7\xa7\xef\x5f\x43\x22\x28\x97\xe4\x96\x91\x4a\xb1\x15\x13\x86\x30\xa5\xe4\xc0\x42\xa2\xce\xe7\x0a\x4f\x92\xd7\x1c\x25\xa0\xe2\xcb\x64\x59\x29\x59\x72\x8d\x07\xc0\xb8\xc7\x4e\x50\xd2\xc3\x35\x20\x89\xc7\x97\x40\x75\x36\xa8\x85\x04\x7a\x05\x88\x65\x82\x40\x2c\x3f\x2d\xb9\x57\xab\xe0\x31\x8e\x5e\xab\x9c\xcf\x89\x74\xcf\xc9\x3d\x32\x2d\x3c\xb2\x22\x28\x2c\xab\x11\xfc\x8c\xc5\x60\xce\xd5\x76\xb4\x3a\xe0\x8d\x54\x41\xe0\x51\xce\x56\x47\x3a\xa7\xaf\xb0\xc0\x49\xbb\x7c\xee\xaa\x3a\xb5\xd5\xee\x10\x2a\x57\x63\xc7\x8b\x57\x2f\xa6\xe4\x8a\x97\xbc\xa0\xaa\x58\x1f\x76\x77\xac\x91\x8e\x55\xd7\x52\x35\x9f\x0c\xe0\x95\x97\x2f\xc8\xbe\xe3\xa9\xc2\xa2\x55\xa8\x20\x05\xa3\x2b\x16\xe8\xbd\xa0\xf3\x85\x43\xc4\x1d\x20\x02\x6a\x12\xfd\xa0\x45\x22\x1f\xb5\x08\x38\x30\x34\x7f\x2f\x0a\x24\x40\x7c\x83\x6a\xd5\x9f\x8e\x17\x46\xd5\xec\x05\xfe\x9a\xcd\xa5\xca\x9c\xaf\x09\x99\xb1\x25\x23\x1f\xfc\x2c\x63\x1b\x8e\x70\xe1\xe3\xb9\x77\xf6\xba\xc1\xc5\x73\x93\x8d\x40\x74\xee\x52\x05\x70\xe2\x80\xd4\x13\x6d\x71\x9f\x84\x6f\x4c\xa2\x9a\x33\xbb\x11\xdc\xdc\x14\x27\xec\xa3\xe0\xff\xaa\x19\x39\x3f\xf5\x5e\x23\x72\x6d\x2b\xa6\x34\xd7\xc6\xda\xf3\xbc\x1b\x71\xe1\x6d\x8d\x0d\xde\xf6\x8f\x4b\xfa\x6f\x29\xc8\xd9\x5f\xaf\xfc\x47\x1f\x38\x8f\x06\x7d\x58\x9f\xca\xe6\xa3\xdc\x02\xfa\xef\x5a\x31\x1b\xd0\x46\x46\xdb\xc7\x41\x4e\x5c\xdd\x83\x8d\xb0\xad\x24\x72\x4a\x0d\x75\x81\xb6\xb3\xb9\x12\xfb\x06\x0d\x7e\xbb\xd5\x52\x33\xa8\x1d\x0d\xfc\xdd\xe8\xb6\x6d\x8f\x16\x88\xda\x3b\x80\x6a\x8d\xe1\xfe\xd3\x8f\x1f\xce\xbf\x70\x08\x9b\x81\xa7\xbb\x78\x27\xf3\x24\x71\xec\xdf\xec\x46\x9e\x38\x99\xa4\x44\x0b\x25\xe4\x42\x0a\x76\x08\xc6\x8a\x58\x6b\xe5\xff\xf5\x7b\xc5\xcd\x30\x72\xe7\x76\x44\xba\xe5\x61\x67\x13\xac\x92\x75\xca\x2f\x3a\xc4\xf5\xa8\x9e\xf3\xed\xac\x42\x2c\x34\x2b\xe4\x8c\x78\xfd\xf5\x58\x2b\xf4\xf1\xc3\x79\xa2\x05\xfa\xf8\xe1\xfc\x97\xb4\x38\xc9\x52\x45\x1b\x99\xa2\xe8\x08\xec\x9d\x2f\x47\xa1\x9d\x58\x1a\x1b\x25\xda\xf9\xb4\x5d\x32\x77\xe6\x64\x90\xa2\x7d\x26\x87\x9c\xdd\x4d\x9f\x63\x36\xe6\x31\x4e\xdc\x0d\x17\xc8\x3a\xdd\xbe\x4a\x3f\xf3\xa4\xc6\x71\x15\x50\xd0\x2d\x20\x7f\x4d\xca\xba\x30\xc0\x21\x0b\x17\xd2\xde\x50\xac\xc4\x8a\xa9\x70\xa1\x89\xef\xa8\x41\xc8\x29\x73\x50\x25\x74\x85\xb2\x2f\x7b\x69\x66\xd7\xfd\x19\xa4\xc8\x66\x72\xef\xa8\xa0\x0b\xbb\x08\xe0\xcf\x91\xd2\xfd\x11\xab\xdc\xac\xef\x05\x33\xdc\x77\x60\x1a\x11\x04\x12\xba\xa2\xbc\xa0\x33\x5e\x70\x74\x74\xa7\x99\x39\x98\x86\x10\x0c\x82\x3b\xe8\x25\x92\x3f\x8a\xe9\x4d\x18\x58\x77\xa9\x1f\x21\xa8\x44\xae\xcf\xbe\x9d\xd3\xd1\xad\x75\x47\x0e\xa6\x6d\x4c\xbd\x64\xe8\x10\x05\xb8\xa0\x5c\xb8\xde\x0b\xd3\x7d\x13\xcc\x34\x51\x7a\x8c\x22\xc2\x85\xad\x70\xd4\xad\xcd\x4a\x11\xba\x58\x39\x89\x42\x17\x10\xe5\x3b\x06\x8d\xd1\x0b\x8c\x09\xd1\x2c\x53\xcc\x20\xe3\x17\x50\x10\xa8\xff\x36\x2e\x82\x19\xb5\xc3\xf3\xd5\x0e\x04\x4c\x4d\x38\x74\x09\x76\xb0\xdb\x5a\xd2\x09\x46\xbf\x78\x74\x09\x62\x9c\xce\xb8\x8a\x72\x03\x42\x5f\x32\x88\xfc\xac\xb6\x18\x4a\x34\xd6\x4c\x2d\xce\x9a\x36\xf7\x34\xc1\x72\xbb\x8e\x60\xe8\x5e\xa0\x11\x5f\x92\xb1\x6a\x39\x8f\x25\x0e\x3e\x61\xd5\xf2\xcd\x55\x1f\x90\x64\xff\x0e\xf1\x31\x6f\xae\x7a\x56\xc4\xd9\x04\x38\x44\xb0\xde\x28\x5b\xe5\x3b\x59\x14\x7c\xce\x0c\x47\x2c\xf1\xa3\xd9\x91\x52\x0a\x6e\x30\x6f\xbb\x91\xcc\x63\xfe\x67\x53\x44\x3d\x1f\xc2\xe7\x93\x77\xd8\x8f\x71\x03\xf8\xaa\x32\x59\x14\x2c\x83\x17\x3e\x39\x87\x23\x86\x5f\x23\x37\x76\xbc\x69\x78\xa8\xba\x9e\xde\xfc\x11\x12\xdb\x3e\x85\x7d\xe4\xae\xca\xd1\x87\xb3\xe3\xd3\x77\x67\xd3\x32\xff\xd5\x52\xde\x4e\x8c\x9c\xd4\x9a\x4d\xb8\x89\xf1\xe8\x1f\x89\x64\x2c\xfa\x81\xdd\x2c\x53\x1c\x91\xb6\x55\xdd\x47\xcd\x90\x30\x7b\x12\x00\x07\x1e\x52\xaa\xa4\x34\x87\x44\x51\x80\x58\x9b\x25\x9a\x6a\x26\x74\x93\x73\x67\xcd\x28\xc6\x0e\xe3\xdf\xd6\x07\x35\xac\xec\xcc\xe5\xc9\x44\x7f\x7b\x5b\xdd\x05\xd1\x7b\xe6\x1d\xc4\x7b\x5c\x3d\xa4\x54\x68\xd5\x7e\x8f\xab\x87\x0f\xe4\x8d\x6f\xd7\xd5\x73\xf5\xd2\xbd\xa6\x7d\x79\xb5\x13\xeb\x6b\xe2\xc2\x51\xf2\x33\xa7\xe9\xaa\x91\x1b\x81\x5c\x01\x20\x88\x59\xda\xb3\x75\xc3\xd6\x04\xc8\xa1\xe6\x68\x96\x91\x8f\x9a\xa9\xc3\xee\x23\xfa\x11\x33\x19\x6c\xca\x51\xad\x99\x9a\x46\x79\xc7\x4f\xc2\xfa\xe0\x3d\x60\xf8\xf4\x0f\x6c\xfe\x10\x87\xe0\x03\xc3\xa2\x1f\x80\xc2\x29\xf0\x63\xf8\xfc\x01\xad\xcd\xd2\xd5\x0b\x47\x00\x78\xdc\xf7\x02\x8e\x67\xf3\x54\x20\x25\x7a\xee\xaa\x27\x71\x0c\x22\x78\x65\xe2\x19\x21\x05\x3a\x8e\x22\x5b\x27\xa9\xf3\x24\x88\x96\x48\xc2\x11\x32\x83\x11\xa0\x72\xc5\xd4\x8a\xb3\xdb\xa3\x5b\xa9\x6e\xb8\x58\x4c\x6e\xb9\x59\x4e\xdc\xea\xea\x23\x68\x00\x7b\xf4\x2b\xf8\x47\xc4\xec\x1c\x16\xf4\x38\xcf\x7d\x15\x59\xad\xd9\xbc\x2e\x5c\x25\x55\x14\x07\x1e\xad\xf8\x77\x4c\x69\x2e\xc5\x21\xbc\x7c\x1c\x92\x9a\xe7\xdf\xe0\xce\x15\x89\x57\x31\x56\xc5\x26\xf7\x31\x15\xfe\xc2\x5a\x5d\xa2\x68\x2e\x81\xd7\x5b\xc1\xb1\x4d\xe0\x10\xd2\xbc\xe4\xe2\x69\x68\x01\x5c\x12\x81\x8b\x1c\xb3\x4f\xfd\x3d\x3a\x01\x29\xb1\xfd\xb3\xdc\x5c\x02\x66\xb3\xa9\x3a\xa1\x21\xa3\x8c\xa4\x32\x09\x15\x2b\xba\x57\x7d\xd2\x55\x0e\x98\x84\xf7\x3d\xdb\x5c\xae\xf5\xbf\x8a\x89\xfb\x92\x49\x95\xb7\xfb\x3c\x96\x92\x7c\x6a\x3c\xb5\x52\x92\xb6\xf0\xe3\xb9\x01\x04\x76\x17\x6d\x20\xc5\x7a\x70\xc1\x2e\x98\x00\x7e\x61\x1b\x70\x41\x12\x98\xc0\x67\x79\xe3\x09\x6f\x26\x19\x43\xfa\x01\xe3\x17\x11\xd2\x3f\xc8\xe9\x89\x8d\xe2\x93\xc7\x6f\x95\xe4\x78\x8a\x4c\xa8\x0e\xf5\x81\x96\xb3\x5a\xe1\xf5\x08\xaf\xd3\x2a\xaa\x68\xc9\x0c\x53\xae\x1b\x8b\xfd\x8d\x4c\x0a\xe1\x1a\xfc\x22\x65\xbe\xaf\x98\xb8\x32\x34\xbb\x89\x42\x51\x8e\x31\x57\x6f\x8c\x31\xd7\x53\x88\xb9\x52\x56\x47\x04\x8a\x81\x3c\xdc\x3c\xac\x5e\x05\xb6\x37\x5f\xe6\xd5\xf2\x16\x38\x55\xfa\x1f\x61\xef\x33\x29\xe6\x7c\xf1\x8e\x56\xb1\x6f\xb5\x41\x4e\x24\x00\xa8\x9d\x50\x78\x9e\x05\xaa\xcc\x4a\x56\x75\x81\xed\x44\xca\xb5\xdf\xdb\x2f\x1b\xe6\xc4\xa9\x52\x1f\xfd\xa7\x42\xfe\xb7\x76\xb4\x94\x39\x23\x33\x1e\x63\x4a\x6b\xcd\x6c\xec\x9a\xf9\xe6\xa9\x10\x78\xd8\x70\xc1\xcf\x19\x7d\x71\x9a\x50\xc6\x51\x70\x06\x12\xe2\x97\x48\x5a\x42\x3b\x5e\xfe\xe1\x0f\x7f\x98\xf6\x90\x43\x2f\xbf\xfe\xfd\xef\xa7\xe4\x94\x2b\x60\xe1\xe2\x68\xdd\x6d\x6d\x41\xa0\x21\xa1\x66\x09\xb4\x8f\x40\xfa\x09\x9d\x83\xe3\x4a\xe5\x1d\x55\x96\x75\x23\x5d\x07\x02\x52\xf2\xc5\x12\x9b\x09\x72\xec\x93\xf6\x5e\x15\x3c\x33\x8e\xe6\xcf\x99\x1a\x09\x87\x02\x9f\xb4\xa2\xe1\x6b\x9b\x62\x6f\x38\x5d\x87\xa4\xe0\x28\x66\x5b\x02\x91\xf6\xb7\x4a\xd6\x55\x4b\xbf\xae\x98\xae\x0b\x83\x64\xaf\x22\xee\xfb\xdd\xe7\x36\x27\xdf\x2e\xee\xb3\xad\x63\x8d\x78\x9b\xef\xa9\x84\xf3\x5e\x70\x7b\x88\x65\x13\x25\xae\xed\xd2\xc4\x5d\xd9\x8a\xf2\x86\x9c\x07\xca\xcf\xc0\x8d\x41\x8a\xf5\xf5\x37\xcd\xab\x4b\xde\x5a\x19\xf4\x9d\x75\x5c\x66\x95\x92\xff\xe3\x50\xf3\xc0\x32\xda\x5a\x7f\xa4\x5c\x60\x51\x85\xf3\xef\x1a\x1a\x00\xc6\x2d\xaa\x79\x54\xe0\xa3\xb5\x51\x8a\xef\xab\x16\xd5\xac\x9f\xb8\x36\x34\x9d\xfd\xb6\xe2\x0a\xae\xed\x22\xdc\xb0\x35\x5e\x0b\xde\xbb\xa2\xcd\x6f\xa1\xe3\x2b\xb3\xd4\x4e\x0f\xd4\xa2\x33\x53\xf8\x4d\x6c\x70\x22\x8d\x9b\x2d\x78\x28\x40\x70\x40\x7d\xa7\x2f\x6c\xb8\x1f\xbe\xd2\xd3\xfc\x7b\xea\x67\xff\x0b\xe8\x78\x1f\x56\xb0\x39\xee\x87\xf1\x47\x54\x33\x53\x57\x6e\xbb\x80\xd9\xc3\xae\x29\xd3\xda\xb5\x7f\x47\xca\x2c\xa9\xba\x61\xb9\x37\x23\xb4\x98\x92\x4b\xbb\x65\xd0\x42\x07\xaf\xab\x5d\x93\xae\x95\x03\x61\x96\x74\x0d\xcb\xe9\x83\xf5\x88\xe7\x95\xbd\xe9\x74\xcf\x19\x6a\xa9\x88\x36\x54\x19\x2c\x9d\xa7\x1d\x56\xda\x73\xef\xff\xf8\x8e\x56\xda\x75\x12\xe2\x62\x11\xd1\x83\xc5\x67\x57\x60\x6d\xbd\x53\x44\xfd\x59\xfd\x8f\xed\x85\x68\x17\x03\xab\xf6\x9e\x58\x1f\xc4\x6b\xdf\xe1\x32\xb2\x5f\x9e\x37\x10\x8f\xde\x77\x2e\xa6\xea\x99\xdc\x1f\x56\x45\xad\x4d\xeb\x98\xb6\xc1\x95\x89\x6d\x3c\x66\xdd\x91\xc3\xa6\x9d\x99\x8f\xa9\xa2\x24\xf6\xe2\x31\x1f\x59\x45\xb6\x87\xb3\xba\x7d\xc3\x27\x89\xb2\x72\x6e\x74\x62\xe7\xc6\x41\xa9\x35\xfe\x05\xc7\x8d\x36\x10\xdb\x08\xa9\xa2\xa4\x6e\x87\x63\xd8\x46\xdc\xed\xd8\x19\x94\x45\x49\xb4\x01\xdd\x56\x68\x16\x25\xb1\x0d\xeb\xfa\x01\x5a\xdc\x09\x8d\x0b\xee\xdc\x88\x0f\xf1\xdc\x88\x0d\xf4\xdc\xc0\xc3\xa1\xdd\xd8\xd2\xe5\xc1\xbf\x8a\xd3\xe6\xe0\x48\xcd\xdb\x23\x66\xe4\x20\xb2\xe0\x5d\xc3\x34\x86\x66\x4a\xde\x79\xbf\x6f\x20\xf5\xef\xe6\xa0\x82\xd0\x99\x96\x45\x6d\x5c\x92\x06\x04\x47\x2b\x2c\xef\x8c\xb6\xa9\x9f\xb8\xc6\x78\x6e\x80\x47\xd9\x7c\x77\xb4\x83\xea\x06\x84\x61\xce\xbf\xc3\x7b\xac\x5e\x54\x9c\xf1\xc5\xbf\x0a\xdd\xfb\x22\xd4\xbe\xeb\xa4\x4b\xd4\x3f\xea\x6b\xd0\x83\xbc\x04\xa5\x7c\x05\x8a\x3c\x03\x32\xca\x59\xea\x57\xb6\x79\x02\xb6\xdb\x25\xf3\xb5\x18\x58\x45\xd1\x3e\x5c\x48\x45\xac\xf9\x80\x14\x83\x77\x9b\xd0\x61\xd6\x9c\x0b\x64\xde\x23\xe6\xf5\x3d\xd3\x3c\xf6\x19\xe7\xea\x9c\xec\x9f\x34\x34\xdb\xf8\x92\xca\x73\x61\x98\x9a\xd3\x8c\x1d\x74\x91\x77\x81\x10\x02\xe9\xe1\x70\x4d\x96\x54\xe4\x85\x03\x27\x51\x41\xd8\x9d\x61\x4a\xd0\x02\xe6\x9d\x2b\xbe\x42\x19\xec\xfd\xe3\xa2\x5a\x52\x32\x67\xd4\xd4\x8a\x21\xfa\x2e\x3c\x1e\x9f\x15\xee\x93\x23\x5f\xa6\xe0\x47\x53\xd4\x73\x83\xa0\x90\xda\x1c\xcc\x94\xde\x0e\x6f\x0f\xda\x43\x10\x9a\x83\xd9\xb3\x82\x7f\xde\x68\xde\x0d\xa7\x56\x4b\x80\xbb\x0a\xde\xfa\x5a\xd6\x58\xbf\xd0\x41\x72\xe7\x52\xb9\xce\x1c\x52\x29\xeb\xa8\x43\xba\x18\x5d\xa0\xa6\xd8\x82\x6b\x03\x3d\x80\xbc\x53\xe2\x3b\x7e\x3c\x0a\xaf\xcd\x93\x65\x52\x4a\xcf\x4d\x34\xf7\x99\x5e\xb9\xe2\x79\x88\x5e\xa1\xf4\x22\x2a\xd6\xe6\x9a\x54\x54\x7b\x40\x11\x14\x99\x68\x2d\x33\x4e\xf1\x4f\x8a\x9d\x7b\xe1\x72\xd4\x10\x13\xe7\xcc\x30\x55\x72\x81\x86\xa0\x76\x48\x40\xbb\x94\xe1\x92\xd0\xaa\x2a\xd6\x8f\x72\xf8\x84\xcc\xd9\x65\x3d\x2b\xb8\x5e\x5e\x25\x44\xa1\x5d\xec\x10\x8b\xdf\x5d\xba\x5d\x47\x14\x55\xed\xb5\x85\x67\x23\x9a\x09\xcd\x23\x62\x3c\xeb\x13\xdb\xd8\x95\x4b\x01\x7d\xfd\xa8\xd6\x61\xa6\x27\x57\xc3\x29\x10\xdd\x08\x9a\x59\x02\x0b\x78\xc1\x0c\x6b\x94\x76\x67\x7d\xbf\x8b\x7a\x86\x13\x39\xc8\xfa\x28\xaa\xae\x34\x92\xd1\xa2\x40\x3b\xd0\x90\xf6\x69\xfa\x8c\x07\x1f\xd6\x25\x41\x48\x89\x0e\x27\x67\x41\x57\x70\xab\x46\x02\x36\x11\x8a\xcc\x9c\x3f\x10\xa1\x96\xda\x23\xb5\x71\x38\xd0\x0f\x3d\xd2\xb5\x15\x10\x44\x8a\x20\xfa\x90\xd0\xa2\x88\x3b\xb9\xcd\x3d\x70\x4d\x33\x9d\xda\x7b\xa4\x26\xe6\x23\xf0\x71\x04\x3e\xde\x33\x9e\x0e\x9c\xfe\xca\xa7\xca\x9d\x11\xa1\xf9\x44\xe2\x71\xea\x0e\x68\x57\x2b\xa7\xe6\x83\x4b\x1a\xf7\x6e\xb7\xc5\xd0\xd4\x47\xeb\x7f\xf1\x80\x98\x34\xb8\xd3\x63\xe3\xbb\xe6\xa7\x80\xce\x7c\xb7\x21\x12\xfb\x24\x6f\xa4\x62\xda\x1b\xc6\x89\x7f\x06\xc9\x3a\x9a\x28\x0a\x98\xd5\x28\xd4\x8e\xe9\xf6\xbf\x85\xdd\xde\x10\x05\xd9\x00\xc8\x8b\xda\xd3\x24\x97\x59\x5d\x32\x61\x62\x6a\xa0\xed\xf1\x6b\x2b\x8f\x1c\x95\xe5\x23\x19\x02\x9a\xe7\xdc\xd9\xf8\xcb\x68\x93\x10\xa1\x39\x72\x79\x2b\x6e\xa9\xca\x8f\x2f\x11\x94\xbd\xfd\x30\xbb\x95\x14\x07\xce\x0d\x53\x22\x56\x12\x9d\xc9\xda\x04\x12\x3d\x6c\x42\x67\x03\xdd\x3b\x62\x75\x47\xac\xee\x88\xd5\x1d\xb1\xba\x23\x56\x77\x13\xab\x6b\xe5\xb8\xdc\x41\xe1\xba\xa4\x62\x83\xf0\xae\x0a\xf7\x05\x2f\x73\x2c\x2f\xce\xd3\x81\xb2\x75\x4c\x9c\xf3\xcd\x22\xb8\x7e\x7a\xdd\x2a\xfb\x99\x10\xb4\x44\xa7\x7d\xdb\x9b\x17\x5d\x7b\xd8\xb4\x96\x8c\x02\x58\x3f\x09\x98\xdd\x23\x43\xe5\x60\xfd\xd0\x69\x42\x37\xee\xe1\x26\x8c\x7a\xba\x77\x6d\xe2\x1d\xae\x9c\x15\x79\x7c\x32\x00\xba\x18\xbf\x76\x9d\xd2\xa9\x10\xd2\xf9\xeb\x3a\x12\x17\x44\x67\xac\xd0\x87\xfe\x05\x43\xe4\xf0\x2f\xba\xa2\xa8\x9e\xae\xed\xb0\xf6\xb9\x09\x07\x12\x80\x79\xa2\x8e\x38\x49\x70\xcc\x09\x1c\x75\xd8\xc9\x4b\xfc\x79\x27\x89\xce\x3c\xe9\x25\x49\xe2\xe4\x6c\x86\xc6\x4e\x66\xa4\xc8\xe6\x49\x4f\x67\x4b\x56\xd2\xe8\x93\x6f\xc7\x9b\xb0\xf8\xd6\x8e\xde\x2a\x6e\x0c\x8b\x9f\xa6\x75\x2a\x99\x2a\x35\x91\xf3\x86\xb0\x27\x0e\xb6\x49\x9c\xdb\xfe\x62\xf5\x0a\xfd\x30\xd5\x88\x49\x81\x97\x25\x41\x47\x5e\x46\x02\xd1\xc8\xe6\x51\xb9\x74\x18\xb2\xf8\xd5\x02\xab\x6a\x75\xa4\x91\x44\x83\xda\x4c\xb2\xaf\xdd\x12\x16\xeb\x2f\x45\x0b\x5d\xb9\xbb\xf1\x24\xb6\x75\x84\x41\xa3\xc7\x08\x83\x1e\x61\xd0\x23\x0c\xfa\xb3\xc7\x13\x84\x41\x27\x72\xd1\x83\x33\xe1\x53\x1f\xa9\x60\xd5\xa2\x03\x71\x45\xc7\xe6\x61\x38\x3e\x2b\x9f\xfd\xf3\x6c\x61\x42\xc6\xdd\x2b\xab\x47\x03\xaa\x5a\xaa\xc8\xda\x3c\x3f\xcd\x25\x23\x7b\x7b\xd3\xe9\xde\x5e\xc0\x69\xe3\x6b\x08\x9b\x49\xd6\x66\x3e\xf9\x23\x61\x22\x93\xb9\xfd\xf6\xeb\xc8\xab\x3a\xe7\x4a\x1b\x48\x5a\xb4\x00\xe4\x54\x7b\x5e\xfa\x7d\x49\x05\xfc\x76\x6b\x19\x7f\xfd\x23\xbd\x8c\xd0\x6e\xf6\x4d\xf2\x20\xbb\x09\x8f\x63\xb5\xaf\x6b\x87\xeb\x37\x34\x0b\xc8\xd7\x38\xc5\x00\x31\x76\x90\xad\x49\xc1\x4b\x7c\x0a\xdf\x0d\x6b\x6a\x6c\x0c\xca\xb4\xd1\x64\xdf\x09\x9c\x66\x55\x1d\x6b\xce\x40\x4e\xc9\x4a\xa9\xd6\x87\xcd\x0f\x58\xc1\xc9\x66\xeb\xa5\x1f\xd8\x98\x3e\x4a\x68\x56\x2b\xc5\x84\x29\xd6\xbf\xc4\xcc\x40\x38\x2c\x4f\x20\x31\xd0\xdc\x01\x7c\x13\x9a\x76\x6c\x50\xb1\x06\xd1\xd1\xa1\x14\x60\x6d\x9a\xb5\x8f\xe0\x61\x6f\x87\x27\xc1\x3d\x6c\x20\x5e\xd1\x12\xe7\x52\x11\x26\x56\x64\x45\x95\x8e\x39\xa9\x24\x65\x2c\x9f\xf3\x15\xd7\x32\x52\xc1\xdd\x07\x4b\x49\x12\xcb\xcb\xda\x54\xb5\xf1\x7e\x63\xaa\x44\x12\xbb\xab\xa4\x66\x79\xab\x95\xe3\x34\x27\x69\xc3\x2b\xd7\x5b\xff\x15\xb6\x15\x69\x18\x15\x35\x86\x29\xf1\x9a\xfc\xf7\xfe\x3f\x7e\xfb\xd3\xe4\xe0\x9b\xfd\xfd\x1f\x5e\x4e\xfe\xf4\xe3\x6f\xf7\xff\x31\x85\x7f\xf9\xcd\xc1\x37\x07\x3f\x85\x3f\xfc\xf6\xe0\x60\x7f\xff\x87\xbf\xbf\xfb\xf6\xfa\xf2\xec\x47\x7e\xf0\xd3\x0f\xa2\x2e\x6f\xdc\x9f\x7e\xda\xff\x81\x9d\xfd\xf8\x99\x42\x0e\x0e\xbe\xf9\x75\xe4\xc4\xa9\x58\xbf\x8f\x32\xec\x04\x34\x60\xaa\x70\xa3\x2b\x2d\xc1\x75\x21\xe4\x6e\xd2\x22\xe5\x26\x5c\x98\x89\x54\x13\x27\xf8\x35\x31\x2a\x32\x97\x10\x8e\x63\x5a\x3d\x9b\x26\xbc\xe9\xce\xaf\x4d\xad\x3d\xa2\x22\x03\xbc\xec\x29\x8f\x66\x04\x3f\xf3\x72\x62\xa9\xea\x0c\x2b\x2b\xa9\xa8\x5a\x93\xdc\x23\x14\xd6\x49\x7a\x8a\x75\x9a\x8a\x0d\x46\x6e\xfa\x0a\xab\x40\xe9\xfe\x2b\x58\xb3\x9c\xab\x2f\x4c\xf1\x1d\xd9\x29\x8c\xe5\xbc\x2e\x53\x40\x69\xbe\xb7\xdb\x01\xe5\x23\x72\x1e\xd9\x27\xd8\x4d\x2a\x40\x96\x66\x34\xbb\x71\xe0\x8f\x66\xef\xf1\x00\x73\xd6\x6d\x04\xf3\xe2\x85\xaf\xd2\x28\x19\xc5\xe3\x3d\x5c\x02\x15\xea\xaa\x64\xce\xec\x91\x0a\x3f\xe1\xbe\x23\x1a\xf7\x23\x3c\x7c\xdd\x97\x17\xef\x7b\xf1\x07\x48\xb9\x52\x91\x77\x10\x28\x3c\xe2\x89\x27\x09\x7a\xd7\xf0\x7f\xb3\xb7\x36\xaa\x4a\x71\x78\xaf\xa5\xa1\x05\xa1\xbe\x71\x21\x36\xc3\x5c\xc8\x8c\x16\x4d\xe5\x65\xd7\x65\x8e\x49\xae\x37\x3a\x34\x54\xc8\xd9\x53\x6c\xbf\xde\x05\x95\x48\xa9\x5c\x13\x5a\x68\x57\x41\xc4\x33\x3a\x2b\x18\xcc\xd3\x85\x90\x51\xf7\xd6\x4d\xb0\xa4\x77\xbc\xac\x4b\x52\x6b\xbb\x16\xe8\x67\x4a\x37\x9f\xa0\x11\x9a\xa5\xb8\xb5\x9a\x01\x0f\x7c\x82\x46\x73\x5c\xc0\x04\x7b\xa0\x3a\x34\xe6\x8b\x91\xab\x70\x1e\x3b\x4f\x59\x11\x7d\x6e\x03\xce\x4b\xd7\x90\x03\xf3\xeb\x10\x95\xdf\x90\x73\xa8\x23\x69\xa2\x4e\x4d\x80\x3f\x0a\xd5\x99\xd9\x8d\x0d\x7d\x2a\x78\x91\x42\xa1\x82\x21\x59\xfa\xe3\x6d\xe5\xd6\xc2\x97\x79\x27\xa2\x1f\xd8\xad\xe6\x6a\xcd\xd4\x64\x51\xf3\x3c\x95\x82\x7b\x66\x71\x46\x44\x74\x91\x22\xa6\x48\x10\x49\x24\x8e\x1f\xe6\x59\xa4\xfb\xfb\xe6\xa4\xdf\x51\xf7\x0d\x9f\xa1\xf4\xc1\xc9\x92\x0a\xc1\x8a\x4e\x88\x60\xaf\x88\xd5\xe0\xbe\x39\x0e\x42\x26\x10\xc9\xf9\x96\x38\x7b\xfd\x9e\x38\x48\x5c\xb1\x59\x32\xd1\x04\xff\x8f\xd6\xf5\x7d\x6c\x3e\xf3\x69\xa1\x5f\xa2\xf9\x4c\xea\x0a\xf0\xed\xb6\x33\xbd\x06\x32\x58\x2f\xa8\xdf\x76\xc6\x17\xca\x2d\xe5\x2d\xc9\xb1\x10\xd4\x5b\xe0\x3c\x5d\x31\x61\x1c\xfb\xa7\x0e\x08\x97\xe8\x7d\x9b\x2b\x59\x42\x45\xaf\x92\x25\xd7\x36\x14\x00\x3f\xc6\x5d\xda\x47\xf1\xc1\x8b\x1a\x09\x69\xbb\xaf\x0a\xe3\xcd\x09\x31\x54\x2d\xd0\x65\xae\x45\x2d\x88\xa8\xcb\x19\x8b\x8a\x49\x1e\x13\xc7\x3e\x76\x04\x7a\x88\x8e\x40\x8f\xd3\x9e\xc7\x1d\xe5\xef\xbf\xbf\x48\xd2\x88\x3d\xdd\x2d\xb9\x95\xaa\xc8\x6f\x79\xee\x98\x60\x34\xd9\xb7\x53\x3c\xf8\xcf\xeb\x7f\x7e\x7b\xcb\xf3\xf4\x5b\x13\x05\x27\x83\xad\x21\xb0\x37\xbe\x63\x0a\xb7\x81\xda\x3e\x4c\x15\x9b\xf1\x39\xe3\x00\x76\x02\x19\x0e\x46\x52\xce\xb8\x88\x29\x22\x95\xf3\xce\xe1\x86\x58\xd5\x6a\xde\x38\x2a\x2f\xcd\xcc\x21\x99\xd5\x0e\x9c\x31\x93\x66\x49\x34\x2f\xeb\xc2\x50\xc1\x64\xad\x8b\x75\xd4\x25\x7e\x7e\x07\x74\x5e\xb0\x3b\xa7\xc3\x62\xa3\x90\x46\x50\x6c\x16\x7e\xc1\x04\x53\x3c\x0b\xd5\x4c\x9b\xe1\x08\x42\x26\x30\xfa\x68\x2e\x05\xcb\x8f\x9a\x4e\x9f\x35\xf8\x36\xc0\x39\xc6\x32\x84\xd0\x19\xb5\x11\x48\x55\xd4\x0b\x8e\x40\x00\x8f\x0c\x63\x9f\xfd\xdf\x3e\x24\xc3\x58\xcb\x61\x53\x6b\x16\x9b\x42\x8d\xa1\x5a\xf8\xa5\x92\x74\xfd\x87\x07\x94\xd7\xbb\x39\xb5\x72\x56\x31\x91\xa3\x33\xac\xa2\xab\x6d\xdd\xe6\x3d\xca\xa9\xf3\xc0\xee\xb4\xbe\xcd\xd9\x9d\x51\x58\x10\x60\x26\xcb\xd2\xba\x09\x01\x71\xce\xe7\x84\x8a\x38\x93\xfe\xfc\x89\x27\xc8\x18\xef\xfd\xa2\xe2\xbd\x07\x6a\xc7\x9a\x80\x08\xef\x1e\x1a\xbc\x38\x4c\xe6\x2e\x1a\xbc\x6e\x19\x37\xfe\xf0\x75\x69\xf0\x9c\x1f\xe7\x95\x69\x1c\xb5\x5c\x49\xd7\xbb\xc9\xe0\xb0\xea\xde\x31\xbe\x71\x4d\x3a\x29\xc4\xf3\x98\xea\xe1\xdd\x54\x72\x40\x0a\x87\x7f\x4d\xbb\x8f\x4a\x0e\xab\x1d\xb6\xf9\x8e\x36\xf6\x68\x6c\xa8\x3b\xf2\xca\xfd\x62\x78\xe5\xe6\x85\xcc\x6e\x30\x21\xd2\x46\x10\x0e\x52\x7a\xef\x81\x88\xaf\x09\x62\x7c\x04\xde\x84\xcc\xfd\xd7\x3c\x84\xe0\xee\xfb\x9f\x27\xd7\xf1\xae\xb0\x2b\x0d\xc5\x9c\xe1\x30\x59\xab\xc6\x94\xb4\x5a\x47\xad\x78\xc6\xc8\x8c\x59\x93\xa1\x6a\x81\x62\xe5\x78\x4c\xf2\x29\x6a\xa8\x66\x06\x8f\xd6\xef\x53\xdd\x76\x8a\xcf\xbc\x64\xac\xd5\x30\x52\xb1\x9c\x50\x4d\x4a\x66\xa8\x95\x45\x26\x7f\xf1\xc5\x6d\x31\x90\x16\x3f\x2b\x88\xbe\xc3\x66\x3a\x50\x1e\x1e\x7a\x93\x49\xa1\x79\xce\xfc\x7c\x73\x7b\x1d\x32\x34\xe1\x72\xa4\xef\xed\xbf\xef\xe3\xc7\x24\xad\xb2\xad\x98\x8d\xfd\x8c\xf2\x56\x00\xf8\xc2\xff\x55\x77\x33\xc1\x78\x6c\x1a\x6d\x76\x30\xe6\xac\x45\x2c\xf8\x22\x63\x97\x56\xa5\x6b\xc3\x84\x39\xe5\xfa\x26\x16\x5b\xfc\xed\xc9\x59\x5f\x60\x6c\x7a\xf3\xdb\x93\x33\xe2\xe5\x3c\x10\xce\xe2\x61\x81\x16\x1d\x17\x01\x63\x01\x10\x00\xd0\x45\xc6\xaa\x66\x0b\x72\xae\x6f\xbe\x30\xf6\x39\x26\xdd\x5a\xe5\x17\x98\x24\xe5\x2f\x0b\x5f\xe2\xd5\x95\x77\x27\xe0\xb8\xaf\x65\x4d\x6e\x29\xba\xc5\x52\x8b\x58\xb9\xe6\xd5\x6b\x72\x26\x74\xad\x58\x83\xe9\xc3\x22\x1f\x36\x72\x9f\x36\xe2\x0a\xe9\x46\xac\x29\xda\x95\xa4\x0c\xe9\x46\xec\x3b\xdb\x1d\x2d\xab\x82\xe9\xd7\xcf\x12\xfb\x12\x09\x06\xdf\xd2\x05\x58\xdb\xd7\x81\xe0\x6c\x83\x69\xb0\xdf\xba\x09\xc1\xd9\x06\xd3\x44\xf8\x49\x8f\x09\xc1\xa9\xa8\x32\x90\xcb\x4c\x02\x83\x07\xd6\x4e\x2f\x90\x44\x35\x01\xde\xa5\x52\xa2\xdf\x2c\xce\xe7\x44\x96\xdc\x98\xc0\xdc\xe2\x13\xf8\xf8\xbc\x58\xd0\x56\x56\x1d\xf8\x19\x5b\xb7\x39\x5e\x01\xbc\x91\x4d\x90\x76\x94\xb3\xd5\x91\xce\xe9\x2b\x6c\x1d\xa4\x5d\x3e\xed\xbb\x70\x99\xde\x0e\xa1\x1b\xd9\xbc\x78\xf5\x62\x4a\xae\x78\xc9\x0b\xaa\x8a\x75\x97\x06\xa7\x95\x8e\xd5\xd5\x52\x35\x9f\x0c\x45\x36\x2f\x5f\x90\x7d\xa9\xec\x57\x60\xf3\x8c\x54\x90\x82\xd1\x95\xcb\x18\x7b\x03\xbc\x76\x69\x3c\x24\xd3\xf9\xe0\x8e\x74\x0f\xe0\xf9\x90\x27\x81\x37\x73\x6e\x50\x0a\xe5\xf1\xd1\x05\x2b\x22\x3a\xef\x75\x79\xda\x7a\xe0\x5c\x58\xb7\x7c\x4a\x3e\x3a\x5f\x17\x7b\xd3\x5d\x00\xe5\xae\x8f\xdd\xad\x46\xee\x3b\x7c\x66\xf5\x89\x1c\x9e\x27\xf1\xf2\x14\x9e\x71\xda\x37\x1e\xbc\xf6\xd8\x78\x19\xea\xbc\xf1\x20\x65\xf6\x5e\x86\xb6\x1b\x27\xfc\x12\x34\x08\xee\xcd\x6a\xc1\xcd\x07\x56\x21\xa2\xc5\x8d\x40\xdc\x89\x89\xcd\x6d\x2e\xb8\xb1\x22\xa4\xe6\x50\xde\x4b\x0d\x74\xba\x57\x86\x67\x75\x41\x15\x51\xcc\x21\x85\x30\xdb\x75\x7a\x76\xf9\xe1\xec\xe4\xf8\xfa\xec\xf4\x35\x09\xb3\xe5\xdd\xec\x13\x46\xe8\xb5\x6c\xe1\x4b\x84\xb6\x65\x55\x8e\x60\x2d\x66\x05\x0e\xbd\x53\x42\x45\x5b\xf1\xc6\x05\x4a\xfb\x51\x41\xce\x05\x37\x6d\x9f\x49\x70\xc8\xb2\x42\x0a\xa6\x91\x2a\xda\xce\xd0\x63\xb4\x16\xdc\x1c\xba\x74\x84\x9b\xb0\xbd\xb7\x61\xc6\x08\xc9\xf6\x1b\x41\xc6\xa5\x2b\xcd\x6e\x96\x14\xf1\xa2\xf4\x68\x79\x85\xf6\x08\x7f\xe9\xec\x74\xa8\x8e\x4e\xa0\xd0\xaf\x01\xdc\xd9\x8a\x8c\x78\x4f\x6b\x99\xd0\x9a\x6e\xce\x52\x39\xf2\x2d\xa4\x54\xb8\x5f\xae\x89\xb3\x8d\x08\xf6\xa6\x7b\x21\x21\x50\x70\x96\x63\xbd\xec\x8e\x0b\xdc\x72\x0c\x78\x2e\xc7\x08\x91\x7d\xad\x36\x25\xe4\xbd\x59\x32\x75\xcb\x35\x9a\x1f\x91\xcf\x77\x13\x58\xc6\x98\xdd\x6e\x9f\xed\x0d\x3d\x1c\x15\x05\xea\x7a\xd6\x5d\x4c\xb3\xf4\xbf\xb0\x42\x97\xda\xe2\xc3\xb3\x68\x77\x29\x2c\x49\x82\xfb\xf5\xa1\x5d\xdf\x8f\x1f\xde\x3e\xce\xe7\x38\xcb\x95\xe0\x63\x4e\x64\x59\x72\x43\x96\x54\x2f\x43\x73\x2b\xec\x43\x56\x53\x39\x1d\x63\xed\xe3\x9e\x29\x5c\x43\xd7\x39\x42\x05\x6f\x78\x45\x41\x50\xf4\xb3\x44\x23\xc8\xd3\x13\x88\x36\x73\x89\x6e\x06\x44\x15\x74\x36\xfb\x19\x0e\x94\x88\x27\x04\xe6\xd3\x20\xd3\x9b\x3f\x82\x23\xec\x5d\xde\xa3\x66\x6d\x8f\x3e\x9c\x1d\x9f\xbe\x3b\x9b\x96\xf9\x33\x32\xec\x4c\xe4\x95\xe4\x98\x5d\x44\x76\x5e\x88\x73\x07\x9a\xe9\xa6\x88\xef\xce\x82\x30\x78\xb4\x46\xe3\xb0\x81\x1e\xcc\x8b\x72\x89\x02\x70\x47\x73\x66\x28\x2f\xb0\x42\xdb\xfb\x61\x64\x25\x0b\xb9\x58\x47\x1e\x63\x82\x3b\xca\xbf\x72\xd4\xaf\x13\x3a\xb1\xb7\xea\x71\x72\xc1\x58\xe6\xde\xfe\x6e\x07\xb6\x5d\xbb\x5d\xcd\xea\x22\x17\xb2\xc9\x2a\x02\xd5\xec\x76\xc8\xfc\xac\x16\xf8\x89\xa7\x4c\xda\x9b\x10\xb2\xef\xd8\x84\xd9\x8c\x39\x63\xc3\x72\xe7\xb5\x35\x1d\x30\x49\xc5\x54\xc9\xb5\x35\xcd\x68\x80\xd7\x76\x06\xe6\x79\xdf\x57\x5c\xf2\xc5\xda\x6f\x5c\xa3\x87\xfe\x39\xfa\x9b\x97\x13\xeb\x66\x54\x8a\x4d\xd8\x1d\xd7\x90\x6b\x03\x12\x77\xa9\xa2\x02\xc0\xae\x9f\x12\x00\x0f\x01\x50\xe1\xe4\xa2\x60\xdf\x1b\xc0\x87\x36\x47\x10\x50\x33\x98\xc4\x0b\x13\x4c\xd1\xa2\x58\x03\x69\xbf\x6b\x91\xe9\x9e\x09\xe9\x02\xb9\xa0\x52\x79\x4c\x64\xa5\xf8\x8a\x17\x6c\x61\xa7\xbc\xe4\x62\x81\x66\xdb\xa7\x8a\x11\x5a\x14\xf2\x96\xf9\xf6\x1b\x6c\x6b\x7d\x31\x37\xf2\x9d\xfd\xef\x3b\x9c\x40\x10\xf2\x5e\xbc\xbf\x26\x82\xb9\x29\xa3\xee\x79\x64\x72\xd4\x7e\x14\xb2\x5b\xd5\x64\x32\x81\x37\xe4\xfd\xff\x91\x82\xe9\xbc\x38\x20\xdf\x33\xff\x2d\x92\x28\x66\x75\x3f\x0a\x5f\x7c\xbb\x94\xf0\x12\x55\x6b\xbf\xe6\x6d\x60\x0b\xaa\x12\x75\xeb\x44\x1e\xe4\x1e\x59\xd9\x42\x1a\xef\xe4\xf7\x7e\x01\x47\xf7\x4a\x35\x69\xab\x37\x9e\x53\x06\xed\x11\x9c\xe5\xa4\x9e\x53\xc0\x00\x46\x26\xcf\x3a\xfa\x33\x54\x15\x38\x06\x7b\xb4\xfb\x4d\x89\x5e\x97\x05\x17\x37\x87\x84\x9b\x50\x89\x63\x35\x4a\x44\xc8\x6e\xc5\x05\x5d\xac\x18\x2d\x3a\x9e\xde\x17\x7f\x57\x0b\x5a\xe3\x51\x7c\x43\x93\x08\xd8\x75\xbd\xae\x5c\xbd\x6b\x30\xec\x51\xaf\x5e\x3d\x67\xeb\xc5\x8b\x74\x8e\xd6\xb3\xd8\x17\xae\x33\xcd\x63\x1d\xac\xf3\xab\x93\xab\xf3\xde\xe3\x16\x26\x77\xe9\xa4\x8c\xf0\xd2\xfb\x1c\x74\xd8\xaa\x67\x99\x17\xe2\xff\x1a\x7e\x1e\x26\xa4\xa8\x31\xff\x95\x23\xdd\xb8\x94\xca\x20\x48\xf3\xe3\x4c\x64\xb6\xa4\xd5\x71\x6d\x96\xa7\x5c\x67\x72\xc5\x92\xa4\xc1\x6f\x97\x0c\x7c\x64\x0f\xe6\x24\xdc\x5e\x12\x6c\x54\x19\xe6\x45\x4e\xfe\x76\x7c\x49\x68\x6d\xcf\xb1\xe1\x19\xbe\x14\x31\xb6\x1c\x34\xac\xd8\x15\xd3\x89\x32\xed\x29\xd7\xcb\xcf\xea\xc9\xac\xd6\x08\x8d\x46\x8d\x11\x1a\xfd\xf4\xa1\xd1\x60\xdb\x90\x53\x19\xe1\xd0\x83\x06\x17\xdc\x70\x6a\x64\x44\x4b\x9d\xfe\xdb\x66\xad\x8d\x2c\x9d\xa2\x05\x24\x0d\x08\x47\x2e\xce\x05\xc0\x21\xce\xe7\xfd\x59\xf6\xea\xc7\x63\x20\x11\x70\xcc\xce\x85\x61\x6a\x4e\x33\xb6\xc1\x9e\x85\x45\x1b\x08\x76\xeb\xbf\x9e\x37\x92\xff\x1c\xc5\x3e\x57\x81\xf7\xf2\x97\xd7\x7f\xee\x00\xae\xff\x12\x89\xb4\xf0\x5d\xf7\xc2\xf3\x33\xc9\xa4\x10\x2c\x33\x8f\xf1\x80\x6c\x07\xff\x57\x0a\x6b\xef\x41\x38\x6e\xf5\xff\xaf\x9a\x16\x31\x27\xe4\xe2\xb1\x70\x13\xfd\x53\x99\x60\x59\xc2\x5d\x0c\xa7\x11\x55\xc6\xe5\x06\xd8\xde\x5a\x33\x1b\xd3\x79\xb9\x46\x51\xa1\xed\x11\x4d\xf1\xba\xb1\xe7\x0b\x14\xf6\xc8\xbe\xc9\x2a\x24\x56\xfd\x49\x70\xb4\xba\xc5\xf1\x27\xf2\x2d\x22\x76\x71\xc3\x71\xb3\xc6\xac\xc3\xa3\x62\xe5\x41\x73\xa5\x78\x50\xef\x2d\x27\x32\x9c\x73\xe3\x2d\xd7\xc6\x75\x5c\x70\xb3\xb3\xd6\x84\x39\xbe\x47\x94\x1b\x6e\xc7\xf9\x25\x91\x8a\xf0\xea\x9f\x34\xcf\xd5\x6b\x17\x69\xf8\xfc\xa3\x44\xa3\xf6\xb8\xf6\x0f\x22\xc0\x48\x12\xa8\xb7\xf6\xcd\xba\xe2\x19\x2d\xd0\x0c\x40\xd7\x27\x97\x30\x2b\x4d\xfe\xf8\xb5\x6b\x13\xfd\xbb\xaf\xbe\x7e\x19\x75\xd5\x9e\x1f\x57\x24\x49\xfb\x36\xfd\x9f\x87\xe6\x7f\x4a\xcc\x4f\x10\x90\x3b\xce\x27\xf0\x67\x62\x82\x7c\xe7\xa8\xc1\xb5\x68\x7c\xce\x74\xc1\xfe\xc8\xd5\xd3\x1b\x23\x57\xcf\x63\x73\xf5\x90\xe6\xc8\x3b\x9b\xfa\x30\x96\x3a\x86\x72\xf2\x72\xdb\x48\x3b\x73\x8b\xb5\xaa\xf7\x18\x69\xfc\x23\xe1\x33\x31\xd2\xa8\xf3\x81\xd3\x19\x7d\x5d\xe1\xec\xcf\xde\x9e\xee\x54\x37\x20\xbe\x03\x98\x57\x4f\x2f\xae\xfe\xf9\xf6\xf8\xaf\x67\x6f\x61\x4d\x3c\xdb\x8b\xbd\xfc\x28\xeb\xb8\xe3\xa1\x26\xb1\xfa\xc1\xbe\xca\xe0\x36\x2b\x1e\x83\x7d\xf1\xe6\xaa\xff\x70\x47\x2e\xde\x5c\x21\x56\x76\x37\xf0\xba\x81\x51\xa3\x42\x89\x1e\xf0\x3a\x36\xc3\x28\xe6\xe8\xbd\x79\x2e\x00\x8f\x09\xf0\x87\x7d\x71\x82\xec\xa4\xc8\x90\xf0\xe0\xcb\xee\x52\x24\xe8\xed\xe9\x76\x6b\x92\x10\x40\xf9\xe0\xa7\x8e\x3c\xa9\x50\xe7\x21\x60\xb8\x76\x5f\xdc\x0e\xfb\xb7\x08\x0f\xa5\x8d\xc9\xed\x3e\x1b\x00\xee\x17\x3c\x3f\x31\xe1\x9a\x4a\xc3\x7a\xbf\x77\x05\x92\x02\x58\xde\x9a\x86\x18\xea\x7b\x65\x7d\x41\xeb\xcf\x31\xad\xc3\x03\x64\xe7\x96\x23\xc5\x3e\x86\x6d\x21\x71\xb7\xbc\xad\x8c\x77\xee\xd6\x49\x41\x39\xa2\x4b\xf1\x86\x0a\xde\x25\xd4\xfd\xeb\x15\x00\x72\x50\xaa\xa8\xd3\xdf\xaf\xc7\xb2\x4c\xc9\xce\xdf\x43\xbd\x69\xb9\x5a\x4a\xea\x1f\x4b\x74\x45\xb3\x54\xa5\x5a\x9f\x73\x10\xda\xcd\x98\x84\x33\xd1\xfe\x95\xfb\x9b\xcc\x7e\xda\x73\x72\x41\x60\xc2\x8f\x40\x00\xd7\xfc\x6e\x0a\xe5\x73\x12\x84\x79\xfd\x13\x91\x49\x81\xe6\xb0\xc9\x4e\x2c\xb9\xef\xd4\x12\x1a\x33\xd1\x4a\x86\xe6\x30\xd0\x0e\x3c\xf4\x43\xfe\xa2\x58\xd3\x07\xbc\x0c\xe4\x49\x79\x46\xdf\x7f\x11\xa2\xfe\xe0\x8b\x60\x9d\xae\xc7\x49\xf9\x56\x4b\x69\xa4\x48\x4a\x67\x7a\xb9\x43\x64\xac\x3d\x72\x32\x4f\x1c\xfd\x72\xc1\x54\xc7\xac\x22\x44\x03\x6f\x52\xc3\x38\x4d\x45\xde\x94\x88\x49\x11\x20\xa8\xb1\xd4\xd3\xcf\xc7\x80\x54\xf9\xf9\xe9\x17\xb6\x1d\x63\x2b\xa1\xa7\xd9\x4a\xe8\xcb\x80\xd0\x1e\xc3\x9c\xd8\x43\x9e\xe0\xbc\x9d\x9f\xfa\xcc\x47\xe0\xb1\xc6\xe6\xa6\x9d\x42\x23\xa9\x34\x1a\xf1\x5a\xed\x8b\x47\x37\x52\x99\x5b\xa9\xd2\xb4\xf7\xbb\xec\x09\x8b\xae\x02\xf5\xd2\xb6\x3a\x0c\x74\xf4\x3d\x42\x70\xc7\x42\x3c\x53\x7d\xef\xd6\xe3\x19\xeb\xfc\x2b\x28\x2c\x8a\x3a\x1e\xc4\x3f\x32\x6c\x62\x8e\x03\xb0\x19\x9b\x9f\xd8\x61\x3e\x36\x0c\x41\x5c\xa2\x34\x31\x92\x79\xc3\x7c\x4c\x3b\x06\x00\x1f\x86\x6c\x9b\x8d\xa7\x60\x00\x12\xc6\x13\x5b\x49\x47\xe4\x5a\xed\x6e\x49\x06\xe9\x5b\x74\x82\x75\x67\xa4\x13\x62\x16\x7c\xfc\xdb\x8b\x74\x1e\x25\xd1\x19\xb4\x56\x82\xfd\xfb\xce\x8b\xf2\xcf\x94\xf8\xb3\xde\x38\x01\x36\x42\xe9\x9b\x9b\x2f\x6e\x88\x95\xb4\x86\x04\x63\x11\xfa\x0e\x8e\x61\xa5\x06\xb0\x0e\x2d\x0a\xbb\xf3\x12\x61\xda\x48\x53\x18\xa8\x43\x83\xae\x43\x92\x49\x31\xe7\x8b\x92\x56\xfa\x10\x59\xce\x97\xcb\x5b\x71\x4b\x55\x4e\x8e\x2f\x87\xa3\x88\x1e\xcd\xdc\xfa\x85\xf8\xc2\xd6\xd6\x03\x1e\xde\xc9\x3c\x85\xc9\xb5\x62\xc8\x8c\x3b\x95\x57\xa3\x15\x9e\x14\x2d\xbc\xdd\xda\x47\x6b\xd5\xfc\x44\xd1\x2f\x02\x8d\xc5\x5d\xd1\xa2\x66\x64\xc6\xcc\x2d\x63\x82\xbc\x44\x9e\x31\x3b\x5e\xfe\xe1\x0f\x7f\x98\x92\xd3\x96\xb2\xc0\x03\x19\x62\xf2\x7d\xd4\x2c\x81\xf6\x42\x48\x43\xe8\x7c\x0e\x57\xd5\x19\x75\x34\xbc\xc5\x2b\x75\xcf\x16\x52\xf2\xc5\x12\x56\x82\x0b\xb8\x6a\x05\x8e\x1b\x82\x84\x67\x3a\x07\x9e\x09\x4d\x4e\x21\xe8\x71\xf3\x8e\xf4\xb6\x48\x29\x73\x76\x48\x0a\x7e\xc3\xc8\x5c\x7f\xab\x64\x5d\x61\x0b\x3a\xac\x23\xef\x8a\xf5\x75\x5d\x18\xa0\xb4\x98\x31\x37\x71\x74\x16\x20\x9c\x73\x74\xcb\xa3\xc7\xc7\x76\x7b\x85\x93\xe0\xda\x17\xdc\x7a\x9b\xf3\x86\xf9\xca\xd9\x18\x7b\x20\x22\x96\xe6\x91\x30\xc9\xfd\x48\xb3\xf9\x12\x2c\x85\x8d\x1b\xbe\x0d\x67\x63\x7c\x09\x2d\xa4\x58\xc0\x05\x42\xcb\x94\xdd\xba\x58\x96\x37\x65\x9b\xeb\x0a\x9d\x6c\x88\xc6\xb8\xa6\x40\xb9\x12\xef\x01\xbc\xa3\x15\x5e\xc4\x26\xa4\x31\xba\x45\xab\x1b\x74\x26\x6b\x13\xca\xad\xdc\x1c\xa1\xb9\x58\x94\x50\x23\xc3\xc1\x88\x10\x93\x60\xeb\x48\xa2\xed\x23\xb1\x57\x30\x8c\xbe\xc3\xd9\x0b\x0d\xb1\xa6\xa0\x1d\x8c\x66\x4b\x72\xc3\xd6\x13\xe7\x0f\x54\x14\xc5\xdf\xdd\x1f\xfe\x01\xf0\x94\x1a\xea\x50\xc6\xd1\x12\x3d\x22\xa2\x79\x66\x8f\x97\x78\xd2\x1c\xdc\xb8\xfa\xc3\x76\xb4\x5a\x2d\xb0\x99\x47\x8b\x0c\xa9\x38\xed\x33\x24\xe4\x76\x29\xd1\xde\x64\x3b\x44\xfb\x70\x6c\xb7\x3e\xc2\xf5\x6b\x47\x26\x85\x61\xc2\x04\xb1\x70\x9a\x62\xb0\xe5\x6e\x9c\x6f\x32\x5e\x47\x4b\xb4\x36\x9a\xe5\xf6\xb3\xf5\x53\xde\xf9\x96\x0f\xd9\xba\xc2\xe8\x10\xb0\x3f\x6a\xb1\xf9\xf5\xf1\x47\x49\x1a\x67\xd1\x21\xb5\x38\x25\xe7\xd8\x2e\x95\xed\xa0\x70\x26\x13\x94\x46\xb7\xe3\x76\xc9\x33\xe0\x35\xb5\xd3\xf5\x73\x4d\xa5\xe5\x1a\x45\x12\xaf\x8b\x3b\xac\x13\x9a\x99\xba\x4a\xb3\x45\xc0\x17\x60\xf7\x9e\x69\x4d\x78\x44\x7d\x40\x3b\x4a\xaa\x6e\x58\xee\xa3\x1d\x5a\x4c\xc9\xa5\x3d\xa4\xf1\x62\x7d\x70\xaa\x58\x41\xa1\xa5\x7c\x8a\x43\x6f\x7d\xce\x6e\x0b\x82\x14\xb7\x73\x6f\x3a\xdd\x73\x31\x6a\x64\x43\x83\x76\xb4\xad\x0d\x22\x45\xc5\x46\x0d\xed\x48\xe2\xbc\x6c\x66\x46\x68\x15\x7f\x4e\x80\xcf\x0e\xb2\x7e\xa0\x2a\xd0\x8f\xd8\x7d\x89\xb0\x9f\x3e\x73\x11\xe7\xc9\xba\xe1\x41\x4a\xf1\x5a\x21\x8d\x4b\xeb\x06\x3e\x33\xb7\x39\x26\x76\xed\x13\x48\x41\x92\x7d\xf6\x47\x2a\x7f\xdd\x8d\x1b\x86\x7c\xf6\xd8\x1c\x7d\x52\x87\x04\x8a\xc7\x0d\x77\xe8\x83\xdb\x11\x7f\xc2\x48\xfc\x73\xd1\xe6\x28\xd1\x89\xd4\xcd\xd1\x07\x3e\xbe\xf7\x26\x27\x8d\xec\x6e\x06\x2b\x89\x16\xb1\xa3\xd6\xcc\x15\x0c\x25\x30\xb4\x6e\x58\xd7\xff\x30\x58\xc7\x44\x32\x37\x12\xc0\x89\xa4\xba\x12\x3f\x48\x08\x27\x92\x78\x3e\x07\xeb\x9d\x30\xe2\x75\xa3\xdb\xf4\xa7\xcd\xfd\x27\x12\xee\x03\x0b\xe0\x94\x4e\xb5\x10\xbd\xac\x75\x22\x99\xf1\xb9\xef\xcd\xb1\x9d\x0b\x4f\xb6\x5f\xb1\x19\xf5\x6d\x89\xdd\x0c\x7b\x22\xa1\x29\xf2\xf4\x9b\xa3\x9f\xb7\x4f\x24\x34\x41\xf6\x7f\x73\xf4\x5f\x03\xf0\x65\xe0\xdd\x11\xff\x3c\xb0\x39\x62\x9f\x0b\x36\x07\xbe\x4c\x70\x73\x3c\x90\xb7\xd0\x44\x53\x49\x3c\x2d\x37\x7c\x3e\xce\x5e\x9f\x54\xb7\x51\x92\x92\x56\x21\x25\x95\x4c\xe8\x94\xbc\x73\xf1\x5f\x22\x89\x33\x1b\x94\x12\x3a\xd3\xb2\xa8\x4d\xaa\x6f\xf7\xc4\xd9\x49\x27\x9a\x32\xdc\x75\x03\xe2\x23\x56\xb0\x32\x45\xf2\xc4\x0d\xd7\xca\x2f\xed\x87\x43\x38\xde\x74\x9c\x4b\x26\x14\xa2\xcd\x14\xf1\xb9\x1b\xc9\xdc\xed\x38\x32\x14\x37\x76\x52\xa2\x24\xc9\x66\xf5\x89\x51\x12\xa4\xdc\x9e\x14\xb1\x8a\x1b\xbb\xe9\x55\xa2\xc5\x7a\x7a\x96\x2e\xc9\x4a\xb4\xcc\x14\x24\x2d\x6e\x24\x3b\xbf\x32\x51\x40\xd7\x3b\xc3\x57\xae\x67\x7e\x82\xbc\x31\xf3\x9c\x28\x9d\x3c\x6f\xfc\x63\x96\x22\xd6\x49\x82\x24\x7c\xaa\xa0\x2e\x67\x73\x2e\xa2\x33\xe5\xb1\xa0\x43\x3f\x17\x8f\x3b\x3b\xbe\x3c\x7f\xc2\x2f\xd7\x9d\x59\x46\x49\xcc\xa9\xa1\xe3\xdb\xf5\x7d\x63\x07\x58\x32\x41\x5a\x84\x36\x50\x9b\xd3\x76\x17\xbf\xc3\x03\x49\xbb\x23\x81\x4f\xfb\xb4\x53\xf0\x5b\x4b\xf6\x26\x8d\x17\xdf\x29\x40\x4c\x75\x5b\xdd\x30\xd2\xc3\x20\x53\xc6\x1c\xde\x3f\x76\x25\xc5\xc0\x9e\x94\x40\x68\x1a\xb0\xc3\x93\x4d\xf8\x3f\xc1\x54\x3d\xac\x38\x9a\x7d\x71\x73\x6c\x12\xc4\xa4\x5a\x3a\x37\xae\x58\x61\xbd\x4f\x92\x0a\x14\xe3\x86\x0c\xd4\x6f\xc9\xe6\x09\x64\x33\x54\x08\x69\xe0\x06\xeb\x64\xb9\x31\x3a\x63\x85\x3e\x24\x11\x3c\x29\x9b\x83\x8a\xbc\xa5\x18\x48\x25\x53\x75\xca\x8f\x92\xa6\xb1\x12\x5d\x69\x92\xf4\x5a\x13\xb8\xda\x70\x22\x23\x7a\x4e\xf5\x47\xda\x3b\x4e\x7a\x54\x93\xa9\x24\x6e\x16\xb9\x38\xe9\xc9\x84\x37\x17\x53\x67\x4b\x56\xa6\x78\x4f\x0e\xc3\x0a\x7d\x93\x74\xbb\xdc\xe0\x9a\xdc\x2a\x6e\x4c\xb2\xc7\x20\xe2\x41\x32\x4c\x95\xa9\x5e\x01\x08\xac\xeb\x61\x78\xb2\x49\x29\xd6\x48\xf2\x62\xf5\x0a\x5d\x0a\xbe\x43\x60\xda\x17\x55\x12\xac\x1d\xae\x75\xec\x7d\xa3\x8f\xf3\x4e\x7b\xa2\x9a\x2c\x71\x3a\x6b\x47\xdc\x4e\x69\x30\xa5\x89\xcf\xa9\xbd\xac\xc9\x20\x67\xed\x38\xbe\x3c\x27\x2b\xa7\x5d\x9e\xec\xe1\x1a\x9f\xeb\xc7\xe7\xfa\x24\x63\x7c\xae\xf7\x63\x7c\xae\x1f\x9f\xeb\xc7\xe7\xfa\xf8\xf1\x4c\x9e\xeb\x93\x27\x0b\x2e\x5d\xbf\x67\x92\xf0\x11\xf3\x21\x80\x00\x22\x49\xff\x84\xee\x80\x3b\xee\xd8\x30\x7c\xf1\x73\x2a\x95\x0c\xb5\xcf\xae\x60\x21\xd5\x55\xf7\x38\x00\x3c\x8b\xff\xe6\x48\xff\x6c\xbf\xb7\x37\x9d\xee\x39\xb4\x7a\xd2\x85\xb4\xf6\xd2\xcc\x27\x7f\x4c\x24\x93\x89\x4c\xe6\x2c\x9f\x26\x04\xbe\xcc\xb9\xd2\x06\x52\xe8\x29\x9e\xb3\xdd\x70\x8a\xdd\xdd\xa3\x94\xb8\x8a\xd2\x9f\xcd\xf4\x20\x08\xb7\xff\xff\x3f\x7b\xef\xda\x1c\x39\x6e\xa5\x09\x7f\xef\x5f\x81\x90\x1d\x21\xc9\x56\x66\x75\xdb\xbd\x1e\x6f\xed\xc4\x38\xd4\x92\xba\x47\xdb\x75\xd1\x48\x55\xe5\xd8\xb7\xed\x9d\x45\x92\xc8\x4c\x58\x4c\x82\x4d\x80\xa9\x4a\x8f\xe7\xbf\xbf\x81\x83\x0b\x41\x26\x49\x80\x17\x5d\xca\x9d\xf8\xd2\xd5\x29\xf2\x10\xd7\x83\x73\x7d\xce\x94\xec\x7d\x32\xad\xc3\xa0\x5e\x7c\xff\x88\x46\x5c\x6d\x74\x9d\x4c\x0c\xb7\x25\xbc\x27\xdd\x52\xfa\xd8\x0f\x45\xa6\xde\x6f\x60\xc3\xb5\xa8\x22\x93\x49\x4b\x1b\x0a\xc5\x14\x62\xb0\x3f\x12\x3e\xd9\xbc\x9e\x28\xd2\xf3\x28\x2b\xa6\x13\xed\x80\xe2\x86\x6c\x58\x3e\xb8\x06\x66\xbd\x99\x61\xcb\x8e\x4e\x28\x2e\x5a\xb2\xaa\xb7\xa7\x13\x5a\xb2\xa3\x22\xcf\x49\x3a\x1c\xa0\xaa\xde\x7e\x71\x96\x71\x73\x88\x5e\xa8\x61\xdc\x72\x8e\xe1\xd0\xd2\x4d\xad\x06\x37\x6d\x3e\x32\xa1\x59\x0c\x02\xd7\xec\x6a\x4d\x48\x78\xc9\x72\x6d\x2a\x98\xcc\x73\x85\x9c\x40\xa5\x89\x7b\x4a\xd2\xed\x84\x14\xb7\x38\x1f\x08\x3f\xdd\xd4\x1e\xc1\x82\x1d\xd3\x2d\xe5\x6c\xb2\x6b\xae\x31\xee\x6b\x38\xca\x68\x53\x93\xd7\x33\x2b\x44\x56\x4c\x69\x6e\x56\x5a\xed\x74\x32\x04\xd2\x1d\x25\x9f\x33\xc6\x27\x3d\x4d\x56\x86\x98\xf2\x2c\x3d\x92\xfb\xe6\x9b\xa1\x80\xbb\xfb\x2d\xc3\x42\x90\x3c\x7d\x8d\xfe\xef\xc9\x5f\x7e\xfb\x8f\xd9\xe9\x9f\x4e\x4e\x7e\xfa\x7a\xf6\x3f\xff\xfa\xdb\x93\xbf\xcc\xe1\x1f\xbf\x39\xfd\xd3\xe9\x3f\xcc\xff\xfc\xf6\xf4\xf4\xe4\xe4\xa7\x1f\xdf\xfe\xf0\xe1\xe6\xea\xaf\xf4\xf4\x1f\x3f\xa5\xc5\xe6\x5e\xfd\xdf\x3f\x4e\x7e\x22\x57\x7f\x0d\x24\x72\x7a\xfa\xa7\x5f\x4f\x36\x04\x9c\xee\xde\x4f\x24\x52\x23\xb8\x09\xa7\x37\xee\xb8\x74\x27\x65\x33\x08\x7d\x9e\x95\xe1\xc1\x33\x9a\x8a\x19\xcb\x67\xea\x13\xaf\x91\xc8\x8b\xe9\x6c\x2a\xea\x78\x3c\xd6\xcd\x3b\xb5\x59\x09\x39\x7d\x7e\x0c\x97\xdc\x0b\xbb\x7c\x14\x9a\xe2\x0b\x8e\x42\x55\x1d\x3c\x80\x27\x35\xb5\x03\x78\xd2\x4b\x05\x4f\xd2\x35\x8a\x8d\xdf\xcc\xe2\xdf\x4c\x30\x78\x85\x9f\x53\x22\x1f\x8d\x26\xe9\x22\x27\x4d\x13\x7a\x56\x45\x4e\x32\xc8\x47\x53\x91\x55\xc8\x49\x55\xe4\xa3\xf1\x21\xa5\x6b\xb2\x87\x7c\x34\x9a\x68\x05\xc9\x4f\xae\xdc\x24\xdd\xac\x23\x1f\x8d\xdf\x00\x50\x60\xd5\x19\xfd\x68\x8a\xb0\xef\x6b\xc8\x47\xa3\x89\x5e\x2f\xbf\x34\xe4\x23\xc5\x05\xa6\x81\xe5\x3a\xc0\x1e\x1d\x60\x8f\x46\xb5\x97\x9d\x73\x71\x80\x3d\xea\xdd\x5e\x6c\x16\xc4\x01\xf6\xc8\xd7\x0e\xb0\x47\xe3\xdb\x21\x8e\xf2\x10\x47\x79\x88\xa3\x3c\xc4\x51\x1e\xe2\x28\x0f\x71\x94\x53\x50\xfc\x42\xe2\x28\x0f\xb0\x47\x93\x10\x3d\xc0\x1e\x1d\x60\x8f\x26\x21\x7a\x80\x3d\xea\xdb\x0e\xb0\x47\xa3\xda\x01\xf6\xa8\x57\x7b\x74\xd8\x23\x65\xe4\x1d\xef\x83\xb2\x98\x47\xff\x94\x90\x47\x5c\x1e\xbb\x88\x9c\x47\x11\x2b\x52\xf1\x81\xdd\x93\x51\x79\xea\x8f\xee\x74\xde\xeb\xed\x28\xca\x2f\x0e\x02\x69\x0a\x73\xdf\x68\x13\xdd\x54\xc6\x39\x5c\xc4\x94\xa4\xe3\x43\x4c\x2a\x9b\xea\x5c\x13\x9d\xca\x6b\x29\x55\x95\x34\x26\xb1\xed\xed\x54\x5e\x6b\x21\x77\xe7\x1c\x9d\xa3\x9c\x44\x34\xa3\x53\x08\x61\x6c\x89\xb0\xa2\xab\x78\x91\xae\x4b\x3a\x9e\x6f\x52\xc1\x49\xb2\x54\x42\x18\x4e\xcb\x7a\xa7\xe3\x35\xb8\xd2\x29\xaa\x7d\x6f\x8f\x32\xcd\xd3\x54\x99\x01\x71\xe0\x81\x72\x82\xf8\x9a\x15\x49\x8c\x72\x32\x89\x0d\xdf\xd9\x0d\x1f\xa6\x9c\x81\xd8\x29\x4f\x0c\x5b\x79\xba\x65\xd3\x93\x8b\x33\x2a\x59\x2e\xc9\xa7\x71\x72\x4d\x20\x7e\x90\xcf\x19\xcd\xe1\x4a\xb9\x23\x11\x4b\xe3\x69\xc3\x6c\xae\xea\xd4\xa7\xe2\x32\x3a\x4f\x82\xc4\x28\x2e\xf2\x69\xe0\xc5\xd8\x12\x6d\x71\x42\x63\x2a\x76\x53\xe5\x31\xea\xeb\x15\x61\x75\xbf\xea\x4d\x3b\x9a\xec\x39\x2f\x8f\x00\xc2\x59\x96\x33\x1c\xad\x27\x10\xe4\xcb\xbd\x70\xa6\xec\x10\xaa\x5c\xff\x54\x2e\xfd\x2c\x29\x56\x34\x9d\xc6\xa7\x0f\x63\x16\x74\x4b\x92\x1d\xca\x99\xc0\x13\x98\x22\x1c\x79\xc8\x2c\xd8\x78\x9a\x25\x97\x9a\x6a\x32\xc1\xb4\xae\x74\x7c\x91\xef\xa6\x70\x56\x09\xa6\xa7\xb0\xdc\x55\xe3\x8f\xa9\x73\x99\xc8\x33\xcb\x92\x78\x02\x2e\x2a\xd6\x38\x45\x7f\xfc\x1a\x65\x24\x8f\x48\x3a\x49\xd4\x3c\x78\xbe\xe8\x06\x12\x8d\x13\xba\x9d\x24\x81\xf7\x11\x07\xff\xbb\x6f\xd1\x9a\x15\x39\x9f\x5f\x4e\x15\x38\x2f\x18\xfa\x06\x68\x82\x99\x5d\x8a\x41\x53\x84\x83\x61\x81\x12\x82\xb9\x40\xdf\x7c\x8d\x36\x34\x2d\x04\x19\x58\xfd\xde\xe9\xe8\x84\x96\x70\xc7\x06\xfe\x87\x6f\x47\xd1\x9a\xc2\xfa\xbd\x87\xbc\x34\x45\x88\x12\x40\x01\x4a\x5a\x93\x25\x29\x6b\xa9\x68\x03\x57\x59\xc6\xe8\x34\x02\xb8\xf5\x42\x4d\xa2\x36\xea\x9e\x96\xa7\x2f\x15\xec\x19\x65\xad\x9f\x0b\xb6\xd8\x89\x01\x0a\x5b\x65\x4b\xfc\x87\xa2\xe2\xe2\xaa\x0e\x89\xcf\x31\x64\xd4\x02\x32\xa5\x3e\xac\x19\x17\xca\xb7\xc8\xd7\x38\x1f\x24\x44\x60\x94\xb1\xf8\x98\xa3\x84\x2e\x89\x64\xa5\xbd\x49\x8c\xd2\xf5\x87\x6b\xf8\x33\x94\x93\x15\xe5\x22\xef\xaf\xef\xcd\xb4\x4c\xd3\xfb\xc5\x71\xa6\x80\x55\xce\x8a\x81\x35\xa0\x2b\x1b\x0a\xbc\xb3\xc6\xe3\x34\x70\x24\xaa\xe1\x28\x22\x1c\x14\x26\x7d\x21\xa9\x08\x53\xd5\xd3\x41\x34\x47\x6a\x36\x39\xc1\xf1\xfb\x34\x19\x18\xbf\x54\x99\xa5\x5b\x4d\x0a\xad\x49\x4e\xc6\x88\xad\x4b\x96\x47\x4a\xb8\x32\x47\xd0\x94\x26\x1f\x1a\x72\xb3\xd0\xa7\x98\xc4\xca\xc6\x20\x47\x3d\x83\x4c\xff\x8c\xe4\x1b\xca\x39\x65\xe9\xe0\x0b\xf7\xd2\x51\x83\x97\x38\xe1\x03\x43\xf8\xc6\xda\x53\xcd\xe1\x9c\x64\x25\x15\x29\x87\x83\x0e\xdd\xef\x88\xd3\x74\x95\x48\x31\x11\x6d\x8a\x44\xd0\x2c\xb1\xab\x3a\x90\xa4\xed\x9c\x56\x3e\xc6\x07\x7d\x43\x95\x68\xed\xb1\xc3\x1c\x58\xfc\xeb\x8c\xe5\x62\x4c\x5a\xca\x89\x1d\x2d\x49\x45\x4e\x09\x57\xe8\xb8\x24\xc3\x39\x1e\x9e\xef\x01\x9b\x37\x62\x9b\x0d\xe6\xa7\x3a\x42\x1d\x03\x30\x32\x1f\xa1\x7f\x4b\xd5\x20\xc7\x89\xdd\x40\x6e\x1e\xf8\x73\xb0\x24\x41\x52\x9c\x0e\x4c\x3d\xab\x86\x44\x00\x21\xc4\x1e\x0c\x58\xf9\xc0\x09\x5a\xd1\x2d\x49\xeb\xbc\x68\x94\xab\xfc\x3b\x1c\xdd\x93\x34\x46\x1f\xb9\xe1\x48\xf1\x2e\xc5\x1b\x1a\xe1\x64\x30\xde\x44\x96\xb3\x2d\x95\x8c\x8c\xc4\xb5\xbe\x0e\x4e\x05\x51\x11\x7f\x14\xe2\x73\xd0\x62\xa7\x64\x64\xb0\x4a\x3c\xc7\xbe\x28\xf8\x50\x94\x97\xca\xae\xf8\xc8\x49\xfe\x38\x77\x39\x57\xd9\x9c\x39\xdd\x46\x64\x9c\x45\x44\x0e\xf5\x39\xa6\x58\xcd\xc7\x04\x93\xfc\x49\x1f\x92\x92\xb3\x0e\x9c\x09\x10\xb5\x6d\x02\x1e\x87\x60\x9a\x44\x5e\xdf\x3b\x03\x72\x36\x90\x70\xed\x38\x2f\x76\x10\x19\x31\xe6\xea\x1e\x34\xce\x7c\x31\x40\x12\xaf\x65\x3a\x7f\x77\x59\x51\x75\xd0\x2d\x8e\xd9\x10\xce\xfd\x5d\xc2\xa2\x7b\x74\x49\xc0\xa4\xd7\xac\xf5\x0c\xa0\xaa\xf4\x24\xad\xf5\x38\x6a\x8f\x0a\xf1\x50\x21\x1a\x03\xc8\x9a\xa0\x0e\xf2\x19\x6f\xb2\x84\xf0\xf9\xfd\x1f\x21\xac\x43\xb3\xbc\x57\xf9\x22\x7e\x75\x7b\x75\x7e\xf9\xf6\x6a\xbe\x89\xfb\x47\x2f\x3c\x9b\x8e\x45\x37\x78\xd5\x9f\x23\xcd\xd0\x86\xa5\x54\xb0\xbc\xff\xba\x8f\x53\xb1\x96\xfc\x83\x9c\xa9\xf1\x1c\xe3\xf8\x7b\x9a\x10\xbe\xe3\x82\x6c\x60\xf2\x07\x1e\x6b\x6d\x21\x31\x0a\x83\xe4\x1e\x3b\x56\xa0\x07\x3c\x98\x17\xcb\xab\x42\x9e\x85\x39\xfa\x40\xb3\xd7\xe8\x2a\xe5\x45\xae\x29\x0f\x17\x00\x96\xd5\xc1\xc2\x1d\x6b\xf0\xa1\x86\xea\x38\xbb\xf2\xa8\xca\x15\xc5\x42\x4a\x3d\xea\x23\x43\x55\x9b\x2b\x7d\xb8\x5e\xa3\x23\xf2\x59\x7c\x7b\x74\x86\x8e\x3e\x2f\xb9\xfc\x4f\x2a\x96\x7c\x30\xe4\xfb\xf5\x26\x4b\x68\x44\x45\xb2\x93\xc7\x9f\xe4\x39\x89\x35\x70\xa5\xfa\xcc\x40\xb2\xb4\x92\xa4\xee\xf2\x97\xa0\x10\x30\x2e\x58\x8e\x57\xc4\x70\x90\x5f\xe5\x8b\xa1\x4b\xa1\x22\xbc\xd6\xec\x01\xc5\x0c\x3d\x40\xaa\xeb\x96\xa4\x42\x65\x56\x0e\x55\xa5\xb4\xff\xda\xd9\x39\xcb\x9c\x6d\xa4\x36\x90\xe5\x6c\x43\xf9\x98\x3b\x96\xa0\x0d\x8e\xd6\x34\x25\xc3\xc2\xbc\x46\x4a\x1d\xc0\xf2\xa6\x60\x21\x1f\xd6\x04\xe5\xf2\xf2\x1b\xc8\x45\x55\x03\x39\xa0\x69\xf3\x04\x5d\x35\xbf\x5a\xb3\x87\x99\x60\xb3\x82\x93\x19\x1d\x88\xea\x31\x72\x3e\xef\xc9\x0e\xe0\x5a\x26\x98\xd1\x1f\x15\x29\xe3\x46\x1e\x11\xd8\x23\x18\xc4\xb0\x01\x35\xa9\x60\xde\x7e\x77\x29\x25\xf1\xb9\x11\x9e\x87\x9e\x0a\x8e\x5e\x11\x11\xbd\x8a\x48\xb6\x7e\xa5\x07\x3e\x52\xb2\x40\x7d\xa5\x8b\x17\xb0\xe4\xe6\xf6\x9f\x62\xcd\xcf\x51\xc4\x92\x84\x44\xf2\x7f\x87\xbb\x0c\x2f\x48\xb6\xb6\xdd\x7a\x09\xc7\x69\x78\x86\xf3\xa8\xbc\xe6\x91\x0b\x9b\x31\x36\x30\xd4\xb5\x8d\x35\x4a\x8a\x23\x74\x1d\xe4\x5a\xae\xf3\x45\xf3\x35\xfb\xa5\x1c\x9b\x09\xad\xdf\xc7\x8f\x60\xfe\xb6\x24\x39\x11\x20\xcd\x0d\x34\xbc\x20\xad\x8f\xbf\x95\x72\x2c\x9f\x4f\x65\xb1\x46\x2f\x60\xe9\x87\xdb\xcb\x15\x80\xd4\x60\xf0\xe4\x3a\x58\xb2\x26\x06\xfe\x9c\xe1\x58\x39\x26\xee\xad\x10\x6b\x92\x0a\x1a\x41\x74\x91\xee\xea\xf0\xed\x54\x5e\xb6\xd7\x4b\x65\x27\x8c\x49\x8c\xd8\x96\xe4\x39\x8d\x07\x07\x42\xd9\xdb\xd6\x75\x65\xd1\x64\x54\xea\xc6\xb3\xee\xa5\x11\xd1\xd3\xe3\x43\x96\xc7\xe5\xe5\x34\x66\xe4\x8c\x8c\xc9\xab\xe6\xe2\xbc\xb4\x5c\x9a\xe6\x2c\x1a\x93\x05\x33\x82\xb0\x93\x3f\x33\x49\xfe\xcb\xcb\xb0\x7a\x3b\x02\x80\xa4\x38\x95\x00\x80\xe3\x0d\x4d\x7f\x61\xf2\x36\x8f\x70\x42\xae\xdf\x8f\x34\xdb\xde\x29\x2a\x63\x83\x54\x0c\x99\x4c\x6e\x59\x2e\x48\x2a\x2c\x02\x9c\x10\x38\x5a\x0f\x32\x27\x41\x64\x9b\xf6\x97\xb3\x14\xfd\x68\xcf\x3a\x4a\x59\x3c\x24\x32\xed\xd9\xac\xa9\x2b\x2c\xc8\xc3\x00\xb1\x7f\x56\x8a\x07\x43\xde\x05\xfb\xcc\x97\x6a\x89\xad\x19\x62\x87\x47\x5d\x68\xb3\xa9\x29\x7a\x82\x1d\xdb\xd5\x08\x65\xaa\x34\x94\x36\x9b\x3c\x07\x92\xd6\x86\x52\x74\xf5\x79\x3e\xad\xb1\xd3\xe1\x96\x40\xef\xc9\x5d\x4c\xb2\xe9\x73\x30\x85\x53\xdd\x4c\x38\x8e\xe3\x9c\xf0\xa1\x57\xb8\x16\x74\x0d\xfb\x3a\xbf\xb9\x46\x3f\xa8\x3e\x3e\xcb\xfc\x64\x39\x13\xca\xe2\x71\xc9\x36\x98\x0e\xcc\x41\xdc\x9b\x28\xa7\xc8\x93\x19\xea\xc0\xf9\xba\xb1\x1d\x44\xaa\x87\x20\xd7\xeb\x0a\x28\x4b\xba\x2a\x86\x97\x02\xd0\x76\xef\x67\x99\xf7\x09\x15\xf0\x3d\xa5\x76\x68\xe4\x8e\xec\xd3\xab\x87\x9c\x0a\x72\x3a\xaf\x06\xb5\x0d\x8e\xda\x49\x92\x0e\xad\x7e\xb8\x3f\xa0\xa2\xd5\x7f\xf1\x4a\x74\xa9\x43\x97\xfe\xfe\xe1\xc6\x66\x07\x23\x5a\x9e\x14\xc3\x68\x06\x47\x56\x28\xa9\x48\xe9\x1a\x9c\xa4\x9c\x02\x44\x8a\x93\x62\x3c\xd8\x19\xb6\x04\xe8\xaf\x12\x6a\x54\xa9\xe7\x67\xe8\x0d\x1b\x1a\x68\x83\xcc\x6d\xc8\x52\xbd\xf9\x30\x4d\xc6\x6c\x90\x83\x66\x5c\x69\x07\xcd\xf8\x25\x68\xc6\x9c\x27\x57\x29\x5e\x24\x43\xb3\xd5\xab\x42\x6f\x82\x57\x92\x6d\x10\xa0\xf8\x2a\xa6\x5c\xfe\x77\xe0\xd0\xee\xee\xde\x40\x94\x66\x91\x1a\x0b\x1e\xc4\xf8\x69\x01\x67\x68\x34\x9e\x4e\xb7\x1d\x71\xb9\x8d\xe6\xf6\x4a\x52\x78\x3b\x18\xab\xb1\x8a\x29\x9f\xc6\x72\x7a\x08\x37\xb0\x19\x23\xdc\xd7\xba\x67\xc0\xea\xb1\xc5\x44\x86\x2c\xea\xa1\xe1\x14\x04\x7d\x58\xd3\xe8\xfe\xc6\x09\xab\x64\xb9\xfc\x2d\x75\x7e\x9a\x40\x29\x98\x84\xe2\xd8\xa3\xa4\xa6\xef\x66\x1a\x67\xd3\x07\x47\xb0\xbf\x53\x94\x87\x4a\xbd\x8c\x25\x08\x73\xce\x22\x8a\x6d\xf0\x3e\x38\xa2\xad\x38\x3c\xf4\x30\x81\x10\xfd\x3c\x93\x0d\x9a\xe6\x23\x68\x18\x7c\xd4\x5c\x6b\x95\x1f\x73\x47\xa3\x90\x42\xa6\x5e\xc9\x67\x99\x2a\x75\x90\x87\x17\x68\x6b\x9d\x2e\x3c\x32\xf4\xb7\x1a\x82\x6a\x71\xdd\x47\xa9\x78\xc6\xe6\xb2\xc6\xca\xb4\x5a\xdd\xf6\x83\x99\x23\xe5\x96\x1f\x42\xf1\x9a\x27\x5f\xc8\xa1\xa5\x64\x9a\x3c\x6c\x63\xcd\xa5\x5a\x23\xd0\x09\x7c\x00\xb2\x91\xb1\xac\x48\x54\x36\xf7\xa0\x34\x52\x0d\xdb\x3d\x36\xda\x4c\xf5\xec\x89\x03\x55\xc7\x09\xe7\x0e\x0e\xee\x14\x1e\x0a\x0b\xd5\x5c\x02\x83\x0e\x57\xff\x34\xa8\xb2\x39\xa0\x60\x79\x44\x8b\x9d\xe9\xf3\x60\x87\xb7\xb5\x65\x56\xd0\x90\x15\x8e\xf1\x40\x9a\x80\x7e\x5c\x31\x5f\x7c\xfd\x87\x6f\xbf\x9d\xa3\x4b\x9a\x93\x48\xb0\x7c\x78\x55\x3e\x0d\x4e\x6f\x53\x9b\x71\x4e\x40\xc7\x54\xb0\xb8\xe3\x22\x4d\x55\x56\x88\x00\x07\x70\x09\x35\x3c\x5c\xd8\x72\xa0\x85\xa7\x03\x05\x76\x40\x80\x6b\xf0\xbd\x00\xbc\x3b\xd4\xa3\xae\xe1\x7a\x6b\x40\xbb\x28\x1a\x8c\x83\x66\x80\x75\x27\x81\xc4\x1d\x9f\xf8\x3f\x16\xf2\x76\x44\xc0\x54\x57\xd5\x29\xa8\x1a\x35\x3c\x58\xc1\xa9\x35\x35\x59\xad\xa8\xbd\x0a\x51\x6e\x85\xa7\xe1\x9b\xa1\x5a\x1d\xc8\x89\x68\x1f\x2a\xaf\xf0\xfd\x6a\x4e\x3a\xa6\x73\xf8\x7c\xba\x35\x9c\xaa\x35\x98\x86\x5b\xc2\x9c\xc5\xae\x55\x5e\x1a\x63\x7b\x6d\x9e\xd1\xb1\x69\xa3\xaa\xca\xd2\x7e\x95\xa4\x31\x6b\x5f\xab\x8d\xe4\xd6\x36\x1a\x2a\x55\x5a\x00\xb4\x09\x2b\x1a\xed\xd7\x31\xaa\xd4\x21\x1a\xb3\x56\xfb\xd5\x87\x74\xf5\xa0\xc1\x96\xd0\x4a\xcd\xa1\xbd\x9a\x41\x23\x8c\xc1\x0d\x95\x82\x00\xf1\x77\xc4\x7e\xb2\xf5\x81\xc6\xd6\xf7\x79\xd6\x98\xd7\xbd\x0a\x3e\x95\xfa\x3b\xc3\xed\x85\xac\x5e\x75\x67\x64\xcd\x9c\x09\x40\x33\xc7\x02\x66\x8e\xa9\x8a\x33\x0a\x68\x73\x0a\x90\xcd\x91\x75\x6f\xf6\xb4\xf3\x09\x8a\x33\x4d\x50\xe3\x66\x12\xac\xc0\xb1\xf5\x6c\x1e\xa3\x8a\x8d\x5b\xbb\x66\xb2\xaa\x33\x95\x5a\x33\x46\x2f\x1a\x45\xb1\xa2\x53\x69\xed\xe8\x7a\x1c\x72\x59\xb5\x22\xcc\x78\x79\x4a\x35\x47\xff\x9d\xb0\x82\x4b\xa5\x6e\xcb\x64\x15\x57\xf6\x55\xaa\xa1\xf9\xbc\x65\x6b\x54\xac\x46\x51\xac\x54\x43\x31\xea\xd5\x28\x8a\xa5\x6a\x56\x55\xb2\xc6\xed\xd0\x29\x6a\x96\x4c\x85\xcf\x36\x4d\x7d\x92\xb1\xb8\x6c\x7b\xbc\x7c\x12\x18\x35\x25\x12\x55\x41\xcf\x36\x78\xa8\x7c\xa9\x9a\xb0\x17\x8d\xad\x24\x31\x16\x54\xdd\xa9\xf0\x51\xd6\xe6\x18\xcd\xb0\x5c\xb1\x72\xb2\x5a\x1a\x95\x0a\x1a\x8e\xa8\x39\x7a\x4a\x27\xaa\x78\x31\xf2\xf2\x1d\x57\x1d\xa0\xa9\x26\x80\x8b\xe9\x3f\xd4\x1d\xac\x4c\x02\x25\x92\x7f\xa9\x85\x8c\x81\xe2\x9f\x26\x76\x67\x22\xe7\x8a\x1b\x59\x31\x2e\x5f\xc5\xec\x78\x85\x16\x01\xc1\x10\x19\x8e\x88\x96\x59\x26\xcc\x54\x7a\x0a\xeb\x3c\x1a\xe9\x3a\x51\xdd\x60\x03\x64\xf4\xea\x5e\x56\x74\xde\xdf\x8d\x43\xf4\xc2\x0e\xa1\x5a\x94\xf9\x40\xfb\xf7\xcb\x89\x32\x3f\x04\x5f\xfb\xda\x97\x18\x7c\xfd\x34\x48\x13\xcf\xe1\x1a\x3f\x44\xce\x1e\x22\x67\xf7\x23\x67\xcd\x9e\x1c\xee\x30\xb3\x51\xb3\xda\x46\xb0\x64\x39\x62\x0b\x29\x88\x8e\x03\x18\x29\x6f\x8e\xf3\x9b\x6b\x14\xe5\x04\x8a\x45\xe0\x84\xcf\xd1\x70\xed\xbe\xa6\xd7\x9b\x08\x39\xb0\x41\x8c\xf5\x18\x60\x21\xc8\x26\x13\xe3\x8e\xf7\x21\x70\xb6\xd2\x0e\x81\xb3\x2f\x21\x70\x76\xd2\xa8\xaa\x4f\x96\xd8\x38\x87\xe2\xba\xd8\xe0\x74\x26\x6f\x10\xbc\x48\x6a\x99\x33\x86\x75\x0c\x24\x6d\x22\x74\x0c\x2a\x21\xec\x13\x08\x86\x60\xe9\x60\xb8\xcd\x22\xa5\x3f\x17\xa4\xf4\x44\x58\x45\xe5\x99\x03\xe5\xa0\x0f\x93\xae\xab\x52\xbf\x26\xb9\x59\x22\x96\x91\x1a\x44\x9b\x9a\xc0\xa1\x9a\xb5\xd9\x19\x73\x5d\xf8\xbb\x5c\x86\xa1\xb2\x81\x03\x27\x2c\xbb\xa9\x94\xd1\x1b\x16\x1f\x0f\x1d\x78\xa9\xc1\x56\x6c\xc4\xca\xd0\x3b\xd4\xfb\x98\x24\xec\x41\x79\xdc\x5d\xb5\x49\x9e\x19\x39\xc7\x23\x6e\x6a\x90\x8d\x37\x34\xcf\x59\xae\x03\x0f\x69\x3a\xfa\x00\x42\xaa\x1a\x5d\xad\x05\xc9\x95\xc1\x53\xe5\xa6\xcc\xd1\xdd\x60\x2b\x81\xc3\x76\x04\x43\x38\x55\xf0\x9d\xf2\xdf\x06\xd6\x62\xc4\x3e\x35\x72\xc4\x82\xac\xf1\x96\xb2\x22\x87\x9e\x0e\xd7\xc5\x8e\x34\xc1\x23\xa9\x38\xec\x58\x61\x03\xb1\x8a\x11\xa8\x6d\x76\x5f\xf1\xbd\x65\x1a\x7a\x57\xbd\x2b\x49\x42\xe4\x54\xcc\x4c\xac\xc0\x8c\x7c\xa6\x83\x2b\x9d\xd4\xbb\x67\x0f\x82\x8e\xce\x7b\x72\x8e\xb9\xe5\x99\x54\x4a\x3e\x0d\x44\xbb\xad\xf2\x49\x97\xd6\x58\xf3\xca\xf6\x0e\x88\x35\x19\x57\x8c\xa9\x64\x88\x51\x34\x35\xd5\x94\x14\xb8\xb9\x01\xfb\x7b\x5a\x03\xcb\x98\x34\x7e\x35\x1f\x37\x43\xbc\xdd\x07\xbb\x8e\xaf\x1d\xec\x3a\xb6\xbd\x00\xbb\x8e\x4d\xc5\x49\x68\xb4\xbb\xbe\x9c\xc2\x3a\xa0\x73\xa3\x14\x49\xf4\x1d\xe6\x83\x83\xa9\xde\xe2\x14\xaf\xc0\x09\x85\x4e\xee\x6e\xbe\x7b\x7b\x2a\x8f\x17\x38\xe6\xae\x2f\x87\x8a\x32\x0d\xd9\x3d\x77\xee\x1c\xbc\x7b\x0e\x58\x6e\x54\x5f\x89\x89\xb4\xa5\x27\x59\x8b\x67\x01\x32\x47\x56\x0b\xb9\x19\xec\x4a\xde\x2f\xec\xa5\x92\x61\x4c\x5d\xd1\xa1\xe2\x72\xed\x5a\xdd\x6e\xe2\xfb\xc7\x9a\x1e\xa7\x9e\x4c\xfb\x1c\x84\x04\xe7\x79\x03\xf0\x6a\xfb\x2a\xc7\x82\xac\x76\x97\x24\x4b\xd8\x4e\x6e\x8a\x9b\xb2\x23\xfa\xd1\x05\xf1\xaa\xe7\xf9\x02\x47\x28\x2f\x12\x00\xda\x8f\xf7\xea\x71\xa6\x84\xc4\xe5\x0d\x41\x53\x2e\x30\x14\x57\x54\xdf\xee\xa0\x1c\x28\x38\x84\x88\x08\x33\xd5\xbf\xce\x27\xaa\x65\xba\xdf\x75\xc3\xf1\x85\x0a\x08\xf0\x59\xdf\xbe\x0e\x0f\xbb\x0c\x0c\xb0\xac\x1e\x09\xe0\x1a\xb7\x45\x22\xaf\xe7\x24\xe6\x2e\xfc\x80\x96\xd8\xf5\x4a\x87\x9c\x14\x8c\x32\xc5\x85\xe4\xc8\xce\xd0\xa2\x90\x02\x3f\xe1\x95\xd8\x83\x7e\x25\xd4\x55\xa1\xf4\x87\xb5\x8a\xaf\x96\x64\x11\xce\xb2\x84\x12\x70\x2d\xb0\x5c\x87\x20\xf7\xd1\xd1\x1b\x08\xf9\x59\x5b\x2f\x39\x35\x5c\x2e\x9d\xa1\x2d\xc9\x17\xfe\xa9\xed\x27\x72\xe2\x8c\x42\xbc\x53\xa0\x7c\x5a\x2d\x46\x7e\x73\xad\xde\x35\xf1\xf7\xae\xd9\xcc\xfc\x31\x90\xd5\xc1\xfe\xd1\xeb\x6e\x8a\x06\xab\x8c\x41\x65\xa2\x2f\xeb\x37\x9d\xdf\x5c\x07\xd2\x5c\xa9\xce\x41\xe9\xa3\xd2\x4c\x2f\xb5\x75\xac\xb0\x6c\xca\xba\xc4\x78\x25\xbf\x1b\xaa\x56\xb0\xd4\x0e\x93\xa4\xc5\x86\x40\x51\xa5\xb2\xc3\x88\xa6\xf0\x95\xf3\x9b\xeb\x5e\xa5\xd5\xac\xed\x3f\x49\xd8\x43\xa8\x00\xd8\x37\xd4\xba\x57\x68\x75\xcf\x1b\x39\x65\xe9\xad\x9e\x84\x8f\xb7\x6f\x86\x6c\xa9\x77\x55\x0a\xba\x84\x0b\x11\x72\xba\x33\x9c\x0b\x8a\x43\x73\x1b\x8a\x3c\xd1\x76\x04\xac\x30\x07\x75\xc2\xe5\x1a\x6f\x49\x59\x3c\x67\x8e\xd0\x6f\x42\xef\x75\xb9\x8f\xf4\xd2\x28\x7e\x05\x25\xdc\x54\xf1\x2b\xb4\x2c\x92\xe4\x0c\x2d\x69\x8a\xe5\x95\x44\x42\x97\xdc\x0d\xb0\xba\xa3\x69\x44\xe4\x1c\xce\xcc\x4e\x42\x30\x07\xda\x5c\x13\x48\xd1\xb2\x37\x88\x34\xa5\x5c\x39\x10\xa0\xb0\x2d\x74\x57\x32\xb2\x08\x8c\xdc\xcb\xe0\xe2\xb9\x17\x49\xc1\x05\xc9\x6f\x99\xbc\x9a\x9d\x6c\x23\x28\x01\x80\xdd\x3f\x7f\x47\xd3\x98\xa6\xab\x50\xf9\xef\x16\x2e\xfb\x08\xa7\x88\x50\x70\x7a\xc8\xee\xed\x24\xbb\x96\x67\xa7\x3c\x50\x27\xbc\x08\xce\xbd\xc2\x1c\x1d\x65\x2c\xe6\x47\x92\xe5\x1f\x29\x77\x22\x3f\x3a\x95\xff\x57\x9f\xdb\x40\x8a\x90\x6a\xa3\xfa\x00\xd4\x5f\xe1\x8c\x1e\x9d\x9e\x21\xd8\x04\x10\xc0\xc7\xc4\xfa\xcb\x3b\xad\x66\x26\xc0\xee\x36\xe0\xac\xde\xba\xef\xc3\x49\x4d\x6d\x04\x9c\xbc\x6b\x83\x6b\xec\x25\x94\xc3\x01\x57\x9e\x11\x53\xdb\x64\xef\xe2\x45\xe8\x3c\xd4\x52\x4f\x36\x99\x00\x3f\x3d\xda\x10\xac\x83\x8d\x11\xd9\x92\x7c\x27\xd6\xba\xa0\xc0\x17\xcb\x64\xed\xa9\x18\xb1\x64\x9a\xb1\x9a\x89\xb7\x24\x83\x2f\x6b\xca\x1b\x96\xc7\x50\x3f\x4f\x92\xfe\xa6\x48\x0c\x2f\x99\x2b\xff\x8b\x5b\x15\x90\xcd\x06\xac\xc8\x27\xf9\x5e\x75\x35\xd4\x4f\xea\xea\x92\xec\x30\xb4\xc3\x0c\x9d\xbf\x79\xa3\x23\x55\xd4\x3c\xfe\x48\xd3\x58\xe9\x52\xe7\x42\xe4\x74\x51\x08\x72\x4b\xe4\x90\xa2\x3e\x69\xcd\x5a\x2a\x33\x40\x13\x7a\xe9\xe7\x08\x3a\x3a\x78\xad\xef\x65\xdf\xbe\xa4\x75\xde\x57\xeb\xc2\xd4\xb1\x56\xd2\x46\x73\x6d\x26\xd3\xf1\xb2\x56\x7d\xdf\xb2\xb8\x89\x09\xd4\x50\x8e\xca\x47\xb5\x10\xbc\x73\xac\xad\x9a\x92\x56\xe1\x76\x59\x03\x07\xe8\x9a\xfc\xd6\x89\x6e\xeb\x43\x69\x6f\x83\xdb\xc2\xf9\xcb\x87\x5d\xa6\xbc\xb1\x08\xa3\x65\x82\x9b\x97\xc2\x6e\x34\xe0\xe1\x4a\x00\xbf\xb8\xfb\x64\x06\xc4\x11\x6d\x92\x92\x3c\xfa\x58\x97\x06\x36\xeb\xac\x8b\x35\x6b\x2b\x15\xe6\x53\xc1\x2c\xd1\xb6\x1d\xe4\x0f\xef\x12\x1d\x8e\x81\xb6\xd9\xff\xa0\x6b\x7d\x61\x67\x07\x80\xf9\x9d\x2d\xcd\x4e\x68\xdd\xd1\x90\xbd\xb5\x64\x39\xcc\xb7\xbb\x6d\x3a\x47\xd0\xb8\x7d\xef\xc9\xee\x81\xe5\x71\xc3\xdc\x0c\xda\x6b\x1d\x5f\x4a\xf0\x82\x24\xbe\x23\xf2\x16\x67\x72\x02\xca\x0c\x51\xc5\x31\x55\x14\x97\xd6\x4b\x55\xfe\x4e\xc1\x95\x9d\x9f\xe5\x2b\x9c\xd2\xbf\x37\xad\x3c\x24\xa5\xcb\x53\xcd\x72\xfa\x77\x82\x4e\x54\xcc\x81\xb2\x66\x25\x24\x12\xa7\x7a\x1f\x36\x70\xbe\xce\x6d\x8a\xe3\x98\x2a\xc9\xea\xa6\x73\x6f\x75\x4d\x06\x4d\xef\xa7\x9d\xf3\xd6\x23\xe5\xdb\xff\x5d\xa1\x61\x5e\x7e\x5c\xe4\xad\xf9\x15\x1d\xef\x6e\x30\x55\xb7\x58\x53\x95\xa2\xe7\x98\x03\xb2\xc1\x74\xc8\x40\x54\x1b\x38\x83\x1b\x2c\x8a\x9c\x8a\x86\x2b\xa7\xeb\x25\x9a\xfe\x58\x2c\x88\x8e\x21\xeb\xf5\x6a\x0a\x49\x58\xe7\x37\xd7\x53\x4d\xfa\x7e\x61\x7c\xdd\x2d\x29\xea\xa0\x22\xc5\x9b\x05\x5d\x15\xac\xe0\xc9\xce\x31\xdc\x23\x0c\xe2\xc6\x1c\xa1\xeb\x66\x35\x3a\x66\x84\xa7\xc7\x02\xe1\x94\xa5\xbb\x8d\x7e\x3d\x8d\x92\x22\x26\x95\xaf\x40\xb4\xc7\x96\xd1\x18\xe1\x42\xb0\x0d\x16\x34\x42\x11\x53\x7f\xf3\x53\x2f\x38\x41\xb8\x85\x5e\x54\x70\xc1\x36\x68\x83\x73\xbe\xc6\x49\xd2\xbc\xee\xa3\x6e\xb2\x36\x4b\xd4\x0c\xe6\xa6\xf1\x0f\x5b\xd5\xcb\x01\xbb\x1b\x3e\x36\x78\x77\xcb\x0e\x0d\x7e\x79\xdb\xb6\x4f\xbd\xef\x6b\xf0\xdb\x86\x82\x17\x9d\x13\xdf\x3d\x17\xed\x27\xd5\x33\x92\x56\x3e\xd7\xf1\x5e\x4e\xb2\x04\x37\xaa\x86\x1d\x58\x74\xf2\x46\x07\xb1\x9e\xa5\xc4\x52\x98\xa3\x3b\x65\x2f\xdb\x60\x11\xad\x5b\x5c\x37\xff\x6f\x43\x04\x8e\xb1\xc0\x73\x29\x0e\xff\x3f\x6d\x6a\xd2\x96\x51\x96\xc4\x92\x74\xdb\x45\xd7\xd8\x7f\x75\x49\xb2\x86\x15\xa8\xf4\xff\x8d\xbc\xd7\xed\xc3\x20\x96\x40\xc2\xa7\x6b\x84\xed\x79\xc1\x76\x2f\x22\x4c\xc2\xd5\x67\x29\x7d\x76\x38\xd7\x2a\x7d\xac\xbf\x52\xd5\xf1\x92\xea\x08\xf4\xc9\xdd\x90\x8e\x84\x00\x95\xd6\x5a\x3e\x07\x76\xc1\xf3\x77\x97\x6d\x36\x0c\x9f\xd6\xd4\xa9\x25\x55\xed\xfc\x1d\xdd\x35\x16\x5a\xfd\x97\xce\xac\x6e\x6b\xde\x57\xb2\xd5\x99\x02\x97\x51\x99\xd6\x60\x3b\x22\x39\x36\x44\xf4\x82\x72\x93\x30\xdb\x4a\xb4\x94\xd5\xda\x26\x2e\xc0\x1f\xe3\xf3\xc2\x74\xe1\x64\xcc\x6c\xc7\x5b\x1e\x08\x71\xc8\x78\xb0\x2c\x2a\xcb\xa1\x00\x79\x14\x42\x11\xac\x0b\xe4\x13\x1b\xab\x99\x5d\x0a\x6d\x9a\xe9\xd4\x51\xbb\xdd\x59\x41\xaa\xb1\x19\x7c\x70\xf7\xed\x32\x57\xaa\x86\xdf\x93\xdd\x31\xd7\x69\xdb\x2c\xe5\x6b\x9a\xf9\x82\x94\xac\x5f\x40\xaf\x3e\xfa\x84\x13\x1a\x5b\xf2\xea\x7c\x5c\xa7\x67\xe8\x1d\x13\xf2\x3f\x57\x9f\x29\xf7\x58\x28\xe4\x5e\xba\x64\x84\xbf\x63\x02\x9e\x1e\x3d\x39\xaa\x6b\xc1\x53\xa3\x75\x0e\x65\x4a\x85\x93\xeb\x68\x26\x66\x98\xd7\xfe\x34\x08\x3b\xc5\x94\xa3\xeb\x14\xb1\xdc\xcc\x81\x05\xc9\xe2\x9a\xbc\xc9\x04\x4e\x59\x3a\x03\xa3\x69\xb7\x45\xe6\x5a\xb3\x76\x87\xbe\x9a\x56\xf9\x0d\x77\xe6\xdc\x4f\x75\x4f\x79\xa5\x1b\xaa\x0b\x0a\x84\x42\xfd\x85\x72\x73\x25\xc5\x28\x2e\x60\x22\xb0\xb1\x9c\xd0\xa8\x93\xf4\x86\xe4\x2b\x70\xad\x44\x9d\xc6\xf9\x30\xeb\x52\x80\x4d\xc9\xb3\x23\xe0\x42\x78\xd3\xa2\x91\xa2\xc6\xeb\x43\x3d\xad\x58\xec\x46\xa9\xa9\xff\x25\x39\x26\xcc\xeb\x7f\x03\x96\x1c\x9f\xa3\x73\xc4\x69\xba\x6a\x85\x0b\x77\xdf\xd0\xee\x26\x97\xb8\xa4\x4b\x39\x92\x0c\x70\x8b\x13\xc9\xd1\x21\xa2\xd9\x93\xee\xcf\x96\x7b\x17\xdc\x99\x46\x77\x93\xdc\xc8\xfa\x9c\x8e\xee\xc9\xee\xe8\xac\xb2\x69\x5a\x28\xca\x87\xaf\xd3\xa3\x12\xd6\xb0\xb2\x4f\xed\xd5\x01\x4e\xac\x23\xf8\xdb\xd1\x7c\xef\x4e\x6c\xa1\x1d\x74\x53\x76\x5c\x10\xa1\xda\x37\xea\xde\x05\xad\x92\x69\x65\xe5\xdf\xeb\x79\x32\x2a\x02\xac\xfe\x43\x8e\xb3\x8c\xe4\x08\xe7\xac\x00\x63\xc2\x66\x4b\xf2\xb9\x79\x04\x02\x1b\x9a\x2c\x8c\xc6\x2e\x16\xb1\x3c\x27\x91\x30\xea\x85\x3c\x45\x82\xa1\xff\x73\xfe\xf6\x0d\x4c\xf7\xff\xbe\x7b\xff\xae\x97\x9c\xf6\x40\x16\x6b\xc6\xee\x01\x3f\x00\x66\xe6\x51\xf4\xbb\x3f\xab\xaf\x5c\x96\xbf\x19\x11\x9d\xa3\x98\x08\x4c\x13\x88\xec\x78\xff\xe6\xad\x8e\xfd\x30\xd7\x78\xe3\xd2\xe8\x3e\x37\xed\x91\x51\x7a\x15\x8e\x75\xa4\xd3\x2d\xd9\x52\xf2\xa0\xd7\xa4\xe9\x33\x33\xb4\x22\x29\x04\x0b\xb4\x04\x05\xcd\x10\xa7\x31\xb9\x02\x60\x9b\x66\x02\x03\x0d\x8e\x2d\x7d\xec\xde\xc3\x5d\x2c\xd1\xc3\x0e\xbd\x97\xa3\xf1\x29\xe4\x37\x2c\x6f\x05\x67\x0e\xc1\xa8\x09\xc1\x9f\xd1\xf9\x0f\xaf\xd1\xb7\xdf\xfe\xbe\xe5\x91\x0d\xfe\x4c\x37\xc5\xe6\x35\xfa\xc3\xff\xf8\x1f\xbf\xff\x1f\x6d\x0f\xd1\x54\x3d\xf4\x4d\xdb\x98\xf4\x09\xbf\xb8\xbd\x7c\xc6\xb9\x8d\x6d\x14\x5e\x97\x93\xc2\x4b\x66\x89\x69\x52\xe4\x3a\x00\x75\x30\x15\x77\xc7\x0f\x26\x02\x57\x4d\x77\x47\x6a\x26\x5d\xfb\x3c\xd8\xbc\x6d\xf6\x18\x5c\x2c\xc6\xe4\xad\x34\x5b\x15\x85\x36\xb4\x67\x8a\x67\xdc\xb5\xaa\xad\x0d\x9d\xdb\xd3\xa6\x94\x62\x08\xbf\xfd\x5c\x90\x7c\x07\x39\x44\x56\xbc\x6d\xdd\x07\x4e\x7c\xd4\x87\x12\x05\xd8\x8c\x4b\xdf\xee\x0a\x28\xb2\x7a\x51\xb7\xab\x52\xf6\x9a\x44\xe7\xa9\xf6\xa1\xd7\xfa\x0a\xb4\x08\x78\xcf\xad\x25\x1b\x9d\xb7\x52\x4c\x8b\x24\x69\x23\x91\xb2\x76\x5b\xb8\x3b\xfb\x9d\x8a\x5b\x88\x6e\x15\xa6\xbc\xab\x36\x58\x85\xef\x94\x0c\x2b\xea\x7d\x6f\x45\xde\x9d\x8c\x09\xc4\xd4\x81\xaa\x7d\x27\xcd\x7a\xfc\x5e\x0f\x05\xdf\x4b\x97\x58\xb4\xdf\x6e\x35\xdf\x9d\xa6\x80\xe0\xcb\xb0\xc0\x4b\x3f\x40\xa6\x57\xfd\x57\x2d\x3c\x2a\x33\x08\xd6\x72\x80\x41\xc0\x4b\x13\x0d\x88\x72\x0d\x8a\x8f\x08\x31\x11\x34\x0c\x2b\xd4\x50\x10\x30\x30\xc0\x6e\xed\x65\x2e\x08\x20\xaa\x35\xdf\x3e\x46\x03\xdd\x9b\xf0\xa9\xf3\x1b\x10\x54\xeb\x6d\x46\x08\x18\x5f\x83\xb2\xdf\x69\x4c\x08\x20\xb9\x6f\x6e\xe8\x34\x29\x04\x50\x6c\x33\x3a\xb4\x1b\x16\x42\xce\x41\x80\xe9\x21\xd4\xbc\xa0\x5a\x9f\x10\x96\xe0\xf0\x95\xa0\x7d\xe4\x35\x3b\xa8\x36\xd0\xf8\xd0\xd9\x4b\x63\x98\xe8\x6d\x82\xf0\xd8\x2c\x1d\xf3\x44\xa8\x21\xa2\x93\x62\x83\x91\x22\xd0\x1c\xd1\x6d\x85\xeb\x34\x55\xf4\xb9\xf5\xbd\xd7\x59\x1f\x03\x85\x4b\xb8\x63\xef\xe4\x84\xa6\x5b\xa6\x0a\xc8\xf5\x10\xbd\x6f\xf7\x5e\xab\x49\xe0\x0f\x70\x2f\x69\x11\xbc\x53\xf8\x56\x97\xbf\x55\x5d\x91\xd4\xde\x51\xc1\x7d\x86\xfe\xae\x31\x75\x25\xd1\x8c\x56\xcc\xaa\xf3\x50\x24\xe4\xcf\x54\xac\xdf\x9b\x52\x98\xfa\x24\x89\x22\x4b\x60\xe8\xce\x1f\xba\xc1\xeb\x6e\x4b\x39\xff\x5a\x28\xa6\x14\xb1\xcd\x86\xa4\xb1\x8a\x46\xd9\xe0\x7b\x82\x78\x91\x13\x1d\x32\x98\x24\x4a\xcb\x91\x1f\xea\x20\x4b\x3e\x67\x38\x55\x62\xad\xdc\x89\x5b\x79\x1b\xb6\xef\xc4\xa0\x7d\x18\x26\xe3\x04\x66\x9c\x74\x67\x9a\xd8\xd4\x8a\x5a\xae\x88\x87\x6b\x2e\x48\xc2\xc0\xf6\x35\x47\xc7\xbf\x39\xd6\x61\xc0\x9a\x10\x5c\x45\xfa\x57\x2d\x6f\x9c\x05\x20\xca\x24\x24\x5d\x95\x30\xb1\x3c\xa1\x11\xb1\xb7\x0e\x4b\xc9\x1c\xdd\x6a\x41\x33\x44\x6e\xf5\x5f\x10\x41\x97\x43\xa0\x80\x51\x02\x03\xf5\x5c\x0b\xf3\x96\xbb\x1a\x5b\xf3\xdb\xf8\xf5\x30\xa4\x7e\x79\x2b\x62\x0b\xe7\xf6\x59\x90\x2a\x8b\x29\x6f\x31\xbb\x1a\x96\x85\x7a\x3a\x09\x0c\x36\xc2\xb9\xbc\xe6\xc0\x9e\x3a\x43\x17\xb7\x57\xe7\x1f\xae\xce\xd0\xc7\x9b\x4b\xf8\x2f\xcb\xd1\x6f\x54\x99\xcb\x24\x71\x3e\xe3\x13\x80\x9a\xd7\xd1\xbb\x52\x1e\xaa\x2f\x77\x1d\x03\x63\xf4\x2b\xcb\x78\xe4\x0b\xce\x2f\x63\xaf\x3d\x9d\x74\x83\xf2\xff\x92\xa2\xef\x59\x8e\xc8\x67\xbc\xc9\x12\xf2\x1a\x1d\x67\x2c\xe6\xc7\x3a\x2d\x42\xfe\x7b\xae\x7e\x7a\x95\xb0\x95\x0f\x12\xcc\xe4\x52\x10\x94\xb0\x15\xe2\xc5\xc2\xe6\xd2\xc0\x55\x0e\xb4\x7e\x63\x68\x57\xe2\xf9\x7d\xea\x94\x49\xa4\x71\x68\xda\x8e\x55\x28\xba\x0f\xf8\xb4\xce\xb2\x4f\xaf\x78\x84\x13\x52\xa1\x23\x7f\xa8\x7f\xee\x37\xaf\x7e\x13\x36\x05\x95\xb1\x19\x09\x91\xe6\x35\x7a\x7f\x49\xe5\xbe\x7f\xa0\x49\x1c\xe1\xdc\x97\x67\x5f\x3f\x1a\x70\x1f\xab\xb8\x6c\x48\xb4\x50\xd5\x69\x52\xb8\xe7\x43\x67\x40\x03\xe8\xb0\x2d\xc9\x13\x9c\xa9\xe8\x6a\x82\x23\x8d\xc4\x0f\x1d\xbc\x24\x19\x81\x8c\x2d\x55\x8d\xc1\xb7\xb3\x48\x1a\x25\x8c\xc3\xe3\x20\x0a\x9c\x55\x86\xac\xeb\x06\xe8\x2a\x42\x81\x09\x36\xf6\x10\x77\xa3\x66\x3c\xc7\x29\x86\xe0\xdd\x1e\x27\x58\x05\xfb\x56\x8d\xcd\x0e\xe8\x98\x4d\x9c\x00\xcb\x43\x90\xe2\x0f\xa2\xd9\x91\xce\xaf\x3b\x3a\x43\x47\x16\x23\x29\xd6\xaa\xc9\xd1\x6f\x8e\xca\x07\x02\xcf\x2f\xd6\xa9\x8b\x91\x7a\x6d\x06\x7d\x74\xf3\x57\x61\xb3\x81\x5a\xe5\xb5\xce\xd9\x41\x95\x58\x6d\x52\x1a\xd0\x96\x5d\xe8\x7f\xf5\x33\xbe\xfd\xe0\x0e\x71\xaf\xc7\x65\x72\x63\xad\xb7\xbe\x91\xeb\x20\x36\xdb\x5b\x39\x6d\x0e\x71\x01\x00\x0d\x2a\xd1\x52\x2f\x59\xee\x24\xca\xf8\xfa\x7c\x57\x39\x04\x26\x60\xae\x02\x38\x47\x73\x94\xe1\x5c\x6a\xac\xe6\x49\x1f\x51\xa7\x48\xf3\xd1\x6f\x3c\x50\x35\xde\x0d\xed\xf8\x15\x07\x7b\x61\x04\xce\x57\x44\x74\x39\xec\x70\xba\x7b\xdf\x8a\x28\x3b\x0b\xf2\xe7\xcd\x42\x0e\xe7\xe7\x59\x89\xd6\x39\xa3\xa9\x98\xb1\x7c\xa6\x5e\x78\x8d\x44\xde\x52\x00\x46\xd0\x0d\x61\x85\xb8\x23\x11\x4b\x9b\x92\x0f\xf4\x53\x93\xf8\x1c\x83\xb3\x33\xb4\x8b\xfb\xdc\x48\x68\x26\x45\xc3\xf5\x53\x95\x1a\x70\x87\x0b\x5b\xb5\x0a\x8e\xd2\xfb\x37\x6f\x87\x2e\x35\x82\xbc\xf6\xf6\x95\xfc\xa4\x6f\xa7\x74\x65\x7b\xae\x47\xd2\xfa\xca\xdb\x42\xf4\x7b\xe1\xc2\xba\x53\xbb\x9e\xd4\x53\xd2\x85\xfa\xd2\x32\x5a\x2e\xb0\x28\x6a\xfb\xa0\xb2\x36\x9a\xab\xde\xa9\xbc\x2f\xad\xf3\xdc\xc1\x5b\xae\x49\xda\x45\xc1\x00\xb1\xb9\xd6\x0d\x55\x9e\x02\xde\x82\x70\xdb\x8c\xc5\x73\xa4\xc9\x6c\xf0\x0e\x89\x1c\x53\xa5\xb2\xe3\x48\x14\x90\x3e\x8e\x85\x0e\xcd\xd5\x08\x56\x5f\xed\x0f\xa7\x41\x15\x6f\x57\xbf\x23\x92\x0b\xfe\x06\x73\xf1\x31\x8b\x71\x63\xda\x51\x2d\xbc\x96\x0b\x38\x2e\x4a\x99\x78\x48\x49\x2c\x99\xba\x9e\x08\x45\x0d\x3d\x48\x8e\x59\x28\x7a\x7b\xe4\x3a\x37\x98\x39\x3e\xf2\xd5\x99\xfc\x4c\x53\x6f\x6f\x99\x9c\x85\xf3\x06\x56\x53\x8d\x64\xf6\xf5\x52\xde\x64\x39\xd0\x42\x29\xf9\xbc\x6f\xbb\x18\xd7\x53\x96\xc6\x6d\xe1\x2f\xd5\x19\xd5\xb2\x7c\xf9\xc2\x19\xc2\x68\x4d\xb9\x60\xb9\x36\xce\x43\x0d\xe8\x1c\xa7\x9c\x36\xe7\x66\x8e\x0f\xa7\xb9\xb0\x1f\x97\x1a\x02\xc1\xb6\x0e\xa9\xde\x9d\x50\xa6\x33\x27\x11\xcb\x63\xdb\xa5\x66\xee\x56\x76\x53\x8b\x8d\xcd\x67\xa5\xe1\xe5\x91\x49\x33\x09\xe6\xe2\x83\xfd\xba\x5c\xfc\x20\x2e\x5b\xdd\xd0\x7a\xb8\xe5\x28\x0c\x92\x01\x4b\xcd\x1f\xdb\xed\x60\x0c\xe1\x54\x89\xcf\xc3\x79\xab\x6f\x5b\x95\x63\x55\xe7\x75\xc0\x38\x1f\xec\xd9\x74\x86\xfc\xd8\x3d\xde\x10\xce\xf1\x2a\xac\xab\xe7\x0a\x72\x19\x59\xc8\x65\xfd\x32\xa2\x69\x4c\x23\xb8\x29\x6c\x8c\x57\x13\x57\x2d\xdb\xc3\x7a\xd7\xbe\x05\xe5\x5d\x6a\xb2\x96\xed\xe1\x1b\xbc\x74\xd9\x1a\xf3\xb0\xe1\xd9\xb3\x66\x8c\x1b\xa1\x07\x24\xa8\x1f\x39\xc1\xbc\x3d\xc3\xa5\x36\xcf\x8b\x9c\x92\x25\xba\xc0\x1b\x92\x5c\x60\xfe\x14\x13\x0d\x9c\x63\x8e\xc8\x7c\x35\x47\xc7\xb7\x8e\xcf\xe3\x1d\x13\x6f\xdb\xeb\xd8\x74\x26\x72\xfa\xcf\xfd\xb8\x13\xdf\x1c\x6d\xde\x7a\xd6\x47\x5d\x1b\xbe\x93\x3d\xea\x4c\x8f\xea\x59\xeb\x09\x1e\x77\x76\xe5\xd6\x69\xba\x0c\x46\x9e\xda\xae\x54\xae\xe6\x93\x5a\x3d\xa3\x45\x0e\x0a\x59\x34\xec\xac\x76\xa6\x61\x35\x9f\xcf\x91\x27\x73\xcc\x34\xf6\x3e\x93\x9d\xc3\xb3\xaf\xdf\x35\x08\xd1\x7b\x23\xfd\x50\x91\x80\xc1\x02\xe5\x86\x19\x01\x3e\xb7\xec\xe3\xc5\xdd\xa7\x69\xc4\x9e\xa7\xce\x93\xd4\x0b\xd7\xf8\xb7\xb4\x35\xd4\xb7\xed\x4e\x1e\x93\x77\x19\x83\x3d\x4f\xae\xeb\xd3\xb8\x39\x2f\xcd\xf7\xb4\x42\xa3\x55\x57\xbd\xda\xe0\x28\x28\xfb\xd4\x69\x30\x2f\xf7\xc3\x89\x60\x28\xcb\xc9\x16\x42\xd0\x52\x88\x30\x97\xc2\x3b\x97\x07\xe2\xb4\x5d\x32\x0b\xf1\x50\xfa\x83\xbe\xda\xd7\xdf\xfc\xbd\x65\x17\x98\x3f\x7b\x04\xc8\xae\xc5\x55\x2d\xcc\x8b\xda\x99\x60\xab\x5a\xa0\x95\xb3\x2b\xd9\xb6\x17\x21\x8f\xf8\xd7\x8b\x56\x93\x72\x5e\x6f\x35\x08\x52\xf9\xc2\x2d\x30\x5e\xe5\x3f\x89\x24\x5f\x8d\x30\x07\x5b\x21\xfc\xac\x18\x8d\xcf\xc6\xed\xea\xea\xb7\x75\x4e\x07\x79\x4e\xd5\x3d\x3f\xc5\x70\x8b\x82\x4e\xb3\x06\x9e\xe4\xe7\x40\x5a\xcf\x98\xbd\xed\xd9\x44\x8f\x05\x8c\xa0\x5a\xf7\xae\x1b\xba\xdf\x7c\x2c\x61\xec\x4e\xf3\x23\x66\x74\xec\xae\xc9\xd3\xe9\x39\xc9\xb7\x24\x76\xec\xb0\x1a\xc8\xda\xfd\xc5\x31\x97\x1b\xba\x7a\xea\xd1\x7f\xfd\xf7\x57\x5f\xcd\x66\xb3\xaf\xca\xd8\x84\xd7\x08\x67\x94\x7c\x16\x44\x45\xab\xcc\xef\xff\x08\x15\x9a\xb6\xdf\x7c\x05\x1b\x0d\x5d\x00\x72\x82\x71\x9e\x5e\xda\x94\xa4\xaf\x4c\x72\xba\xfc\x04\x4e\x53\x26\x5c\xcf\x7a\xc4\x52\x91\xb3\x24\x21\xf9\x6c\x45\xd2\xf9\x7d\xb1\x20\x8b\x82\x26\x31\xc9\x81\xb8\xf9\xf4\xf6\xeb\xf9\xef\xe7\x5f\x7f\x85\x54\xb1\x08\xad\x7b\x70\x81\x37\xd9\x6b\x08\x6e\xff\x4a\xef\x38\x03\x89\x93\x25\x38\xe5\x73\x1b\x54\x3a\x8f\x58\x4e\x98\xfc\xcf\xe6\x2b\x9e\x91\x48\x7e\x5b\x1d\x2e\xd4\xf8\x8c\x86\x6f\xd4\x5d\xd4\x38\x32\xe6\xff\x67\x88\x25\x0a\x65\x5f\x0d\x5c\x23\xfb\xdc\x24\x1a\x22\x28\xa1\x5c\xfc\x58\xff\xcb\x1b\x53\x38\x23\x4b\x8a\x1c\x27\xd5\x8e\xaa\xd5\x58\xb3\x5c\x38\x18\x80\x33\xa4\x43\x6a\x39\x4d\x57\x45\x82\xf3\xca\x3b\x5f\x19\xb7\x58\xe9\xf0\x91\xb7\xe1\xd6\x89\x23\x99\x55\xc2\xd1\x68\x2a\x48\x7e\xc1\x92\x62\x93\xda\x0f\xec\x49\x87\x4b\x9a\x73\xa1\xa1\x85\x94\x83\xd9\x18\xcc\x9a\xe4\xda\x77\x4e\xa5\xad\xbf\x71\x96\x82\xf1\x17\xcd\xe5\x04\xcf\xdb\x5f\xf8\xe9\xeb\xbf\xea\x77\xd4\x8a\x95\xd2\xe6\xde\x1e\x6e\xe8\x21\xce\xb2\x9c\x6d\x71\xe2\x96\xef\xae\x7f\xdb\x3c\x53\xf9\xcc\x79\xf5\xc7\x86\x6f\x35\x93\xb1\x56\x55\x97\x8c\xfd\x71\x1f\x20\x4a\x3d\xb6\xfd\x06\x27\xd9\x1a\xab\x04\x25\x1e\xad\xc9\x06\x9b\x13\xc6\x32\x92\x9e\xdf\x5c\x7f\xfa\xfd\x5d\xe5\xe7\x66\xb8\x28\xb9\x75\x74\x79\x60\xee\xc2\x6d\x63\xa3\x27\xd9\x70\xea\x72\x1f\x7f\x55\xe5\x09\x35\x51\x6c\x5f\xf4\x92\x72\xb3\x3a\xa1\xce\x4f\x72\x06\xec\xff\x36\x8b\x42\x0e\x6b\xa8\x30\xa5\x6a\xc9\xb8\x32\x4c\xa9\x32\x0e\xbd\x51\x49\xac\x67\xa7\x74\xcd\x1a\x8b\x7e\x13\xaa\x95\x1c\x70\xaa\x47\x34\x47\x72\x73\x91\x9c\x1b\x44\x59\x95\xf7\x25\xc0\x74\xba\x4a\xe9\xdf\x2d\x6d\xc8\x4e\x54\x51\xf9\x82\xec\x81\x0b\xc3\xc1\x48\x71\xa2\x5c\xbd\x67\x3a\x55\x67\x87\x72\x22\xbf\x82\x8a\xd4\xa1\x67\x62\xd6\x1b\xea\xd6\xad\xa8\x30\x2c\x31\x62\x9b\x4d\x91\x52\xb1\x7b\x05\xdc\x8d\x2e\x0a\xb9\x2e\xaf\x62\xb2\x25\xc9\x2b\x4e\x57\x33\x9c\x47\x6b\x2a\x48\x24\x8a\x9c\xbc\xc2\x19\x9d\x41\xd7\x53\xe5\xe3\xdc\xc4\xbf\xb2\x5c\xb9\xaa\x0e\xb6\xdc\x11\xfb\xf7\x7c\x75\x05\x00\x92\x47\xe5\x90\x38\xa1\xe7\x55\x10\x37\x40\x2b\xbc\xba\xfb\x60\xbd\xa2\xb0\x18\xf5\xd9\x87\x79\x77\x7c\x2e\xe5\x12\xc8\x09\x83\x12\x1c\x1a\xeb\x36\x67\x1b\x0d\xcb\x1c\x67\x8c\xa6\x2a\x03\x22\x4a\xe8\xbe\xf6\xc1\x8b\xc5\x86\x0a\x6e\x30\xa0\x55\xb4\xcc\x05\xdc\x13\x80\xf5\xa5\x2c\x2d\x73\x74\x9d\x96\x1a\xfa\xa3\x2f\x00\x40\xf0\xcd\x00\x1a\x31\x68\x09\xdc\x2b\xae\xfe\xf0\x9e\x2a\x64\x2e\xa0\x96\xf5\x72\x4e\xfe\x5d\x46\x22\x7b\x6a\xec\x49\x3f\x57\xd0\xc1\x1a\x39\xdb\x06\x25\xd5\xed\x66\x0b\xcb\x2c\x6a\x8e\xa1\x56\x0d\xad\x59\x2b\x9b\xa1\x1a\x3f\xad\xfe\x5c\x23\x3e\xf3\x5f\x15\xaa\xb5\xab\x57\xe6\x73\x3e\xbb\x8d\xb9\x09\xb4\xae\x0b\xe0\xd2\xf6\x7a\xd0\xa0\xf6\xa0\xf9\xa6\xee\x9c\x36\x19\x9d\xaf\x85\x1b\xee\x26\xe7\xf8\xe8\xdc\xe0\x4a\x29\xf8\xe2\xb7\x38\x2d\x70\xd2\xe0\xfd\xef\x90\xdb\xcc\xfc\xb4\xa5\x64\x37\xc3\x0a\xb6\x4f\xdf\x44\xa9\xdd\x1d\x3d\xd6\x49\xa2\x1d\xe8\x62\xcd\x0e\x79\xb5\x07\xdb\xde\x69\x46\x18\x2a\x21\x8b\x9b\x4b\x15\x0e\xf5\x16\x1f\xb9\xe7\x67\xcf\x49\xac\xae\xd0\x9a\xa3\xb8\x5d\x39\x00\xf7\x1b\xc9\xb8\x3d\x1a\xf2\x26\x89\xd8\x26\x4b\x88\xa8\xde\xc5\x10\xc5\xd5\xe4\x4d\xae\x6f\x8a\x36\xdf\xf2\xd1\xb8\x33\x1a\x61\x81\x13\xb6\xba\x6b\x08\x48\x9b\x29\x2b\x6c\xe8\xe9\x13\x82\xa4\x85\xe4\xb9\x77\x15\xa0\xd5\xc6\x1a\xc5\xd5\x03\xd9\xfe\x66\x09\x56\xae\xed\x52\xd5\x92\x22\x4d\xbb\x14\x4a\xbe\x70\x8b\xf5\x18\xeb\x78\xa0\xd8\x49\x0d\x51\xd3\x3f\x29\xc0\x54\x9b\x4c\xd3\x3c\xe0\x32\xdc\xda\x98\xac\x6d\x69\xdb\xc6\xb7\x3d\x4a\x1e\x24\xc9\xb4\x47\x50\x54\x6f\xf5\x6b\x3d\xa9\xb9\x06\x91\xc0\x28\xa3\x44\x85\x80\x5a\x11\x09\xa6\x88\xe0\xb8\x3d\x7d\x19\xa7\x48\x5e\x7b\x39\xb1\x81\x84\xda\x4a\x0d\x64\x4b\xc1\x0a\xca\x80\x60\x15\x0d\x09\x30\x15\xaf\x7e\x68\x43\x05\x52\xa9\x3e\x1a\xd9\x1f\xf6\xf9\x06\xa2\x29\x0d\x6c\x7b\x4c\xb8\xdc\xc0\x77\x60\x08\xdf\xe0\x94\x2e\x09\x17\x73\x0b\x44\xc0\x7f\xfa\xdd\x5f\xdb\x1c\x83\x4e\x04\xed\x99\xc1\x9d\xb5\x42\x89\xde\x60\x70\x1d\xc8\xe9\xb0\x14\xbb\x8b\x8b\x42\x20\x88\x1e\xf6\x03\x0c\x57\xe0\x7b\x79\x0f\xa8\xe1\x16\x52\x07\xba\x27\xaf\xd1\x91\x52\x6b\x6c\x37\xff\x4b\x0a\xfa\xff\xdd\x16\xea\x77\xf2\x00\x91\x6c\x47\xf2\xa1\x23\xd5\x39\x2b\x85\xba\xd5\x39\xca\x4e\xaa\xf8\xb7\x9c\xae\x56\xa4\x0d\x39\x43\xb9\x18\xc0\x20\x0b\x30\xfa\x14\x6a\x9d\x96\x24\x52\x5d\x7e\xb7\x2c\x5d\x5a\xef\xf4\x4f\xbf\xfb\x6b\x6b\x8f\xab\xf3\x85\x68\x1a\x93\xcf\xe8\x77\xd6\x71\x91\xb1\xf8\x54\x23\x02\xf1\x5d\x2a\xf0\x67\xf9\xa5\x68\xcd\x38\x69\x9b\x59\x88\x14\x14\x4c\x55\x7a\xe0\x0c\x3c\x67\x49\x32\x53\xf2\x4c\x8c\x1e\x54\x3a\xa4\x59\x38\x95\xd6\x97\xe1\xbc\x23\xd9\xde\x91\xfd\x55\x95\x66\xe8\x99\xdc\x50\x2b\x30\xfe\x48\x99\x51\x95\x7e\x50\xb1\xc0\x4e\xd5\x85\x16\x8a\xbc\x50\xdb\x47\xb2\xf5\x35\x4e\xc1\xe9\xa3\xeb\x48\x48\xd9\x70\xde\xec\x23\xf5\x9c\xe3\x76\xc3\x5b\x83\x60\x5e\x67\x1c\xcf\x26\xda\x06\x0e\xae\xdd\xb0\xd7\x5a\x2a\xfc\x29\x0a\x7e\x0f\x1e\x4b\x47\xa5\xe4\xfd\x01\xa9\xc0\xda\x27\x18\x15\x94\x5f\x7d\x35\x68\x50\x46\x25\x08\xbf\xc7\x8e\xef\x14\xc3\x88\xea\xef\xca\x63\xa1\x8a\x35\x69\xd5\x5c\xf3\xd8\x96\xc3\x44\xa5\xe8\x13\x2b\xd6\x8c\xd3\xdd\xa3\x6f\x65\x39\xa1\xe0\x3b\x8e\x76\x33\x6d\x47\x9c\xe1\x34\x96\xff\xe6\x94\x0b\xf9\xfb\xa0\x19\x6c\x35\xd3\x56\x67\xed\xe3\xf5\xe5\xd3\x6c\xf0\x82\x0e\x38\xab\x8b\x22\x8d\x13\xf2\x86\xb1\xfb\xc6\x14\xbf\xca\x50\xbe\x73\x9f\xb5\xbe\x43\xa5\x6d\xd2\x74\x96\xe5\x6c\x95\xcb\xdb\xdc\xd1\xd1\x51\x56\x34\x46\x7b\x63\x80\xff\xcd\x70\x74\x8f\x57\x44\x77\x02\xae\x28\x8d\x68\xa6\xec\x00\xa0\xe2\xb4\x09\x6e\x63\x62\xeb\xdc\x91\x28\x9b\x87\xee\xb3\xe9\x72\xad\x83\x6d\x6e\x28\xd3\x63\x90\xd0\xf5\x28\x7c\xbd\x1f\xe9\xef\xae\x48\xf0\xb7\xa4\xe9\x0e\x9c\x95\x58\xca\x4d\x31\xd1\x33\xa8\x90\xd3\xf8\x07\x03\x27\xdb\xf0\x47\x9f\x9f\xb3\xde\xaf\xb0\xb8\xab\xda\x4b\x66\x2d\x8c\x90\xa6\xe7\xb2\xf2\x58\x0b\x5d\x25\xf5\xe8\x35\x80\x02\x4d\x0f\x98\x03\xa7\x4a\xb6\x3a\x7e\xe8\x91\x81\x6b\x7c\x4a\x41\xc3\xf8\x7b\xab\x06\x6e\x87\x3d\xde\x45\x8f\x9a\xd0\xd0\x9b\x5e\xca\x42\x07\x51\x63\x80\xed\xad\x32\x74\xd2\xd4\xea\xc4\x63\x2a\x0e\xaa\x0d\x53\x1f\x3a\x49\xea\xa2\xe6\x8f\xa3\x44\xa8\x36\x4c\x95\xe8\x24\x69\xd5\x8c\xbe\x0a\x45\x27\xd5\x26\x65\x23\x4c\xad\xe8\x24\xdb\xa8\x72\x04\x28\x17\xbe\x7d\xdc\xa8\x78\x74\xaa\x18\x9d\x14\xbb\xd5\x8f\x56\x45\xa3\x93\x66\xa7\x12\xa2\x5a\x10\xc7\xf0\x85\x96\x7c\x09\x6a\x49\x8f\xe1\x76\xc5\x1e\xec\x0f\xf7\x45\x28\x2a\x3d\x47\xd7\xa1\xb4\xb4\x0d\xf1\x45\xa8\x2e\x3d\x86\x19\xa4\xc6\x34\x0d\x76\x22\x65\x46\xb5\x2f\x46\xa5\xe9\x31\xb3\x9e\x18\xa7\x17\xa7\xe4\x04\x0e\xad\x2b\x09\xa8\x61\x64\x4e\x16\x4e\xcd\x3f\x20\xbb\xab\x2a\x5a\x5b\x1b\xbd\xab\x56\x74\x0b\x9b\xa3\x01\x45\x27\x88\x9c\xf4\x86\x3e\xb6\xa0\xd7\xaa\x16\x16\xf7\x18\x9e\x01\xa4\x5a\x47\x56\x40\x19\xf7\xbd\x97\x18\xd0\x49\x12\x55\xd3\x06\x7c\x09\x41\xaa\x05\x63\xbe\x85\xa5\xda\x94\x93\xe1\x4f\x11\xea\x31\x11\x52\xc3\xc9\x72\xb6\x08\xc3\xd4\x98\x78\x34\x41\xf1\xa3\x43\x13\x11\x3c\x2b\x5a\xfa\xe3\xca\xbd\x30\xc9\x14\x74\xa7\xea\x34\x8c\x49\xe1\x84\x55\xe2\x07\xed\xfa\x1c\x73\x58\xf2\xa9\xfb\x38\x30\xd8\xd6\x51\x00\x54\xf7\xce\x8c\x17\xfb\x43\x5e\x90\x33\xf4\x3d\x4e\x38\xf1\x21\x7f\x7c\x4c\xef\x53\xf6\x30\xcd\x38\xba\xb2\xae\x1b\x46\xf1\x41\xe7\x57\x7b\xf3\xc2\x02\x3b\x51\xda\x48\x82\x2e\x82\x6b\xfb\xb8\xb1\x7c\x69\x8b\xc7\xac\x48\xe9\xcf\x45\x55\xc9\xf2\x62\x8c\x9e\xd4\xd5\xb2\x8b\xbb\x4f\xb0\x81\x94\x01\x83\x57\x00\x5a\xe5\x1f\x79\x5b\x28\xbd\x3f\x0b\xae\xc3\x04\x50\x19\xe1\x0d\x16\xeb\x9a\xe2\x98\x68\x68\xb8\xba\x81\x2b\x2b\x9a\x1c\xaa\xa6\x5d\x8b\x63\x2e\xfb\x45\x23\x9c\x24\x3b\xa9\x2b\xd1\x8d\x3c\xe6\x56\x96\x1a\x9e\xd1\xe7\xbd\x74\xf6\x0e\x27\x01\x18\x05\xba\x25\xce\xcb\x66\xd2\x95\x81\x8f\xc4\x7a\x64\xc3\x81\xea\x5a\xeb\x38\x35\x74\xea\x56\x3f\xdc\x54\x85\xbf\x9c\x61\x4d\x12\xb4\xe1\x4e\x8b\x97\x3c\xc3\x4b\xa8\x32\x80\x05\x2c\xe1\x80\x51\x54\xa3\x02\x1e\x3f\x80\xa4\x4b\x06\x1b\x6f\xdc\x75\x22\x3b\xca\xbc\xce\x0e\xe1\xad\x45\x06\xd2\x4b\x42\x3e\x93\xa8\xb0\x67\xc0\x1b\x23\xf4\x64\x19\xd3\x4f\x9c\xb8\xfc\x54\x59\xc7\x53\x26\xd3\xda\xd5\x1f\x97\x67\x52\x4f\xf6\x1f\xcc\x26\xba\x2f\x6e\x3f\xa0\x4b\x28\x4a\x49\xd3\x01\x80\xdb\x53\x3d\xb5\x20\x65\xd6\x17\xe9\x82\xac\xaf\xee\x76\xc9\x5f\x30\xe0\x34\xc8\x2b\x49\x85\x6b\x02\x06\xc1\xc3\x9a\x0d\xe2\x9d\x21\x49\x9f\xce\xf7\x6f\xe4\xe3\xf6\xee\xd5\xc9\xa0\x6e\xf6\x4f\x3d\xc0\xbe\x36\x98\x8e\xae\x76\x75\x32\xc1\xad\x51\x6e\x63\x98\xd4\x9d\x20\x59\x9d\x29\x39\x83\x49\x41\x26\xde\xd2\x58\x45\x81\x91\x0c\xb5\x44\xa6\x8c\xe6\x48\xdd\xde\x26\xe5\x3f\x69\xde\x91\x33\x6b\x3a\x69\xfc\x63\x2b\x6b\xf5\xf1\x40\xfb\xcd\x11\x3c\xa2\x2d\xd4\x50\xb5\xbd\x95\x30\xe9\x28\x1d\x2b\xd2\x35\x58\xdd\x2d\x86\x16\xc0\x27\x94\x48\xb1\x0b\x58\x1b\x14\xa6\xcf\xfb\xeb\xdd\x75\x65\x41\x76\xe6\x40\xb6\x66\xbc\xaa\x3f\x96\xf1\x97\x01\x8f\x80\x4d\xaf\xf5\xb9\xee\x44\xca\x10\x73\x82\x37\x89\x72\x12\x2b\x77\x20\x4c\xb7\xf2\x2b\x8d\x26\xe4\x33\x42\x07\x11\x29\x97\x60\x42\x52\x5e\xe3\x71\x10\xbd\x80\x0c\xc7\x69\xf3\xfc\x48\x56\xcd\x6d\x6e\xba\x29\x32\x9c\x0b\x1a\x15\x09\x6e\x57\xd0\x6c\x82\x03\xb0\x62\xcf\xdd\xd2\x38\x8a\x5f\x68\x66\x9d\x51\x7d\x35\x4a\xf3\xd3\xe4\xd6\x99\x22\x6c\x3f\x58\x36\x58\x66\xd7\x55\xfe\xb6\x97\x5f\x57\xed\xae\x5a\x95\xbd\x0c\x3b\xa6\x57\xd4\x66\xd8\x55\xde\x0a\xca\xb1\x33\xf9\x5e\x8a\xd0\x80\x4c\xaf\xca\x30\x6c\x32\x43\x4a\x15\xa6\x7e\x91\x08\x2a\x48\x8a\x53\x9d\xcc\xf0\xfe\xcd\x5b\xc9\xa3\xf0\xca\x89\x84\xae\xe0\x22\x5e\x83\x75\x81\x8b\x1c\x0a\xc0\x34\xa5\x8c\x95\xa5\x36\x68\x8a\xa8\xe0\xa5\x47\x49\xd7\xe7\x68\xf0\xf6\xea\x60\x20\x05\x3d\x58\xbe\x30\x49\xb2\xd9\x21\xbb\xec\x90\x5d\x76\xc8\x2e\xeb\x58\x82\x29\xb3\xcb\x2a\xdc\x06\xf2\xcb\x4c\xb8\x9f\xfc\xb7\x4e\x97\xaa\xb2\xa4\x66\xa0\xd4\x01\xf0\x87\x81\x55\xc5\x4d\x15\x37\xfd\xbc\xea\x5e\xa5\x4b\xc7\xbc\x8b\x13\x79\x7b\xd8\xdd\x4b\x74\xa8\x33\x7e\xa8\x33\x7e\xa8\x33\xde\xf6\xd0\xa1\xce\xf8\xa1\xce\xf8\xa1\xce\x38\xf2\xef\x88\x43\x9d\xf1\x5f\x7a\x9d\x71\x5e\x49\x83\x6d\xb6\xe2\xd4\x24\x9f\xfa\x0b\x86\xf1\xe3\x78\x43\x53\x27\xb1\xcf\x9f\x40\xab\x42\xdd\x00\x77\x79\x41\xca\x34\x5a\xa8\x49\x6c\xd7\xe6\x84\x9f\xda\x48\x5c\x7b\xc8\x41\xf7\xed\x65\x4b\xe7\x52\x9d\x8a\x6e\x54\x4d\xf0\xf8\xfc\xe6\xda\x97\x70\x72\x07\x2f\x20\x41\x92\x84\x83\x4a\x2b\xe5\x71\xc1\xb4\x3c\xde\x28\xf0\x65\x0e\xf5\x86\xe1\x96\xe6\x8f\x96\x8e\x37\x67\xdb\x2b\x31\xd2\xaa\xf7\x5e\x04\xc5\xda\xe3\x9a\x75\x93\xcf\x59\x42\x23\x2a\xcc\x0d\x55\x4a\xa5\xcd\x97\x9a\xfa\x2a\xb0\x76\x0a\x12\x15\x27\xe2\xac\x94\x7b\x29\x47\x74\x95\xb2\xc6\x8a\x3a\x53\x7b\x6c\x6b\x20\xfe\x52\x5e\x9d\xe9\xc7\x49\x45\xad\xf0\xe5\xdd\x57\x15\x8b\x56\x14\xc2\x9a\x72\x71\xdb\x4f\xb7\x68\xcb\x7e\x2f\x5d\x9d\x71\xa0\x2e\x92\xf4\x42\x61\xd7\x4f\xea\xd2\x71\xc6\x40\x66\x3c\xc9\x49\x25\x8a\xab\xb6\x71\x1b\x96\x43\xcf\xc7\x03\xe6\x48\x13\x9e\x18\xd8\x36\x0d\xdd\xcf\xd5\x9d\xec\x64\x7d\xed\xa9\x57\x36\x08\xaa\x32\xbc\x97\xb3\x3f\xd1\x1e\xbf\xf5\x03\x16\xf4\x85\x29\x68\xbf\x32\x2c\x63\x3e\x80\x11\x1c\xc0\x08\x0e\x60\x04\x07\x30\x82\x03\x18\xc1\x01\x8c\x60\xc0\x58\x0e\x60\x04\x07\x30\x82\x5a\xfb\x82\xc1\x08\xc6\x3b\xca\x5d\x07\x2b\x00\x6a\xaa\x32\x5f\x07\x37\xeb\xc1\xcd\x5a\xa5\x79\x70\xb3\x1e\xdc\xac\x07\x37\xab\xee\xda\xc1\xcd\x7a\x70\xb3\x1e\xdc\xac\xe8\xe0\x66\x3d\xb8\x59\x0f\x6e\xd6\x83\x9b\xf5\xe0\x66\x3d\xb8\x59\x0f\x6e\xd6\x83\x9b\xf5\xb9\xdc\xac\x07\xd7\xe9\xc1\x75\xfa\x1c\xae\xd3\x83\x3b\xf4\xe0\x0e\x6d\x1a\xc5\xc1\x1d\x7a\x70\x87\x1e\xdc\xa1\x7b\xed\xe0\x0e\x3d\xb8\x43\x0f\xee\xd0\x83\x3b\xf4\x19\xdc\xa1\x4b\x9c\xf0\x7f\xfe\xc4\xe1\xa7\xce\x19\x86\x9f\xf6\xd3\x85\x5b\x33\x85\x75\x92\xf0\x5e\x2e\x70\x99\x06\xac\xab\xbb\x3f\x5e\x0e\x70\xd5\x78\xab\x91\xe6\x6d\x47\x3c\x5e\xe0\x83\x83\xf7\xe0\xe0\x3d\x38\x78\x3b\x96\xe0\x31\x1c\xbc\x95\x12\x8d\x72\xfa\xb4\x0a\x55\xa2\xc7\xbe\x6f\x32\xd0\xb6\x7d\x34\xd4\x54\xa4\xad\x44\xee\x87\xd9\x42\x5d\x30\x0e\x6e\x6d\xda\xfc\x71\xe5\x91\x91\xcb\x19\xb1\x4d\xc6\xd2\x3d\x13\xef\x00\xa7\x73\x49\xc9\x63\x65\xb8\xb0\x0f\x3a\xa8\x55\x4e\x19\x4b\x05\x8f\xb8\xc9\x18\x27\x15\xfb\x76\x4f\x53\x42\xbb\xeb\x71\xa6\xdc\x7b\xc6\x0c\xd8\xd3\x08\x51\x79\x37\x40\x12\x79\xe3\x3e\xaf\x9d\xd5\xe0\x5d\xfc\xb9\x20\xf9\x0e\xe0\xea\x4a\x97\x9b\x9d\x86\x16\x21\xce\x98\x97\x95\x33\xb2\x32\x3d\xc7\xad\x8b\x19\x34\x5d\xfe\x81\xa3\x60\x7f\xfd\xde\x1c\xf4\xf1\xd9\x77\xb8\x82\x2a\xde\xfc\xde\x7e\x7b\x14\xe8\x93\xf2\x7a\xa4\x06\xfa\xf0\x3b\x28\xa2\x0a\x28\x68\x2f\x3f\xbe\x87\xaa\x72\x1b\xf9\x7d\xf9\x28\x14\x7e\x3a\x04\x80\xba\xdb\xaf\x8f\x42\x7c\xfb\x28\x18\x87\xda\xeb\xe3\x47\xc3\xfc\xfc\x1e\x8a\xc8\xc4\x01\x78\x7c\xfd\xa8\x0f\x48\x73\x88\xcf\x7f\x6f\x38\xa1\x7e\x7f\xef\x80\x54\x50\x62\x1f\xdf\xbf\x97\xa4\x76\x62\xf7\xf1\xff\xa3\x3e\x13\xe6\x8f\x03\x40\x03\x63\x01\xfc\xb3\x55\xf3\xd7\xfb\xe3\x01\xbc\x24\x2b\xf1\x02\x3d\x62\x02\x82\xfa\xda\x18\x9e\xd0\x19\x17\xe0\x25\xbb\x1f\x37\x10\x1a\x1b\x80\x82\xe3\x03\x50\x58\x8c\x00\x0a\xdb\x35\xde\x58\x01\x34\x26\x5e\xa0\xa3\x87\x2a\x92\xa0\x77\xcc\x40\x17\xb7\x76\xa3\x09\x7a\xc6\x0d\x74\x91\xad\x6d\xb9\xd0\xd8\x81\x0e\x92\xad\x51\x05\xe1\x37\xb6\xe7\x52\xea\x13\x47\x80\x42\x8c\x74\xcb\x90\x50\x92\x5b\xb2\x54\x43\x70\xc4\xb7\xd2\x5d\xc6\x5a\xa5\xb3\x96\x8e\x59\xd9\xef\x4c\xdf\x41\x24\x56\xc6\xfe\x8a\x04\xf9\xd8\x31\x89\xb7\x34\x5a\xdf\xba\xee\x9a\x5a\xd1\xb6\x12\x2d\xf3\x0c\x91\x34\xa7\xd1\xba\x83\x51\x28\x5f\x85\xe0\xc6\x6b\x5b\xa2\x43\xff\xb2\x0a\xb6\xf9\x2b\x93\xec\x75\xa7\xbd\x3a\x89\xb2\x8e\x94\x4a\x9e\x2f\x68\xcd\xee\xbb\x27\x09\xd6\x6a\x1e\x44\x39\x06\x77\x08\x78\x8b\x69\x82\x17\xad\x11\x56\xa6\x29\xc5\x56\x09\x32\x5a\xad\xb5\x83\x3a\xd6\x6e\xcc\x90\x92\x01\x5e\xd1\x36\x4c\xb8\x0d\xa8\xb0\x82\xfc\x55\x56\x50\x0f\x09\xb7\x7f\xb5\x15\x34\xa4\xe2\x8a\x97\x22\x52\x16\xa3\x01\x55\x57\x50\x1f\xa9\x0e\xf5\xac\x57\x82\x7a\x56\x60\x41\xfd\xab\xb0\x3c\xef\xe0\x82\x0a\xb2\xec\x8d\x6a\xba\xa2\x2c\x68\x50\x61\x16\xd4\x6f\x5a\x42\x0a\xb4\xec\x8d\x71\xca\x22\x2d\x3d\xfb\x1b\x52\xac\x65\xaf\xbf\x41\x05\x5b\x02\x56\x43\x95\x74\x09\x2b\xda\xd2\x73\x5c\xfe\xe2\x2d\x7b\xa3\xea\x59\xc0\x25\xb8\x43\x87\x42\xa7\x87\x42\xa7\x87\x42\xa7\x87\x42\xa7\xd0\x26\x81\x80\xff\x12\x62\x7c\x7a\x0c\xf7\x50\xe8\xf4\xa5\xc6\x01\xf5\x18\xe6\xa1\xd0\xe9\xa1\xd0\x69\xe7\xd0\x7e\xa1\xf5\x06\x78\xb1\xb0\xeb\xf3\x54\xa1\x43\x77\xce\x37\xe1\xe7\x32\x7c\xc8\xfd\xd3\x5e\x08\x51\xa5\xaf\x6a\x45\xf6\x6a\x0d\xf0\x62\x51\xfe\xab\x1e\x6b\xc4\xab\x1f\xf6\x97\x1d\x70\x6d\x9e\x10\x1b\x73\xc1\x92\x62\x93\xda\xaf\xed\xa9\x49\x19\x8e\xee\xa5\xf6\xa7\xbf\xb4\x00\x4f\xb2\xde\x2a\x7f\xe3\x2c\x05\x39\x1b\xcd\x41\xb4\x71\x2a\xc7\xa8\xb5\xb8\x51\x2f\x7f\xd5\xb2\x43\x1b\x3e\xa7\x2b\xcf\xe9\xb2\x23\x56\x3b\x2b\xc3\x9f\xb3\x0a\xc9\x7a\x0f\x2a\x15\x79\x54\x1f\xee\xdc\x9f\x82\xba\xb0\xc6\x69\x4a\x12\x79\xaa\x55\x7c\x0a\x48\x93\x76\xfc\xed\xc3\xd7\x2f\x56\xbe\x7e\x51\xf9\x6d\xef\xf3\x15\x90\x92\xe1\x71\x60\xee\x26\x43\xf7\x84\x64\xdc\x71\xbe\x15\x19\xa4\x96\x61\x41\xd0\x62\xa7\xca\x11\x49\x91\x4e\x49\x59\xb5\x14\xa8\x0b\x35\xfd\x93\x00\x87\xcc\x60\xd5\xec\xff\x1e\xc2\xcc\x0e\x61\x66\x87\x30\xb3\x8e\x25\x98\x32\xcc\xcc\x65\x08\x95\x50\x33\x9c\xa2\xf3\x2c\x4b\xa8\x2e\xe3\xaa\x02\x48\x70\x2a\x67\x49\x03\x11\xd5\x94\xd8\xde\x89\x81\x7b\xe5\xc3\x4c\x45\xb0\xc6\x1f\x9b\xcb\x84\x75\xc4\x8b\x29\x7e\xba\x2f\x9f\x75\x48\x76\x11\x4b\x97\xb4\xa1\x78\x5c\xeb\x8c\x5d\xc0\x0b\xa5\xa7\x52\x11\x28\x72\x35\x67\xe5\x5d\xb4\x6c\x8c\xf7\xc0\x95\x5b\x79\xd2\x54\x36\x92\x6e\x03\x3c\x8c\x57\xe9\xb6\x1a\x2a\x45\xd2\x2d\xcd\x59\x0a\x2e\xdf\x2d\xce\x29\x5e\x24\xfa\x52\x23\xa2\xad\x8e\x20\xaa\xda\x4c\x9a\x8e\x53\xe3\x7b\xd3\xf9\x14\xaf\xd2\xed\x27\x5c\x8d\x4f\x49\x1b\x87\x82\xf4\x03\xad\xc2\x31\x18\xa0\x2e\xec\x50\xda\xc6\x3b\x05\x30\x49\x47\xf1\xbc\x10\xb7\x4d\x2f\xcd\xdc\x55\xcc\x9b\xe6\x65\x8e\xde\xea\x80\x0d\xdc\xa9\xc3\x5d\xfc\xe7\xf5\xe5\xd5\xbb\x0f\xd7\xdf\x5f\x5f\xdd\x4e\x83\xb1\x11\xae\x3e\x7d\x32\x6b\xe8\x38\xc1\x7f\x7d\xf2\xe9\xfc\xf6\x3f\xdf\x9d\xbf\xbd\x3a\x05\x47\x39\xf9\x9c\xe1\x34\xf6\x18\xd7\x0a\x6e\xae\xa0\x2c\x27\x5b\xca\x6c\x94\x6b\xdc\xb2\xfd\x03\xcc\x4b\xa5\x69\x4e\xc5\xd2\xed\x6c\x2a\x6b\x23\x49\x08\xbe\xe9\x9e\x6a\xbb\x65\x23\x7b\x9a\x54\x75\x4b\x12\x9f\xb9\x3a\x64\x64\x93\xd6\x68\x9a\x15\xdd\xc6\x4a\x7d\x21\x5b\x2c\x81\x54\x49\x76\xb1\x8a\x9c\x70\x27\x53\x1b\x09\x15\xbf\xef\xa4\x49\x78\x84\x33\x13\x49\x80\x51\xcc\x0a\xd9\xe9\x5f\xff\xfa\x0c\x51\xf2\x1a\xfd\xda\x21\x3a\x47\x57\xfa\xd9\x72\x05\x3d\x16\xe1\x24\x41\x29\xd9\x92\x1c\x42\x89\xf4\xda\x9e\xa1\x9c\xac\x70\x1e\x27\x84\x83\x9f\xe3\x61\x4d\xc4\x9a\xe4\x3a\x7c\x44\x4d\x5a\x77\x8f\x6d\x90\x53\xca\xc4\x1c\x5d\x92\x25\x2e\x12\x90\x04\xd0\xd1\xd1\x78\x0b\x21\x6c\xeb\xef\x73\xb6\x09\xde\xda\x77\x55\x0d\xa6\x69\xc7\x1c\xeb\x98\xcd\x6e\xfb\xae\xc3\x78\x39\x89\x11\xd5\x61\x76\xc6\xa0\xea\xc5\x89\x09\xf4\x62\x87\x7a\x95\xd5\x65\xf8\x16\x67\x3f\x92\x5d\x63\x72\x78\xd7\x9c\x68\xc8\x30\x08\x34\x54\xa5\x17\x2f\x0c\xb9\xb0\xc0\xaf\x00\x67\x7c\xa8\x3b\xde\x1f\x6f\x8a\x7a\x39\xdb\x83\x42\x4a\x51\x93\x2b\x12\x22\x49\x4d\x78\xb6\xdf\x09\xd6\xd3\x6d\xec\xbb\x53\x1a\xbb\xf5\xd4\x56\xdf\x80\xfe\x21\xed\x70\x38\x8f\x63\x04\xb1\x03\xf2\x3c\x2c\x8b\x44\xf9\x10\xf8\xdc\xd1\x25\xcf\x40\x9f\x09\xf1\x88\x82\xb5\xef\x4f\x5d\xec\xc1\xb4\x5e\x73\xce\x32\x65\x64\xe9\x3d\xef\xca\x38\xbb\xab\xf0\x3f\x7b\x44\xc0\x05\xe5\x01\xcd\x32\x4d\xee\x29\x13\xaf\xa9\x2f\xc2\xe0\x41\x36\x83\xb1\x54\x1b\x4c\x7a\xdf\xf3\x7f\x5c\x32\x00\xe5\xf8\xd1\x1b\x2c\x63\xf1\x6b\xc4\x8b\x2c\x63\xb9\xe0\x56\x11\x02\x7b\x92\x7f\x11\x2b\x8f\x83\x2e\x71\x56\xfe\x06\xa1\xda\xdc\xf9\xc1\xb1\x3f\xfa\x49\x2b\xab\x16\x8b\x41\x4d\x39\x53\xff\xbb\x0f\x1b\x74\xa6\x6d\xa6\xf3\x35\xe3\xe2\xfa\x26\x80\xac\x7a\x3c\x63\xf1\xf5\xcd\x59\xe5\xff\x78\xe7\x4d\x85\x1e\x8b\x0d\x5a\x8f\xf9\x84\xcc\x30\x2c\x98\xce\xb4\xca\x36\xf9\x54\x0d\xa8\xd3\xc6\x1d\xf9\xcf\xef\x03\x3b\xaa\x1a\xe5\xe8\x21\xa7\x42\x10\x28\xd9\x2b\x48\xbe\x91\xb2\xc5\x99\x3c\x0f\xa5\x70\xb0\xfd\xe6\x68\x72\x96\x1b\x14\x81\xd0\x38\x74\xf9\x92\x19\xb7\x3a\x22\x65\xde\x4e\x80\xc4\x6a\x5a\xa9\xa3\x3a\x01\x8a\x93\x0e\xd3\xd8\x78\xbe\x1f\xc9\x07\xac\xad\xa8\xee\xa5\x7f\xed\x0b\x10\xae\xf6\x83\xa3\x84\x82\x0d\x48\x8a\xea\xd6\x0e\x74\xa2\x7e\x9c\x47\x59\x71\xa6\x1f\x98\x6f\xc8\x86\xe5\x3b\xff\x29\xd5\x8f\x93\x6c\x4d\x36\x24\xc7\xc9\x4c\xfb\x4f\xce\x2c\x79\x45\xd6\xfe\x9f\x22\xec\x3f\x18\x4e\x07\xf7\xa9\x2b\x95\x47\x17\xa9\x4e\x76\x86\x2b\x92\xf8\x79\x38\x83\xb7\xc8\xbd\x6a\x7d\x18\x83\x5d\x61\x5f\x7d\x72\xd3\xaa\x5b\xe7\xa2\x12\x7d\xf1\xda\x8e\x05\x24\xed\x2d\x4b\x8a\x0d\x09\xe0\xec\xc8\xb9\xa4\xe1\x4d\x92\x6e\xa5\x5c\xde\xe9\x62\x33\xad\x17\x2f\x88\xe9\x96\x72\x7f\x72\xce\xde\x40\xb5\x9b\xd6\x64\x69\x16\x22\x2b\x84\x0e\x01\x0c\x89\xdf\x35\x8d\x7c\xce\x18\x07\xed\xcc\xc6\x89\x57\xd8\xdf\x37\xdd\xc1\x35\xaa\x65\x58\x08\x92\xa7\xaf\xd1\xff\x3d\xf9\xcb\x6f\xff\x31\x3b\xfd\xd3\xc9\xc9\x4f\x5f\xcf\xfe\xe7\x5f\x7f\x7b\xf2\x97\x39\xfc\xe3\x37\xa7\x7f\x3a\xfd\x87\xf9\x9f\xdf\x9e\x9e\x9e\x9c\xfc\xf4\xe3\xdb\x1f\x3e\xdc\x5c\xfd\x95\x9e\xfe\xe3\xa7\xb4\xd8\xdc\xab\xff\xfb\xc7\xc9\x4f\xe4\xea\xaf\x81\x44\x4e\x4f\xff\xf4\xeb\x80\xce\xe1\x74\xf7\xde\xcb\x7e\x90\x0d\xad\x7d\x0d\xc6\xfa\x95\x27\x6e\xa9\xfa\x46\xe0\x52\xd7\x8a\x0e\xd1\x54\xcc\x58\x3e\x53\x2f\x3b\x5e\xd7\xae\x66\x96\xa9\xff\xb9\xb8\x35\x67\xda\x31\xbf\x9b\xab\x63\xd2\x4d\xcd\x49\x94\x13\x31\x8d\xf6\xa7\x68\x19\x5b\x47\xc6\xe2\x46\xf4\xb6\x6a\x4b\x1b\x4d\xc6\x6d\x03\xfa\xa7\x55\x18\x8d\x70\xa4\x66\xb0\x94\x12\x96\x39\xdb\xcc\x11\x98\xfe\x82\x18\xc4\x82\x58\x10\x30\x4d\xeb\x9e\x78\x70\x67\x55\x3b\x28\xa1\xbf\x24\x25\xf4\x4e\xed\x0d\xa5\x81\x06\x1c\x03\xd5\xa6\xd7\x40\x49\xba\x6d\x37\xc3\xd5\xfd\x07\xf2\xc9\xaa\x2b\xc4\xe2\x05\x30\x94\xb1\xac\x48\xb0\xa8\x98\xe6\x5a\x3a\x58\xb7\x1a\xbb\x7e\x11\x7d\x1e\x4b\x73\xb3\x0d\x79\xed\x94\x9c\xcc\xcc\xe0\xaa\xf9\x1d\x9d\x27\x09\xa2\xa9\x3a\x8f\x40\xd6\xd8\x75\x73\xa2\xe4\x40\x84\x5b\x71\x75\x53\x15\xaa\x2a\xd7\xad\xd6\x4d\x88\xb0\x14\x38\x17\x34\x5d\xcd\xd1\x9f\xe5\xdf\x15\x17\xd6\x66\xd3\x56\x27\x10\x54\x38\xc9\x12\x82\xac\xf4\x60\x13\xfa\x10\xe6\x9c\x45\x14\xdb\x8c\x33\x0b\xcc\xd9\x39\x70\x18\x0f\x44\xff\x66\x39\x89\x48\x4c\xd2\x88\x40\xc6\x70\x41\xca\x39\x5c\xec\xe4\x68\xae\xd2\xad\xb5\x40\x17\xca\x69\xd9\x46\x55\x8e\xa5\x99\xf2\xf5\x66\x53\x08\x70\x87\x3c\xbe\xbf\x4a\xee\x37\x6d\xf7\xad\xa5\x5f\x95\x4a\x8e\x49\xfb\x6b\x3d\x0b\xd6\xdc\xd3\xb6\xce\x13\x65\xbb\x59\x43\xae\xe7\x1e\xdf\xbb\x7d\x4a\x7b\x54\xf5\xd6\x79\x3a\x1b\x74\xc8\x6d\xf2\xb2\x6f\x92\xbe\xb7\x48\xd0\x0d\xd1\x03\x31\x20\xec\x66\xe8\x61\x9a\xec\xc7\xe9\xc3\xec\x8c\x59\x4e\x96\xf4\x73\x78\x2e\x66\x5a\xaa\x74\x34\x26\xa9\x90\xea\x53\x0e\xac\x3e\x27\x19\x49\xc1\x96\x42\x70\xb4\xf6\x5e\x5f\x9a\xcb\x97\xbe\x89\xd2\x93\x3a\xad\xb7\x54\x49\x5c\x7d\x0f\xe0\x5d\x93\xcc\x77\x38\x7d\xbf\xb8\xd3\xa7\xf7\xc1\xb4\x47\x2f\x65\x31\xe9\x01\x54\x74\xfc\xce\x79\xbe\x56\x7e\x46\x45\x93\x9b\xee\x49\xfd\xb7\x25\x64\x06\xe9\x70\x93\x8c\xc1\x19\x5d\x52\xa1\x52\x83\x64\x5f\xe6\x25\xf2\xba\x43\x0f\x60\x0b\xf4\x13\xc7\xad\x4a\xa3\xb2\xfe\x5b\x1f\xac\x26\xbf\x50\x26\xe5\xb8\x48\x48\x8c\x4c\x10\x94\xfa\x54\xb9\x25\x5b\x28\x86\x6c\xd4\x4a\xb8\xd0\x2b\xcc\x39\x5d\xa5\xb3\x8c\xc5\x33\xf9\x8d\x4e\x00\xd0\xc7\x2f\x7a\x80\x5c\x93\x69\xc8\xf2\xde\x5a\xfb\xaa\x23\xd1\x44\x6c\x93\x15\x82\x38\xc6\x57\xa3\x41\xb7\xf4\x68\xb1\x53\x31\x7d\x8e\xdc\x5c\xca\x65\x7d\x19\x41\x75\x7e\x55\xb9\xbd\x99\xee\xd2\xcc\x76\x69\x66\xbf\x35\x74\xca\xfd\xfc\x50\x99\x88\x03\x31\x41\x8e\xdf\x28\x03\x75\x09\x5f\xa6\x80\x3c\x3e\xd3\x4d\xb1\x41\x78\xa3\xb0\xd1\x97\x66\x72\x3b\x8e\x71\x39\xed\x38\x49\xd8\x03\x89\x9f\x6b\x0a\x83\xa6\x11\x0d\x80\xda\x78\x91\x06\x47\xaf\xa1\x31\xdc\xc0\x18\x6c\x58\x1c\x68\x50\x34\xfe\x85\xd0\xad\x79\x6b\x1c\x26\xb5\xcd\x49\xd3\x11\x9b\xd3\xf0\x04\x88\x8b\xb2\x5f\xa0\x1c\xb1\x0d\x15\x42\x5b\xec\x9d\x44\xd2\x2e\x53\x09\x15\x15\xb3\xb5\x3e\x4a\x90\xa3\x8a\x01\x31\xcd\x14\xf9\x48\x76\xa5\xf3\xeb\x4c\x5d\xef\x0f\x94\x77\x75\x58\x41\xe2\xd0\x4d\xa6\x40\x71\xe0\x48\xd8\x3c\x49\x15\x9f\x73\x38\x5e\x87\xe3\x65\x5a\x7b\x99\x44\xd4\x5a\x2a\xb1\x82\x1b\x67\xc5\x23\xb9\xfd\x33\x16\x73\x2d\x93\x98\x4d\xd3\x8e\x6b\x04\xb8\x5d\x34\x5d\xa1\x5b\x02\xd6\x90\x3b\x22\xb8\x86\x6b\x02\x3a\x38\x27\x25\x08\x90\xb9\x72\xb5\xfd\xa8\x43\xea\x62\x10\x18\xbe\x5c\x56\xdf\x53\xb5\x88\x36\x20\xa9\x5f\x0b\x57\xea\xd2\xa2\x54\x1b\x45\xb2\xc9\x12\x2c\x08\xe0\x28\x48\xf1\x6b\x60\x95\xa7\x03\xac\x24\x3a\xc0\x4a\x1e\x60\x25\x0f\xb0\x92\x07\x58\xc9\x03\xac\xe4\x01\x56\xf2\x00\x2b\xf9\x0b\x85\x95\x14\x2c\x21\x39\xee\x80\x01\xac\x9a\x87\xcb\xa7\x61\x40\x36\xac\xc2\xa5\xf3\xd8\x9e\xb0\x0f\xc6\xd6\x26\x4f\x72\xd9\x23\xd8\xb2\x42\xe0\x68\xad\xe0\xc8\x75\x8f\x3a\xc4\x06\x9c\xee\x90\x5c\x55\xa1\x6e\x44\xd8\x54\x5a\x35\x15\x39\xb8\x25\xff\xd5\xee\xe1\x33\x02\x12\xec\xbf\xa9\x4c\xa0\xf6\x25\x34\xbb\x5c\x32\x0b\xbb\xb7\xfe\xd5\xfc\xeb\xdf\x1e\x19\x62\x52\x75\x32\x58\xa0\xbb\x82\xc7\x0d\xf4\x9a\x19\x3a\xcc\x88\xa2\x24\xe7\x71\xe3\x67\x70\x57\x92\xb5\xa2\x0d\xc1\x29\x37\xa6\x53\xf0\x95\x96\x84\xb8\x76\x0b\x3b\xca\xb3\x36\x2e\x05\xdc\x79\xb0\xd5\xde\xb1\x3b\x6d\x55\x3d\x43\x37\x60\xe5\x2f\x7f\x81\x33\xfb\x8e\x5d\x7d\x26\x51\xd1\x8d\xba\x18\x86\xd7\xd3\xa3\x3e\xf7\x8f\xa5\x80\xa5\xc6\x5b\x11\xb0\xca\x53\x11\x5a\xa1\xbb\x73\x2e\xef\xc9\xce\xd6\x84\x36\xa2\x1d\x5c\x6b\xdd\xd7\xa2\xdd\x87\xe6\x2a\x54\x77\xeb\xff\x32\x46\xd3\xcd\x82\xa6\xaa\x93\xea\xb3\x66\xd1\x3b\x89\xca\x5e\x99\xe5\x91\x32\x7b\x92\xa8\xee\x8d\x9d\xfc\xde\x25\xc6\x9b\xab\xd4\xf4\x2f\x31\x6e\x79\x7e\xb3\x24\xe8\x88\x77\x57\x3f\x17\x38\x29\x93\xc0\x3c\x4b\x6a\x1e\xd7\x04\xf6\xca\x2f\x3f\xd0\x24\x8e\x70\xae\x23\x4c\x81\xd7\x74\x52\xe4\x4c\xed\x2f\x00\x3d\x83\x6c\x3b\xc3\xe9\xca\x9d\xa2\x10\x49\x01\x55\x8b\x46\x45\x82\xbb\x25\x7c\x8d\x3f\x12\x90\xe6\xe5\x59\xbb\x72\xbb\xdf\x91\x88\xa5\x71\xb8\x6a\xf9\xa1\xfe\x66\x3d\xc2\x21\x23\x39\x65\x1d\x65\x29\x75\x07\x0c\x5c\xa6\x73\xf0\x4e\xaa\x7e\x22\xb6\x34\xbc\xcd\x32\x0c\xcf\xe9\x31\x46\xbe\x1a\xa4\x98\xae\xd2\x7b\x5a\x5e\x34\x25\x17\xe8\x66\x97\xdf\xed\x8c\xb5\xf1\x4c\x97\x00\x4e\x99\x50\x65\x80\x75\x5f\xf5\x31\xd4\xcb\x6a\xc9\x76\x52\x5d\xb2\x1c\xd2\x1e\x4f\x62\xa6\x32\xf7\xb6\x34\x12\xa7\x73\xf4\xff\x91\x9c\xc1\xb6\x4d\xc9\x0a\x0b\xba\xb5\x92\xcd\x03\x4d\x92\x4e\x8a\xe0\x55\x23\x58\x45\x05\xa1\xaf\xd1\x09\x90\x44\x74\xb3\x21\x31\xc5\x82\x24\xbb\x53\x65\xcf\x21\x88\xef\xb8\x20\x1b\xff\x06\xf2\x1b\xd7\x0c\x0c\x29\x4d\xc5\x1f\xbe\x6d\x7d\xae\x5f\x1e\xf0\x27\x93\xd1\x58\xb2\x69\x15\x63\x54\xdb\x2a\x5a\x02\xf0\xf2\xe8\x56\x75\xc5\x8d\x5f\xd2\x90\x1f\x46\xf3\x08\xdd\x64\x7f\x93\xfb\x14\xa3\x9c\x00\x06\x8f\x3e\x71\x23\x4e\xa6\x8a\x59\x7f\xcb\x8a\xc6\x22\x38\x7b\x53\xf5\x46\x1b\xaa\x3e\x39\xaf\x95\xb9\xfc\xb5\xe8\xb4\x47\x16\xf4\x9c\x3e\x38\x9e\x03\x8c\xc0\x5d\x00\x02\x96\x64\x72\xea\xa9\xee\x92\xad\xc8\x75\x04\x3c\x6a\x86\x3e\xf4\xad\x23\x85\x68\x74\x0e\xbf\xfd\x40\xf0\xee\x87\xa4\x1f\x1d\x36\x58\x0d\xdb\xc3\xc2\x42\xb2\x11\xbd\x51\xba\xaf\x1e\xbb\xa5\xa1\x17\x24\xd6\x91\xc0\xc0\x6f\x0c\xe6\xe8\xf1\xeb\xe3\xd1\x17\x89\x1a\x64\xce\x32\xbc\x82\x93\x19\x3c\xd6\xfa\x8b\x28\x26\x82\xe4\x1b\x00\x27\x59\xb3\x07\xf5\x77\xb8\xd0\x3b\x07\x9a\x69\x0a\x24\x2e\x71\x62\xd6\x8c\x2b\xfc\xc8\x4a\xda\x3e\xf0\x01\x08\x99\xf0\x61\x5e\xe2\x9c\x15\x69\xac\xe5\x60\xcb\xf0\xdf\xd6\x3a\xfc\x8e\xa5\xc0\xa9\x0a\xae\x52\xec\x5b\xeb\xd0\xaa\x66\x6f\xa3\x05\x11\x58\x1e\xd0\x6f\xe6\xdf\x7c\x3d\x7a\xfa\x7b\xe1\x44\x80\x41\xa5\x66\xbf\x37\x11\x39\xe6\x74\x8e\xee\x51\x4e\x70\xfc\x3e\x4d\xc2\xe5\xf2\xb7\x6a\x83\xc2\x8b\x33\x40\x2b\xa5\x4b\xf0\xb9\x9c\xa9\x9f\x1e\x72\x2a\x48\x90\x03\x0f\xa1\x13\xa8\x84\x89\x58\x8e\x8a\xd4\x2a\x30\xa7\x55\x14\x00\x78\xc4\x3f\x4c\x5f\x4c\x1a\x2f\x16\xa3\xce\xb6\x3a\xc4\x6a\xd3\x96\x47\xdb\x6e\x59\x4f\xfe\x83\x7e\xbb\xe1\x98\x57\x01\x0f\xd0\x89\x7a\x52\x4a\xd8\x8c\x89\x4e\x04\xd9\xb0\x40\x35\x35\xec\xab\xcf\x59\xb8\xdc\x7f\xa5\xb1\x1d\x50\xe6\x9b\x03\xaf\xd8\xef\xcc\x4f\xc7\x1c\x7c\x47\xd6\x78\x4b\x38\xe2\x74\x43\x13\x9c\x7b\xb2\x07\x05\x43\x77\x6a\x54\x68\x51\x88\x66\x64\x99\x66\x54\x12\x0f\x17\x29\x51\x2d\x1c\x54\x12\x77\x04\xce\xa7\xc2\x95\x94\x86\x45\x35\xfd\x97\xab\x02\xbc\xce\x8c\x47\xf6\x61\x53\x88\x02\x27\x9e\x39\x20\x9f\xa3\xa4\xe0\x74\x3b\xe6\xfc\xeb\x9c\xbb\xde\xa2\x4b\x5d\x6a\xc9\x58\x7c\x97\x91\xe8\x69\x64\x96\xaa\x2e\x2a\xd9\x69\x6c\x36\x96\x81\xab\xee\x86\x89\xde\xe0\x1d\xc4\x83\x02\x1a\xb7\x89\x58\xdf\xb9\x11\xf7\x76\x54\x2f\x19\x70\x08\x3f\xf0\xab\x04\x73\x41\xa3\xef\x12\x16\xdd\xdf\x09\x96\xf7\x40\xef\x39\xff\xf3\xdd\xde\xdb\x35\xc0\xa6\xf3\x3f\xdf\xa1\x4b\xca\xef\x3b\xb7\xa1\x03\x18\xa7\xa2\x39\x5c\x33\x21\x46\xf7\xc5\x82\x24\x44\x1c\x1f\x73\x75\xc7\x6f\x70\xb4\xa6\x69\xf7\x95\xa0\xaf\xfe\xd4\x26\x40\x6a\xf8\x3e\xb9\x1e\x7d\xc3\x39\x74\x6a\xee\x2b\xbd\xd3\x7f\x85\x1f\x38\x51\xc3\x5e\xc8\x61\xcb\x3f\x13\x3f\xc2\xcc\x44\xbe\x4c\xd5\x89\xeb\xcb\x09\x7c\x95\x4b\xfe\x21\x00\xb5\xbf\xba\xe4\xdf\xd3\x84\x28\x5d\x12\x86\x65\xa2\x7a\xf5\xd9\x81\xf5\xdb\xb1\xc2\xeb\x1e\x79\xc0\xca\xb6\x02\xbc\x7b\x8e\x3e\xd0\xec\x35\xba\x4a\x79\x91\x93\xd2\x36\xb7\xac\x7e\xca\x4b\x13\x50\xc4\x75\xb6\xb4\x51\x7b\x61\xbf\x28\x35\x10\xd0\xf7\x95\x16\x8c\xae\x14\xca\x7d\x80\x1f\xe7\x88\x7c\x16\xdf\x1e\x9d\xa1\xa3\xcf\x4b\x2e\xff\x93\x8a\x25\x3f\x9a\xa3\xeb\x8d\x0d\x37\x02\xc8\xc2\x9c\x98\xd0\x52\xf5\x82\xbf\xb3\x4b\x57\x56\x79\x94\x2d\xe9\xed\x83\x0a\x83\x96\x52\x77\xcc\xd0\x83\x42\xce\x92\xd7\x1f\xc9\x73\x96\xdb\x5c\x27\x67\x19\x3c\x71\xe6\xaa\x45\x6c\x93\xe5\x6c\x43\xed\xd5\xa7\x8f\xeb\x64\xf1\xd3\x60\x34\xf3\x29\x1d\x68\x6f\xe7\x2a\x34\x5b\xfd\x2a\xaa\x8a\x22\x66\xdf\xc2\xbe\xf4\xfb\xf6\xec\xbe\xbd\x5e\x9a\x60\xb6\x33\x5d\xc5\x17\x2e\x73\x5d\x24\x41\x45\xcd\x2d\x76\x21\x9a\x1b\xd2\x52\xbd\xb3\x37\xa1\x1e\x83\xee\xe0\xab\x98\x6c\x5f\xf1\x18\x7f\x73\x06\xdd\x54\x1b\xc7\x9f\x83\x27\x2a\x63\xc6\x1c\x1d\x7d\x73\x34\x47\x77\x46\x3e\x3a\x73\xe7\xc0\x3e\xe7\xa5\xba\x64\xb9\xed\x10\xb8\xe5\xbe\x3e\x42\x27\x2c\x87\x9e\x45\x38\x45\x09\xc1\x5b\xed\x7a\x52\x9c\xc8\xdf\x51\xb0\xc0\x9c\x06\x62\x1c\x84\x25\x70\x3b\x76\xaa\xdf\xff\xce\x73\xfd\xf8\x75\x17\xd4\x82\xa3\xbe\x43\x47\x52\x69\x39\x02\x15\x83\xc9\x3b\x4c\xde\x3c\x52\xac\x01\x38\x54\x4d\xd9\x3b\x7e\x33\x51\x72\x5f\xd6\x2d\x3b\xea\x03\x7b\x9b\xcd\x4b\xd3\xd9\x8c\x47\xa0\xfd\x1c\x3d\xf9\xcd\x87\x7a\x61\x0a\x99\xab\xad\xdf\x3a\x7c\x4c\xe9\xcf\x05\x41\x25\x0e\x7b\x46\x72\x85\x05\x2f\x50\x4c\xf9\x7d\x28\x86\x05\xa4\xfd\x48\x71\xe5\xe4\x7c\x83\xff\xce\x52\x74\xf5\xdd\x9d\xee\xd2\xe9\x33\x4e\x9c\x87\x21\xe2\xbf\x17\x39\x91\x02\x56\x78\x90\x98\x79\xa3\x2e\xa9\xc9\xdf\xd1\x25\x16\x18\x04\x36\xc5\xbd\xba\x6d\xa2\x69\x79\xc7\xca\x5d\xbf\xa0\x69\xac\x99\x9e\x23\x6d\x3d\x95\x60\x24\xd7\xfa\x5d\xbb\x34\x5c\x3e\xf4\xf1\xf6\x7a\x02\xe1\x29\x82\x5b\x6d\xf5\x96\xc5\x3d\x25\xa8\x7f\x97\xd3\x75\xa1\xde\x46\x1b\xf9\x3a\x7a\xc7\x52\x72\x06\xcc\x02\x49\x6e\xa1\xfe\xe9\xdd\xae\x7f\xce\xa9\xe8\x2e\x7e\x82\xfa\x5c\xab\x66\xfe\x7a\x8d\xe6\x83\x63\x4b\x82\x0b\x50\x6e\x1f\x38\x75\xfa\x82\x5d\x24\x6c\x61\x2a\x0f\x4c\xd9\xd3\x8f\xb7\xd7\xbd\x3b\xfa\xf1\xf6\xfa\xe9\x3a\x39\x40\xb8\xae\xcb\xd6\xa5\x9c\x51\xa6\x1f\x96\xd2\x98\xff\xf2\x97\x34\xc2\x25\xe2\xb9\x91\x75\xfd\x32\x71\x3f\x59\x18\x51\x7f\x00\x9b\x2b\x0b\x4f\xb5\x02\xbe\xaa\x3e\x68\xef\x68\x5e\x7d\xce\x54\x10\xb4\x76\xc0\xdd\xad\x31\x20\xaa\xd8\x2c\x78\xb9\x51\xfc\xf7\x2e\xe5\xf7\x5c\xde\x42\x66\x4b\x21\xac\xc0\xe2\x10\xba\x24\x2a\x90\x23\x7e\x6d\x82\xb0\x82\x29\x36\x13\x7c\x0b\xb9\x05\xf1\x6b\x75\x0f\x20\x95\x6a\x10\xa3\x0a\x10\x7f\x27\xd5\x13\x65\x7a\x4d\xed\xab\xba\xbc\x26\x4d\xa8\xd8\x49\x39\xe6\x74\x6e\x33\x2f\x42\x04\x63\x0e\x53\x36\x19\x53\x1a\x24\x9a\xed\x99\x7d\xd1\x89\xa4\xf3\x0a\x4c\xca\xa7\xf3\x70\xa9\x0c\x0a\x8b\x41\x00\xbd\x12\xed\x5c\x91\x4e\xce\x0d\x9c\xa0\x9a\xc4\x16\xb6\x7d\x7d\xe2\x10\x2c\xa7\xe4\x07\xfd\xae\x75\xf9\x46\xe3\xb5\x0e\x7f\xb8\x53\xd0\x85\x9d\x1d\xd4\x99\x3e\x2f\xea\x66\x57\x59\xd2\xde\xbb\x1d\xb6\x9e\xe7\xa9\xd0\xdb\xfd\x97\xba\xef\x90\x4d\x4a\xef\x2d\x0a\xb8\xf5\xf6\x0c\x2a\x51\x25\x91\x00\x76\xa2\x77\xec\x77\x9a\xc5\x69\x80\x4d\x25\x5d\xc8\x3d\xf8\xa3\x17\x73\x26\x1c\xc2\xca\xec\x94\x7e\x29\xd8\x6b\x08\x73\xeb\xde\x60\xc1\xfd\x88\x48\xb6\x6e\x2b\x18\xde\xf0\xf1\x0b\x92\xad\xbf\xbf\xab\x9a\xad\xe5\x6f\xe8\xfb\xbb\xfd\x33\xeb\xf1\xa7\x60\xa1\x66\x80\x2b\x43\xf7\x31\x47\x09\x5d\x12\x4f\x45\xd9\x49\x4f\xf4\x86\xa5\x54\xb0\xbc\xeb\x46\x09\x3d\xa9\x86\x54\xbf\x9b\xbe\x44\x4b\x7b\xab\xdf\x57\x01\xd5\x11\x4b\x12\x12\x09\x85\x3e\xea\xdd\xab\xb0\x00\xa6\x03\x4d\x2a\xa2\xae\xa6\x59\xd6\xca\x52\xea\xe0\x2b\xb5\xf8\xaf\x6e\xaf\xce\x2f\xdf\x5e\xcd\x37\xf1\xaf\xd6\xec\x61\x26\xd8\xac\xe0\x64\x46\xbd\x70\x6d\xcf\x11\xac\xae\x5a\x16\x80\x69\x5a\x9d\xe8\xf7\x06\xec\x00\x7d\xe4\x2a\x4c\x09\x4c\x82\xc6\xf9\xcb\x98\x38\x43\x39\x16\xeb\x00\x3c\x3e\xb1\xc6\xda\x22\x59\x24\x89\x9a\x7b\x91\x13\x72\xe6\x1a\x3a\x3a\xeb\xea\xf5\x1a\xea\x30\xa3\x50\x39\x5c\xcf\x65\xe0\x1d\xad\xe5\xf7\x8f\x71\x19\xa0\xa7\xde\xac\xe1\xf7\x8e\x4f\xe8\x41\x1d\x73\x7e\x67\x29\x98\x58\x32\x70\x3d\x0b\x16\x04\x58\x06\xf9\x23\x4b\x96\xcb\x9d\x9a\x57\x77\x15\x11\x11\x4c\xc3\xab\x82\x93\x7c\xae\x6f\xb7\xb7\x21\x36\xf6\xa7\x9b\xe2\x60\xe8\xc6\xde\x68\xbd\xf5\x09\xbe\x25\x4b\xe4\x56\x88\xd4\x32\xa1\x77\x2e\x70\x21\xd6\x24\x15\xa6\xf8\x90\x9e\xc6\xc6\x19\xf7\x56\x35\x50\xed\x89\x77\x71\x10\x98\x64\x1f\x00\xc8\x03\x2c\x62\x67\x9b\x1c\x16\x51\x1e\xdf\x11\xf7\x97\xcd\xe4\xce\x71\xcc\x20\x04\x4c\xa1\x10\xfb\x47\xe3\x6c\x6d\x1c\x6f\x68\xfa\xd4\x3b\xd7\x27\x8c\xd2\x34\xee\x9e\x99\x1a\x08\x33\x3c\x5f\x95\x46\x15\x0d\xe3\x4d\x32\x1e\xfc\xce\xde\x61\xa3\x55\x2a\x20\x1e\xed\xe7\xaf\x7a\xf9\x1b\x37\x76\x7d\xaa\x36\x3b\xfe\x73\x32\x53\x3d\x98\x65\x71\x39\x57\xbf\x54\xb7\xfc\xd3\x9a\x0e\xbf\x00\x67\xfa\x24\x3b\x06\x1d\x04\x48\xdb\x1e\x7f\x8e\xc3\x65\xc6\x11\x12\x0d\x54\x96\xe4\x26\xdd\x5c\x61\xdc\xaa\x12\x95\xda\x6e\x11\x82\xb4\x9b\xe1\x1c\x6f\x88\x20\xb9\x0a\x0b\xd6\x41\xc8\xa9\xce\xcf\x7b\x9f\x91\xf4\x4e\xe0\xe8\x7e\x4a\x08\xff\x83\x94\xf1\x72\xa5\x8c\x61\x7e\x6c\x13\x7e\x18\xdb\x3d\xa4\x41\x2c\x77\xa1\xd1\xff\x48\xf9\xb0\xd5\x81\x7b\x01\x5c\xd0\x22\xcc\x86\x5b\xb9\x2c\x9e\x68\x55\xb4\x28\x11\x67\x95\xf1\x8a\x15\x49\xb7\x64\x61\xc1\x9d\x21\x25\xcc\x3b\x77\x13\x23\x64\x6a\x69\xaf\xbf\x6f\xb8\xe4\x4b\x1b\x16\x13\xb4\xa0\x8a\x35\x15\x9c\x48\xf9\x28\x52\xb9\x5e\xde\x3d\x00\x17\xbd\xbc\xb4\x75\x3f\x5c\x21\x40\xa5\x3e\x2d\x88\x78\x20\x24\x45\x5f\x83\x08\xf6\xf5\xbf\xfc\xcb\xbf\xf8\x19\xbe\x7b\x1f\x7d\xfd\x87\x6f\xbf\x9d\xa3\x4b\x9a\x03\x3a\x09\x85\x5c\x35\x1b\xde\x9d\xe9\x10\x64\x3f\x5f\x62\x62\x1f\x77\x48\x5f\x48\x1a\x07\x62\x43\x57\x6b\xa1\xaa\xd3\xc2\x2e\x48\xa8\x97\x33\x22\x85\x19\xad\x18\x84\xc2\xda\xe4\x3a\x21\x53\xa7\x4c\xeb\xa0\x36\x98\xe3\x33\x94\xd0\x7b\x7f\x57\x97\xfc\x87\x9c\x15\x59\x09\x3e\x90\x13\x2e\xe5\x79\x5d\x3b\x57\x7d\xac\x5c\x33\x4e\xc4\x33\xc5\x32\x05\x59\xfc\x2a\x9b\xee\xba\x22\x3c\x9d\x59\x84\xdc\x99\xda\x2a\x19\xa6\x79\x3b\x3e\xb8\x33\x9c\xb5\x0e\x1e\xa9\x54\xf6\xb2\x36\x82\xd8\x39\xdb\xdd\x90\x54\x65\xcb\x72\xf6\x37\xb5\x39\x68\xaa\xdd\x4e\x46\xbb\xe0\x5a\x9e\xd5\xb0\x12\xe0\x77\xf0\x64\xe2\xa0\x1a\x06\x91\xbc\xdf\x35\x2e\x92\x93\x59\x7c\xbd\x74\x53\xe0\x43\xac\x1a\x09\xe5\xb2\x8b\x15\xb0\xf6\x86\x9e\xbb\x25\xec\xc5\x3a\xa0\x44\x8d\xec\x63\x91\xee\x51\xd7\xb5\x20\x35\x77\x54\x35\x47\x75\xaa\xb9\x97\x64\xd9\x07\x95\x7a\xa2\x13\x5b\x35\xad\x3d\xd8\xe3\xb0\xf1\x9b\x7c\x0c\x22\x0a\xbd\xb4\x10\x3f\x2a\xfb\x4e\x38\xd7\xf9\xb3\x1b\x9c\xdf\x4b\x25\x4f\xf3\x37\x3f\xb7\xb9\x91\x93\x64\x73\x82\x55\x9a\xf8\x96\xd8\xc2\xea\x6e\x3e\x9b\xec\xf3\xf1\xdc\x7b\xde\x94\xf5\x1a\xb1\x5c\x21\xe1\x2b\x2e\x21\xdf\x7b\x72\x6c\x98\x6a\x1e\x14\xce\x9c\xb2\xea\xba\x14\x24\xae\xe4\xcc\xf8\x5d\xf9\x66\x15\xfc\xf3\xda\x43\xc4\x0c\xaf\x8b\x12\x56\x19\x45\x3e\x95\x85\xd4\x6e\xeb\x23\xdb\x06\x17\x51\x69\xaf\xbb\xa9\x0f\x6b\x48\xcd\x93\x9e\x15\x38\x90\x8a\xef\xea\xdf\x3b\x8f\x20\xd0\x50\x57\xbf\xad\x49\x26\x79\xe6\x54\x9b\x68\xbd\xff\x43\x60\xa6\x54\x83\xd4\xc8\x0a\x8f\x34\x3c\xc0\x91\x7b\x82\x99\xbc\x6a\x65\x36\x65\xe3\x95\xdf\x70\xa5\x07\x12\xf6\x5c\xfc\x95\x8b\x3d\x98\xe4\x14\xd7\xbf\xa6\xd5\xb3\x22\x55\x1f\x51\x40\xb5\x10\x97\x9d\x6a\x7b\xe7\xc3\x72\xdd\xac\x52\x95\x30\x21\x3e\xa4\x8e\xb2\x6d\x40\x66\x37\x47\x6d\x8e\xde\x6a\xde\x2d\xf7\x62\x8a\xf0\x82\xb3\xa4\x10\xea\x03\x61\xe7\x0f\x59\x12\x2e\xfb\x87\x0e\x1a\xf8\x29\xe0\xe9\xe6\xb1\x40\xa2\xce\x95\x00\x97\xb5\xe2\xc6\x21\xb7\x83\x6a\xc1\x6c\xe1\x00\x9e\x3f\x6e\xfe\x1e\xa1\x74\x45\x59\xd3\xc8\x3f\xf8\xc7\x28\x73\x11\x71\x1a\xae\x20\xdf\x5d\xa3\x93\xb2\x04\xa2\x09\x96\xb9\x4e\x05\xc9\x97\x38\x22\xa7\x8e\xe2\xdc\x6d\x38\xd3\x6f\x9a\x8c\xbb\x35\x4e\xe3\xc4\x56\xde\x21\x9f\x05\xc9\x53\x9c\xc0\xf7\xe2\x9c\x02\x6c\xc9\x79\x92\xad\xbb\x45\x91\x25\xc1\xa2\xc8\xbb\x8d\x93\xd3\xc6\x7c\x43\xd7\xa6\xd0\xd8\x81\x50\xbf\x68\x2f\x35\x2d\x5a\x7d\x48\x9d\x53\xea\x4c\x5a\x67\x0e\xa9\x69\x6a\xee\xb9\x6b\xab\x98\xcb\xfd\x09\x57\x0c\xf0\xa4\x1d\x2b\x72\xed\x38\xd2\xc5\x0c\xbc\x44\x23\x96\x4b\xed\x5c\x75\x0c\x73\x94\x93\x95\x54\x25\x72\xd0\x49\x54\x4a\x72\x52\xc8\x1f\x26\x8b\xb7\x9d\x34\xe2\xd9\x89\x47\xd6\xee\x02\xbf\x77\xc1\xb8\x13\x96\x5a\xab\x61\x5b\x1a\x1b\x09\x05\x1c\xca\x65\xe5\xfc\x0c\x73\x1e\x60\x49\xd1\xba\x9b\x53\xe9\xca\x59\x5b\xa5\x43\x81\x9c\x63\x41\x2c\x82\x34\x50\xe3\x0c\x74\x13\x1c\x19\xe0\x8f\x79\x5d\xde\xe1\xf7\x0c\x8b\xc9\x4d\xb1\x48\x28\x5f\xdf\x0d\xb2\x91\xbf\x6b\x20\xa0\x62\xa4\x5c\xbf\x7f\xd0\x78\xdb\xec\xea\x88\x93\x94\x53\x90\x30\xe4\x4d\x26\xe5\x9a\x90\xf4\x33\x29\xb2\x63\xce\xcd\xe2\xb8\xa7\x8d\x41\xf6\x61\x42\x34\x26\x93\xfc\x93\x33\x8e\x4f\x61\x26\x54\x85\x55\x17\x93\x8f\x69\xe6\xbe\x87\x22\x9c\x24\x5c\x0b\xa9\x16\xd6\xc3\xdc\x47\x61\xfa\xbc\x49\x1b\x57\xbb\x91\xca\x8d\x6a\x6b\x60\xd6\x00\xf3\x43\xce\x78\xe3\xc4\x72\xb4\x61\x2a\x8d\x36\x45\x2c\x35\xb3\x0f\x70\x7e\xfa\xdf\x01\x7a\x9f\x85\x3d\xc0\x39\xd1\x87\x25\x6c\x6b\x1e\x9c\x17\xad\xed\xcb\x70\x5e\x0c\x72\x5b\x96\xc5\x8a\xb1\x03\xe8\x52\x29\x83\xd0\x51\xfa\xc7\xe9\xa5\xd5\x25\x1b\xc0\x5b\x7a\xf9\x3f\xfb\x66\x1d\x9e\x0b\x91\xd3\x45\x21\x7a\x02\x38\x7f\xaa\xbd\x0c\x72\x15\xe1\x9a\x21\xcd\xb4\x9a\x1c\xf5\x30\x79\x68\x8d\xd5\x1e\xbb\x7d\x36\x67\x65\x03\x2f\x55\x10\x1b\xd4\x4b\xc7\x1c\xc5\x2c\x2a\x6c\x85\x0b\x90\x23\x4a\x0f\xbf\x1f\x90\x1d\xf5\x3b\xe2\x7d\x51\x70\xdd\x0f\x78\x76\x69\xcc\x1e\xd2\x07\x9c\xc7\xe7\x37\x9d\x29\x60\x55\x61\xad\x7c\xc7\x75\x2d\x19\x52\x50\x26\x1f\x2f\x58\x21\xbc\x7c\xd7\x20\x83\x18\x00\x9a\x83\xa7\xe9\xe0\x69\x3a\x78\x9a\xda\x5a\xd5\xd3\x24\xdf\xa8\x96\xdb\xa8\x1c\xc0\x40\x17\xb7\x9c\xd1\x67\x35\xd9\x3b\xcc\x44\xf1\xff\x7a\xda\x55\x1f\x69\x16\xe4\x59\x75\xde\xca\xfd\xe2\xc8\xc8\xa6\x70\x1d\x88\x09\xcf\x67\xde\x7f\x04\xc3\x3d\x8c\x28\x40\x2d\x51\xad\x2d\x7f\xa3\xac\x2a\xef\x3a\x1e\x03\xcd\x7e\x19\x8b\x5f\x03\x62\x3c\xc2\x69\xca\xd4\xcd\xc8\xcf\x74\xe1\x9a\x33\xad\x3b\xa7\x71\x70\xcd\x79\xd3\xa0\x12\x8f\xb9\x5c\x7b\x99\x82\x03\x97\x0e\xf5\x5a\x3e\x04\x4b\x08\xf3\xd3\x81\x7c\x59\x6d\xfd\xd6\x12\x41\x0d\x12\x23\xc0\x86\xbe\x51\x17\xa6\xd4\xdb\xb6\xb4\x7d\xb4\x26\x1b\x0c\xff\xfc\xbe\x57\xd7\x55\xa3\x1c\x49\x51\x51\x10\x05\xf6\x42\xf2\x0d\x47\x6c\x79\x56\xa9\x23\x76\xb4\xfd\xe6\x28\xd4\xee\xdc\xdb\xf7\x83\xcc\x1e\xf7\x01\x06\x56\xdb\x3e\x7c\xa0\xb5\xbc\xcb\xfd\x5d\x56\x7d\x0d\x70\xca\x3b\x7d\xaf\xb8\xa0\x81\xdb\xaa\xd9\x7e\xb4\xe1\x1f\x5c\x5f\x61\x34\x0f\xae\xaf\x17\xe6\xfa\x72\x2e\x17\x38\x7e\x94\x9b\x81\x2b\x77\x58\xe8\xdd\x22\xdf\x75\xcd\xc2\xda\x73\x06\xb5\xde\x94\x7c\x3d\xb7\xe0\xbc\x81\x34\xe5\x3e\x36\x3e\x33\x96\x57\x23\x20\x8e\xe7\xf3\xe3\x63\xe5\x49\x03\xb2\xe1\x24\x0b\xb1\x9c\xfd\x11\x91\x34\x62\xb1\xda\x8a\xb2\xaf\x39\x17\x20\x1c\x95\x56\x94\xfe\xa3\xdf\x18\xe8\x61\x37\xe2\x02\xfa\xd9\x67\x8b\x04\x73\x1c\x03\xf4\xf3\xfd\x08\xc1\xa2\x14\x27\x2c\x28\xa1\x9e\x00\x0b\xed\x18\xca\xca\x41\xae\x28\xcb\x61\xaa\x62\xb1\xc0\x75\x4c\x79\x4e\x74\xa2\x7e\x9c\x47\x59\x11\x66\xee\x31\x35\x67\xe7\x1b\xb2\x61\xf9\xee\xcc\x92\x92\x24\x2a\xb4\xf5\x13\xdd\x60\xa5\x65\x93\x12\x4b\x54\xe4\x39\x49\xa1\x84\xe6\x4b\x93\x5d\x82\x31\x9c\xd0\x20\xd1\xc5\xae\x6d\x48\x52\x78\xd9\x6a\x49\x31\xd6\x2d\x07\x36\x4b\x3b\xc6\x20\xcb\x57\xd9\x74\xda\xcf\x59\x59\xcc\x7e\xc9\x72\x44\xd2\x2d\xda\xe2\x9c\x87\xad\x07\x1a\x26\xad\xc4\x74\x4b\xb9\xbf\xe2\x9b\xf3\x42\xb3\x11\x10\x30\xb7\x0b\x91\x15\x42\xf3\xec\x90\x64\x6a\xa7\xe7\x6b\x62\x61\x3b\xed\xf9\xa9\x09\x6e\xdf\xf8\xb3\x42\x4c\x7b\x91\xd5\x4e\xab\xcd\x5b\xfb\xb4\xda\xc2\x2b\xa1\x36\xbf\xd7\x6b\x53\x0c\x2e\x42\x5c\x6f\x66\x29\x87\x9e\xaf\xf2\x5a\x2e\xf1\x62\x8d\x30\x3c\xf1\xb1\x00\xff\xcc\x25\xed\x91\x11\x77\xa5\xdf\xa8\x06\xae\x0b\xb2\xc9\x58\x8e\xf3\x1d\x8a\xb5\x05\xcb\x83\x49\xbd\x87\xcd\xe0\x80\x33\x8c\x06\xa1\x83\x51\xc5\x34\x9f\x20\x29\x2e\x18\x9d\x81\xc4\xb4\xd8\xf4\x33\x4d\xfe\x19\x00\x60\x35\xb8\xac\x89\x53\x50\x84\x2c\xea\x37\x8e\xba\x11\x85\xd5\x64\x52\x5e\xce\xbb\x92\x6b\x5c\x4c\xc4\xa3\x5a\x31\x17\x29\x89\x07\x79\x28\x52\x16\x13\xb9\x30\x86\x98\xea\x9b\x63\xfb\x4c\xb5\x83\x2f\xf0\x9c\x9d\x68\x42\xa7\x52\xa6\x7b\x0b\xd7\xf6\x93\xac\x35\xea\x95\x3b\x4e\xff\x4e\xa0\xec\x76\x4f\xd4\x55\x26\x70\xe2\x14\x10\x4f\x58\x84\x13\xbb\xaa\xe6\x8a\xf4\xdb\xfc\x20\xea\x81\x72\x64\xcf\x99\x71\x13\xc9\x55\x95\x7d\x53\x82\x11\x58\x17\x13\xae\xbc\xe9\x34\xc2\x0b\xaf\xa9\x50\xd1\x56\xc2\x92\x5d\xc9\x0f\x4e\x65\xfe\x82\xcb\x9e\x42\xed\x2d\xe7\x19\x2f\x55\xdb\xd1\x07\x83\x53\x2f\x9c\x8a\xea\x55\x5d\x54\xfe\xe5\xce\xcc\xaf\xdf\xeb\x6b\xd5\x78\xc8\xec\x33\x76\x62\x5e\x80\xac\xae\x7b\xa9\xa5\x4d\xb6\x44\xd8\x53\x44\x08\xb9\xf2\x0f\xb7\xf0\xe7\x7b\xe7\x25\xa5\x89\x7b\x60\x02\x4e\x8a\xc6\x71\xb6\x0b\x53\xa4\x3a\x6c\x6a\x6f\x77\x37\x6f\xee\x82\x93\x7c\xb6\x2a\x68\xdc\x7f\x5b\xbf\xd8\x3b\x3f\xe8\xa6\xef\x77\xbf\xf7\xba\xd5\x07\xdf\xe5\xcb\x28\xf8\x32\xfc\xfe\xa2\x7a\x0b\x7e\x4f\x17\x39\x41\x17\x6b\x9c\xa6\x24\xa9\x82\xbd\x77\x7b\x18\xda\x80\xe0\xab\x19\xe2\x7b\x58\xef\xdd\x57\xec\x94\xf8\x65\xff\xbc\x29\xdd\x2f\x06\x0d\x32\x0c\xa5\x3c\xcc\x53\x59\xa2\x98\x3f\x3e\x4a\x79\x52\xf4\xc4\x27\x2f\xed\x9e\xdf\x5f\x20\x81\xf3\x15\x11\x92\x08\x4a\x8b\xcd\x82\x04\xde\xe3\x2f\x03\x19\xfb\xa5\xe4\xb0\x4f\x97\x66\xae\x96\xe3\xcf\x7f\x7e\xd7\x13\x66\xac\x69\x4d\x1f\x58\x9e\xc4\x0f\x34\x56\x31\xa3\x1c\x9d\x48\xb2\xa7\x2f\x17\xf3\xeb\xe1\x81\x76\xd7\x89\x44\xdd\xc3\xd6\x06\x72\x18\x36\x82\x71\xeb\xbc\x66\x4a\x3a\x01\xe0\x54\x3b\x81\xcf\x9f\xa2\x2b\xaa\x6a\x78\xc9\xff\x53\xa6\xcf\xb2\x28\x2a\x5b\x3a\x0b\xe4\xa5\x28\x6f\x0b\x79\xae\x8c\x63\x00\xaa\x7c\x2d\x0a\x65\xa8\x5c\x30\xb1\x46\x9c\x6e\x8a\x44\xe0\x94\xb0\x82\x27\xbb\xc0\x6d\xf4\xd4\x4b\xb3\x4c\xc8\x67\xb5\xdb\xc3\xef\x65\xfb\x4a\xf5\x7e\x5e\x91\x94\xe4\x34\x32\x2b\x15\x64\x6b\x33\x71\xe3\x10\x65\xcb\x29\x4b\x49\xfc\xca\x5e\xd6\xaa\xec\x11\xc4\x91\x93\x08\x2d\x30\x27\x31\xca\x92\x62\x45\x3b\xbd\x4d\xbf\x80\xc8\xf0\x32\x4e\x35\x44\xd7\xb4\x4a\x4f\x58\x72\xdf\x01\x9a\x7a\x4f\x18\xf9\xd0\x1c\x6d\x1d\x93\x8c\xa4\x92\x8f\xa4\xce\x99\xf0\xeb\x5d\x30\x1d\x93\xad\x82\x76\xe6\x0d\xe5\xac\x57\x9f\x45\x8e\x25\x1b\xdc\x48\x86\x66\xa2\x8f\xe8\x52\x6a\x18\x53\x02\x8d\x3c\x62\x20\x1f\x3a\x48\x18\xb6\x3d\x33\x34\x5f\xbf\x10\xfd\x90\xc0\x7f\x37\x44\x5f\xf1\x7e\x7d\x80\x4c\x08\xfd\x7e\x28\x7c\xcf\x5e\x52\x8e\x1c\x35\x41\x97\xfc\x6d\x0e\x89\xf7\x52\xf6\x85\xcc\xf3\xfd\x88\x5c\xff\x0c\x54\x47\x7d\x00\xff\xf9\xa7\x8f\x9f\x5f\x26\x2c\xba\xef\x81\xa3\xf7\xbd\x7a\xbe\x66\x2d\xd1\x3f\xf6\x01\xd2\xeb\xb0\x8e\xe8\xd3\xe6\x5c\x79\x10\x50\xa5\x3e\xd2\x49\x54\x1e\x9e\x9c\xc9\x13\x00\xb0\xf1\x68\x41\x24\x43\xc8\x8b\xd4\x83\x89\x35\x75\x88\x33\x16\x98\x0f\xc0\x23\xaf\x97\x25\xe1\x44\xa8\xe8\x7c\x40\x21\xde\x10\x81\x83\xaa\x24\xcc\xfe\x4d\x4b\x70\x69\x85\x92\x94\xcd\xcc\x4a\x95\xa5\x48\x23\x96\x72\x1a\x93\x10\x8b\x36\x86\x35\xc9\x49\x14\x10\x68\x1d\x5e\x19\x45\xf5\xee\xe3\xc7\x9e\xe0\x53\xf2\x85\xda\x5c\xe9\x7d\x03\x66\x5b\x28\xb0\x54\x6a\x6d\xde\xb1\x41\x61\x61\x33\x3b\x9a\xde\x14\x43\x5c\x45\xe4\xc6\x16\x77\xea\x55\xf4\xe8\xf8\x87\x8b\xab\xea\xab\xd5\x43\xf7\xc3\xc5\x15\xba\x0c\x2e\x16\xd5\xab\x4c\xa5\x35\x4f\x76\x92\x7c\x84\x32\x95\xab\x88\x94\xa5\xb0\x62\xca\xef\x9f\x0c\x0c\x33\x8b\x27\x2a\xc3\x70\xa8\x50\xf9\xa2\x41\x35\x47\xed\x46\x6f\x07\x0e\xe5\x29\x0f\xe5\x29\x5f\x56\x79\xca\x27\xe5\xc8\xe8\xd1\xac\xfa\x8a\x3d\x0f\xaa\xb2\xe8\x1a\xb3\x6e\x2e\x4b\x5f\x1e\x4d\xe5\x15\xea\x57\xb7\x3f\x36\x41\x5b\x9a\x52\x6c\x92\xc2\x33\x4d\xf1\xa3\x59\x2a\x82\xec\x0b\x01\x8a\x6f\xb3\xfd\x61\xdf\xfc\xe1\x4e\xa0\x97\xec\x13\x4e\xb0\xcf\x06\xb2\xa2\xe2\x96\x64\x9d\x7d\xae\x09\x74\xea\x85\x9a\x25\x9b\x0a\xf9\x03\xe3\x54\xb0\x7c\x87\xb0\x00\x24\xb5\x5c\xd0\xa8\x48\x70\xf7\x01\xca\x89\xb2\x63\xcf\xd1\xe5\xd5\xcd\xed\xd5\xc5\xf9\x87\xab\xcb\xd7\xc8\x7c\x85\xba\xd2\xfa\x1c\x7d\x60\xa5\xe1\xbb\x93\x2a\x76\x2a\xc2\x43\xf8\x73\xd9\xc7\x33\xcd\x80\x71\x5a\xc6\x8a\x00\x5a\xa0\xc7\x52\x74\x9d\x52\x51\x86\x9a\xaa\x12\x4b\x09\x4b\x75\xd8\xa5\xa4\xac\xed\xef\x2b\x2a\xce\x94\x5f\xdc\x5f\xca\x53\xbe\x5a\xed\x05\x9c\x70\x15\x80\x66\x87\xd0\x69\xc3\x98\x54\x82\x2c\x17\x71\x0a\x0d\xd2\xc4\x80\xf5\xab\x18\xa9\xdc\x75\xf6\x65\x7d\xff\x99\x88\x7d\x33\x2b\x7e\x65\x68\x1f\x70\x10\xc9\x9b\xf9\x78\x7e\x6c\x04\xc2\xa4\x96\x4d\xe2\xa5\x59\x76\xca\x20\x4e\xca\x97\xab\xbb\x7f\x8e\xd0\x7b\xb1\x26\xf9\x03\xe5\x01\x05\x0a\x68\x1d\xf7\xd2\xfa\xed\xe4\x07\xdc\x44\x83\xea\x57\xfc\x84\x53\x1d\x9d\xb4\x70\x3b\xad\x71\xb6\x56\x74\x4b\x52\x35\xb1\xd3\xb1\x69\xd3\xb5\x5e\xab\x7d\x5b\x72\x8d\x8f\xb7\x6f\xa6\xeb\x8c\xe2\x11\xbd\xba\x72\xc1\x36\x1b\x2a\xd0\x1a\xf3\xb5\x41\xfb\x71\x62\xbe\x2c\x9f\x9a\x44\xa1\x56\x10\x40\x3d\xea\x90\x1d\xff\x60\x5e\xa9\x29\xd0\xf6\x67\x53\x8d\xcc\xcb\x6f\x40\xf3\xe9\x1f\xf1\xda\x56\x26\xc3\x8e\xe5\x19\xaa\x3f\x90\x34\x56\x40\xf2\xdd\x6a\x71\x77\x02\x63\x28\x3b\xb3\x1f\xeb\x59\xdc\xd4\xbc\xf6\x4e\x81\xe5\xaa\x30\x7b\xfd\xa3\x12\xec\x82\xd0\xaa\x62\x22\x30\x4d\xb8\xb3\xe2\x82\x65\x2c\x61\xab\xe6\xa0\xd5\x1e\xcb\xf5\x2b\x95\x16\x35\xc3\x33\xb9\x0f\xa6\xd3\xc7\xfa\xd6\x2c\x33\x59\x5f\x72\x82\xca\x51\x5a\x3d\x04\x12\xac\xa6\xab\xfd\xf4\x64\x13\xf1\x08\x02\xac\x9d\x1d\xef\x5c\x18\x4d\x16\x2c\x10\xa6\xe6\x0b\xdc\x03\x25\x5e\x4c\x46\xf2\x0d\xe5\x92\xb9\x39\x92\x6d\x88\xba\xbb\x27\xf9\x3e\xd1\xa4\xfb\x84\x5a\xc9\xe1\x7c\xc9\xbf\xfb\xc5\xc1\x61\xfb\x55\x98\x6b\x96\x93\x19\xf9\x4c\x39\xe8\x00\x90\x46\xe8\xc9\x28\x2a\xaf\x5a\xb7\x92\xab\x31\x48\x1a\xf3\xa5\x7a\x2a\xd9\xf5\x89\x9b\x2c\x65\x41\x6b\x1f\x86\xf0\x11\x9c\x24\x3b\x55\xb8\x00\x80\x65\x94\x41\x06\xaf\xbc\x38\x84\x2c\xd7\xde\x9c\x2c\xa7\x5b\x9a\x90\x95\xd4\x0f\xd7\x34\x5d\x39\x40\x38\x38\x49\xd8\x03\xd1\xa9\xcf\xc4\xeb\x7b\xab\x57\x0f\xe2\xc2\x8d\x6f\x86\x1d\xfc\xee\xfd\x07\x94\x12\xf5\x29\x1e\x70\x9a\x87\xeb\xa3\xb2\x33\x5e\xec\x84\xd9\x6c\x06\xd6\xae\x93\xbf\x49\x39\x3e\x4e\x4e\xd1\x9f\x89\xee\x9f\x54\x70\xe4\xd9\x8e\x04\x7a\x58\x33\xb0\x5f\x14\x3c\xa0\xca\x67\xb9\x03\xe0\xb0\xa9\xbc\x43\x4d\xe1\x95\xa4\x22\x45\x58\x75\x55\xc3\x7c\xc5\x25\xc2\x4a\xb7\x42\xc3\x51\xe9\x5f\x7f\x3a\x7d\x60\xa2\xab\x73\xe0\x5d\x60\x3c\x23\x4d\xa7\x2a\x28\x7b\xdc\x82\xd5\x00\xf8\x09\xdf\x6d\x12\x9a\xde\x9f\x21\x2a\x0c\x43\x95\x3b\x5c\x07\xcb\xa7\xf7\xa1\xb8\x7a\x39\xc1\x89\x73\x1f\x4d\xb0\x4b\x27\xbb\x6b\x44\x6f\xb3\xfd\x87\x5d\x46\x80\x77\x58\x16\xa8\x43\xd5\x5c\x13\xc7\x91\xdf\x6c\xfd\x92\x66\x82\xf2\x3e\xd8\xae\xc7\xd7\x77\x17\x77\xd7\xb5\xf2\xdd\xea\xb7\x8a\x6b\x6a\x44\xe0\xfc\x54\x91\xf3\x7d\xae\x5a\x98\x84\x67\x90\xc9\xe9\xcf\x5d\x2a\xc8\x0c\x25\x45\xf7\xdf\x55\x48\xe9\x0d\xcb\x05\xee\x4a\xa0\x09\x65\x3d\xd1\x1a\x67\xe7\x85\x58\x5f\x52\x1e\xb1\x2d\xe9\xa9\x9e\x1a\xe4\x62\xed\x3e\x42\xd4\x6c\x0b\x45\x0b\x5d\xfc\xfb\xf9\x4d\xad\xbe\xe6\x24\x12\x8c\xdb\xf3\x3b\xc2\x7b\xeb\xb2\xcd\xfd\xd6\x94\x1e\xb5\xd7\x07\xd7\xe1\x3f\x8d\xeb\x10\x38\xc8\x3f\xab\xbb\x90\xa6\x54\x50\x2c\x58\x10\xf4\x40\xd5\x4e\x54\x70\xc1\x36\xfa\x48\x5d\x1b\x32\x10\xf7\x02\xae\xbf\x0a\xe5\xa0\x0d\x56\x96\x87\xa1\x20\xab\x44\x9c\x5a\x64\xf1\x5a\x54\xfc\x19\x4a\xc9\x83\x9f\x28\xf4\x8d\x5a\x1a\xff\xaa\x73\x20\x32\xe0\xaa\xff\xf6\xfa\x5f\xf5\xd1\x4a\xf1\x86\xfc\x1b\xc8\x42\x5e\x92\x25\x7a\x8a\x35\x8e\xe9\x5a\x7b\x53\x19\xc5\xa0\xe3\x3f\xf7\xe3\x73\xda\x58\xac\xc6\xfb\x1f\x05\x4e\xd4\x3c\xbe\x9b\xd2\xb2\x59\x5d\x8f\x5e\xdd\x33\x7b\xc4\xac\xc3\x3b\x63\xed\x91\xca\x04\xc8\x19\xf0\x84\x5f\xea\xcc\x71\xca\xe5\xe2\x55\x3d\x4f\xc7\xda\xb1\x7c\x8c\x4e\x44\x94\x05\x62\xb3\x3e\x42\x0e\x95\x1a\xa6\x5e\x8b\x37\x36\x77\x2a\xac\x3f\x93\x7b\x59\x61\x8f\xf7\x33\xd2\x55\x06\xa0\x44\x0f\xf4\x86\x72\xa1\x22\xd9\x15\xc5\x90\x42\x4f\x44\x65\xcb\x48\xf9\xf1\x06\xea\x1b\x64\xff\x89\xe3\x38\x7f\xad\xee\xe0\xa5\x96\xe3\x72\xb0\x02\xb0\xf0\xe2\xfb\x26\x7e\xe0\x44\xec\x32\x1a\x81\xca\xff\xe1\xe2\x06\x28\x71\xf4\xc7\x3f\x28\x48\xad\xdf\xff\xee\x0f\x5f\x07\x6e\x81\xe7\x48\x67\x1a\x64\x05\xeb\x15\x25\x1e\xe2\x12\xf1\x79\x71\x27\x13\x83\x86\xc5\x95\x83\x60\x76\x57\xd6\x67\x57\xfb\x52\x33\x6f\xb9\xc8\xf6\x6e\xf1\x0e\x76\x80\x78\x77\x88\x81\x6e\x6d\x2f\x3f\x06\x1a\xd9\x74\x49\xc5\xbf\xc6\xf2\x3f\xc5\xfa\x6e\x0c\xeb\xd3\xac\xcd\xbf\xed\x82\x59\x5f\x85\xb5\x79\xe9\x4e\xc5\xfa\x3c\xb3\xe8\xdb\xb1\xd5\x9d\xaa\xb8\x89\xd4\xee\x1d\x1f\x35\xe4\x64\x5d\xbe\xbb\xfb\xcf\x37\xe7\xdf\x5d\xbd\xd1\xe5\x04\xe9\xcf\x1e\xb8\x1e\x17\x5d\x79\x40\x0c\x6a\xf8\x76\xf7\xdb\x01\x7c\x53\xd4\xc7\x6b\xf9\xee\xfb\xbb\x9a\x61\x45\xfe\x62\x5c\x95\x55\x77\x64\x37\x3f\x6d\x71\x55\x8e\xd5\x71\xd2\x65\xc0\x8c\x3c\x8d\x31\x75\x06\x11\xff\x93\x24\x4f\x0e\xb4\xb7\x1a\x07\x05\xf9\x5c\x55\x78\xe5\x9a\xa9\xbe\x0d\xaa\x4f\x3e\xe1\x7a\xa0\x67\x76\xbc\xc9\x99\x50\xb3\x13\xe2\x1f\x7b\x52\x97\xdb\xa3\xcc\x72\x98\xa8\x93\xf7\xcd\xd4\x3d\xbe\x83\x77\x8c\xb3\x57\xb2\x00\x15\xe1\x98\xcb\xdb\x43\xde\x1b\x84\xf3\x10\xf0\xba\xda\xee\x7c\x29\xbb\xaf\x8c\xd4\x53\x57\xc4\x45\x82\x69\x27\x1a\x57\xed\x30\x36\xbd\xae\xfe\x79\xa7\x4c\xd1\x81\xd5\xc6\xaa\x45\x83\x10\x46\x8d\x94\x6d\xac\x10\xd6\x26\x01\x80\xdc\xee\x3e\xea\x03\x27\xba\x9c\x98\x99\x99\xf3\xf2\x27\xf5\x4b\x24\xbb\xf4\x74\x4c\x19\x3e\x37\x51\xda\x84\xa5\xd5\xef\x30\x5c\x98\xd7\xea\xa9\xeb\x2d\xeb\x15\xa2\xe8\xec\xaf\x27\xc2\xdc\x82\xda\x17\xda\xac\x16\x9c\xe3\xfe\xbc\x0b\x8e\x1e\x9d\xeb\xff\xb9\x67\x02\xb2\x77\xba\x2e\x4d\xf6\xfb\x74\x6a\x65\xb6\x66\x82\xa5\x03\x13\xb1\x6e\x1a\x5e\xae\x06\x3b\xa8\x27\x2e\x54\xf2\x61\xe2\x11\xf5\xcb\x35\x54\x51\xe4\xd6\xed\x05\x85\xa2\xf5\x9d\xc7\x52\xe3\x00\xe3\x7e\xc7\xb9\xb6\xef\x3e\x99\x2c\x16\x5f\x5f\x4e\x70\xe2\x7f\x39\x90\x0e\x53\xe3\x4b\x4d\x75\xdc\xe5\x42\xf6\xab\x86\x72\xa9\xe5\x5c\x93\x57\xc9\xf5\xd6\x47\xe5\xde\x77\xf6\xb7\x77\x50\x01\x39\x55\x61\x32\x03\xcb\xc5\x03\xcb\xfb\x82\xcb\xdc\x54\x5e\xab\xc5\x2f\xe9\xbf\x85\x84\x37\x07\x9d\xe0\xa7\x3e\xa5\xaa\xdf\xcf\x76\x52\xef\x20\x38\xc2\x99\xd2\x06\x0f\x62\x48\xd0\x88\xd2\x77\x9b\x8e\x77\xc7\xf1\xf5\x52\xed\x3c\xde\xea\xf8\x36\x1e\xdb\x40\xcd\xc5\x1e\xeb\x47\x39\xb6\x83\x6e\x69\x0f\xe8\x48\x78\x5e\xcf\x20\xd0\x91\xc9\x14\x26\xb3\xab\x07\x54\xbc\xbb\xbe\xd4\xc6\x24\xb9\x9e\x25\x03\xc3\x96\x0d\x78\x87\x1e\x94\xe9\x10\xc6\xb0\x54\xfd\xfe\xee\x33\xdc\x50\x88\x6a\xc9\x72\x40\xf8\xa0\x0a\xf4\xa3\x44\xea\xd7\x90\x1f\x67\xba\x80\xe1\x06\x67\xbc\xfb\x9a\x92\xac\xca\xad\x64\xf5\x54\x6c\x49\x77\x78\x02\xae\x34\xb4\x8e\xdc\xdb\xf6\xe2\x71\xfb\xc5\xe1\xfc\xb2\x7d\x40\xad\x96\xfd\x52\x70\x41\xca\xb9\x29\x15\x17\x5c\x0a\xce\x4b\xd5\x5b\xa6\xa5\x5e\x80\xc5\x4b\xb1\xab\x40\x4b\x5b\xe9\x95\x00\x9e\xef\x96\x66\x79\x16\x4f\xa8\xde\xa6\xbd\x36\x96\x29\x10\x67\xa2\xee\xd5\x19\x0f\xa8\x7e\xf3\xb8\xa5\xdf\x6e\x6c\x3f\xd4\xea\x6a\x10\x23\xcb\x82\x10\x4e\x58\x10\xb2\xbe\xb3\x5d\x9c\x2a\x9c\x3a\xd0\x68\x97\x05\xb8\x83\x7a\xd5\xdc\xe8\x57\x12\x23\x32\xb5\xf1\x07\x54\x50\x71\x61\xa2\x6c\x45\xcd\x92\x22\x0a\x02\x5d\xd1\x23\x64\x66\x62\x83\x5e\xe8\x5d\x84\xa4\x7f\x9d\x90\xc0\x2d\x63\x5a\xf5\xd2\xa9\x08\x30\x67\x88\xe0\x68\x8d\xee\xc9\x6e\x06\xbc\x2e\x98\x26\x42\x19\x86\x1c\x4d\x98\xd7\x4b\x2c\xaa\x85\xef\x4a\x43\x5b\x68\x4d\x27\xd9\x2e\xec\xf2\x98\x7c\xc2\x72\x47\xdb\x6c\xd0\xc0\xdc\xc4\xb2\x61\xae\x65\x4c\xf4\xb0\x66\x5c\x9b\x93\xb4\x69\xe9\x9e\xec\x80\xad\x45\x2c\x0d\xd2\x6e\xca\xa6\x09\xc0\xac\x41\x9c\x53\x2d\x6f\x51\x72\x0e\x12\xcb\x0f\x84\x16\xca\x42\x70\x1e\x5b\xc7\x5d\x86\x45\xc9\x4b\xc4\x23\x0a\xd4\x66\x00\x9c\x6e\x4e\x8f\xd4\x77\x00\x69\x14\x22\xd4\x38\x49\xc3\x22\xc8\x1d\x9a\x30\x77\xd5\x70\x2d\x80\x65\xa7\x5c\xd7\xbd\x07\xaa\x7d\x66\x54\xed\x25\xbb\x09\x2a\xf9\x9f\x9c\x88\x22\x0b\x0b\xcd\x2a\x1b\xc4\xdc\xc9\x91\x13\xce\x91\x02\x7f\xdf\xe0\xfc\x9e\xc4\xb6\xa8\xcd\x1c\x6a\x6b\xf5\x59\x21\x83\xd7\x6a\x0a\x51\x29\x05\x11\xef\xdc\x64\xdc\x1e\xa5\x1f\x65\x3b\x9e\xcf\x55\xc5\xac\xa6\x24\xdd\x60\x3a\xe1\x37\x4e\xd9\x7a\x32\x92\xba\xd4\x85\x33\xc8\x23\x00\xb9\x18\xb6\x03\x18\xd5\x83\x6a\x74\xba\x4d\x3b\x7b\x71\xb0\xf1\xb5\x6c\xbd\x99\xad\x6a\xfd\xea\x3e\xa9\x36\x93\x23\xec\xf5\x7c\xcf\x89\xe8\x7f\x0f\xa8\x76\x4f\xbc\x6a\x63\xbd\x55\x83\x06\x35\x1f\x2c\xef\xb9\x3e\x2b\x80\x86\xd5\x78\x52\x2d\xbc\x38\x63\x4b\xdf\x5b\xca\x34\xf6\x24\x89\xdc\xb2\x8e\xcd\x05\x1b\x7b\x53\x6c\x2e\xf0\x58\x2b\xdd\xd8\x9b\x6a\x77\xa9\x47\x55\xc4\xb1\x37\xd1\x90\xa2\x8f\xbd\x89\xfa\x0b\x51\xf7\x26\x19\xa0\x8d\xf4\xef\xe6\xe0\xc2\x91\x65\x1b\x56\x05\x4b\xb5\xbe\xc5\x24\xcb\x16\x5e\x56\xb2\x6c\x7b\xe7\xde\xde\x62\x59\x99\x60\xd6\x7b\x0e\x4d\x45\xc9\x0d\xce\xac\x50\x25\xd8\x1c\xbd\xd5\xb7\xe2\x80\x65\xc1\x69\x59\x61\x52\xa7\x96\x55\xaf\xd8\x41\x27\x07\x06\x49\x12\xb2\x21\xa9\xd0\x10\x18\x86\x2c\x5c\xbb\xbd\x89\x5a\x04\x09\x7d\x07\xf6\xbb\xb1\x75\xc7\xfa\x33\xcf\xd0\x40\x42\xd5\xfa\x85\x13\xf6\xe8\xfd\x33\x04\x1e\xaa\x16\x1e\x7e\xd8\x83\x28\x04\x2a\x06\x07\x21\xaa\x36\x60\xed\x8c\xe4\x39\xaa\xba\xe1\xce\x66\x34\x55\x24\xe6\x1e\xa3\x65\x39\x92\xec\x0e\x94\x01\x73\xd5\xe9\xb2\x48\x3d\x47\x1f\x62\xe2\xd5\x03\x29\x0b\xd6\x4f\xa6\xd1\x3b\x34\x03\xfb\x2d\x35\xff\x7f\x36\x9d\x1e\x0c\xc9\x90\xd4\x6b\x0c\x56\x97\xe5\xbc\x04\xe2\xca\x97\x4d\xf2\xf3\x17\xac\x76\xec\x0d\xed\x7b\x79\xff\x04\x86\x00\xed\x75\xa5\x02\x27\xae\x8d\xc6\xa5\xa0\x52\x42\x90\xf7\xa2\x6a\x02\x4b\x80\x23\xbd\x54\x75\xe6\x89\xd4\x93\x65\xaf\x32\xc8\x65\x6b\xab\xba\x59\x96\x46\xee\x3b\xbb\xaa\x31\x13\x7c\x1d\xbf\x56\xb5\x91\x71\x9a\x32\x01\x3b\x80\x9f\xa1\x04\x2f\x48\xd2\xcb\xb8\xa2\x1a\x18\x95\xa4\x48\xea\x04\x18\xe5\xa4\x77\x05\xe3\xb2\x0d\xdc\x0a\x68\xe0\x76\x40\xb0\x25\x60\x46\x6f\xfa\xea\xef\xc3\xf7\x86\x6c\xe5\x6d\xdd\xff\xdd\xba\x53\x50\xd1\x31\x4b\xcc\xa3\x35\xd9\x84\x5a\x79\xab\x0d\xc0\xc9\xcd\x64\x48\xce\xfa\x90\x53\x21\x88\x42\x44\x25\xf9\xa6\x1f\x93\x31\x8d\x2d\x6b\xe5\x83\xb7\xdf\x1c\xf5\x57\xd7\x46\xe8\xdb\xc8\x9c\x47\x1f\x1c\x4c\x5b\xab\x7a\x21\x1c\x50\x0a\x65\xfc\x1d\xa0\x79\x23\x08\x99\x4d\xa0\x92\x42\x5a\x33\x74\x9e\xdf\x5c\xa3\xad\x5a\xd3\x27\x9d\xa6\x83\x59\xa2\x67\x3b\x98\x25\x0e\x66\x09\xdd\x46\x9b\x25\x9c\xab\xde\x30\xdf\x41\x56\x89\xaa\x69\xc3\x45\x0c\xd6\xf6\x8a\x01\x67\xc7\x04\x15\x38\xf8\x9b\xf2\x2c\x1a\x4b\x45\xaf\x02\xfb\xaa\xb9\x90\x96\xc7\xc7\xf3\xf9\xf1\xb1\xb1\x77\xe8\x83\x5e\x88\xe5\xec\x8f\xbd\xc9\x92\x34\x62\x31\xd1\xd5\x73\x97\x34\xe7\x02\x84\xee\x52\xf1\x57\x73\xd3\x9b\x2e\xcc\xe5\xc6\x8c\xdd\xf5\x55\x40\xdf\x87\x6d\xd1\x01\x1c\xda\x44\xc9\x7c\x3f\x89\x70\x59\x8a\x94\x16\xdc\x26\x20\xd9\xa2\xde\x2a\xb8\x64\x5a\xb6\x2c\xa3\x79\x54\x25\xe4\x01\x86\xb0\x18\xe4\x39\xc2\x05\x47\x27\x8a\xc8\x3c\xca\x8a\x33\x4d\x70\xae\x0a\x2d\xf7\xe7\x5a\x86\xa8\x24\x56\xf9\x8a\xa6\x78\xda\xbf\xab\x39\x41\x51\x91\xe7\x24\x15\xc9\xee\x4b\x93\x7c\x83\x0a\x6e\xec\xb7\x31\x82\xaf\xdd\x2b\x21\x29\x12\x4d\xad\x96\x36\x61\xc1\x98\xc1\x3c\x18\x5e\xd4\xbc\xa9\x2d\x2d\xa8\x3e\x3f\xb3\x26\x2b\xf8\x95\xa4\xdb\x41\x14\xb7\x38\xf7\x26\x35\x34\xb5\x51\xb2\x6e\x4c\xb7\x94\x33\x6f\x32\x56\xe3\xab\xfb\x56\x37\xaa\xc1\xad\x59\x21\xb2\xa2\xbf\xb1\x18\xd9\x7b\xd5\xb0\x61\x53\x6d\xc5\x72\x89\xfe\xc7\x18\x95\x51\x73\x4a\xa5\xf8\xc6\x8f\x8b\xb3\xdf\x5e\x6c\x9d\xf2\xa6\x16\x54\xbb\xbc\xa9\xf5\xab\x67\xde\x45\x61\xe0\x76\x1c\x51\xf7\xbc\xad\x99\xad\x33\x9e\x7f\x94\x62\xd7\x40\x5e\xa8\x1a\xa0\x63\xca\xeb\xf4\x09\x0e\xbb\x8a\x90\x9d\xcc\x96\xac\x8b\xf6\x1d\x42\xc3\x5e\x60\x68\x98\x46\x01\x39\xc4\x85\xfd\x62\xe3\xc2\xee\x74\x35\xcc\xc6\xa0\x30\x15\xea\xd5\x83\x68\x40\x50\x18\xe8\x39\x3d\x48\x06\x04\x85\x81\x83\xb8\xd7\x41\x3a\x04\x85\x1d\x82\xc2\x0e\x41\x61\xfd\xfa\x7e\xb0\xbe\x1e\xac\xaf\x07\xeb\x6b\x70\x3b\x04\x85\x1d\x82\xc2\x0e\x41\x61\xcd\xed\xcb\x0d\x0a\xd3\x0a\x53\x2f\xa1\x58\x47\x84\x3d\x59\x40\x98\x2e\xe9\x7d\x1e\x45\xac\x48\xc5\x07\x76\x4f\x02\x63\x00\x82\x94\xf9\x3d\xda\x81\xe3\x78\x92\x00\xb1\x7e\xc2\x66\x0f\xb1\xb1\xbf\xc0\x88\x8b\x98\x4a\x75\x7c\xe0\xe6\x3b\xd7\xaf\x1b\xcd\x57\x5e\x79\x69\x4c\x62\x4b\xb7\xc7\x06\xd4\x2c\x48\xc8\xd5\x9a\xa3\x73\x94\x93\x88\x66\x54\x32\x66\x80\xff\x81\xdf\xfb\xaa\x65\xb6\xc6\x27\x15\x9c\x24\x4b\x5d\xff\x30\x75\x0a\x89\x97\xb2\x57\x7f\xad\xd4\x0c\xb2\xd2\x75\x25\x87\x30\x53\xf6\xae\x07\x55\x5d\xc3\x3d\x27\x7f\x33\xa2\x91\x9e\x8b\x0f\xee\xb7\xe2\x50\x84\xb4\xb2\x69\x63\x81\x33\x68\xdd\x61\x9c\xd1\x50\x2c\x3b\x4b\xab\x3f\x83\x23\x9f\x33\x9a\xc3\x11\xbd\x23\x11\x4b\xe3\xa1\x26\xaa\xab\x3a\x1d\xb3\xeb\xb4\xf7\xaa\xd7\x12\xc6\x85\x22\x05\x09\xbe\x38\xa1\x31\x15\x3b\x1b\x3b\xa4\xd8\x07\xc2\x8a\x7f\xf4\x9a\x69\xb5\x79\x79\xb9\x7c\x08\x67\x59\xce\x70\xb4\x26\xdc\x99\x89\x3e\xf7\x10\x48\x50\x0a\x7a\xc4\xe6\x22\x27\xc5\x8a\xa6\x4a\xca\x07\xea\x52\x64\x0b\x00\x7b\x28\x5b\xce\x84\x09\x76\xac\x0d\xd7\xdd\x75\xfa\xb3\x7d\x8d\x55\xca\x64\x21\xf2\x1d\x40\x6b\x31\xf7\x63\x6a\x4e\x02\x00\x72\xaa\xe3\xd7\xaf\x71\xc4\x92\xd8\xe0\xa5\xfe\xf1\x6b\x94\x91\x3c\xd2\x1c\xa2\x9f\x83\x15\xf0\x32\x05\x43\x89\x14\x75\x59\x6e\x50\x59\x1b\x3e\xd3\x83\xe8\xef\xbe\x45\x6b\x56\xe4\x7c\xee\x82\x73\x7c\x03\xbf\x29\xa3\x90\xba\x5a\xfb\x18\xd4\x04\x4a\x08\xe6\x02\x7d\xf3\x35\xda\xd0\xb4\x90\x12\x55\xcf\xa3\xda\x57\x0b\x71\xf4\x8f\x3f\x7c\x1b\xf8\x56\x3f\xcd\x63\x3f\x8e\x4c\x9f\xe3\x4c\x55\x1d\xd3\x0a\x48\x2f\xa5\x1d\xca\x22\xc0\xee\x55\xb5\x04\xab\xd1\x1e\xe6\x3a\xef\xa9\xcc\xe8\xdd\x90\x0a\x36\x31\x7f\xfc\xb9\x60\x8b\x9d\x08\x07\x36\xfa\x0f\xf5\x7c\x15\xd1\xc8\xfc\xb8\x87\x20\xdb\xd9\xd7\xfd\x62\x97\x25\x80\x6c\xc7\x8b\x13\x57\xd6\x5d\x51\x2e\x3a\x0b\xb7\xce\xfc\x26\xfd\x50\x61\x67\x95\xb3\xc2\x8b\x22\x50\x99\x6e\xb0\x27\x18\xfd\x55\x73\x5c\x1c\x45\x84\xc3\x81\xbe\xb4\x15\xec\xbd\x9b\x22\x65\xea\xeb\x9e\x07\x9f\x11\x38\xde\x6c\xa2\x40\x07\xca\x63\x02\xb9\x06\x4d\x52\x88\x7e\x61\xb6\x57\xcf\x59\x52\x2f\x55\xcf\x18\xa7\xe9\x0a\x4a\x1d\xa2\x4d\x91\x08\x9a\x05\xe4\x46\x98\x19\xb5\x04\xf5\xf5\xea\x3a\x45\xb0\x63\x25\xc7\xfe\x29\x92\x87\x5a\x81\x87\x83\x73\xed\xc4\xf4\x05\x91\x54\x00\x08\x0d\x44\x9b\x93\x0c\xe7\xd8\x2c\x8b\x97\x66\xc4\x36\x1b\xcc\x4f\xb5\x7f\x06\x43\x04\x94\xe2\xc2\xf2\x42\xcd\x71\x62\xa7\xd1\x8d\x07\x99\x6a\x23\x0b\x92\xe2\xd4\xeb\xbc\xad\x1a\xa7\xe0\x15\xc4\x1e\x52\x53\x06\x47\x55\x6e\xee\xb9\x83\xb5\xe8\xfe\x1d\x8e\xee\x49\x1a\xa3\x8f\xdc\xec\xe3\x78\x97\xe2\x8d\x86\x55\xb7\x85\xd5\x49\x6c\xe8\x7b\x09\xdb\x88\x19\x85\x1b\xa4\x10\x7d\x0c\x88\x99\x92\xd7\xa6\x9a\xbd\x82\xf7\xc4\x18\xfe\xc8\xa5\x30\xd3\xcd\xcf\x82\xac\xe4\x9c\xe4\x74\x1b\x11\x23\x29\xca\x8e\x4c\x35\xa8\xad\x17\xeb\x6f\x6f\x58\x1a\xe7\x8f\x3a\xa7\x09\xae\x37\xeb\x64\x06\x94\x75\x9c\x48\x16\xe5\x97\x8d\x0d\x66\x54\x75\x43\xc9\x15\x9c\xac\x38\x78\xbe\x08\x07\x08\x3b\xbe\xfd\xee\xb2\xca\x8c\x6e\x71\xcc\x38\xfa\x2e\x61\xd1\x3d\xba\x24\x20\xb2\xfb\xab\xea\xd7\x91\xe5\x83\x0a\x5d\x77\x52\xf4\x15\xdb\xcb\x17\xf1\x73\x94\xda\xdb\xe0\x55\xd7\x21\x9d\xa1\x0d\x4b\xa9\x60\xf9\x14\x50\x65\x87\xc2\x6e\xff\x34\x85\xdd\xf2\x85\xdf\x6a\xf0\xa5\x96\x75\x93\x47\xa2\x67\x05\xd4\x35\x41\x39\xb0\x19\x78\xd9\xd4\xf2\x08\xaf\xb4\x59\x39\xfc\xbf\x5a\xb3\x87\x99\x60\xb3\x82\x93\x19\xf5\xc6\x84\x05\x8f\xeb\x9e\xec\x20\x68\xae\xd7\xc8\x7e\x54\x2f\x55\x54\x4d\xc1\xc0\xe2\x0d\xbf\x4b\x21\xe7\xf6\xbb\x4b\x79\x53\x86\x23\x5a\x53\x8e\x5e\x11\x11\xbd\x8a\x48\xb6\x7e\xa5\xbb\xf5\xe2\xa6\xcb\xf0\xbd\x7e\xf3\x75\x8e\x22\x96\x24\x1a\x67\x8e\x2d\xd1\x05\xc9\xd6\x96\x54\x2f\xf7\xd0\xa3\xcf\xc1\x73\x94\xf0\xca\x18\xeb\x57\x56\xc8\x39\x5a\xf2\x5d\x7d\xb2\x9c\x8d\x94\x2f\xe2\x49\x6b\xfa\x3f\xc5\xd6\x7a\x84\xaa\x22\xc1\xb8\xb5\x6d\xd0\xb4\x0d\x95\xcc\x5e\xd4\x6e\x7d\xbc\x8a\x69\xc7\x77\xe6\x35\x88\xb7\x73\xdc\xba\xbd\x0a\xa0\x99\xcf\x57\x58\x22\xba\x5e\x2a\xad\x28\x26\x31\x62\x5b\x92\xe7\x34\x26\xdc\xb0\xe2\x5e\x1c\x33\xa5\xc9\xd3\xf2\xc8\x43\x2d\xb7\xd6\xf6\x65\xd4\x72\xeb\xad\xef\x3a\xcc\x56\xbe\xbb\xcf\x6c\x71\xbc\xa1\x01\x69\xc5\x2f\xe8\x26\xe7\x11\x4e\xc8\xf5\xfb\x60\xf5\xf1\x4e\x3d\x5f\xd5\x20\xcd\x8f\x4e\xc9\x8a\x11\x70\xf8\x3f\xda\x7d\x8a\x52\x16\x77\x7b\x26\x26\xd5\xf5\x56\x58\x90\x87\xce\x2b\x7f\x56\xb2\xd0\xee\xa7\x7c\x85\x25\x0e\xc5\x2f\xea\x0a\x9c\x73\x8a\x14\xae\xfe\x54\xc2\x84\x5e\xd5\x7e\x46\x41\x33\xc4\xb2\x4e\x96\x0a\x80\xd1\x1b\xfd\xfc\xe6\x1a\xfd\xa0\xe8\x4e\x57\x65\x23\x67\x42\xc9\xc5\x97\x6c\x83\x69\xcf\x22\xcd\x4e\x49\x23\xb7\xa3\x37\x96\x28\x52\x54\xbd\xcb\xe2\x54\x9e\x5e\xd2\x55\x21\xf5\x68\xad\xdb\x1e\x0a\x13\x78\x86\xfe\x78\x22\x58\x29\x81\x39\x36\x48\x93\xab\x61\xa5\x2a\xef\xd0\xcd\xae\x80\xcb\xcb\x86\x93\x20\x4e\x52\x4e\xc1\x37\xea\x84\x3d\x81\x68\x26\xd6\x01\xde\x28\x9b\x84\xa1\xc4\xb8\x33\xf4\x86\xad\x68\x6a\xb8\x03\xd3\xe1\x04\x4b\x4c\x93\xb0\x69\x3c\xc8\x55\xad\xed\xcb\x90\xab\x38\x4f\xae\x52\xbc\x48\xfc\x91\x68\xd5\x8b\x2b\xc1\x10\xd5\x41\xe0\xdd\x57\x31\xe5\xf2\xbf\xe8\xee\xee\x0d\x78\x95\x8a\x34\x54\xcf\x00\xbf\x8b\x66\xcf\x16\x1c\x47\x31\x8d\xe9\xce\xb1\xe2\x89\xbd\xab\x4a\x5c\xa7\xb1\x1c\x06\xe1\x95\xc0\x4a\x4d\x4d\xd5\xed\x08\x75\x39\xe9\xb8\xae\x05\x41\x1f\xd6\x34\xba\xbf\x71\x9c\x4b\x2c\x97\xbf\xa5\xce\x4f\xf6\x82\x0d\x39\xce\xf5\x77\xa7\x62\xfc\x7a\x98\x37\x7d\x8d\x1c\x1f\x9c\x1b\xed\x4e\x4f\x95\x24\x82\x30\xe7\x2c\xa2\xe1\xde\x49\x30\xd1\x95\x57\x62\x0c\x57\xe2\x74\xc3\x03\x29\x68\xd4\xbd\x6d\x36\x82\x16\xe0\x30\x77\xee\xe1\x10\x1f\xa4\x9e\xa5\xc9\x86\xa4\xb6\x62\xef\x7a\x8b\x1f\x2a\x15\x16\x8d\x6b\x50\x39\xcc\xac\x43\x2c\xb0\xbc\x89\x59\x78\x23\xd3\xea\x02\xba\xb5\xa5\x77\x2b\x2d\xfa\x4f\x0e\xa4\x22\x4f\x32\x49\xfe\x74\xe1\x26\x5b\x4a\x2d\x1a\x40\xfd\xa6\xdd\x68\x70\xa8\x33\x96\x15\x09\xf6\xb8\x87\xdd\xe2\x92\x63\xfd\x15\xaa\x0f\x13\xb8\xd5\x1e\xbb\x2c\x4f\x4b\x22\x56\xad\x42\x8f\x5f\xcc\xad\x57\xf0\x09\xa9\xd0\x13\x6a\x8e\x82\x0e\x7d\xfd\x87\x6f\xbf\x6d\xaa\xe9\x53\xa9\xd9\xe3\x97\x5d\x02\x6b\xfa\xd4\x12\xaa\xc2\xee\xc8\xce\x9a\x3e\xf5\x9a\x3d\xfe\x29\x0d\xa8\xe9\xd3\x33\x01\xea\x71\x8a\xf6\x04\x19\xed\x7b\x64\xb1\x9b\xdc\xf4\x20\x76\xd6\x95\xbb\xde\x9a\x91\x1e\xc0\xfa\x2b\x19\xeb\x21\x79\xe8\x01\x8e\x44\xc8\x53\x9f\x34\xfb\xbc\x47\xce\x79\x25\x93\xdc\x4b\xb8\x2b\xd3\xbc\x35\x7f\x3c\x5c\xb5\x01\x5a\x41\x59\xe3\x5e\x9a\xc1\x05\x44\x82\xe3\x7a\x83\x32\xc4\xab\x79\xdf\x61\xfc\x21\x24\xcb\xec\x71\x8b\x52\x75\x64\x7e\xdb\x6c\xee\x00\xd5\x25\x34\xdf\xbb\x57\xca\x4d\x78\xba\x4d\x58\x46\x77\x60\x42\x4e\xbf\x64\x9c\xe0\x9c\xed\x49\x32\xb5\x7b\x66\x71\x84\x67\x65\xf7\x11\x01\x82\x8c\x16\xaa\x35\x66\x60\xb7\x64\x54\x07\x92\xac\xe6\x5d\x7b\xf2\xa8\x03\x69\x42\xb6\x75\x50\xf6\xb4\xb9\xcc\x03\x09\x7b\xae\xfc\xca\x95\x1e\x4c\x72\x8a\x8b\x5f\xd3\xea\x9d\x69\xd0\x37\xcb\x39\x3c\xc3\x20\x28\xa3\xb9\x27\x0c\x64\x7b\x1e\xf3\x7e\x5e\x72\x20\xc9\xb7\x0d\xec\xbf\x3d\x1b\x39\x90\xa8\x03\x15\x32\x28\x07\x39\x98\x2d\x84\xe6\xac\x86\x67\xaa\xda\x8a\x04\xde\x8e\xf6\x4b\x50\xed\x6b\xf1\xed\xad\x42\x57\xec\x8f\x5a\x43\x34\xeb\xa9\x22\x2c\x2d\x2a\xb8\xff\x5a\x03\xde\xf8\x04\x3a\x22\x0a\x56\x9b\x15\x69\xd6\x79\x87\x55\x57\x59\xbd\xf1\xfe\xae\xe6\x7a\xb4\x3f\x1b\xc9\x57\x7b\x15\xbb\x5d\x8f\x8f\xee\x71\x3c\x38\xf8\xbe\x94\xea\xf6\x07\x6f\xd4\x70\x6f\x14\xaf\x60\x58\x1a\x3b\x96\x92\xc4\x42\x1c\x52\x6c\xa1\x2b\x61\x28\xa6\x6d\xcf\xf2\xf9\xcd\x35\x8a\x72\x02\x89\xc5\x38\xe1\x73\x34\x00\xd1\xc6\xd8\xfd\x41\xa6\xe3\x56\xf3\xc4\x42\x90\x4d\x26\x42\x37\xd0\xc1\x19\xd5\xda\xbe\x0c\x67\xd4\x40\x0b\xf6\x27\xfb\x9a\xb1\x7f\xac\x8b\x0d\x4e\x67\xf2\x94\x83\x5b\x4a\x9b\xb7\xc3\x4c\xd8\xb5\x4b\x6a\x8e\x4c\x8e\x09\xcc\x36\xe4\x59\x41\xaa\x9b\x2a\x3c\x1f\xa4\x9c\x03\x8e\x99\x15\x01\x1e\xc1\xe0\x0f\x74\x07\xce\x99\x2a\x56\x52\xe3\x0e\x11\xcb\x82\x67\x4c\x5f\xe6\x7a\xa0\x76\xfe\x0c\x23\x70\x2a\xa2\xb8\x56\x9d\x10\xd2\x4a\x84\xba\x81\x04\xd5\x92\x4a\x05\xd7\x4a\x03\x55\xe1\x24\x61\x0f\x01\x89\x86\x6b\x52\x11\x20\xe4\xbe\x90\x63\xd5\x39\xea\x0b\x82\x36\x34\xcf\x59\xae\x1d\x15\x01\x66\xc2\x72\xbb\x40\x30\x86\xd4\xf8\x48\xae\xd4\xa0\x5c\xfb\xe6\xef\x88\x70\xa6\x3b\x44\x00\xc4\xa9\x4a\x38\x92\xff\x36\x81\x96\xaa\xda\x95\xe6\x93\x0b\xb2\xc6\x5b\xca\x8a\x1c\xa8\x87\x90\x3c\xd2\xaf\xca\xab\x1b\xed\x58\x61\x8b\xd0\x17\x90\x7b\x60\x67\x37\xb8\x9a\xbd\xb3\xce\xef\xca\x97\x41\x49\x8d\x99\xb1\xc4\xcd\xc8\x67\xca\x45\xff\xb9\x34\x4b\x6c\xe0\xf6\xa7\x38\x31\x5b\x9e\xc9\x0b\xfc\x93\x37\xc7\xac\x7a\x4e\xdc\xb7\xaa\xe2\xec\xf6\x0e\xfe\x34\x46\x98\xd5\xd8\x0a\x5c\x89\x70\x3a\xf9\x63\xbc\x40\x1b\x16\x42\xa7\xfa\xed\xa9\xf6\x73\x90\x8d\xbf\x14\xd9\xd8\x3a\xec\x13\x1a\xed\xae\x2f\xfb\x49\x89\xd6\x51\x2f\x5f\x46\xdf\x61\x4e\x62\xf4\x16\xa7\x78\xa5\x0c\x11\x27\x77\x37\xdf\xbd\xf5\x57\x04\xc8\x72\x06\x46\x95\xeb\xcb\x06\x97\xaf\xbd\x5a\xd5\x47\xde\x4d\x95\x50\xb9\x37\xf6\xde\xf2\xc3\xc4\xa3\x9f\x2c\x55\x14\xd9\x3b\x3e\xa4\x5c\xd3\x3e\xa4\x86\x72\xbf\x1b\xc4\x1f\x5e\x67\x58\xdb\x4d\x7c\x3f\xbc\x9b\x34\xe5\x02\x27\xc9\x4d\x82\xd3\xf3\x2c\xcb\xd9\xb6\xc9\x12\x54\x05\x8a\xd2\x8f\x19\x21\x4d\x45\xb6\x99\x1f\x33\x35\xf9\x10\x55\x93\xa2\xeb\x92\x7a\xd3\x54\x5e\x0b\x6b\x02\x62\x29\x08\xdb\x47\xe7\x85\x60\x1b\x2c\x68\x74\x84\x58\x8e\x8e\xde\xe2\xb4\xc0\x49\x43\x64\x6a\xc7\x90\x9a\xc5\xfd\x8e\x17\xda\xa0\xd7\xbd\xaf\x74\xc8\x6c\x5d\xef\x0a\x9c\x4b\x2e\x76\x71\xf7\x29\xf8\x3d\x2e\xb0\x28\x6a\xbc\xbb\xf5\x16\x69\xbe\x37\x66\x28\xc1\x5c\x7c\xcc\xe2\x3d\x67\x7d\xfb\xe5\x10\x61\x81\x13\xb6\xfa\x77\x82\x93\xa6\x9d\x5b\xd9\x17\x17\xee\xb3\xc6\x18\xaa\xb6\xc8\x5d\xb1\xb0\x0f\x1e\x73\x24\x15\xa2\x76\x9c\x9f\x9c\x24\x64\x8b\x53\x61\x08\xde\xa9\x9a\x0a\xc7\x7a\x0e\xe6\x72\xd7\x50\xc8\x06\x00\x86\x1d\x13\x41\xf2\x0d\x4d\xab\x5f\xb9\x83\x67\x2f\x58\x1a\xd3\x36\xe3\x3c\x18\x93\x15\x8d\xea\x97\xda\x36\x5b\xb3\xc3\xad\xd5\xc5\x56\xe5\x4d\x4e\xdf\xaa\x13\xa5\x1e\x5b\x68\x89\x7d\xad\x7e\x64\xcb\x16\x1f\x5b\xa5\xa7\x7b\x73\x8b\xee\x53\xf6\xc0\x15\x7a\x5e\xd3\x79\xf3\xc8\x1d\x5d\xf2\xc6\xcc\xec\x05\xf5\xe9\xe6\x68\xfc\x99\xee\x7f\x93\x0d\xa6\x7d\xfb\xa9\xe6\x93\x50\xea\x9f\x6f\xe3\xa3\x4d\x7b\xd2\xbe\xa4\x00\x06\xac\xf7\x5f\x79\x36\x2b\x0f\xb5\x71\xfc\x00\x91\x2d\x44\xc6\x0a\xab\x92\x58\xe5\xb7\x65\xf5\xbc\x3d\x73\x84\x57\xc6\xf4\x5c\x4d\x41\x45\x04\xab\x66\x91\x6b\x1d\x10\x9d\x6b\x65\x0b\xa3\x8c\x12\x05\x9c\x87\x53\x3d\x41\x70\xab\x10\xdc\x2d\x43\xab\x17\xe4\xad\x26\x55\x71\x78\xef\x4c\xc7\xda\x28\x67\x87\x8e\xcb\x32\x6e\x15\xac\xc0\xdd\x3a\x69\xfe\xef\xbb\xf7\xef\x5e\xfd\xc0\x74\xb0\x87\x06\xc6\x90\x7c\x03\x24\x80\x33\xc4\x8b\x68\x8d\x30\x97\x43\x92\x1b\x5d\x72\x09\x32\xdf\xe0\x94\x2e\x09\x17\x73\x5b\xc9\x87\xff\xf4\xbb\xbf\x76\x5f\xfd\xdf\xb3\x1c\xe9\xfc\xa1\x33\x83\x38\xa6\xc7\x5e\xee\x2e\xca\xd5\x04\x59\xba\x9d\x24\xad\x85\x21\x63\xb1\x9e\x88\x07\x98\x00\x81\xef\xc1\xc9\x6a\x7c\xa5\x09\xbd\x27\xaf\xd1\x91\x14\x3d\x9d\x2e\xff\x97\xbc\xf6\xfe\xbb\x3b\xe9\xfe\xe4\x01\x04\x87\x23\xf9\xe8\x91\xea\xa8\x8d\x69\x77\x43\x22\x2d\x55\x90\x3d\x3a\x49\x8a\x9c\xae\x56\x04\x84\xe7\x35\x41\x90\x4c\x7f\xaa\x51\xd8\x52\xe6\x10\x32\xd1\x30\x61\x86\x83\xfa\xe0\x7e\xfa\xdd\x5f\x8f\xd0\x49\x49\x0d\x64\x51\x9a\xc6\xe4\x33\xfa\x9d\x72\xd1\x50\x2e\xe7\xed\xb4\x7b\xd5\xc0\xc6\xc0\x77\xa9\xc0\x9f\x65\x5f\xa2\x35\xe3\x24\x55\x66\x20\xc1\xd0\x1a\x6f\x09\xe2\x6c\x43\xd0\x03\x49\x92\x99\x76\x4a\xa1\xee\xf4\x24\xd8\xc7\x66\xc9\x01\x04\x08\x65\x38\x17\x95\xe3\x30\xd7\x76\x3b\xe8\xa5\xdc\x7a\xab\x6e\x25\x5a\x87\xc0\x2c\x69\x8a\x13\x1d\xd9\x05\xd0\xe5\x72\x4f\x03\xc0\x83\xda\x68\x82\xa1\x68\x8d\xd3\x15\xd1\x4e\xaa\x6e\xc5\xae\x10\x45\x4e\x3a\x9d\xc0\x41\x1c\xe3\x9e\xa6\x3d\x80\x4f\x7e\xa4\x69\x3d\xe6\xaa\xd9\x86\xba\xa2\xc2\xa4\xe1\xe9\xc0\x73\xb1\x7b\x25\xd7\x3b\xa7\x8b\x42\xb0\x9c\xbf\x8a\xc9\x96\x24\xaf\x38\x5d\xcd\x70\x1e\xad\xa9\x20\x91\x1c\xd0\x2b\x9c\xd1\x59\xc4\x52\xb9\xef\x00\xad\x6a\x13\xff\x4a\x8e\x83\xcf\x64\x47\x3b\x2b\x55\x05\x0d\xd7\x67\x3a\x7e\x56\x93\xf1\x24\xa3\xf3\xda\x1c\xf7\x87\xa8\xec\x77\x4f\x30\x4e\x30\x46\xbd\x1a\x3d\x4c\x53\x08\xa9\xef\xcd\x7b\xac\xeb\x85\x45\x75\x0a\xf2\xe8\x29\xb4\x2d\x38\x99\x96\xe3\xfb\x4e\xf5\x06\xc7\xea\xba\xc0\xe9\xee\xd1\x8f\x81\x9c\x68\x28\xe3\x17\xed\x66\x40\x82\x25\x33\x9c\xc6\xf2\xdf\x2a\x63\x34\xda\x8d\x9e\xd9\x82\xf6\x60\x06\x1f\xaf\x2f\x9f\xe6\x70\x14\x74\xe4\xc9\xd7\x52\x6c\x90\x88\xa9\xc4\x78\x08\x75\x14\x79\x41\x8c\x30\x50\x15\xd4\x29\x37\x34\xff\x57\xbb\x2c\x06\x3e\x4d\x8b\x36\xdc\x2d\x88\x76\x79\x1a\x1d\x39\x3b\x68\x04\x6f\xca\xe7\x5d\xcb\x28\xc4\x99\x62\x2e\x34\xc0\xaa\x41\x24\xaa\x0c\x4c\x0d\xbe\x75\x48\xea\x7a\x6a\xbb\xea\x03\x76\x98\x89\x2d\x92\x9d\x9b\x35\xe0\x5a\x46\x56\xc1\xf3\x29\xa7\xf6\x41\xa5\x02\x24\x94\x5b\x64\x51\xa9\x06\x72\x81\xf0\x16\xd3\x04\xfc\x4c\x6c\xc1\x49\xbe\xc5\x6d\x8a\xa3\x02\x27\xc7\x75\xad\x56\xd7\xcc\x54\xe2\xe6\xa3\xeb\x90\x66\x3c\xfb\x2b\x56\x1d\x4c\xe3\xc4\xba\x03\x54\xf9\x22\xb5\xb1\xb4\x8c\x61\xa4\x06\xa9\x14\xf8\xc6\x3f\xb5\x80\x5b\xf9\x54\x2a\xb9\x3f\xff\x9d\xe0\x5c\x2c\x08\x16\x1f\x68\xfb\x5d\xbd\xb7\xe1\x2b\x6f\x19\x53\x56\xb9\xdd\x1f\x08\x5a\x31\x21\x45\xb8\x02\x4e\x46\xeb\x16\x07\xb9\x5c\xc1\x17\xda\xcd\xf8\x78\xfb\xbd\x1c\xf5\x87\x1c\x43\x06\x29\x4b\x7b\x0d\xbb\xfa\xda\xfe\xb8\xb5\xf4\xdf\x39\x0e\x29\xf4\x03\x15\x00\xc7\x02\xcb\x9d\x5a\x59\xe5\xf3\xea\x2a\x29\x33\xd9\x14\x6c\x08\xe7\x1d\x90\x58\xd5\x80\x66\xf5\xac\x3a\xf8\x35\x97\xf2\xc6\xfc\x4d\xe5\x08\x76\xdd\x75\x31\x11\x98\x26\xda\xba\xa2\xa7\xcc\xce\x66\x37\xb7\xee\x18\x70\x4e\x30\x6f\x17\x49\xea\xe8\xaf\x9c\xa5\x6a\x18\x2c\x25\xb3\x07\x96\xc7\xe8\x02\x6f\x48\x72\x81\x39\xd1\x94\xdc\x64\x72\xb5\x8a\xc7\xed\xfe\xd4\xa9\x06\xd1\x64\x9d\x6c\x19\x84\x32\xcc\x99\x8d\xa7\xf7\x4d\xa9\x76\xaa\x2e\x9f\x19\x73\xf0\x87\xbc\xe8\xa8\x25\xf4\xbd\xbc\x31\xcf\xd0\xc7\xf4\x3e\x65\x0f\xc3\x7b\x2f\x3a\x3c\x5e\xd5\x10\xd4\x5d\x66\x8f\x8c\x01\xfe\xab\x98\xdf\xec\x00\x06\xf4\x45\x5f\x1f\x8d\x46\xe1\xea\x55\x66\x1f\x34\x7d\x91\xff\xdc\x33\x05\x4a\x85\x38\x67\xab\x9c\x70\xde\x3c\xf0\x26\x28\xec\x30\x47\xc1\x0f\x24\xd5\x79\xe6\x9e\xae\x5e\x37\xbd\x63\x7a\x6d\xee\xcb\x55\xf9\x97\xd6\x1a\x45\xfa\xe3\x59\xd2\x20\xf2\x74\x45\x2c\x3b\x9d\x6e\x34\x19\xb6\xf5\xb6\xd9\x54\xe8\xdc\xaf\xce\xb3\x4d\x53\x2b\x85\xa5\x2e\x0b\xb8\x19\xfb\xc5\xdd\xa7\xb6\x45\x68\xb9\x63\xbb\x6f\x44\x9f\x79\x71\x9c\x61\xd1\x73\x92\x3c\xc6\xc4\xe1\x66\xc4\xf6\x08\x96\x21\x06\x44\x63\x24\x6c\xbb\x7f\x1e\xcf\x74\x38\xcc\x68\xd8\x1d\x76\xf1\x38\xe6\xc2\x61\x86\xc2\xd2\x18\xd8\xc6\xfe\xfa\x99\x08\x1b\xcd\x80\x6d\x3d\x0e\x31\x0e\x36\x1b\x00\x5b\x28\xfa\xcd\x82\xad\xa6\xbf\xf6\xdd\xda\x6a\x10\xf4\x18\xfd\x5a\x28\xb6\x99\x02\xbb\xcd\x7d\x9e\x73\xdc\x6e\xe2\xfb\x12\x8c\x7b\x9e\xc1\xb5\x1b\xf4\x5e\xa0\x29\x2f\x60\x2c\x1d\xe6\xbb\x17\x6a\xb8\xf3\x0c\x2a\xc8\x58\xf7\x28\x66\xba\x2f\xc6\x40\xe7\x99\xc1\x56\xa3\xdc\x8b\x33\xc7\xf9\xc5\x4d\x12\xfb\x05\xe2\x6b\xe7\x51\x57\x24\xd6\x42\x16\x04\x78\xe9\x27\x4c\x38\x99\x2b\x8e\x0d\x91\x82\xa5\x20\xea\xe9\xd5\xb1\xee\x56\xb0\x1c\x69\x04\xe1\xc6\xdb\xd3\x68\x75\x95\x8e\xa3\xcb\xab\x9b\xdb\xab\x8b\xf3\x0f\x57\x97\x75\xe9\x75\x7f\xbe\x3b\xa5\xca\x76\xbb\xcd\xcc\x91\x29\x1b\xfe\x28\x19\x71\xc3\xcf\x69\x53\x84\xec\x0c\x15\x45\x83\xff\x76\x9c\x44\x3b\xf8\x2e\x1b\x7c\x4f\xf8\x4e\x5f\xd8\xf1\x93\xa7\x0f\x76\x86\x8a\x99\x94\xd2\xd3\x9a\x25\x31\xd7\xf1\xe8\xe8\xfa\x52\x67\x51\x9c\x21\x9a\x46\x49\x11\xb7\x9b\x26\x3e\x7e\xbc\xbe\xe4\x73\x84\xbe\x23\x11\x2e\x38\xd8\xae\x62\x96\x1e\x0b\xf4\xfe\xdd\x9b\xff\x03\x79\x21\xf0\x84\x16\x12\xa9\xae\xa4\x40\x71\x47\x99\x08\x35\x3a\xa0\xa9\x04\x1b\xe8\x65\x84\x33\xc9\xcb\xb8\xaa\x0d\x28\x40\x4a\x59\x93\x24\x93\x7c\xf3\x9e\x20\x8b\x5c\xdf\xd6\xcf\xeb\x4b\x0e\xef\xa8\x08\x7c\x1d\x5e\xbc\x22\x42\x65\xd5\xb6\x47\x08\x77\xcc\x78\xa7\xad\x7b\x84\x95\xdb\x3d\x67\x0d\x7d\xd2\x76\x8b\x07\xcc\xb5\x7d\xb0\xa1\xe7\x9d\xfb\xc4\x67\xe5\x6a\x33\x0b\xb5\x18\x84\x14\x13\x87\xff\xdb\x33\x04\xc8\x4e\x96\x36\x9e\x46\xee\x22\x18\xe4\x6c\x06\x59\xb0\xdb\x42\xda\x9a\x6a\x60\xed\x59\x7e\x48\x7d\xea\x2b\x9f\xb4\x48\x8a\x5d\x93\xbf\xd7\x0b\x28\x7b\x18\xbf\x06\xef\x8b\xfa\x41\xc5\x81\xba\xbf\x14\x0b\x23\x1a\x58\x26\xa3\x6d\x56\xe8\xbf\xfe\xfb\xab\xaf\xfe\xff\x00\x00\x00\xff\xff\x2a\x39\x44\x18\xcf\x97\x0c\x00") + +func olmManifests0170CrdsYamlBytes() ([]byte, error) { + return bindataRead( + _olmManifests0170CrdsYaml, + "olm-manifests/0.17.0-crds.yaml", + ) +} + +func olmManifests0170CrdsYaml() (*asset, error) { + bytes, err := olmManifests0170CrdsYamlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "olm-manifests/0.17.0-crds.yaml", size: 825295, mode: os.FileMode(420), modTime: time.Unix(1607105037, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _olmManifests0170OlmYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5a\xdd\x6f\x1b\xb9\x11\x7f\xd7\x5f\x31\x10\x0a\xb8\x2d\xb2\xfa\x70\x2c\xdb\xb7\xc0\x01\xe7\xfa\x72\x97\x43\x63\x5b\xb0\x9d\xbe\x14\x45\x41\x71\x47\x2b\xd6\xfc\xd8\x23\xb9\x52\x74\x45\xff\xf7\x82\xfb\xcd\x15\x25\x2b\x3e\xa7\xe9\x43\xf8\x22\x8b\x9c\xe1\x0c\x87\xc3\xf9\xf8\xc9\x51\x14\x0d\x48\xc6\xfe\x86\xda\x30\x25\x63\x58\x4f\x07\x4f\x4c\x26\x31\xdc\x12\x81\x26\x23\x14\x07\x02\x2d\x49\x88\x25\xf1\x00\x40\x12\x81\x31\x28\x2e\x06\x2f\x63\xcc\x50\x13\xab\xb4\x29\xd8\x4b\xfa\x07\xd4\x6b\x46\xf1\x8a\x52\x95\x4b\xdb\xdf\x33\x28\x3c\xaa\xf7\x89\x4c\xc9\x4c\x2a\xe6\x92\xa6\x90\x1e\xd6\x52\x2f\x08\x1d\x91\xdc\xae\x94\x66\xbf\x11\xcb\x94\x1c\x3d\x5d\x9a\x11\x53\xe3\x46\xff\x6b\x9e\x1b\x8b\xfa\x5e\xf1\xd0\x09\xcc\xd6\x58\x14\x31\x55\xd2\x6a\xc5\x39\xea\xb8\xd1\x85\xb3\x25\xd2\x2d\xe5\x18\x09\x22\x49\x8a\x7a\xa0\x73\x8e\x26\x1e\x44\x40\x32\xf6\xb3\x56\x79\x66\x62\xf8\xfb\xf0\xcf\xc3\x7f\x0c\x00\x34\x1a\x95\x6b\x8a\x9d\xa9\x35\xea\x45\xf3\x35\x02\xa9\xe4\x7d\x45\xf4\xf1\xfe\xc3\x5e\xba\xdf\x75\xc2\xbf\x30\x99\x30\x99\x3e\x67\xe6\x45\x49\x16\x39\x93\x6a\xc5\xf1\x1e\x97\x8e\xb2\x3e\xd6\x01\xa9\x03\x80\x5d\xb3\xbe\xc8\x98\x26\x5f\xfc\x0b\xa9\x2d\xec\x19\xf4\x9c\x57\x71\x10\x92\x65\xa6\xb5\xd4\x8f\x98\x71\xb5\x15\x28\xed\x33\x16\xda\xdd\x18\x80\x93\x05\x72\xe3\xe8\x9d\xa5\xb2\x1e\x83\xc9\x90\xba\x35\x63\x35\xb1\x98\x6e\x4b\x3a\xbb\xcd\x30\x86\x7b\xc5\x39\x93\xe9\xc7\x2c\x21\x16\x0b\x5f\xc9\x38\xa3\xc4\xc4\x30\x75\x1c\xc8\x91\x5a\xa5\x4b\x0e\x41\x2c\x5d\x7d\xe8\x88\x0a\x09\x03\xb0\x28\x32\x4e\x2c\x56\x4c\x9d\xc3\xb8\xc1\x3d\xfe\xf0\x0e\x00\xb5\xca\xc5\xdf\x9e\xed\x6f\x8f\x30\xbc\x1b\xee\xa6\x09\x93\xa8\x3b\xb2\xa2\xb0\x39\xeb\x41\x95\x10\x44\x26\x71\x67\x2a\x82\xf1\x82\xc9\x71\x69\xe5\x46\x65\x9d\x1a\x9f\x28\x8a\x9a\x2b\xf1\xe6\xff\xf0\xc7\xbb\xf9\xbb\xfb\xab\xc7\xbb\xfb\x7f\xde\x5e\xdd\xbc\x7b\x98\x5f\x5d\xbf\xfb\x53\x8f\x73\xa3\x99\xc5\x07\x4b\x6c\x6e\xdc\xd9\xbc\xd5\xe1\xb0\xf3\x95\x09\x92\x62\x0c\xbf\xe6\x64\xeb\xde\x58\x73\xfc\xa5\x26\x02\x37\x4a\x3f\x39\x35\x7f\x30\x2b\x72\x3a\x3b\x8f\x13\x7c\xfb\xdd\xf9\x62\x76\x36\x59\x5c\x9e\x9e\x4e\xbf\xbb\x9c\x9e\x4e\xce\xa7\xc9\x24\xb9\x98\xbd\x3d\x3b\x9b\x24\xb3\xf3\xd9\xec\x74\x36\xa1\xe7\xa7\x53\x7a\x31\x7b\x8b\xc9\x34\xa1\xe7\x17\xc9\xf9\x74\x76\x76\x71\x36\x3d\x9f\x5c\xf4\xe5\xce\x73\xce\xe7\x8a\x33\xba\x8d\xe1\x97\xe5\xad\xb2\x73\x8d\x06\x1b\x6b\xbb\x91\x29\x6d\x3d\xbb\xb8\x13\x34\xd7\x30\x57\xda\xc6\x70\x39\xb9\x9c\x3c\x4b\x31\xf5\x28\xea\x37\x20\xd0\x6a\x46\x4d\x6f\x2d\xd3\xca\x2a\xaa\x78\x0c\x8f\xd7\xf3\xce\x1a\x67\x6b\x94\x68\xcc\x5c\xab\x05\xfa\x4a\xad\xac\xcd\x7e\x46\x1b\xf7\x77\x22\x76\x15\xc3\x78\x85\x84\xdb\xd5\x6f\xfd\xc5\x90\xf6\x1a\x49\xc2\xbe\xb4\x10\x8b\x5a\x30\x59\xc4\xb9\x1b\x34\xc6\x5d\x45\x75\x0d\x3f\x11\xce\x17\x84\x3e\x3d\xaa\x0f\x2a\x35\x77\xf2\x9d\xd6\x9e\x3b\xa3\x5c\xb7\xe2\x3d\xb7\x2a\x0d\xba\xeb\x9a\x9e\x3e\x6b\xc2\x73\xfc\x49\x2b\xd1\x3f\xc3\x92\x21\x4f\xaa\xb0\x1c\x58\x99\x17\x47\xac\x9f\xfd\x28\xfc\x30\x02\x1a\xec\x0a\xdf\xfb\x50\xdb\x84\xe6\x31\x69\xfc\x35\x47\xd3\xf7\x41\x00\x9a\xe5\x31\x4c\x27\xa2\x37\x2d\x50\x28\xbd\x8d\x61\x7a\x3e\xb9\x61\x9d\xb5\x81\xf7\x21\x55\x82\x0f\x5e\x18\x74\xe3\x29\x5f\xa0\x96\x68\xb1\x48\x77\xca\xc4\xc0\x99\xcc\x3f\xfd\x9e\x18\x4f\x89\x25\x5c\xa5\x9f\x17\xe7\x77\x98\xbe\x74\xac\x0f\x68\xf9\x82\x78\x1f\xd8\xe5\x4b\xc7\xfc\xa0\xc8\x9a\x6d\x5f\xdc\xaf\x98\x0e\xc6\xfe\x93\x36\xf6\x9f\x78\x0b\x7e\xd2\x88\x20\xa2\x4a\x2e\x59\x2a\x48\xe6\xaa\x09\xd4\xbf\xb8\xb8\xfa\xfd\x81\x70\xde\xd0\xb7\xc7\xd6\x98\x32\x63\xf5\x36\x76\x06\x37\xd6\xdf\x3f\xb7\x8c\x47\x45\xb4\xf6\xe6\xbf\x52\xc6\xf8\x96\xa9\xfc\xb5\x6f\x99\xea\xb8\x4c\xe5\xe5\xaa\xd7\x8d\xf4\x97\xaf\x1b\xe8\x77\xbb\x8d\xa3\xbb\xa3\xdd\xf0\x4f\xd2\x54\x63\x4a\x2c\xba\xce\x27\xc2\x84\xd9\x5e\xbc\xdf\xbf\x5f\xcb\x6a\x55\x44\x12\xc1\x64\x0c\x43\xab\x73\x1c\x7e\x0e\xa3\x13\xd9\xf0\x85\xdb\xc9\xa6\xa7\x1e\x51\xa5\x51\xb9\x0f\xb1\xdb\x61\x9a\x7c\x61\xa8\x66\x99\x93\x64\xfc\x2e\x92\x6a\x24\x16\x87\x6f\x60\x98\x17\x49\xc8\xfd\x95\xb9\x4c\xe3\xfe\x48\x90\xa3\xc5\xa2\x1f\x7d\x81\x54\x5a\x5e\x43\x95\x17\xd6\xe5\x2d\x18\xb7\x6f\x15\xc4\x2b\x5a\x37\xc3\xa4\xb1\x84\xf3\x8c\x93\x92\xe2\x80\xc6\xad\x52\x5f\xf6\xc2\xd7\x0c\x37\x5f\xf3\xc2\x3f\x83\xcf\xa9\xfa\x2a\x8e\xf2\x7a\x57\xf6\x06\x1a\x91\x69\xa1\x84\x7f\x89\x29\x5a\x47\xc2\x99\x29\x3e\x37\x85\xc7\xed\xf8\x59\x46\xe8\x13\x49\xd1\x8c\x8e\xd3\xbe\x22\x17\x44\xb2\xa5\x8b\x45\xa5\x2f\xfb\x73\x63\x46\x95\x3c\x4e\x97\x5e\xe1\x18\xd2\xa1\x2d\x24\xef\xaa\xd5\x42\xf9\x80\x6f\xa5\x5c\x2d\x08\x8f\x5a\x0c\xcc\xaf\x25\x3d\x68\xec\xf5\xa4\x76\x0b\xb4\xbe\x48\x2e\x9a\xd2\xd4\x12\x9d\xa2\x6d\xb0\xbb\xca\xdb\xa3\x20\x46\xb2\x47\x21\xc2\xb3\x15\xe9\x61\x4c\x15\x44\x53\xb1\x06\xd4\xab\xef\xb7\x28\xbe\x9e\xab\xae\x15\x17\xa3\x75\xad\xc5\x64\x34\xbd\x18\x4d\x9a\x03\x24\xcc\x64\x9c\x6c\xcb\xaa\x74\x5e\xee\x0a\x0f\xf5\xb6\x09\x36\x8e\x19\xc3\x3d\x66\x65\xf5\x61\x80\xc8\xc6\x80\xb5\x2a\x60\x57\xc4\x02\x33\x40\xd6\x84\x71\xb2\xe0\x08\x4b\xad\x04\x10\x48\x5d\x51\x00\xd7\xe5\x33\x78\x28\x9c\x0e\x36\x2b\x46\x57\xb0\x61\x9c\x17\x8e\xc8\xd7\x08\x56\x01\x09\x9f\x7f\x34\x00\x10\x4c\xfe\x35\x5f\x60\x63\xcc\xe9\x68\x3a\x1d\xb9\x8c\xfd\x84\xdb\x8d\xd2\x89\xf3\xc7\x93\xbe\xcb\x9e\xbc\x81\x13\xc5\x85\xfb\xa8\x0d\x76\xe2\x1c\x58\x10\xd6\x2d\xae\xeb\xb2\xfa\x1e\x13\x78\x4f\xca\xe2\x0a\x05\x61\xbc\xb8\x33\x69\x56\x6c\x69\x5b\x67\xf8\x41\x63\xb2\x22\xd6\xdd\xde\xa0\xa8\x84\xd6\x2c\xc1\x2a\xcb\xf6\xf7\xe1\x4c\x3e\x79\x22\x76\x2c\x0c\x90\x6b\x1e\x17\x85\x8b\x89\xc7\xe3\x94\xd9\x55\xbe\x28\x3c\x23\x54\x69\xee\x85\xf9\xc6\x56\x23\x8e\x05\x71\xc6\x1b\x67\x4f\xe9\xb8\x3a\x6f\xd4\x78\x48\x15\x74\x6e\x54\x82\x95\x46\x65\x23\x75\xb7\x91\xb7\x5e\x5b\x6b\xf2\xcc\x95\x44\x98\xc4\xe0\xc2\x62\x87\xf4\x81\xc9\x94\xe3\xb1\xd4\x37\x39\xb7\xec\x58\xe2\x2b\xce\xdb\x47\xb4\x87\xb6\x3a\x41\x69\xe9\xa6\x27\x84\xa4\x6d\x44\xa1\xd7\x79\x55\x41\x79\xee\x8a\x39\x53\x04\xe4\x7a\x25\x7a\x61\x57\x06\x50\x25\x89\xfa\x6b\x37\xee\xf6\x4a\xec\x3d\xb8\xee\x33\xe5\x60\x04\x15\x62\x4b\x28\x45\x63\x34\xba\x14\xd5\xad\xbf\xcb\xe8\xdb\x2f\xe7\x8b\x62\xa4\x37\x99\xa2\x7d\x4e\xcf\x1e\x2c\x17\xd4\xa9\x68\x16\xca\xe6\xed\xa0\x1e\xbe\x40\xf7\xdd\x25\x06\x6f\xa2\xc8\x10\x47\xe8\x14\xcc\x5a\x47\xe8\xe9\xa5\xda\xff\x91\xae\x87\x53\xed\xf3\x4a\xf7\x83\xd6\x8b\xd5\x6e\x1f\x42\xc7\xcd\xc3\xe9\xa2\x1c\xdd\xa7\x02\xd0\xc7\x59\xea\x11\xc6\x5b\xda\x43\xd5\xb8\xcb\x69\x77\xa7\x9d\xde\x03\xc2\x38\x4c\x3d\x0a\x24\x25\xac\x65\x1f\x94\x69\x76\xeb\x81\x33\xf5\xe8\x83\x34\x47\x89\xd8\x35\x06\xbc\x18\xb9\xa9\x47\xb8\x09\xab\xc7\xbe\x66\xcc\xa7\x0a\xa1\x40\xe5\x38\x7c\xb5\x2d\xff\x0e\x1c\x54\xb3\x17\xa0\xd0\x4e\x9a\xe8\x53\x45\xeb\xef\xcf\x42\xd3\x91\x41\x9a\x6b\x8c\x5c\x8c\x0e\xac\x0f\x67\x67\x67\x6f\x87\x41\xc6\xaa\x9e\x0b\x61\xa9\x35\x91\x8f\x36\x95\xe3\x6b\xe1\x30\x1d\xe9\x5d\x34\xe6\x8a\x6f\xc8\xb6\x0f\x8b\x04\xd1\x18\x08\xe1\x2d\xce\x3c\x3b\x54\x07\xd0\x93\x72\xec\x81\x37\xca\x61\xe8\x0a\x9d\x43\xbc\x7f\x7c\x9c\x3f\x04\x29\x0e\xc2\x20\xad\xfe\x7b\xb4\x3b\x84\xbb\xfc\x1f\xa8\xf7\x72\xc4\xa6\x3e\x5e\x30\x1d\xd7\x8b\x61\x8c\xa6\x1c\x7b\x90\x9a\x72\xd4\x78\xcd\xcc\xc7\x6b\x2a\xa3\xb8\x47\xc4\xec\xf6\x5a\x49\x8b\x9f\x82\x96\xd3\xb9\xbc\x32\x1f\x0d\x6a\x27\x62\x32\xd9\xa1\x58\x2b\x9e\x0b\xbc\x71\xf1\x27\xe8\x78\x65\x94\xb0\x22\x5b\xee\x7a\x2b\x80\x70\x7c\xe5\xaf\x1c\x63\x2b\xb2\x41\x68\xef\xbd\xa1\x27\xbc\x29\x8a\xcc\x6e\x7f\x64\x3a\x86\x7f\xff\xa7\xa8\xb5\x6d\x71\xc4\x18\x8a\x46\xa7\x6c\x1f\xbd\x56\xa4\xf8\x41\xbc\x8a\xa4\x09\x2e\x99\x64\xb6\x2d\xd5\xd4\x46\x62\x52\x77\x55\x69\xf9\xab\xf9\xc1\x8c\x5b\xe9\xb3\xee\xfc\x33\x44\x39\x53\x36\x58\x55\x01\x7e\x53\x65\xdb\x1a\x2f\xeb\x86\xd2\x7e\x26\x0e\xb5\x48\x3d\x7e\xaf\x4f\xba\xea\x13\x15\x5d\x51\xe3\x60\x90\xa2\x74\x6a\x63\x52\x36\x48\xf8\x89\x19\xcb\x64\xea\x77\x48\xae\xc7\x4a\xc0\xae\x90\x69\xb8\x2e\xca\xaf\x9b\xb6\xfc\x6a\x33\xfd\xed\xde\x1c\x10\x0a\x38\x2f\xea\x48\xbb\x5a\x1d\xf8\xdf\x94\x55\xbe\x60\x2a\x6a\x7f\x64\xd8\xd3\x30\x97\x36\x78\x2c\x6a\x8a\x54\x67\x74\xb0\x37\xb2\x17\x1b\xd6\xbf\x5a\xb4\xbf\x11\x78\xb7\x71\xad\x84\xc8\x25\xb3\xdb\xa6\x1d\x75\x26\xca\xf2\x05\x67\x66\xe5\x9e\x4c\x3d\xfd\x3e\x5f\xb8\xea\xfb\xbf\x01\x00\x00\xff\xff\x21\x6c\xa1\x2c\xb7\x23\x00\x00") + +func olmManifests0170OlmYamlBytes() ([]byte, error) { + return bindataRead( + _olmManifests0170OlmYaml, + "olm-manifests/0.17.0-olm.yaml", + ) +} + +func olmManifests0170OlmYaml() (*asset, error) { + bytes, err := olmManifests0170OlmYamlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "olm-manifests/0.17.0-olm.yaml", size: 9143, mode: os.FileMode(420), modTime: time.Unix(1607105036, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -217,6 +259,8 @@ var _bindata = map[string]func() (*asset, error){ "olm-manifests/0.15.1-olm.yaml": olmManifests0151OlmYaml, "olm-manifests/0.16.1-crds.yaml": olmManifests0161CrdsYaml, "olm-manifests/0.16.1-olm.yaml": olmManifests0161OlmYaml, + "olm-manifests/0.17.0-crds.yaml": olmManifests0170CrdsYaml, + "olm-manifests/0.17.0-olm.yaml": olmManifests0170OlmYaml, } // AssetDir returns the file names below a certain @@ -265,6 +309,8 @@ var _bintree = &bintree{nil, map[string]*bintree{ "0.15.1-olm.yaml": &bintree{olmManifests0151OlmYaml, map[string]*bintree{}}, "0.16.1-crds.yaml": &bintree{olmManifests0161CrdsYaml, map[string]*bintree{}}, "0.16.1-olm.yaml": &bintree{olmManifests0161OlmYaml, map[string]*bintree{}}, + "0.17.0-crds.yaml": &bintree{olmManifests0170CrdsYaml, map[string]*bintree{}}, + "0.17.0-olm.yaml": &bintree{olmManifests0170OlmYaml, map[string]*bintree{}}, }}, }} diff --git a/internal/bindata/olm/versions.go b/internal/bindata/olm/versions.go index 03d140716c2..add8b67d4e8 100644 --- a/internal/bindata/olm/versions.go +++ b/internal/bindata/olm/versions.go @@ -17,6 +17,7 @@ package olm var availableVersions = map[string]struct{}{ "0.16.1": {}, "0.15.1": {}, + "0.17.0": {}, } // HasVersion returns whether version maps to released OLM manifests as bindata. diff --git a/internal/olm/installer/client.go b/internal/olm/installer/client.go index 9214e6dc9b2..51bdd049e27 100644 --- a/internal/olm/installer/client.go +++ b/internal/olm/installer/client.go @@ -175,7 +175,7 @@ func (c Client) GetStatus(ctx context.Context, namespace, version string) (*olmr func (c Client) getResources(ctx context.Context, version string) ([]unstructured.Unstructured, error) { log.Infof("Fetching CRDs for version %q", version) - version = formatVersion(version) + resolvedVersion := formatVersion(version) var crdResources, olmResources []unstructured.Unstructured var err error @@ -196,13 +196,13 @@ func (c Client) getResources(ctx context.Context, version string) ([]unstructure return nil, err } } else { - log.Infof("Fetching resources for resolved version %q", version) - crdResources, err = c.getCRDs(ctx, version) + log.Infof("Fetching resources for resolved version %q", resolvedVersion) + crdResources, err = c.getCRDs(ctx, resolvedVersion) if err != nil { return nil, fmt.Errorf("failed to fetch CRDs: %v", err) } - olmResources, err = c.getOLM(ctx, version) + olmResources, err = c.getOLM(ctx, resolvedVersion) if err != nil { return nil, fmt.Errorf("failed to fetch resources: %v", err) } diff --git a/internal/testutils/olm.go b/internal/testutils/olm.go index f10ac2f85aa..2d3b3213f0d 100644 --- a/internal/testutils/olm.go +++ b/internal/testutils/olm.go @@ -24,7 +24,7 @@ import ( ) const ( - OlmVersionForTestSuite = "0.15.1" + OlmVersionForTestSuite = "0.17.0" ) var makefilePackagemanifestsFragment = ` From 75f7f0b7c3e06b5381bdf9d861d557660a5f6ebe Mon Sep 17 00:00:00 2001 From: Varsha Date: Fri, 4 Dec 2020 16:25:53 -0800 Subject: [PATCH 231/376] Bump k8s to 1.19.4 and controller-runtime to v0.7.0-alpha.7 (#4259) * Modify go.mod and fix internal/registry This PR bumps controller-runtime to v0.7.0-alpha.6 and k8s dependencies to v0.19.2 * Fix internal/olm/operator * Fix internal/cmd * Fix internal/ansible * Fix internal/helm * Rewrite unit tests in internal/kubebuilder/machinery Co-authored-by: Eric Stroczynski * Rewrite unit tests in internal/kubebuilder/filesystem * Update k8s version in Makefile * Add changelog Co-authored-by: Eric Stroczynski Signed-off-by: reinvantveer --- Makefile | 2 +- ...update-k8s-controller-runtime-version.yaml | 7 + go.mod | 28 +- go.sum | 276 +++++++++++++----- internal/ansible/controller/reconcile.go | 8 +- internal/ansible/controller/reconcile_test.go | 2 +- internal/ansible/predicate/predicate.go | 8 +- internal/ansible/proxy/proxy.go | 9 +- internal/ansible/proxy/proxy_test.go | 3 +- internal/cmd/ansible-operator/run/cmd.go | 26 +- internal/cmd/helm-operator/run/cmd.go | 24 +- .../operator-sdk/generate/internal/genutil.go | 8 +- .../generate/internal/manifests.go | 6 +- .../collector/clusterserviceversion.go | 6 +- .../collector/clusterserviceversion_test.go | 14 +- internal/helm/controller/reconcile.go | 24 +- internal/helm/release/manager.go | 2 +- .../kubebuilder/filesystem/errors_test.go | 6 - .../filesystem/filesystem_suite_test.go | 27 ++ .../kubebuilder/filesystem/filesystem_test.go | 6 - internal/kubebuilder/filesystem/mock_test.go | 6 - internal/kubebuilder/machinery/errors_test.go | 6 - .../machinery/machinery_suite_test.go | 27 ++ .../kubebuilder/machinery/scaffold_test.go | 82 ++---- internal/olm/client/client.go | 30 +- internal/olm/client/status.go | 12 +- internal/olm/installer/client.go | 4 +- internal/olm/operator/config.go | 2 +- .../registry/configmap/configmap_test.go | 24 +- .../operator/registry/configmap/registry.go | 6 +- .../registry/configmap/registry_test.go | 140 ++++----- .../operator/registry/operator_installer.go | 5 +- internal/olm/operator/uninstall.go | 10 +- .../plugins/helm/v1/chartutil/chart_test.go | 2 +- 34 files changed, 452 insertions(+), 396 deletions(-) create mode 100644 changelog/fragments/update-k8s-controller-runtime-version.yaml create mode 100644 internal/kubebuilder/filesystem/filesystem_suite_test.go create mode 100644 internal/kubebuilder/machinery/machinery_suite_test.go diff --git a/Makefile b/Makefile index 774ac6d9dba..81d3a37805a 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ export IMAGE_VERSION = v1.2.0 export SIMPLE_VERSION = $(shell (test "$(shell git describe)" = "$(shell git describe --abbrev=0)" && echo $(shell git describe)) || echo $(shell git describe --abbrev=0)+git) export GIT_VERSION = $(shell git describe --dirty --tags --always) export GIT_COMMIT = $(shell git rev-parse HEAD) -export K8S_VERSION = 1.18.8 +export K8S_VERSION = 1.19.4 # Build settings export TOOLS_DIR = tools/bin diff --git a/changelog/fragments/update-k8s-controller-runtime-version.yaml b/changelog/fragments/update-k8s-controller-runtime-version.yaml new file mode 100644 index 00000000000..44b27aeea10 --- /dev/null +++ b/changelog/fragments/update-k8s-controller-runtime-version.yaml @@ -0,0 +1,7 @@ +# entries is a list of entries to include in +# release notes and/or the migration guide + +entries: + - description: > + Updated helm-operator's Helm dependency to v3.4.1. + kind: "change" diff --git a/go.mod b/go.mod index 4ec6a3bcf1e..75ce83074a8 100644 --- a/go.mod +++ b/go.mod @@ -5,18 +5,18 @@ go 1.15 require ( github.com/blang/semver v3.5.1+incompatible github.com/fatih/structtag v1.1.0 - github.com/go-logr/logr v0.1.0 + github.com/go-logr/logr v0.3.0 github.com/iancoleman/strcase v0.0.0-20191112232945-16388991a334 github.com/kr/text v0.1.0 github.com/markbates/inflect v1.0.4 - github.com/onsi/ginkgo v1.12.1 - github.com/onsi/gomega v1.10.1 + github.com/onsi/ginkgo v1.14.1 + github.com/onsi/gomega v1.10.2 github.com/operator-framework/api v0.3.20 - github.com/operator-framework/operator-lib v0.1.0 + github.com/operator-framework/operator-lib v0.2.1-0.20201119204525-6700ae54da56 github.com/operator-framework/operator-registry v1.14.3 - github.com/prometheus/client_golang v1.5.1 + github.com/prometheus/client_golang v1.7.1 github.com/sergi/go-diff v1.0.0 - github.com/sirupsen/logrus v1.6.0 + github.com/sirupsen/logrus v1.7.0 github.com/spf13/afero v1.2.2 github.com/spf13/cobra v1.0.0 github.com/spf13/pflag v1.0.5 @@ -24,15 +24,15 @@ require ( github.com/stretchr/testify v1.6.1 golang.org/x/tools v0.0.0-20201014231627-1610a49f37af gomodules.xyz/jsonpatch/v3 v3.0.1 - helm.sh/helm/v3 v3.3.4 - k8s.io/api v0.18.8 - k8s.io/apiextensions-apiserver v0.18.8 - k8s.io/apimachinery v0.18.8 - k8s.io/cli-runtime v0.18.8 - k8s.io/client-go v0.18.8 - k8s.io/kubectl v0.18.8 + helm.sh/helm/v3 v3.4.1 + k8s.io/api v0.19.4 + k8s.io/apiextensions-apiserver v0.19.4 + k8s.io/apimachinery v0.19.4 + k8s.io/cli-runtime v0.19.4 + k8s.io/client-go v0.19.4 + k8s.io/kubectl v0.19.4 rsc.io/letsencrypt v0.0.3 // indirect - sigs.k8s.io/controller-runtime v0.6.3 + sigs.k8s.io/controller-runtime v0.7.0-alpha.7 sigs.k8s.io/controller-tools v0.3.0 sigs.k8s.io/kubebuilder/v2 v2.3.2-0.20201111001842-c158f4fa4207 sigs.k8s.io/yaml v1.2.0 diff --git a/go.sum b/go.sum index 8278f5466fa..ae6e707bbf1 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,17 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw= cloud.google.com/go v0.38.0 h1:ROfEUZz+Gh5pa62DJWXSaonyu3StP6EA6lPEXPI6mCo= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.51.0 h1:PvKAVQWCtlGUSlZkGW3QLelKaWq7KYv/MW1EboG8bfM= +cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= @@ -11,21 +22,30 @@ github.com/Azure/go-autorest v13.3.2+incompatible h1:VxzPyuhtnlBOzc4IWCZHqpyH2d+ github.com/Azure/go-autorest v13.3.2+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.9.0 h1:MRvx8gncNaXJqOoLmhNjUAKh33JJF8LyxPhomEtOsjs= github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= +github.com/Azure/go-autorest/autorest v0.9.6 h1:5YWtOnckcudzIw8lPPBcWOnmIFWMtHci1ZWAZulMSx0= +github.com/Azure/go-autorest/autorest v0.9.6/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630= github.com/Azure/go-autorest/autorest/adal v0.5.0 h1:q2gDruN08/guU9vAjuPWff0+QIrpH6ediguzdAzXAUU= github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= +github.com/Azure/go-autorest/autorest/adal v0.8.2 h1:O1X4oexUxnZCaEUGsvMnr8ZGj8HI37tNezwY4npRqA0= +github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= github.com/Azure/go-autorest/autorest/date v0.1.0 h1:YGrhWfrgtFs84+h0o46rJrlmsZtyZRg470CqAXTZaGM= github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= +github.com/Azure/go-autorest/autorest/date v0.2.0 h1:yW+Zlqf26583pE43KhfnhFcdmSWlm5Ew6bxipnr/tbM= +github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.2.0 h1:Ww5g4zThfD/6cLb4z6xxgeyDa7QDkizMkJKe0ysZXp0= github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.3.0 h1:qJumjCaCudz+OcqE9/XtEPfvtOjOmKaui4EOpFI6zZc= +github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= github.com/Azure/go-autorest/logger v0.1.0 h1:ruG4BSDXONFRrZZJ2GUXDiUyVpayPmb1GnWeHDdaNKY= github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= github.com/Azure/go-autorest/tracing v0.5.0 h1:TRn4WjSnkcSy5AEG3pnbtFSwNtwzjr4VYyQflFE619k= github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/DATA-DOG/go-sqlmock v1.4.1 h1:ThlnYciV1iM/V0OSF/dtkqWb6xo5qITT1TJBG1MRDJM= -github.com/DATA-DOG/go-sqlmock v1.4.1/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= +github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd h1:sjQovDkwrZp8u+gxLtPgKGjk5hCxuy2hrRejBTA9xFU= github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E= @@ -117,6 +137,9 @@ github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghf github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= @@ -233,7 +256,6 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/evanphx/json-patch v0.0.0-20200808040245-162e5629780b/go.mod h1:NAJj0yf/KaRKURN6nyi7A9IZydMivZEm9oQLWNjfKDc= github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M= github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= @@ -262,6 +284,7 @@ github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0 github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/go-bindata/go-bindata/v3 v3.1.3 h1:F0nVttLC3ws0ojc7p60veTurcOm//D4QBODNM7EGrCI= github.com/go-bindata/go-bindata/v3 v3.1.3/go.mod h1:1/zrpXsLD8YDIbhZRqXzm1Ghc7NhEvIN9+Z6R5/xH4I= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -271,8 +294,15 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v0.1.0 h1:M1Tv3VzNlEHg6uyACnRdtrploV2P7wZqH8BoQMtz0cg= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= +github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-logr/logr v0.2.1 h1:fV3MLmabKIZ383XifUjFSwcoGee0v9qgPp8wy5svibE= +github.com/go-logr/logr v0.2.1/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-logr/logr v0.3.0 h1:q4c+kbcR0d5rSurhBR8dIgieOaYpXtsdTYfx22Cu6rs= +github.com/go-logr/logr v0.3.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/zapr v0.1.0 h1:h+WVe9j6HAA01niTJPA/kKH0i7e0rLZBCwauQFcRE54= github.com/go-logr/zapr v0.1.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk= +github.com/go-logr/zapr v0.2.0 h1:v6Ji8yBW77pva6NkJKQdHLAJKrIJKRHz0RXwPqCHSR4= +github.com/go-logr/zapr v0.2.0/go.mod h1:qhKdvif7YF5GI9NWEpyxTSSBdGmzkNguibrdCNVPunU= github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= @@ -349,7 +379,7 @@ github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJA github.com/gocql/gocql v0.0.0-20190301043612-f6df8288f9b4/go.mod h1:4Fw1eo5iaEhDUs8XyuhSVCVy52Jq3L+/3GJgYkwc+/0= github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godror/godror v0.13.3/go.mod h1:2ouUT4kdhUBk7TAkHWD4SN0CdI0pgEQbo8FVHhbSKWg= -github.com/gofrs/flock v0.7.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gofrs/uuid v3.3.0+incompatible h1:8K4tyRfvU1CYPgJsveYFQMhpFd/wXNM7iK6rR7UHz84= github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= @@ -367,6 +397,8 @@ github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef h1:veQD95Isof8w9 github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7 h1:5ZkaAPbicIKTF2I64qf5Fh8Aa83Q/dnOafMYV0OMwjA= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1 h1:qGJ6qTW+x6xX/my+8YUVl4WNpX9B7+/l2tRsHGZ7f2s= @@ -399,6 +431,8 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -407,15 +441,21 @@ github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.3.1 h1:WeAefnSUHlBb0iJKwxFDZdbfGwkd7xRNuV+IpXMJhYk= github.com/googleapis/gnostic v0.3.1/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU= +github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= +github.com/googleapis/gnostic v0.5.1 h1:A8Yhf6EtqTv9RMsU6MQTyrtV1TjWlR6xU9BsZIwuTCM= +github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= github.com/gophercloud/gophercloud v0.1.0 h1:P/nh25+rzXouhytV2pUHBb65fnds26Ghl8/391+sT5o= github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= @@ -474,11 +514,12 @@ github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/iancoleman/strcase v0.0.0-20191112232945-16388991a334 h1:VHgatEHNcBFEB7inlalqfNqw65aNkM1lGX2yt3NmbS8= github.com/iancoleman/strcase v0.0.0-20191112232945-16388991a334/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.9 h1:UauaLniWCFHWd+Jp9oCEkTBj8VO/9DKg3PV3VCNMDIg= -github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.10 h1:6q5mVkdH/vYmqngx7kZQTjJ5HRsx+ImorDIEQ+beJgc= +github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= @@ -497,10 +538,10 @@ github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22 github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA= @@ -517,6 +558,8 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxv github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= @@ -528,8 +571,8 @@ github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhR github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.7.0 h1:h93mCPfUSkaul3Ka/VG8uZdmW1uMHDGxzu0NWHuJmHY= -github.com/lib/pq v1.7.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.8.0 h1:9xohqzkUwzR4Ga4ivdTcawVS89YSDVxXMa3xJX3cGzg= +github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= @@ -564,6 +607,8 @@ github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK86 github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mikefarah/yaml/v2 v2.4.0/go.mod h1:ahVqZF4n1W4NqwvVnZzC4es67xsW9uR/RRf2RRxieJU= @@ -584,6 +629,8 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/moby/term v0.0.0-20200312100748-672ec06f55cd h1:aY7OQNf2XqY/JQ6qREWamhI/81os/agb2BAGpcx5yWI= +github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -624,6 +671,8 @@ github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+ github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= github.com/onsi/ginkgo v1.12.1 h1:mFwc4LvZ0xpSvDZ3E+k8Yte0hLOMxXUlP+yXtJqkYfQ= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.1 h1:jMU0WaQrP0a/YAEq8eJmJKjBoMs+pClEr1vDMlM/Do4= +github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= @@ -633,6 +682,8 @@ github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoT github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.10.2 h1:aY/nuoWlKJud2J6U0E3NWsjlg+0GtwXxgEqthRdzlcs= +github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= @@ -661,8 +712,8 @@ github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnh github.com/operator-framework/api v0.3.7-0.20200602203552-431198de9fc2/go.mod h1:Xbje9x0SHmh0nihE21kpesB38vk3cyxnE6JdDS8Jo1Q= github.com/operator-framework/api v0.3.20 h1:2Ks8GXXl/H2sV9ll2iQBUO65ABQ5VuzN3IKEZCJWljo= github.com/operator-framework/api v0.3.20/go.mod h1:Xbje9x0SHmh0nihE21kpesB38vk3cyxnE6JdDS8Jo1Q= -github.com/operator-framework/operator-lib v0.1.0 h1:7Qy6v2ZccvCeFLWEkrGnN+U+DkaeIWp0gAZaBM9T3DI= -github.com/operator-framework/operator-lib v0.1.0/go.mod h1:HLw61JTIEeq0YLeVf4dwYx/zt4DmLGZUVWI1y3Lf5Hg= +github.com/operator-framework/operator-lib v0.2.1-0.20201119204525-6700ae54da56 h1:RFuLAujDg2trSdvasocuc4MM/QS8eKRYmTerKQxIrv0= +github.com/operator-framework/operator-lib v0.2.1-0.20201119204525-6700ae54da56/go.mod h1:7JYMD1tU8z+dvtttqwPC59lOTEGAQRdGr+VlxkGJW2k= github.com/operator-framework/operator-registry v1.14.3 h1:WiIYJy9cfnbzvlwoO5ikgqHnj/WwKLqItJlTz5EeEzQ= github.com/operator-framework/operator-registry v1.14.3/go.mod h1:0x4Kkl/1LaK5g/6XgEiJrHF/jEAW3QKYg91M4sYuN0o= github.com/otiai10/copy v1.2.0 h1:HvG945u96iNadPoG2/Ja2+AUJeW5YuFQMixq9yirC+k= @@ -702,8 +753,8 @@ github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDf github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= -github.com/prometheus/client_golang v1.5.1 h1:bdHYieyGlH+6OLEk2YQha8THib30KP0/yD0YH9m6xcA= -github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_golang v1.7.1 h1:NTGy1Ja9pByO+xAeH/qiWnLrKtr3hJPNjaVUwnjpdpA= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= @@ -719,8 +770,8 @@ github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= -github.com/prometheus/common v0.9.1 h1:KOMtN28tlbam3/7ZKEYKHhKoJZYYj3gMH4uc62x7X7U= -github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= @@ -730,8 +781,8 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= -github.com/prometheus/procfs v0.0.11 h1:DhHlBtkHWPYi8O2y31JkK0TF+DGM+51OopZjH/Ia5qI= -github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= @@ -762,6 +813,8 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= @@ -791,6 +844,7 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= +github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= @@ -846,7 +900,10 @@ go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.4 h1:hi1bXHMVrlQh6WwxAy+qZCV/SYIlqo+Ushwdpa4tAKg= go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= +go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0= +go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.etcd.io/etcd v0.5.0-alpha.5.0.20200819165624-17cef6e3e9d5/go.mod h1:skWido08r9w6Lq/w70DO5XYIKMu4QFu1+4VsqLQuJy8= go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.0/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= @@ -864,16 +921,25 @@ go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk= +go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0 h1:sFPn2GLc3poCkfrpIXGhBD2X0CMIo4Q/zSULXrj/+uc= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A= +go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.8.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0 h1:nR6NoDBgAf67s68NhaXbsojM+2gxp3S1hWkHDl27pVU= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +go.uber.org/zap v1.15.0 h1:ZZCA22JRF2gQE5FoNmhmrf7jeJJ2uhqDUNRYKm8dvmM= +go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -883,25 +949,38 @@ golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f h1:J5lckAjkw6qYlOZNj90mLYNTEKDvWeuc1yieZ8qUzUE= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -925,6 +1004,7 @@ golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190424112056-4829fb13d2c6/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -936,10 +1016,13 @@ golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191021144547-ec77196f6094/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191028085509-fe3aa8a45271/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -948,6 +1031,8 @@ golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6 h1:pE8b58s1HRDMi8RDc79m0HISf9D4TzseP40cEA6IGfs= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -970,15 +1055,19 @@ golang.org/x/sys v0.0.0-20190102155601-82a175fd1598/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190426135247-a129542de9ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -988,13 +1077,19 @@ golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191020212454-3e7259c5e7c2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae h1:Ih9Yo4hSPImZOpfGuA4bR/ORKTAbhZo2AbWNRCnevdo= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= @@ -1005,6 +1100,8 @@ golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZe golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s= +golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1014,25 +1111,36 @@ golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190425222832-ad9eeb80039a/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191004055002-72853e10c5a3/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191030203535-5e247c9ad0a0/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200403190813-44a64ad78b9b h1:AFZdJUT7jJYXQEC29hYH/WZkoV7+KhwxQGmdZ19yYoY= golang.org/x/tools v0.0.0-20200403190813-44a64ad78b9b/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20201014231627-1610a49f37af h1:VIUWFyOgzG3c0t9KYop5Ybp4m56LupfOnFYX7Ipnz+I= golang.org/x/tools v0.0.0-20201014231627-1610a49f37af/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1043,6 +1151,8 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1N golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.0.1 h1:xyiBuvkD2g5n7cYzx6u2sxQvsAy4QJsZFCzGVdzOXZ0= gomodules.xyz/jsonpatch/v2 v2.0.1/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU= +gomodules.xyz/jsonpatch/v2 v2.1.0 h1:Phva6wqu+xR//Njw6iorylFFgn/z547tw5Ne3HZPQ+k= +gomodules.xyz/jsonpatch/v2 v2.1.0/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU= gomodules.xyz/jsonpatch/v3 v3.0.1 h1:Te7hKxV52TKCbNYq3t84tzKav3xhThdvSsSp/W89IyI= gomodules.xyz/jsonpatch/v3 v3.0.1/go.mod h1:CBhndykehEwTOlEfnsfJwvkFQbSN8YZFr9M+cIHAJto= gomodules.xyz/orderedmap v0.1.0 h1:fM/+TGh/O1KkqGR5xjTKg6bU8OKBkg7p0Y+x/J9m8Os= @@ -1051,13 +1161,20 @@ google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+ google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.3.2/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -1066,8 +1183,11 @@ google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= google.golang.org/genproto v0.0.0-20191009194640-548a555dbc03/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200117163144-32f20d992d24/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200701001935-0939c5918c31 h1:Of4QP8bfRqzDROen6+s2j/p0jCPgzvQRd9nHiactfn4= @@ -1078,6 +1198,7 @@ google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZi google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= @@ -1135,98 +1256,109 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20190905181640-827449938966/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= -helm.sh/helm/v3 v3.3.4 h1:tbad6WQVMxEw1HlVBvI2rQqOblmI5lgXOrWAMwJ198M= -helm.sh/helm/v3 v3.3.4/go.mod h1:CyCGQa53/k1JFxXvXveGwtfJ4cuB9zkaBSGa5rnAiHU= +gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= +helm.sh/helm/v3 v3.4.1 h1:NIdlBGKFRTAkhz0ooYKw1VBbmTldxNAZRY1nH6Glk6I= +helm.sh/helm/v3 v3.4.1/go.mod h1:MeRlXlmCr5CWYKvqIPgXrSmcIXJpv7qcsKV3uTvcZSM= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= k8s.io/api v0.18.0/go.mod h1:q2HRQkfDzHMBZL9l/y9rH63PkQl4vae0xRT+8prbrK8= k8s.io/api v0.18.2/go.mod h1:SJCWI7OLzhZSvbY7U8zwNl9UA4o1fizoug34OV/2r78= -k8s.io/api v0.18.4 h1:8x49nBRxuXGUlDlwlWd3RMY1SayZrzFfxea3UZSkFw4= -k8s.io/api v0.18.4/go.mod h1:lOIQAKYgai1+vz9J7YcDZwC26Z0zQewYOGWdyIPUUQ4= -k8s.io/api v0.18.6 h1:osqrAXbOQjkKIWDTjrqxWQ3w0GkKb1KA1XkUGHHYpeE= -k8s.io/api v0.18.6/go.mod h1:eeyxr+cwCjMdLAmr2W3RyDI0VvTawSg/3RFFBEnmZGI= -k8s.io/api v0.18.8 h1:aIKUzJPb96f3fKec2lxtY7acZC9gQNDLVhfSGpxBAC4= -k8s.io/api v0.18.8/go.mod h1:d/CXqwWv+Z2XEG1LgceeDmHQwpUJhROPx16SlxJgERY= +k8s.io/api v0.19.2 h1:q+/krnHWKsL7OBZg/rxnycsl9569Pud76UJ77MvKXms= +k8s.io/api v0.19.2/go.mod h1:IQpK0zFQ1xc5iNIQPqzgoOwuFugaYHK4iCknlAQP9nI= +k8s.io/api v0.19.3/go.mod h1:VF+5FT1B74Pw3KxMdKyinLo+zynBaMBiAfGMuldcNDs= +k8s.io/api v0.19.4 h1:I+1I4cgJYuCDgiLNjKx7SLmIbwgj9w7N7Zr5vSIdwpo= +k8s.io/api v0.19.4/go.mod h1:SbtJ2aHCItirzdJ36YslycFNzWADYH3tgOhvBEFtZAk= k8s.io/apiextensions-apiserver v0.18.2/go.mod h1:q3faSnRGmYimiocj6cHQ1I3WpLqmDgJFlKL37fC4ZvY= -k8s.io/apiextensions-apiserver v0.18.4 h1:Y3HGERmS8t9u12YNUFoOISqefaoGRuTc43AYCLzWmWE= -k8s.io/apiextensions-apiserver v0.18.4/go.mod h1:NYeyeYq4SIpFlPxSAB6jHPIdvu3hL0pc36wuRChybio= -k8s.io/apiextensions-apiserver v0.18.6 h1:vDlk7cyFsDyfwn2rNAO2DbmUbvXy5yT5GE3rrqOzaMo= -k8s.io/apiextensions-apiserver v0.18.6/go.mod h1:lv89S7fUysXjLZO7ke783xOwVTm6lKizADfvUM/SS/M= -k8s.io/apiextensions-apiserver v0.18.8 h1:pkqYPKTHa0/3lYwH7201RpF9eFm0lmZDFBNzhN+k/sA= -k8s.io/apiextensions-apiserver v0.18.8/go.mod h1:7f4ySEkkvifIr4+BRrRWriKKIJjPyg9mb/p63dJKnlM= +k8s.io/apiextensions-apiserver v0.19.2 h1:oG84UwiDsVDu7dlsGQs5GySmQHCzMhknfhFExJMz9tA= +k8s.io/apiextensions-apiserver v0.19.2/go.mod h1:EYNjpqIAvNZe+svXVx9j4uBaVhTB4C94HkY3w058qcg= +k8s.io/apiextensions-apiserver v0.19.3/go.mod h1:igVEkrE9TzInc1tYE7qSqxaLg/rEAp6B5+k9Q7+IC8Q= +k8s.io/apiextensions-apiserver v0.19.4 h1:D9ak9T012tb3vcGFWYmbQuj9SCC8YM4zhA4XZqsAQC4= +k8s.io/apiextensions-apiserver v0.19.4/go.mod h1:B9rpH/nu4JBCtuUp3zTTk8DEjZUupZTBEec7/2zNRYw= k8s.io/apimachinery v0.18.0/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA= k8s.io/apimachinery v0.18.2/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA= -k8s.io/apimachinery v0.18.4 h1:ST2beySjhqwJoIFk6p7Hp5v5O0hYY6Gngq/gUYXTPIA= -k8s.io/apimachinery v0.18.4/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko= -k8s.io/apimachinery v0.18.6 h1:RtFHnfGNfd1N0LeSrKCUznz5xtUP1elRGvHJbL3Ntag= -k8s.io/apimachinery v0.18.6/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko= -k8s.io/apimachinery v0.18.8 h1:jimPrycCqgx2QPearX3to1JePz7wSbVLq+7PdBTTwQ0= -k8s.io/apimachinery v0.18.8/go.mod h1:6sQd+iHEqmOtALqOFjSWp2KZ9F0wlU/nWm0ZgsYWMig= +k8s.io/apimachinery v0.19.2 h1:5Gy9vQpAGTKHPVOh5c4plE274X8D/6cuEiTO2zve7tc= +k8s.io/apimachinery v0.19.2/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= +k8s.io/apimachinery v0.19.3/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= +k8s.io/apimachinery v0.19.4 h1:+ZoddM7nbzrDCp0T3SWnyxqf8cbWPT2fkZImoyvHUG0= +k8s.io/apimachinery v0.19.4/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= k8s.io/apiserver v0.18.2/go.mod h1:Xbh066NqrZO8cbsoenCwyDJ1OSi8Ag8I2lezeHxzwzw= -k8s.io/apiserver v0.18.4 h1:pn1jSQkfboPSirZopkVpEdLW4FcQLnYMaIY8LFxxj30= -k8s.io/apiserver v0.18.4/go.mod h1:q+zoFct5ABNnYkGIaGQ3bcbUNdmPyOCoEBcg51LChY8= -k8s.io/apiserver v0.18.6 h1:HcWwcOfhj4Yv6y2igP4ZUuovyPjVLGoZcG0Tsph4Mxo= -k8s.io/apiserver v0.18.6/go.mod h1:Zt2XvTHuaZjBz6EFYzpp+X4hTmgWGy8AthNVnTdm3Wg= -k8s.io/apiserver v0.18.8 h1:Au4kMn8sb1zFdyKqc8iMHLsYLxRI6Y+iAhRNKKQtlBY= -k8s.io/apiserver v0.18.8/go.mod h1:12u5FuGql8Cc497ORNj79rhPdiXQC4bf53X/skR/1YM= +k8s.io/apiserver v0.19.2 h1:xq2dXAzsAoHv7S4Xc/p7PKhiowdHV/PgdePWo3MxIYM= +k8s.io/apiserver v0.19.2/go.mod h1:FreAq0bJ2vtZFj9Ago/X0oNGC51GfubKK/ViOKfVAOA= +k8s.io/apiserver v0.19.3/go.mod h1:bx6dMm+H6ifgKFpCQT/SAhPwhzoeIMlHIaibomUDec0= +k8s.io/apiserver v0.19.4 h1:X40UuyVt6DcYWIh2olcePkyKO0LRJFvxWC0kLxYvkZU= +k8s.io/apiserver v0.19.4/go.mod h1:X8WRHCR1UGZDd7HpV0QDc1h/6VbbpAeAGyxSh8yzZXw= k8s.io/cli-runtime v0.18.0/go.mod h1:1eXfmBsIJosjn9LjEBUd2WVPoPAY9XGTqTFcPMIBsUQ= -k8s.io/cli-runtime v0.18.8 h1:ycmbN3hs7CfkJIYxJAOB10iW7BVPmXGXkfEyiV9NJ+k= -k8s.io/cli-runtime v0.18.8/go.mod h1:7EzWiDbS9PFd0hamHHVoCY4GrokSTPSL32MA4rzIu0M= +k8s.io/cli-runtime v0.19.3/go.mod h1:q+l845i5/uWzcUpCrl+L4f3XLaJi8ZeLVQ/decwty0A= +k8s.io/cli-runtime v0.19.4 h1:FPpoqFbWsFzRbZNRI+o/+iiLFmWMYTmBueIj3OaNVTI= +k8s.io/cli-runtime v0.19.4/go.mod h1:m8G32dVbKOeaX1foGhleLEvNd6REvU7YnZyWn5//9rw= k8s.io/client-go v0.18.0/go.mod h1:uQSYDYs4WhVZ9i6AIoEZuwUggLVEF64HOD37boKAtF8= k8s.io/client-go v0.18.2/go.mod h1:Xcm5wVGXX9HAA2JJ2sSBUn3tCJ+4SVlCbl2MNNv+CIU= -k8s.io/client-go v0.18.4 h1:un55V1Q/B3JO3A76eS0kUSywgGK/WR3BQ8fHQjNa6Zc= -k8s.io/client-go v0.18.4/go.mod h1:f5sXwL4yAZRkAtzOxRWUhA/N8XzGCb+nPZI8PfobZ9g= -k8s.io/client-go v0.18.6 h1:I+oWqJbibLSGsZj8Xs8F0aWVXJVIoUHWaaJV3kUN/Zw= -k8s.io/client-go v0.18.6/go.mod h1:/fwtGLjYMS1MaM5oi+eXhKwG+1UHidUEXRh6cNsdO0Q= -k8s.io/client-go v0.18.8 h1:SdbLpIxk5j5YbFr1b7fq8S7mDgDjYmUxSbszyoesoDM= -k8s.io/client-go v0.18.8/go.mod h1:HqFqMllQ5NnQJNwjro9k5zMyfhZlOwpuTLVrxjkYSxU= +k8s.io/client-go v0.19.2 h1:gMJuU3xJZs86L1oQ99R4EViAADUPMHHtS9jFshasHSc= +k8s.io/client-go v0.19.2/go.mod h1:S5wPhCqyDNAlzM9CnEdgTGV4OqhsW3jGO1UM1epwfJA= +k8s.io/client-go v0.19.3/go.mod h1:+eEMktZM+MG0KO+PTkci8xnbCZHvj9TqR6Q1XDUIJOM= +k8s.io/client-go v0.19.4 h1:85D3mDNoLF+xqpyE9Dh/OtrJDyJrSRKkHmDXIbEzer8= +k8s.io/client-go v0.19.4/go.mod h1:ZrEy7+wj9PjH5VMBCuu/BDlvtUAku0oVFk4MmnW9mWA= k8s.io/code-generator v0.18.0/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc= k8s.io/code-generator v0.18.2/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc= -k8s.io/code-generator v0.18.4/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c= -k8s.io/code-generator v0.18.6/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c= -k8s.io/code-generator v0.18.8/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c= +k8s.io/code-generator v0.19.2/go.mod h1:moqLn7w0t9cMs4+5CQyxnfA/HV8MF6aAVENF+WZZhgk= +k8s.io/code-generator v0.19.3/go.mod h1:moqLn7w0t9cMs4+5CQyxnfA/HV8MF6aAVENF+WZZhgk= +k8s.io/code-generator v0.19.4/go.mod h1:moqLn7w0t9cMs4+5CQyxnfA/HV8MF6aAVENF+WZZhgk= k8s.io/component-base v0.18.0/go.mod h1:u3BCg0z1uskkzrnAKFzulmYaEpZF7XC9Pf/uFyb1v2c= k8s.io/component-base v0.18.2/go.mod h1:kqLlMuhJNHQ9lz8Z7V5bxUUtjFZnrypArGl58gmDfUM= -k8s.io/component-base v0.18.4 h1:Kr53Fp1iCGNsl9Uv4VcRvLy7YyIqi9oaJOQ7SXtKI98= -k8s.io/component-base v0.18.4/go.mod h1:7jr/Ef5PGmKwQhyAz/pjByxJbC58mhKAhiaDu0vXfPk= -k8s.io/component-base v0.18.6 h1:Wd6cHGwJN2qpufnirVOB3oMhyhbioGsKEi5HeDBsV+s= -k8s.io/component-base v0.18.6/go.mod h1:knSVsibPR5K6EW2XOjEHik6sdU5nCvKMrzMt2D4In14= -k8s.io/component-base v0.18.8 h1:BW5CORobxb6q5mb+YvdwQlyXXS6NVH5fDXWbU7tf2L8= -k8s.io/component-base v0.18.8/go.mod h1:00frPRDas29rx58pPCxNkhUfPbwajlyyvu8ruNgSErU= +k8s.io/component-base v0.19.2 h1:jW5Y9RcZTb79liEhW3XDVTW7MuvEGP0tQZnfSX6/+gs= +k8s.io/component-base v0.19.2/go.mod h1:g5LrsiTiabMLZ40AR6Hl45f088DevyGY+cCE2agEIVo= +k8s.io/component-base v0.19.3 h1:c+DzDNAQFlaoyX+yv8YuWi8xmlQvvY5DnJGbaz5U74o= +k8s.io/component-base v0.19.3/go.mod h1:WhLWSIefQn8W8jxSLl5WNiR6z8oyMe/8Zywg7alOkRc= +k8s.io/component-base v0.19.4 h1:HobPRToQ8KJ9ubRju6PUAk9I5V1GNMJZ4PyWbiWA0uI= +k8s.io/component-base v0.19.4/go.mod h1:ZzuSLlsWhajIDEkKF73j64Gz/5o0AgON08FgRbEPI70= k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200114144118-36b2048a9120/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog/v2 v2.0.0 h1:Foj74zO6RbjjP4hBEKjnYtjjAhGg4jNynUdYF6fJrok= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= +k8s.io/klog/v2 v2.2.0 h1:XRvcwJozkgZ1UQJmfMGpvRthQHOvihEhYtDfAaxMz/A= +k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E= -k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6 h1:Oh3Mzx5pJ+yIumsAD0MOECPVeXsVot0UkiaCGVyfGQY= -k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E= +k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6 h1:+WnxoVtG8TMiudHBSEtrVL1egv36TkkJm+bA8AxicmQ= +k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= k8s.io/kubectl v0.18.0/go.mod h1:LOkWx9Z5DXMEg5KtOjHhRiC1fqJPLyCr3KtQgEolCkU= -k8s.io/kubectl v0.18.8 h1:qTkHCz21YmK0+S0oE6TtjtxmjeDP42gJcZJyRKsIenA= -k8s.io/kubectl v0.18.8/go.mod h1:PlEgIAjOMua4hDFTEkVf+W5M0asHUKfE4y7VDZkpLHM= +k8s.io/kubectl v0.19.3/go.mod h1:t5cscfrAuHUvEGNyNJjPKt+rGlaJzk8jrKYHXxEsANE= +k8s.io/kubectl v0.19.4 h1:XFrHibf5fS4Ot8h3EnzdVsKrYj+pndlzKbwPkfra5hI= +k8s.io/kubectl v0.19.4/go.mod h1:XPmlu4DJEYgD83pvZFeKF8+MSvGnYGqunbFSrJsqHv0= k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= k8s.io/metrics v0.18.0/go.mod h1:8aYTW18koXqjLVKL7Ds05RPMX9ipJZI3mywYvBOxXd4= -k8s.io/metrics v0.18.8/go.mod h1:j7JzZdiyhLP2BsJm/Fzjs+j5Lb1Y7TySjhPWqBPwRXA= +k8s.io/metrics v0.19.3/go.mod h1:Eap/Lk1FiAIjkaArFuv41v+ph6dbDpVGwAg7jMI+4vg= +k8s.io/metrics v0.19.4/go.mod h1:a0gvAzrxQPw2ouBqnXI7X9qlggpPkKAFgWU/Py+KZiU= k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= -k8s.io/utils v0.0.0-20200603063816-c1c6865ac451 h1:v8ud2Up6QK1lNOKFgiIVrZdMg7MpmSnvtrOieolJKoE= -k8s.io/utils v0.0.0-20200603063816-c1c6865ac451/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20200729134348-d5654de09c73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20200912215256-4140de9c8800 h1:9ZNvfPvVIEsp/T1ez4GQuzCcCTEQWhovSofhqR73A6g= +k8s.io/utils v0.0.0-20200912215256-4140de9c8800/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/letsencrypt v0.0.3 h1:H7xDfhkaFFSYEJlKeq38RwX2jYcnTeHuDQyT+mMNMwM= rsc.io/letsencrypt v0.0.3/go.mod h1:buyQKZ6IXrRnB7TdkHP0RyEybLx18HHyOSoTyoOLqNY= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7 h1:uuHDyjllyzRyCIvvn0OBjiRB0SgBZGqHNYAmjR7fO50= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.9 h1:rusRLrDhjBp6aYtl9sGEvQJr6faoHoDLd0YcUBTZguI= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.9/go.mod h1:dzAXnQbTRyDlZPJX2SUPEqvnB+j7AJjtlox7PEwigU0= sigs.k8s.io/controller-runtime v0.6.0/go.mod h1:CpYf5pdNY/B352A1TFLAS2JVSlnGQ5O2cftPHndTroo= -sigs.k8s.io/controller-runtime v0.6.1/go.mod h1:XRYBPdbf5XJu9kpS84VJiZ7h/u1hF3gEORz0efEja7A= -sigs.k8s.io/controller-runtime v0.6.3 h1:SBbr+inLPEKhvlJtrvDcwIpm+uhDvp63Bl72xYJtoOE= -sigs.k8s.io/controller-runtime v0.6.3/go.mod h1:WlZNXcM0++oyaQt4B7C2lEE5JYRs8vJUzRP4N4JpdAY= +sigs.k8s.io/controller-runtime v0.7.0-alpha.6 h1:ieFqEijQyDEZVIGwI5sYkk7VTa8Itim0kU/TCOnCkto= +sigs.k8s.io/controller-runtime v0.7.0-alpha.6/go.mod h1:03b1n6EtlDvuBPPEOHadJUusruwLWgoT4BDCybMibnA= +sigs.k8s.io/controller-runtime v0.7.0-alpha.7 h1:KtMmb2Ef/S38GNbf0Jpa+FWXqnxFYeWAyhipMmmPCcQ= +sigs.k8s.io/controller-runtime v0.7.0-alpha.7/go.mod h1:pJ3YBrJiAqMAZKi6UVGuE98ZrroV1p+pIhoHsMm9wdU= sigs.k8s.io/controller-tools v0.3.0 h1:y3YD99XOyWaXkiF1kd41uRvfp/64teWcrEZFuHxPhJ4= sigs.k8s.io/controller-tools v0.3.0/go.mod h1:enhtKGfxZD1GFEoMgP8Fdbu+uKQ/cq1/WGJhdVChfvI= sigs.k8s.io/kubebuilder/v2 v2.3.2-0.20201111001842-c158f4fa4207 h1:JtlaBrtWymJbh6ea+TJUZkzBb0x0dMKV+P0+ZPaldxk= @@ -1236,6 +1368,8 @@ sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5 sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= sigs.k8s.io/structured-merge-diff/v3 v3.0.0 h1:dOmIZBMfhcHS09XZkMyUgkq5trg3/jRyJYFZUiaOp8E= sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= +sigs.k8s.io/structured-merge-diff/v4 v4.0.1 h1:YXTMot5Qz/X1iBRJhAt+vI+HVttY0WkSqqhKxQ0xVbA= +sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/internal/ansible/controller/reconcile.go b/internal/ansible/controller/reconcile.go index 12a10e9c804..60ba02f9ffd 100644 --- a/internal/ansible/controller/reconcile.go +++ b/internal/ansible/controller/reconcile.go @@ -63,11 +63,11 @@ type AnsibleOperatorReconciler struct { } // Reconcile - handle the event. -func (r *AnsibleOperatorReconciler) Reconcile(request reconcile.Request) (reconcile.Result, error) { //nolint:gocyclo +func (r *AnsibleOperatorReconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) { //nolint:gocyclo // TODO: Try to reduce the complexity of this last measured at 42 (failing at > 30) and remove the // nolint:gocyclo u := &unstructured.Unstructured{} u.SetGroupVersionKind(r.GVK) - err := r.Client.Get(context.TODO(), request.NamespacedName, u) + err := r.Client.Get(ctx, request.NamespacedName, u) if apierrors.IsNotFound(err) { return reconcile.Result{}, nil } @@ -106,7 +106,7 @@ func (r *AnsibleOperatorReconciler) Reconcile(request reconcile.Request) (reconc logger.V(1).Info("Adding finalizer to resource", "Finalizer", finalizer) finalizers := append(pendingFinalizers, finalizer) u.SetFinalizers(finalizers) - err := r.Client.Update(context.TODO(), u) + err := r.Client.Update(ctx, u) if err != nil { logger.Error(err, "Unable to update cr with finalizer") return reconcileResult, err @@ -232,7 +232,7 @@ func (r *AnsibleOperatorReconciler) Reconcile(request reconcile.Request) (reconc // Need to get the unstructured object after the Ansible runner finishes. // This needs to hit the API server to retrieve updates. - err = r.APIReader.Get(context.TODO(), request.NamespacedName, u) + err = r.APIReader.Get(ctx, request.NamespacedName, u) if err != nil { if apierrors.IsNotFound(err) { return reconcile.Result{}, nil diff --git a/internal/ansible/controller/reconcile_test.go b/internal/ansible/controller/reconcile_test.go index 8a3ae9996cb..a697aac2839 100644 --- a/internal/ansible/controller/reconcile_test.go +++ b/internal/ansible/controller/reconcile_test.go @@ -545,7 +545,7 @@ func TestReconcile(t *testing.T) { ReconcilePeriod: tc.ReconcilePeriod, ManageStatus: tc.ManageStatus, } - result, err := aor.Reconcile(tc.Request) + result, err := aor.Reconcile(context.TODO(), tc.Request) if err != nil && !tc.ShouldError { t.Fatalf("Unexpected error: %v", err) } diff --git a/internal/ansible/predicate/predicate.go b/internal/ansible/predicate/predicate.go index e3753906a91..9f0e372314e 100644 --- a/internal/ansible/predicate/predicate.go +++ b/internal/ansible/predicate/predicate.go @@ -40,17 +40,17 @@ func NewResourceFilterPredicate(s metav1.LabelSelector) (predicate.Predicate, er // Predicate functions that call the EventFilter Function func (r resourceFilterPredicate) Update(e event.UpdateEvent) bool { - return r.eventFilter(e.MetaNew.GetLabels()) + return r.eventFilter(e.ObjectNew.GetLabels()) } func (r resourceFilterPredicate) Create(e event.CreateEvent) bool { - return r.eventFilter(e.Meta.GetLabels()) + return r.eventFilter(e.Object.GetLabels()) } func (r resourceFilterPredicate) Delete(e event.DeleteEvent) bool { - return r.eventFilter(e.Meta.GetLabels()) + return r.eventFilter(e.Object.GetLabels()) } func (r resourceFilterPredicate) Generic(e event.GenericEvent) bool { - return r.eventFilter(e.Meta.GetLabels()) + return r.eventFilter(e.Object.GetLabels()) } diff --git a/internal/ansible/proxy/proxy.go b/internal/ansible/proxy/proxy.go index b04ba8e8916..f44cbeb3577 100644 --- a/internal/ansible/proxy/proxy.go +++ b/internal/ansible/proxy/proxy.go @@ -16,6 +16,7 @@ package proxy import ( "bytes" + "context" "encoding/base64" "encoding/json" "errors" @@ -128,15 +129,15 @@ func Run(done chan error, o Options) error { if err != nil { return err } - stop := make(chan struct{}) + ctx, cancel := context.WithCancel(context.TODO()) go func() { - if err := informerCache.Start(stop); err != nil { + if err := informerCache.Start(ctx); err != nil { log.Error(err, "Failed to start informer cache") } - defer close(stop) + defer cancel() }() log.Info("Waiting for cache to sync...") - synced := informerCache.WaitForCacheSync(stop) + synced := informerCache.WaitForCacheSync(context.TODO()) if !synced { return fmt.Errorf("failed to sync cache") } diff --git a/internal/ansible/proxy/proxy_test.go b/internal/ansible/proxy/proxy_test.go index 0a677b94ff0..b9a442f0255 100644 --- a/internal/ansible/proxy/proxy_test.go +++ b/internal/ansible/proxy/proxy_test.go @@ -25,7 +25,6 @@ import ( kcorev1 "k8s.io/api/core/v1" kmetav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/config" "sigs.k8s.io/controller-runtime/pkg/manager" @@ -99,7 +98,7 @@ func TestHandler(t *testing.T) { } } -func createPod(name, namespace string, cl client.Client) (runtime.Object, error) { +func createPod(name, namespace string, cl client.Client) (client.Object, error) { three := int64(3) pod := &kcorev1.Pod{ ObjectMeta: kmetav1.ObjectMeta{ diff --git a/internal/cmd/ansible-operator/run/cmd.go b/internal/cmd/ansible-operator/run/cmd.go index 58661752b7c..fe3764c5a3e 100644 --- a/internal/cmd/ansible-operator/run/cmd.go +++ b/internal/cmd/ansible-operator/run/cmd.go @@ -24,9 +24,8 @@ import ( "github.com/spf13/cobra" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/rest" + "k8s.io/client-go/tools/leaderelection/resourcelock" "sigs.k8s.io/controller-runtime/pkg/cache" - "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/config" "sigs.k8s.io/controller-runtime/pkg/healthz" logf "sigs.k8s.io/controller-runtime/pkg/log" @@ -106,22 +105,13 @@ func run(cmd *cobra.Command, f *flags.Flags) { // Set default manager options // TODO: probably should expose the host & port as an environment variables options := manager.Options{ - HealthProbeBindAddress: fmt.Sprintf("%s:%d", metricsHost, healthProbePort), - MetricsBindAddress: f.MetricsAddress, - LeaderElection: f.EnableLeaderElection, - LeaderElectionID: f.LeaderElectionID, - LeaderElectionNamespace: f.LeaderElectionNamespace, - NewClient: func(cache cache.Cache, config *rest.Config, options client.Options) (client.Client, error) { - c, err := client.New(config, options) - if err != nil { - return nil, err - } - return &client.DelegatingClient{ - Reader: cache, - Writer: c, - StatusClient: c, - }, nil - }, + HealthProbeBindAddress: fmt.Sprintf("%s:%d", metricsHost, healthProbePort), + MetricsBindAddress: f.MetricsAddress, + LeaderElection: f.EnableLeaderElection, + LeaderElectionID: f.LeaderElectionID, + LeaderElectionResourceLock: resourcelock.ConfigMapsResourceLock, + LeaderElectionNamespace: f.LeaderElectionNamespace, + ClientBuilder: manager.NewClientBuilder(), } namespace, found := os.LookupEnv(k8sutil.WatchNamespaceEnvVar) diff --git a/internal/cmd/helm-operator/run/cmd.go b/internal/cmd/helm-operator/run/cmd.go index 7b99c33a0bd..195d4a9f9c1 100644 --- a/internal/cmd/helm-operator/run/cmd.go +++ b/internal/cmd/helm-operator/run/cmd.go @@ -23,9 +23,8 @@ import ( "github.com/spf13/cobra" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/rest" + "k8s.io/client-go/tools/leaderelection/resourcelock" "sigs.k8s.io/controller-runtime/pkg/cache" - crclient "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/config" logf "sigs.k8s.io/controller-runtime/pkg/log" zapf "sigs.k8s.io/controller-runtime/pkg/log/zap" @@ -96,21 +95,12 @@ func run(cmd *cobra.Command, f *flags.Flags) { // Set default manager options options := manager.Options{ - MetricsBindAddress: f.MetricsAddress, - LeaderElection: f.EnableLeaderElection, - LeaderElectionID: f.LeaderElectionID, - LeaderElectionNamespace: f.LeaderElectionNamespace, - NewClient: func(cache cache.Cache, config *rest.Config, options crclient.Options) (crclient.Client, error) { - c, err := crclient.New(config, options) - if err != nil { - return nil, err - } - return &crclient.DelegatingClient{ - Reader: cache, - Writer: c, - StatusClient: c, - }, nil - }, + MetricsBindAddress: f.MetricsAddress, + LeaderElection: f.EnableLeaderElection, + LeaderElectionID: f.LeaderElectionID, + LeaderElectionResourceLock: resourcelock.ConfigMapsResourceLock, + LeaderElectionNamespace: f.LeaderElectionNamespace, + ClientBuilder: manager.NewClientBuilder(), } namespace, found := os.LookupEnv(k8sutil.WatchNamespaceEnvVar) diff --git a/internal/cmd/operator-sdk/generate/internal/genutil.go b/internal/cmd/operator-sdk/generate/internal/genutil.go index 46590416f27..0b6f6672cb3 100644 --- a/internal/cmd/operator-sdk/generate/internal/genutil.go +++ b/internal/cmd/operator-sdk/generate/internal/genutil.go @@ -26,7 +26,7 @@ import ( "github.com/blang/semver" apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" apiextv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/yaml" ) @@ -55,7 +55,7 @@ func IsPipeReader() bool { } // WriteObjects writes each object in objs to w. -func WriteObjects(w io.Writer, objs ...controllerutil.Object) error { +func WriteObjects(w io.Writer, objs ...client.Object) error { for _, obj := range objs { if err := writeObject(w, obj); err != nil { return err @@ -65,7 +65,7 @@ func WriteObjects(w io.Writer, objs ...controllerutil.Object) error { } // WriteObjectsToFiles creates dir then writes each object in objs to a file in dir. -func WriteObjectsToFiles(dir string, objs ...controllerutil.Object) error { +func WriteObjectsToFiles(dir string, objs ...client.Object) error { if err := os.MkdirAll(dir, 0755); err != nil { return err } @@ -97,7 +97,7 @@ func makeCRDFileName(group, resource string) string { return fmt.Sprintf("%s_%s.yaml", group, resource) } -func makeObjectFileName(obj controllerutil.Object) string { +func makeObjectFileName(obj client.Object) string { gvk := obj.GetObjectKind().GroupVersionKind() if gvk.Group == "" { return fmt.Sprintf("%s_%s_%s.yaml", obj.GetName(), gvk.Version, strings.ToLower(gvk.Kind)) diff --git a/internal/cmd/operator-sdk/generate/internal/manifests.go b/internal/cmd/operator-sdk/generate/internal/manifests.go index 54d17fe41ae..d40c2e03888 100644 --- a/internal/cmd/operator-sdk/generate/internal/manifests.go +++ b/internal/cmd/operator-sdk/generate/internal/manifests.go @@ -16,13 +16,13 @@ package genutil import ( "github.com/operator-framework/operator-registry/pkg/lib/bundle" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sigs.k8s.io/controller-runtime/pkg/client" "github.com/operator-framework/operator-sdk/internal/generate/collector" ) // GetManifestObjects returns all objects to be written to a manifests directory from collector.Manifests. -func GetManifestObjects(c *collector.Manifests) (objs []controllerutil.Object) { +func GetManifestObjects(c *collector.Manifests) (objs []client.Object) { // All CRDs passed in should be written. for i := range c.V1CustomResourceDefinitions { objs = append(objs, &c.V1CustomResourceDefinitions[i]) @@ -66,7 +66,7 @@ func GetManifestObjects(c *collector.Manifests) (objs []controllerutil.Object) { // not include explicit namespace settings. OLM automatically installs namespaced // resources in the same namespace that the operator is installed in, which is determined // at runtime, not bundle/packagemanifests creation time. -func removeNamespace(objs []controllerutil.Object) { +func removeNamespace(objs []client.Object) { for _, obj := range objs { obj.SetNamespace("") } diff --git a/internal/generate/collector/clusterserviceversion.go b/internal/generate/collector/clusterserviceversion.go index f8bdd67365a..73464bfb1cc 100644 --- a/internal/generate/collector/clusterserviceversion.go +++ b/internal/generate/collector/clusterserviceversion.go @@ -16,7 +16,7 @@ package collector import ( rbacv1 "k8s.io/api/rbac/v1" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sigs.k8s.io/controller-runtime/pkg/client" ) // TODO(estroz): there's a significant amount of code dupliation here, a byproduct of Go's type system. @@ -31,7 +31,7 @@ const ( // SplitCSVPermissionsObjects splits roles that should be written to a CSV as permissions (in) // from roles and role bindings that should be written directly to the bundle (out). -func (c *Manifests) SplitCSVPermissionsObjects() (in, out []controllerutil.Object) { //nolint:dupl +func (c *Manifests) SplitCSVPermissionsObjects() (in, out []client.Object) { //nolint:dupl roleMap := make(map[string]*rbacv1.Role) for i := range c.Roles { roleMap[c.Roles[i].GetName()] = &c.Roles[i] @@ -127,7 +127,7 @@ func (c *Manifests) SplitCSVPermissionsObjects() (in, out []controllerutil.Objec // SplitCSVClusterPermissionsObjects splits cluster roles that should be written to a CSV as clusterPermissions (in) // from cluster roles and cluster role bindings that should be written directly to the bundle (out). -func (c *Manifests) SplitCSVClusterPermissionsObjects() (in, out []controllerutil.Object) { //nolint:dupl +func (c *Manifests) SplitCSVClusterPermissionsObjects() (in, out []client.Object) { //nolint:dupl roleMap := make(map[string]*rbacv1.ClusterRole) for i := range c.ClusterRoles { roleMap[c.ClusterRoles[i].GetName()] = &c.ClusterRoles[i] diff --git a/internal/generate/collector/clusterserviceversion_test.go b/internal/generate/collector/clusterserviceversion_test.go index 01fde88ecc7..9ae61b7cbb9 100644 --- a/internal/generate/collector/clusterserviceversion_test.go +++ b/internal/generate/collector/clusterserviceversion_test.go @@ -20,13 +20,13 @@ import ( . "github.com/onsi/gomega" appsv1 "k8s.io/api/apps/v1" rbacv1 "k8s.io/api/rbac/v1" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sigs.k8s.io/controller-runtime/pkg/client" ) var _ = Describe("ClusterServiceVersion", func() { var ( c *Manifests - in, out []controllerutil.Object + in, out []client.Object ) BeforeEach(func() { @@ -244,23 +244,23 @@ var _ = Describe("ClusterServiceVersion", func() { }) -func getRoleNames(objs []controllerutil.Object) []string { +func getRoleNames(objs []client.Object) []string { return getNamesForKind("Role", objs) } -func getRoleBindingNames(objs []controllerutil.Object) []string { +func getRoleBindingNames(objs []client.Object) []string { return getNamesForKind("RoleBinding", objs) } -func getClusterRoleNames(objs []controllerutil.Object) []string { +func getClusterRoleNames(objs []client.Object) []string { return getNamesForKind("ClusterRole", objs) } -func getClusterRoleBindingNames(objs []controllerutil.Object) []string { +func getClusterRoleBindingNames(objs []client.Object) []string { return getNamesForKind("ClusterRoleBinding", objs) } -func getNamesForKind(kind string, objs []controllerutil.Object) (names []string) { +func getNamesForKind(kind string, objs []client.Object) (names []string) { for _, obj := range objs { if obj.GetObjectKind().GroupVersionKind().Kind == kind { names = append(names, obj.GetName()) diff --git a/internal/helm/controller/reconcile.go b/internal/helm/controller/reconcile.go index f93b492fbc0..edba053458d 100644 --- a/internal/helm/controller/reconcile.go +++ b/internal/helm/controller/reconcile.go @@ -25,7 +25,6 @@ import ( "helm.sh/helm/v3/pkg/storage/driver" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/tools/record" @@ -65,7 +64,7 @@ const ( // release changes are necessary, Reconcile will create or patch the underlying // resources to match the expected release manifest. -func (r HelmOperatorReconciler) Reconcile(request reconcile.Request) (reconcile.Result, error) { //nolint:gocyclo +func (r HelmOperatorReconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) { //nolint:gocyclo o := &unstructured.Unstructured{} o.SetGroupVersionKind(r.GVK) o.SetNamespace(request.Namespace) @@ -78,7 +77,7 @@ func (r HelmOperatorReconciler) Reconcile(request reconcile.Request) (reconcile. ) log.V(1).Info("Reconciling") - err := r.Client.Get(context.TODO(), request.NamespacedName, o) + err := r.Client.Get(ctx, request.NamespacedName, o) if apierrors.IsNotFound(err) { return reconcile.Result{}, nil } @@ -102,7 +101,7 @@ func (r HelmOperatorReconciler) Reconcile(request reconcile.Request) (reconcile. return reconcile.Result{}, nil } - uninstalledRelease, err := manager.UninstallRelease(context.TODO()) + uninstalledRelease, err := manager.UninstallRelease(ctx) if err != nil && !errors.Is(err, driver.ErrReleaseNotFound) { log.Error(err, "Failed to uninstall release") status.SetCondition(types.HelmAppCondition{ @@ -158,7 +157,7 @@ func (r HelmOperatorReconciler) Reconcile(request reconcile.Request) (reconcile. Status: types.StatusTrue, }) - if err := manager.Sync(context.TODO()); err != nil { + if err := manager.Sync(ctx); err != nil { log.Error(err, "Failed to sync release") status.SetCondition(types.HelmAppCondition{ Type: types.ConditionIrreconcilable, @@ -176,7 +175,7 @@ func (r HelmOperatorReconciler) Reconcile(request reconcile.Request) (reconcile. r.EventRecorder.Eventf(o, "Warning", "OverrideValuesInUse", "Chart value %q overridden to %q by operator's watches.yaml", k, v) } - installedRelease, err := manager.InstallRelease(context.TODO()) + installedRelease, err := manager.InstallRelease(ctx) if err != nil { log.Error(err, "Release failed") status.SetCondition(types.HelmAppCondition{ @@ -242,7 +241,7 @@ func (r HelmOperatorReconciler) Reconcile(request reconcile.Request) (reconcile. "Chart value %q overridden to %q by operator's watches.yaml", k, v) } force := hasHelmUpgradeForceAnnotation(o) - previousRelease, upgradedRelease, err := manager.UpgradeRelease(context.TODO(), release.ForceUpgrade(force)) + previousRelease, upgradedRelease, err := manager.UpgradeRelease(ctx, release.ForceUpgrade(force)) if err != nil { log.Error(err, "Release failed") status.SetCondition(types.HelmAppCondition{ @@ -294,7 +293,7 @@ func (r HelmOperatorReconciler) Reconcile(request reconcile.Request) (reconcile. // no longer being attempted. status.RemoveCondition(types.ConditionReleaseFailed) - expectedRelease, err := manager.ReconcileRelease(context.TODO()) + expectedRelease, err := manager.ReconcileRelease(ctx) if err != nil { log.Error(err, "Failed to reconcile release") status.SetCondition(types.HelmAppCondition{ @@ -356,7 +355,7 @@ func hasHelmUpgradeForceAnnotation(o *unstructured.Unstructured) bool { return value } -func (r HelmOperatorReconciler) updateResource(o runtime.Object) error { +func (r HelmOperatorReconciler) updateResource(o client.Object) error { return retry.RetryOnConflict(retry.DefaultBackoff, func() error { return r.Client.Update(context.TODO(), o) }) @@ -369,11 +368,8 @@ func (r HelmOperatorReconciler) updateResourceStatus(o *unstructured.Unstructure }) } -func (r HelmOperatorReconciler) waitForDeletion(o runtime.Object) error { - key, err := client.ObjectKeyFromObject(o) - if err != nil { - return err - } +func (r HelmOperatorReconciler) waitForDeletion(o client.Object) error { + key := client.ObjectKeyFromObject(o) ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) defer cancel() diff --git a/internal/helm/release/manager.go b/internal/helm/release/manager.go index 33ce5e5d1a8..f6b671b9335 100644 --- a/internal/helm/release/manager.go +++ b/internal/helm/release/manager.go @@ -248,7 +248,7 @@ func reconcileRelease(_ context.Context, kubeClient kube.Interface, expectedMani } helper := resource.NewHelper(expected.Client, expected.Mapping) - existing, err := helper.Get(expected.Namespace, expected.Name, expected.Export) + existing, err := helper.Get(expected.Namespace, expected.Name) if apierrors.IsNotFound(err) { if _, err := helper.Create(expected.Namespace, true, expected.Object); err != nil { return fmt.Errorf("create error: %s", err) diff --git a/internal/kubebuilder/filesystem/errors_test.go b/internal/kubebuilder/filesystem/errors_test.go index cc3651a1017..090101fa4e4 100644 --- a/internal/kubebuilder/filesystem/errors_test.go +++ b/internal/kubebuilder/filesystem/errors_test.go @@ -19,18 +19,12 @@ package filesystem import ( "errors" "path/filepath" - "testing" . "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo/extensions/table" . "github.com/onsi/gomega" ) -func TestErrors(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Error suite") -} - var _ = Describe("Errors", func() { var ( path = filepath.Join("path", "to", "file") diff --git a/internal/kubebuilder/filesystem/filesystem_suite_test.go b/internal/kubebuilder/filesystem/filesystem_suite_test.go new file mode 100644 index 00000000000..c3be2d93bde --- /dev/null +++ b/internal/kubebuilder/filesystem/filesystem_suite_test.go @@ -0,0 +1,27 @@ +/* +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 filesystem + +import ( + "testing" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +func TestScaffold(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Filesystem Suite") +} diff --git a/internal/kubebuilder/filesystem/filesystem_test.go b/internal/kubebuilder/filesystem/filesystem_test.go index 9f98ce400ac..6a3d216f112 100644 --- a/internal/kubebuilder/filesystem/filesystem_test.go +++ b/internal/kubebuilder/filesystem/filesystem_test.go @@ -18,17 +18,11 @@ package filesystem import ( "os" - "testing" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) -func TestFileSystem(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "FileSystem suite") -} - var _ = Describe("FileSystem", func() { Describe("New", func() { const ( diff --git a/internal/kubebuilder/filesystem/mock_test.go b/internal/kubebuilder/filesystem/mock_test.go index 37f9e827cce..e9e7d58ccbf 100644 --- a/internal/kubebuilder/filesystem/mock_test.go +++ b/internal/kubebuilder/filesystem/mock_test.go @@ -20,17 +20,11 @@ import ( "bytes" "errors" "path/filepath" - "testing" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) -func TestMockFileSystem(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "MockFileSystem suite") -} - //nolint:dupl var _ = Describe("MockFileSystem", func() { var ( diff --git a/internal/kubebuilder/machinery/errors_test.go b/internal/kubebuilder/machinery/errors_test.go index adcf32b4f70..3d6b8ce14e4 100644 --- a/internal/kubebuilder/machinery/errors_test.go +++ b/internal/kubebuilder/machinery/errors_test.go @@ -19,18 +19,12 @@ package machinery import ( "errors" "path/filepath" - "testing" . "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo/extensions/table" . "github.com/onsi/gomega" ) -func TestErrors(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Error suite") -} - var _ = Describe("Errors", func() { var ( path = filepath.Join("path", "to", "file") diff --git a/internal/kubebuilder/machinery/machinery_suite_test.go b/internal/kubebuilder/machinery/machinery_suite_test.go new file mode 100644 index 00000000000..107008e04da --- /dev/null +++ b/internal/kubebuilder/machinery/machinery_suite_test.go @@ -0,0 +1,27 @@ +/* +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 machinery + +import ( + "testing" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +func TestScaffold(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Machinery Suite") +} diff --git a/internal/kubebuilder/machinery/scaffold_test.go b/internal/kubebuilder/machinery/scaffold_test.go index 65d4222dba9..e553f9abe5a 100644 --- a/internal/kubebuilder/machinery/scaffold_test.go +++ b/internal/kubebuilder/machinery/scaffold_test.go @@ -17,7 +17,6 @@ package machinery import ( "bytes" "errors" - "testing" . "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo/extensions/table" @@ -28,11 +27,6 @@ import ( "github.com/operator-framework/operator-sdk/internal/kubebuilder/filesystem" ) -func TestScaffold(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Scaffold suite") -} - var _ = Describe("Scaffold", func() { Describe("NewScaffold", func() { var ( @@ -41,61 +35,27 @@ var _ = Describe("Scaffold", func() { ok bool ) - Context("when using no plugins", func() { - BeforeEach(func() { - si = NewScaffold() - s, ok = si.(*scaffold) - }) - - It("should be a scaffold instance", func() { - Expect(ok).To(BeTrue()) - }) - - It("should not have a nil fs", func() { - Expect(s.fs).NotTo(BeNil()) - }) - - It("should not have any plugin", func() { - Expect(len(s.plugins)).To(Equal(0)) - }) - }) - - Context("when using one plugin", func() { - BeforeEach(func() { - si = NewScaffold(fakePlugin{}) - s, ok = si.(*scaffold) - }) - - It("should be a scaffold instance", func() { - Expect(ok).To(BeTrue()) - }) - - It("should not have a nil fs", func() { - Expect(s.fs).NotTo(BeNil()) - }) - - It("should have one plugin", func() { - Expect(len(s.plugins)).To(Equal(1)) - }) - }) - - Context("when using several plugins", func() { - BeforeEach(func() { - si = NewScaffold(fakePlugin{}, fakePlugin{}, fakePlugin{}) - s, ok = si.(*scaffold) - }) - - It("should be a scaffold instance", func() { - Expect(ok).To(BeTrue()) - }) - - It("should not have a nil fs", func() { - Expect(s.fs).NotTo(BeNil()) - }) - - It("should have several plugins", func() { - Expect(len(s.plugins)).To(Equal(3)) - }) + It("should create a valid scaffold", func() { + By("passing no plugins") + si = NewScaffold() + s, ok = si.(*scaffold) + Expect(ok).To(BeTrue()) + Expect(s.fs).NotTo(BeNil()) + Expect(len(s.plugins)).To(Equal(0)) + + By("passing one plugin") + si = NewScaffold(fakePlugin{}) + s, ok = si.(*scaffold) + Expect(ok).To(BeTrue()) + Expect(s.fs).NotTo(BeNil()) + Expect(len(s.plugins)).To(Equal(1)) + + By("passing multiple plugins") + si = NewScaffold(fakePlugin{}, fakePlugin{}, fakePlugin{}) + s, ok = si.(*scaffold) + Expect(ok).To(BeTrue()) + Expect(s.fs).NotTo(BeNil()) + Expect(len(s.plugins)).To(Equal(3)) }) }) diff --git a/internal/olm/client/client.go b/internal/olm/client/client.go index b904f0ecb0d..acacb683648 100644 --- a/internal/olm/client/client.go +++ b/internal/olm/client/client.go @@ -34,7 +34,6 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/kubernetes/scheme" @@ -110,44 +109,33 @@ func NewClientForConfig(cfg *rest.Config) (*Client, error) { return c, nil } -func (c Client) DoCreate(ctx context.Context, objs ...runtime.Object) error { +func (c Client) DoCreate(ctx context.Context, objs ...client.Object) error { for _, obj := range objs { - a, err := meta.Accessor(obj) - if err != nil { - return err - } kind := obj.GetObjectKind().GroupVersionKind().Kind - log.Infof(" Creating %s %q", kind, getName(a.GetNamespace(), a.GetName())) - err = c.KubeClient.Create(ctx, obj) + log.Infof(" Creating %s %q", kind, getName(obj.GetNamespace(), obj.GetName())) + err := c.KubeClient.Create(ctx, obj) if err != nil { if !apierrors.IsAlreadyExists(err) { return err } - log.Infof(" %s %q already exists", kind, getName(a.GetNamespace(), a.GetName())) + log.Infof(" %s %q already exists", kind, getName(obj.GetNamespace(), obj.GetName())) } } return nil } -func (c Client) DoDelete(ctx context.Context, objs ...runtime.Object) error { +func (c Client) DoDelete(ctx context.Context, objs ...client.Object) error { for _, obj := range objs { - a, err := meta.Accessor(obj) - if err != nil { - return err - } kind := obj.GetObjectKind().GroupVersionKind().Kind - log.Infof(" Deleting %s %q", kind, getName(a.GetNamespace(), a.GetName())) - err = c.KubeClient.Delete(ctx, obj, client.PropagationPolicy(metav1.DeletePropagationBackground)) + log.Infof(" Deleting %s %q", kind, getName(obj.GetNamespace(), obj.GetName())) + err := c.KubeClient.Delete(ctx, obj, client.PropagationPolicy(metav1.DeletePropagationBackground)) if err != nil { if !apierrors.IsNotFound(err) { return err } - log.Infof(" %s %q does not exist", kind, getName(a.GetNamespace(), a.GetName())) - } - key, err := client.ObjectKeyFromObject(obj) - if err != nil { - return err + log.Infof(" %s %q does not exist", kind, getName(obj.GetNamespace(), obj.GetName())) } + key := client.ObjectKeyFromObject(obj) if err := wait.PollImmediateUntil(time.Millisecond*100, func() (bool, error) { err := c.KubeClient.Get(ctx, key, obj) if apierrors.IsNotFound(err) { diff --git a/internal/olm/client/status.go b/internal/olm/client/status.go index 8bd5e90059d..16152c57926 100644 --- a/internal/olm/client/status.go +++ b/internal/olm/client/status.go @@ -25,7 +25,6 @@ import ( "sort" "text/tabwriter" - log "github.com/sirupsen/logrus" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" @@ -35,6 +34,7 @@ import ( "k8s.io/apimachinery/pkg/types" apiutilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apimachinery/pkg/util/sets" + "sigs.k8s.io/controller-runtime/pkg/client" ) type Status struct { @@ -50,17 +50,13 @@ type ResourceStatus struct { requestObject runtime.Object // Needed for context on errors from requests on an object. } -func (c Client) GetObjectsStatus(ctx context.Context, objs ...runtime.Object) Status { +func (c Client) GetObjectsStatus(ctx context.Context, objs ...client.Object) Status { var rss []ResourceStatus for _, obj := range objs { gvk := obj.GetObjectKind().GroupVersionKind() - a, aerr := meta.Accessor(obj) - if aerr != nil { - log.Fatalf("Object %s: %v", gvk, aerr) - } nn := types.NamespacedName{ - Namespace: a.GetNamespace(), - Name: a.GetName(), + Namespace: obj.GetNamespace(), + Name: obj.GetName(), } rs := ResourceStatus{ NamespacedName: nn, diff --git a/internal/olm/installer/client.go b/internal/olm/installer/client.go index 51bdd049e27..75a1defeac2 100644 --- a/internal/olm/installer/client.go +++ b/internal/olm/installer/client.go @@ -33,12 +33,12 @@ import ( olmmanifests "github.com/operator-framework/operator-sdk/internal/bindata/olm" log "github.com/sirupsen/logrus" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/util/yaml" "k8s.io/client-go/rest" + "sigs.k8s.io/controller-runtime/pkg/client" olmresourceclient "github.com/operator-framework/operator-sdk/internal/olm/client" ) @@ -299,7 +299,7 @@ func (c Client) doRequest(ctx context.Context, url string) (*http.Response, erro return resp, nil } -func toObjects(us ...unstructured.Unstructured) (objs []runtime.Object) { +func toObjects(us ...unstructured.Unstructured) (objs []client.Object) { for i := range us { objs = append(objs, &us[i]) } diff --git a/internal/olm/operator/config.go b/internal/olm/operator/config.go index a60402fd3b9..9e7d545a796 100644 --- a/internal/olm/operator/config.go +++ b/internal/olm/operator/config.go @@ -108,7 +108,7 @@ type operatorClient struct { client.Client } -func (c *operatorClient) Create(ctx context.Context, obj runtime.Object, opts ...client.CreateOption) error { +func (c *operatorClient) Create(ctx context.Context, obj client.Object, opts ...client.CreateOption) error { opts = append(opts, client.FieldOwner("operator-sdk")) return c.Client.Create(ctx, obj, opts...) } diff --git a/internal/olm/operator/registry/configmap/configmap_test.go b/internal/olm/operator/registry/configmap/configmap_test.go index 9aeda0ec106..b54c86222b3 100644 --- a/internal/olm/operator/registry/configmap/configmap_test.go +++ b/internal/olm/operator/registry/configmap/configmap_test.go @@ -244,20 +244,16 @@ var _ = Describe("ConfigMap", func() { ) BeforeEach(func() { fakeclient := fake.NewFakeClient( - &corev1.ConfigMapList{ - Items: []corev1.ConfigMap{ - { - ObjectMeta: metav1.ObjectMeta{ - Namespace: "testns", - Labels: makeRegistryLabels("test"), - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Namespace: "testns2", - Labels: makeRegistryLabels("test"), - }, - }, + &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "testns", + Labels: makeRegistryLabels("test"), + }, + }, + &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "testns2", + Labels: makeRegistryLabels("test"), }, }, ) diff --git a/internal/olm/operator/registry/configmap/registry.go b/internal/olm/operator/registry/configmap/registry.go index 5f8bba2f53c..c06dd5a5613 100644 --- a/internal/olm/operator/registry/configmap/registry.go +++ b/internal/olm/operator/registry/configmap/registry.go @@ -24,8 +24,8 @@ import ( log "github.com/sirupsen/logrus" appsv1 "k8s.io/api/apps/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" olmclient "github.com/operator-framework/operator-sdk/internal/olm/client" @@ -130,7 +130,7 @@ func (rr *RegistryResources) CreatePackageManifestsRegistry(ctx context.Context, } // Objects to create. - objs := make([]runtime.Object, 0, len(binaryDataByConfigMap)+2) + objs := make([]client.Object, 0, len(binaryDataByConfigMap)+2) // Options for creating a Deployment, since we need to mount all package // ConfigMaps as volumes into pods. opts := make([]func(*appsv1.Deployment), 0, 2*len(binaryDataByConfigMap)+1) @@ -193,7 +193,7 @@ func (rr *RegistryResources) DeletePackageManifestsRegistry(ctx context.Context, } // Delete registry Deployment, Service, and ConfigMaps by type. - objs := make([]runtime.Object, len(configMaps)+2) + objs := make([]client.Object, len(configMaps)+2) for i := range configMaps { objs[i] = &configMaps[i] } diff --git a/internal/olm/operator/registry/configmap/registry_test.go b/internal/olm/operator/registry/configmap/registry_test.go index 4ee359efa22..e1436c01ae3 100644 --- a/internal/olm/operator/registry/configmap/registry_test.go +++ b/internal/olm/operator/registry/configmap/registry_test.go @@ -62,14 +62,10 @@ var _ = Describe("Registry", func() { Describe("DeletePackageManifestsRegistry", func() { It("should delete the package manifest registry", func() { fakeclient := fake.NewFakeClient( - &corev1.ConfigMapList{ - Items: []corev1.ConfigMap{ - { - ObjectMeta: metav1.ObjectMeta{ - Namespace: "testns", - Labels: makeRegistryLabels("test"), - }, - }, + &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "testns", + Labels: makeRegistryLabels("test"), }, }, newRegistryDeployment("pkgName", "testns"), @@ -128,14 +124,10 @@ var _ = Describe("Registry", func() { BeforeEach(func() { testns = "testns" fakeclient := fake.NewFakeClient( - &corev1.ConfigMapList{ - Items: []corev1.ConfigMap{ - { - ObjectMeta: metav1.ObjectMeta{ - Namespace: testns, - Labels: makeRegistryLabels("test"), - }, - }, + &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: testns, + Labels: makeRegistryLabels("test"), }, }, newRegistryDeployment("pkgName", testns), @@ -205,22 +197,18 @@ var _ = Describe("Registry", func() { BeforeEach(func() { testns = "testns" fakeclient := fake.NewFakeClient( - &corev1.ConfigMapList{ - Items: []corev1.ConfigMap{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "config1", - Namespace: testns, - Labels: makeRegistryLabels("pkgName"), - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: "config2", - Namespace: testns, - Labels: makeRegistryLabels("pkgName"), - }, - }, + &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "config1", + Namespace: testns, + Labels: makeRegistryLabels("pkgName"), + }, + }, + &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "config2", + Namespace: testns, + Labels: makeRegistryLabels("pkgName"), }, }, newRegistryDeployment("pkgName", testns), @@ -279,22 +267,18 @@ var _ = Describe("Registry", func() { It("should return true if the number of files to be added to the registry don't match the numberof files currently in the registry", func() { rr.Client.KubeClient = fake.NewFakeClient( - &corev1.ConfigMapList{ - Items: []corev1.ConfigMap{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: getRegistryConfigMapName("pkgName") + "-package", - Namespace: testns, - Labels: makeRegistryLabels("pkgName"), - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: "config2", - Namespace: testns, - Labels: makeRegistryLabels("pkgName"), - }, - }, + &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: getRegistryConfigMapName("pkgName") + "-package", + Namespace: testns, + Labels: makeRegistryLabels("pkgName"), + }, + }, + &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "config2", + Namespace: testns, + Labels: makeRegistryLabels("pkgName"), }, }, newRegistryDeployment("pkgName", testns), @@ -315,23 +299,19 @@ var _ = Describe("Registry", func() { val2: "val2", }, "userInput") rr.Client.KubeClient = fake.NewFakeClient( - &corev1.ConfigMapList{ - Items: []corev1.ConfigMap{ - { - BinaryData: binarydata, - ObjectMeta: metav1.ObjectMeta{ - Name: getRegistryConfigMapName("pkgName") + "-package", - Namespace: testns, - Labels: makeRegistryLabels("pkgName"), - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: "config2", - Namespace: testns, - Labels: makeRegistryLabels("pkgName"), - }, - }, + &corev1.ConfigMap{ + BinaryData: binarydata, + ObjectMeta: metav1.ObjectMeta{ + Name: getRegistryConfigMapName("pkgName") + "-package", + Namespace: testns, + Labels: makeRegistryLabels("pkgName"), + }, + }, + &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "config2", + Namespace: testns, + Labels: makeRegistryLabels("pkgName"), }, }, newRegistryDeployment("pkgName", testns), @@ -353,23 +333,19 @@ var _ = Describe("Registry", func() { }, }) rr.Client.KubeClient = fake.NewFakeClient( - &corev1.ConfigMapList{ - Items: []corev1.ConfigMap{ - { - BinaryData: binarydata, - ObjectMeta: metav1.ObjectMeta{ - Name: getRegistryConfigMapName("pkgName") + "-package", - Namespace: testns, - Labels: makeRegistryLabels("pkgName"), - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: getRegistryConfigMapName("pkgName2") + "-package", - Namespace: testns, - Labels: makeRegistryLabels("pkgName"), - }, - }, + &corev1.ConfigMap{ + BinaryData: binarydata, + ObjectMeta: metav1.ObjectMeta{ + Name: getRegistryConfigMapName("pkgName") + "-package", + Namespace: testns, + Labels: makeRegistryLabels("pkgName"), + }, + }, + &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: getRegistryConfigMapName("pkgName2") + "-package", + Namespace: testns, + Labels: makeRegistryLabels("pkgName"), }, }, newRegistryDeployment("pkgName", testns), diff --git a/internal/olm/operator/registry/operator_installer.go b/internal/olm/operator/registry/operator_installer.go index aa1b68e0849..f49d71078ee 100644 --- a/internal/olm/operator/registry/operator_installer.go +++ b/internal/olm/operator/registry/operator_installer.go @@ -99,10 +99,7 @@ func (o OperatorInstaller) InstallOperator(ctx context.Context) (*v1alpha1.Clust //nolint:unused func (o OperatorInstaller) waitForCatalogSource(ctx context.Context, cs *v1alpha1.CatalogSource) error { - catSrcKey, err := client.ObjectKeyFromObject(cs) - if err != nil { - return fmt.Errorf("error getting catalog source key: %v", err) - } + catSrcKey := client.ObjectKeyFromObject(cs) // verify that catalog source connection status is READY catSrcCheck := wait.ConditionFunc(func() (done bool, err error) { diff --git a/internal/olm/operator/uninstall.go b/internal/olm/operator/uninstall.go index 427964e1540..cd21d17ba58 100644 --- a/internal/olm/operator/uninstall.go +++ b/internal/olm/operator/uninstall.go @@ -29,7 +29,6 @@ import ( "k8s.io/apimachinery/pkg/util/wait" "k8s.io/kubectl/pkg/util/slice" "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" ) const ( @@ -161,7 +160,7 @@ func (u *Uninstall) Run(ctx context.Context) error { return nil } -func (u *Uninstall) deleteObjects(ctx context.Context, waitForDelete bool, objs ...controllerutil.Object) error { +func (u *Uninstall) deleteObjects(ctx context.Context, waitForDelete bool, objs ...client.Object) error { for _, obj := range objs { obj := obj lowerKind := strings.ToLower(obj.GetObjectKind().GroupVersionKind().Kind) @@ -171,10 +170,7 @@ func (u *Uninstall) deleteObjects(ctx context.Context, waitForDelete bool, objs u.Logf("%s %q deleted", lowerKind, obj.GetName()) } if waitForDelete { - key, err := client.ObjectKeyFromObject(obj) - if err != nil { - return fmt.Errorf("get %s key: %v", lowerKind, err) - } + key := client.ObjectKeyFromObject(obj) if err := wait.PollImmediateUntil(250*time.Millisecond, func() (bool, error) { if err := u.config.Client.Get(ctx, key, obj); apierrors.IsNotFound(err) { return true, nil @@ -207,7 +203,7 @@ func (u *Uninstall) getInstalledCSV(ctx context.Context, subscription *v1alpha1. } // getCRDs returns the list of CRDs required by a CSV. -func getCRDs(csv *v1alpha1.ClusterServiceVersion) (crds []controllerutil.Object) { +func getCRDs(csv *v1alpha1.ClusterServiceVersion) (crds []client.Object) { for _, resource := range csv.Status.RequirementStatus { if resource.Kind == crdKind { obj := &unstructured.Unstructured{} diff --git a/internal/plugins/helm/v1/chartutil/chart_test.go b/internal/plugins/helm/v1/chartutil/chart_test.go index b489fa093ed..f0df663d2cd 100644 --- a/internal/plugins/helm/v1/chartutil/chart_test.go +++ b/internal/plugins/helm/v1/chartutil/chart_test.go @@ -30,7 +30,7 @@ import ( ) func TestCreateChart(t *testing.T) { - srv, err := repotest.NewTempServer("testdata/*.tgz") + srv, err := repotest.NewTempServerWithCleanup(t, "testdata/*.tgz") if err != nil { t.Fatalf("Failed to create new temp server: %s", err) } From 844883a39c8cd16b188cbd117591a3c922136026 Mon Sep 17 00:00:00 2001 From: Camila Macedo Date: Sat, 5 Dec 2020 17:37:39 +0000 Subject: [PATCH 232/376] e2e-intgration-tests: keep using OLM version 0.15.1 (#4283) Signed-off-by: reinvantveer --- hack/tests/integration.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hack/tests/integration.sh b/hack/tests/integration.sh index 673c5e0f02d..b0be6164bdf 100755 --- a/hack/tests/integration.sh +++ b/hack/tests/integration.sh @@ -24,10 +24,11 @@ load_image_if_kind "$OSDK_INTEGRATION_IMAGE" popd +# todo: upgrade to use the 0.17.0 when the issue https://github.com/operator-framework/operator-sdk/issues/4284 be solved # Install OLM on the cluster if not installed. olm_latest_exists=0 if ! operator-sdk olm status > /dev/null 2>&1; then - operator-sdk olm install --version=0.17.0 + operator-sdk olm install --version=0.15.1 olm_latest_exists=1 fi @@ -38,7 +39,8 @@ go test -v ./test/integration header_text "Integration tests succeeded" +# todo: upgrade to use the 0.17.0 when the issue https://github.com/operator-framework/operator-sdk/issues/4284 be solved # Uninstall OLM if it was installed for test purposes. if eval "(( $olm_latest_exists ))"; then - operator-sdk olm uninstall --version=0.17.0 + operator-sdk olm uninstall --version=0.15.1 fi From 0137188539891eef386a00cf52c8e53f3b3a506e Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Sat, 5 Dec 2020 10:16:15 -0800 Subject: [PATCH 233/376] *: upgrade kubebuilder, add go/v3-alpha to the list of available plugins (#4282) go.mod: upgrade kubebuilder to latest master commit internal/came/operator-sdk: add go/v3-alpha to the list of available plugins testdata: update v2 samples and add v3 samples test: test go/v3-alpha Signed-off-by: reinvantveer --- changelog/fragments/go-v3-alpha.yaml | 8 + go.mod | 2 +- go.sum | 4 +- hack/generate/samples/generate_testdata.go | 4 +- hack/generate/samples/internal/go/generate.go | 27 + .../go/{ => v2}/memcached_with_webhooks.go | 8 +- .../internal/go/v3/memcached_with_webhooks.go | 447 ++++++++++++ hack/generate/samples/internal/pkg/context.go | 18 +- internal/cmd/operator-sdk/cli/cli.go | 13 +- .../cli_suite_test.go} | 4 +- .../{version/cmd.go => cli/version.go} | 19 +- internal/cmd/operator-sdk/cli/version_test.go | 41 ++ internal/cmd/operator-sdk/version/cmd_test.go | 65 -- internal/kubebuilder/cmdutil/cmdutil.go | 8 +- internal/plugins/ansible/v1/api.go | 3 +- internal/plugins/ansible/v1/init.go | 19 +- internal/plugins/ansible/v1/scaffolds/api.go | 8 +- internal/plugins/ansible/v1/scaffolds/init.go | 8 +- internal/plugins/golang/v2/plugin.go | 2 +- internal/plugins/golang/v3/api.go | 70 ++ internal/plugins/golang/v3/init.go | 64 ++ internal/plugins/golang/v3/plugin.go | 55 ++ internal/plugins/helm/v1/api.go | 5 +- internal/plugins/helm/v1/init.go | 33 +- internal/plugins/helm/v1/scaffolds/api.go | 8 +- internal/plugins/helm/v1/scaffolds/init.go | 8 +- internal/plugins/manifests/v2/plugin.go | 70 ++ internal/plugins/scorecard/v2/plugin.go | 53 ++ internal/testutils/utils.go | 49 +- test/e2e-go/e2e_go_cluster_test.go | 54 +- test/e2e-go/e2e_go_suite_test.go | 2 + .../{ => v2/go}/memcached-operator/.gitignore | 0 .../{ => v2/go}/memcached-operator/Dockerfile | 0 .../{ => v2/go}/memcached-operator/Makefile | 0 .../go/{ => v2/go}/memcached-operator/PROJECT | 0 .../api/v1alpha1/groupversion_info.go | 0 .../api/v1alpha1/memcached_types.go | 2 - .../api/v1alpha1/memcached_webhook.go | 8 +- .../api/v1alpha1/zz_generated.deepcopy.go | 0 .../go}/memcached-operator/bundle.Dockerfile | 0 .../cache.example.com_memcacheds.yaml | 0 ...nitoring.coreos.com_v1_servicemonitor.yaml | 0 ...er-manager-metrics-service_v1_service.yaml | 0 ...c.authorization.k8s.io_v1_clusterrole.yaml | 0 ...d-operator-webhook-service_v1_service.yaml | 0 ...cached-operator.clusterserviceversion.yaml | 0 .../bundle/metadata/annotations.yaml | 0 .../bundle/tests/scorecard/config.yaml | 0 .../config/certmanager/certificate.yaml | 0 .../config/certmanager/kustomization.yaml | 0 .../config/certmanager/kustomizeconfig.yaml | 0 .../bases/cache.example.com_memcacheds.yaml | 0 .../config/crd/kustomization.yaml | 0 .../config/crd/kustomizeconfig.yaml | 0 .../patches/cainjection_in_memcacheds.yaml | 0 .../crd/patches/webhook_in_memcacheds.yaml | 0 .../config/default/kustomization.yaml | 0 .../default/manager_auth_proxy_patch.yaml | 0 .../config/default/manager_webhook_patch.yaml | 0 .../default/webhookcainjection_patch.yaml | 0 .../config/manager/kustomization.yaml | 0 .../config/manager/manager.yaml | 0 ...cached-operator.clusterserviceversion.yaml | 0 .../config/manifests/kustomization.yaml | 0 .../config/prometheus/kustomization.yaml | 0 .../config/prometheus/monitor.yaml | 0 .../rbac/auth_proxy_client_clusterrole.yaml | 0 .../config/rbac/auth_proxy_role.yaml | 0 .../config/rbac/auth_proxy_role_binding.yaml | 0 .../config/rbac/auth_proxy_service.yaml | 0 .../config/rbac/kustomization.yaml | 0 .../config/rbac/leader_election_role.yaml | 0 .../rbac/leader_election_role_binding.yaml | 0 .../config/rbac/memcached_editor_role.yaml | 0 .../config/rbac/memcached_viewer_role.yaml | 0 .../memcached-operator/config/rbac/role.yaml | 0 .../config/rbac/role_binding.yaml | 0 .../samples/cache_v1alpha1_memcached.yaml | 0 .../config/samples/kustomization.yaml | 0 .../config/scorecard/bases/config.yaml | 0 .../config/scorecard/kustomization.yaml | 0 .../scorecard/patches/basic.config.yaml | 0 .../config/scorecard/patches/olm.config.yaml | 0 .../config/webhook/kustomization.yaml | 0 .../config/webhook/kustomizeconfig.yaml | 0 .../config/webhook/manifests.yaml | 0 .../config/webhook/service.yaml | 0 .../controllers/memcached_controller.go | 3 - .../controllers/suite_test.go | 0 .../go/{ => v2/go}/memcached-operator/go.mod | 2 +- .../go/{ => v2/go}/memcached-operator/go.sum | 4 +- .../hack/boilerplate.go.txt | 0 .../go/{ => v2/go}/memcached-operator/main.go | 0 .../go/v3/memcached-operator/.dockerignore | 5 + testdata/go/v3/memcached-operator/.gitignore | 25 + testdata/go/v3/memcached-operator/Dockerfile | 27 + testdata/go/v3/memcached-operator/Makefile | 119 ++++ testdata/go/v3/memcached-operator/PROJECT | 14 + .../api/v1alpha1/groupversion_info.go | 36 + .../api/v1alpha1/memcached_types.go | 70 ++ .../api/v1alpha1/memcached_webhook.go | 82 +++ .../api/v1alpha1/webhook_suite_test.go | 133 ++++ .../api/v1alpha1/zz_generated.deepcopy.go | 119 ++++ .../v3/memcached-operator/bundle.Dockerfile | 12 + .../cache.example.com_memcacheds.yaml | 60 ++ ...nitoring.coreos.com_v1_servicemonitor.yaml | 13 + ...er-manager-metrics-service_v1_service.yaml | 16 + ...-operator-manager-config_v1_configmap.yaml | 17 + ...c.authorization.k8s.io_v1_clusterrole.yaml | 10 + ...d-operator-webhook-service_v1_service.yaml | 13 + ...cached-operator.clusterserviceversion.yaml | 254 +++++++ .../bundle/metadata/annotations.yaml | 8 + .../bundle/tests/scorecard/config.yaml | 49 ++ .../config/certmanager/certificate.yaml | 25 + .../config/certmanager/kustomization.yaml | 5 + .../config/certmanager/kustomizeconfig.yaml | 16 + .../bases/cache.example.com_memcacheds.yaml | 68 ++ .../config/crd/kustomization.yaml | 21 + .../config/crd/kustomizeconfig.yaml | 19 + .../patches/cainjection_in_memcacheds.yaml | 7 + .../crd/patches/webhook_in_memcacheds.yaml | 14 + .../config/default/kustomization.yaml | 80 +++ .../default/manager_auth_proxy_patch.yaml | 26 + .../config/default/manager_config_patch.yaml | 20 + .../config/default/manager_webhook_patch.yaml | 23 + .../default/webhookcainjection_patch.yaml | 15 + .../manager/controller_manager_config.yaml | 11 + .../config/manager/kustomization.yaml | 16 + .../config/manager/manager.yaml | 55 ++ ...cached-operator.clusterserviceversion.yaml | 48 ++ .../config/manifests/kustomization.yaml | 4 + .../config/prometheus/kustomization.yaml | 2 + .../config/prometheus/monitor.yaml | 16 + .../rbac/auth_proxy_client_clusterrole.yaml | 7 + .../config/rbac/auth_proxy_role.yaml | 13 + .../config/rbac/auth_proxy_role_binding.yaml | 12 + .../config/rbac/auth_proxy_service.yaml | 14 + .../config/rbac/kustomization.yaml | 12 + .../config/rbac/leader_election_role.yaml | 27 + .../rbac/leader_election_role_binding.yaml | 12 + .../config/rbac/memcached_editor_role.yaml | 24 + .../config/rbac/memcached_viewer_role.yaml | 20 + .../memcached-operator/config/rbac/role.yaml | 53 ++ .../config/rbac/role_binding.yaml | 12 + .../samples/cache_v1alpha1_memcached.yaml | 7 + .../config/samples/kustomization.yaml | 4 + .../config/scorecard/bases/config.yaml | 7 + .../config/scorecard/kustomization.yaml | 16 + .../scorecard/patches/basic.config.yaml | 10 + .../config/scorecard/patches/olm.config.yaml | 50 ++ .../config/webhook/kustomization.yaml | 6 + .../config/webhook/kustomizeconfig.yaml | 25 + .../config/webhook/manifests.yaml | 56 ++ .../config/webhook/service.yaml | 12 + .../controllers/memcached_controller.go | 195 ++++++ .../controllers/suite_test.go | 79 +++ testdata/go/v3/memcached-operator/go.mod | 13 + testdata/go/v3/memcached-operator/go.sum | 638 ++++++++++++++++++ .../hack/boilerplate.go.txt | 15 + testdata/go/v3/memcached-operator/main.go | 109 +++ website/content/en/docs/cli/operator-sdk.md | 2 +- .../en/docs/cli/operator-sdk_create_api.md | 3 - .../docs/cli/operator-sdk_create_webhook.md | 3 - .../content/en/docs/cli/operator-sdk_init.md | 2 +- .../en/docs/cli/operator-sdk_version.md | 10 +- 165 files changed, 4009 insertions(+), 230 deletions(-) create mode 100644 changelog/fragments/go-v3-alpha.yaml create mode 100644 hack/generate/samples/internal/go/generate.go rename hack/generate/samples/internal/go/{ => v2}/memcached_with_webhooks.go (98%) create mode 100644 hack/generate/samples/internal/go/v3/memcached_with_webhooks.go rename internal/cmd/operator-sdk/{version/version_suite_test.go => cli/cli_suite_test.go} (93%) rename internal/cmd/operator-sdk/{version/cmd.go => cli/version.go} (67%) create mode 100644 internal/cmd/operator-sdk/cli/version_test.go delete mode 100644 internal/cmd/operator-sdk/version/cmd_test.go create mode 100644 internal/plugins/golang/v3/api.go create mode 100644 internal/plugins/golang/v3/init.go create mode 100644 internal/plugins/golang/v3/plugin.go create mode 100644 internal/plugins/manifests/v2/plugin.go create mode 100644 internal/plugins/scorecard/v2/plugin.go rename testdata/go/{ => v2/go}/memcached-operator/.gitignore (100%) rename testdata/go/{ => v2/go}/memcached-operator/Dockerfile (100%) rename testdata/go/{ => v2/go}/memcached-operator/Makefile (100%) rename testdata/go/{ => v2/go}/memcached-operator/PROJECT (100%) rename testdata/go/{ => v2/go}/memcached-operator/api/v1alpha1/groupversion_info.go (100%) rename testdata/go/{ => v2/go}/memcached-operator/api/v1alpha1/memcached_types.go (99%) rename testdata/go/{ => v2/go}/memcached-operator/api/v1alpha1/memcached_webhook.go (95%) rename testdata/go/{ => v2/go}/memcached-operator/api/v1alpha1/zz_generated.deepcopy.go (100%) rename testdata/go/{ => v2/go}/memcached-operator/bundle.Dockerfile (100%) rename testdata/go/{ => v2/go}/memcached-operator/bundle/manifests/cache.example.com_memcacheds.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/bundle/manifests/memcached-operator-controller-manager-metrics-monitor_monitoring.coreos.com_v1_servicemonitor.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/bundle/manifests/memcached-operator-controller-manager-metrics-service_v1_service.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/bundle/manifests/memcached-operator-metrics-reader_rbac.authorization.k8s.io_v1_clusterrole.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/bundle/manifests/memcached-operator-webhook-service_v1_service.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/bundle/metadata/annotations.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/bundle/tests/scorecard/config.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/certmanager/certificate.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/certmanager/kustomization.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/certmanager/kustomizeconfig.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/crd/bases/cache.example.com_memcacheds.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/crd/kustomization.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/crd/kustomizeconfig.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/crd/patches/cainjection_in_memcacheds.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/crd/patches/webhook_in_memcacheds.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/default/kustomization.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/default/manager_auth_proxy_patch.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/default/manager_webhook_patch.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/default/webhookcainjection_patch.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/manager/kustomization.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/manager/manager.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/manifests/kustomization.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/prometheus/kustomization.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/prometheus/monitor.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/rbac/auth_proxy_client_clusterrole.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/rbac/auth_proxy_role.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/rbac/auth_proxy_role_binding.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/rbac/auth_proxy_service.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/rbac/kustomization.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/rbac/leader_election_role.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/rbac/leader_election_role_binding.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/rbac/memcached_editor_role.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/rbac/memcached_viewer_role.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/rbac/role.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/rbac/role_binding.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/samples/cache_v1alpha1_memcached.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/samples/kustomization.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/scorecard/bases/config.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/scorecard/kustomization.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/scorecard/patches/basic.config.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/scorecard/patches/olm.config.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/webhook/kustomization.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/webhook/kustomizeconfig.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/webhook/manifests.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/config/webhook/service.yaml (100%) rename testdata/go/{ => v2/go}/memcached-operator/controllers/memcached_controller.go (99%) rename testdata/go/{ => v2/go}/memcached-operator/controllers/suite_test.go (100%) rename testdata/go/{ => v2/go}/memcached-operator/go.mod (85%) rename testdata/go/{ => v2/go}/memcached-operator/go.sum (99%) rename testdata/go/{ => v2/go}/memcached-operator/hack/boilerplate.go.txt (100%) rename testdata/go/{ => v2/go}/memcached-operator/main.go (100%) create mode 100644 testdata/go/v3/memcached-operator/.dockerignore create mode 100644 testdata/go/v3/memcached-operator/.gitignore create mode 100644 testdata/go/v3/memcached-operator/Dockerfile create mode 100644 testdata/go/v3/memcached-operator/Makefile create mode 100644 testdata/go/v3/memcached-operator/PROJECT create mode 100644 testdata/go/v3/memcached-operator/api/v1alpha1/groupversion_info.go create mode 100644 testdata/go/v3/memcached-operator/api/v1alpha1/memcached_types.go create mode 100644 testdata/go/v3/memcached-operator/api/v1alpha1/memcached_webhook.go create mode 100644 testdata/go/v3/memcached-operator/api/v1alpha1/webhook_suite_test.go create mode 100644 testdata/go/v3/memcached-operator/api/v1alpha1/zz_generated.deepcopy.go create mode 100644 testdata/go/v3/memcached-operator/bundle.Dockerfile create mode 100644 testdata/go/v3/memcached-operator/bundle/manifests/cache.example.com_memcacheds.yaml create mode 100644 testdata/go/v3/memcached-operator/bundle/manifests/memcached-operator-controller-manager-metrics-monitor_monitoring.coreos.com_v1_servicemonitor.yaml create mode 100644 testdata/go/v3/memcached-operator/bundle/manifests/memcached-operator-controller-manager-metrics-service_v1_service.yaml create mode 100644 testdata/go/v3/memcached-operator/bundle/manifests/memcached-operator-manager-config_v1_configmap.yaml create mode 100644 testdata/go/v3/memcached-operator/bundle/manifests/memcached-operator-metrics-reader_rbac.authorization.k8s.io_v1_clusterrole.yaml create mode 100644 testdata/go/v3/memcached-operator/bundle/manifests/memcached-operator-webhook-service_v1_service.yaml create mode 100644 testdata/go/v3/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml create mode 100644 testdata/go/v3/memcached-operator/bundle/metadata/annotations.yaml create mode 100644 testdata/go/v3/memcached-operator/bundle/tests/scorecard/config.yaml create mode 100644 testdata/go/v3/memcached-operator/config/certmanager/certificate.yaml create mode 100644 testdata/go/v3/memcached-operator/config/certmanager/kustomization.yaml create mode 100644 testdata/go/v3/memcached-operator/config/certmanager/kustomizeconfig.yaml create mode 100644 testdata/go/v3/memcached-operator/config/crd/bases/cache.example.com_memcacheds.yaml create mode 100644 testdata/go/v3/memcached-operator/config/crd/kustomization.yaml create mode 100644 testdata/go/v3/memcached-operator/config/crd/kustomizeconfig.yaml create mode 100644 testdata/go/v3/memcached-operator/config/crd/patches/cainjection_in_memcacheds.yaml create mode 100644 testdata/go/v3/memcached-operator/config/crd/patches/webhook_in_memcacheds.yaml create mode 100644 testdata/go/v3/memcached-operator/config/default/kustomization.yaml create mode 100644 testdata/go/v3/memcached-operator/config/default/manager_auth_proxy_patch.yaml create mode 100644 testdata/go/v3/memcached-operator/config/default/manager_config_patch.yaml create mode 100644 testdata/go/v3/memcached-operator/config/default/manager_webhook_patch.yaml create mode 100644 testdata/go/v3/memcached-operator/config/default/webhookcainjection_patch.yaml create mode 100644 testdata/go/v3/memcached-operator/config/manager/controller_manager_config.yaml create mode 100644 testdata/go/v3/memcached-operator/config/manager/kustomization.yaml create mode 100644 testdata/go/v3/memcached-operator/config/manager/manager.yaml create mode 100644 testdata/go/v3/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml create mode 100644 testdata/go/v3/memcached-operator/config/manifests/kustomization.yaml create mode 100644 testdata/go/v3/memcached-operator/config/prometheus/kustomization.yaml create mode 100644 testdata/go/v3/memcached-operator/config/prometheus/monitor.yaml create mode 100644 testdata/go/v3/memcached-operator/config/rbac/auth_proxy_client_clusterrole.yaml create mode 100644 testdata/go/v3/memcached-operator/config/rbac/auth_proxy_role.yaml create mode 100644 testdata/go/v3/memcached-operator/config/rbac/auth_proxy_role_binding.yaml create mode 100644 testdata/go/v3/memcached-operator/config/rbac/auth_proxy_service.yaml create mode 100644 testdata/go/v3/memcached-operator/config/rbac/kustomization.yaml create mode 100644 testdata/go/v3/memcached-operator/config/rbac/leader_election_role.yaml create mode 100644 testdata/go/v3/memcached-operator/config/rbac/leader_election_role_binding.yaml create mode 100644 testdata/go/v3/memcached-operator/config/rbac/memcached_editor_role.yaml create mode 100644 testdata/go/v3/memcached-operator/config/rbac/memcached_viewer_role.yaml create mode 100644 testdata/go/v3/memcached-operator/config/rbac/role.yaml create mode 100644 testdata/go/v3/memcached-operator/config/rbac/role_binding.yaml create mode 100644 testdata/go/v3/memcached-operator/config/samples/cache_v1alpha1_memcached.yaml create mode 100644 testdata/go/v3/memcached-operator/config/samples/kustomization.yaml create mode 100644 testdata/go/v3/memcached-operator/config/scorecard/bases/config.yaml create mode 100644 testdata/go/v3/memcached-operator/config/scorecard/kustomization.yaml create mode 100644 testdata/go/v3/memcached-operator/config/scorecard/patches/basic.config.yaml create mode 100644 testdata/go/v3/memcached-operator/config/scorecard/patches/olm.config.yaml create mode 100644 testdata/go/v3/memcached-operator/config/webhook/kustomization.yaml create mode 100644 testdata/go/v3/memcached-operator/config/webhook/kustomizeconfig.yaml create mode 100644 testdata/go/v3/memcached-operator/config/webhook/manifests.yaml create mode 100644 testdata/go/v3/memcached-operator/config/webhook/service.yaml create mode 100644 testdata/go/v3/memcached-operator/controllers/memcached_controller.go create mode 100644 testdata/go/v3/memcached-operator/controllers/suite_test.go create mode 100644 testdata/go/v3/memcached-operator/go.mod create mode 100644 testdata/go/v3/memcached-operator/go.sum create mode 100644 testdata/go/v3/memcached-operator/hack/boilerplate.go.txt create mode 100644 testdata/go/v3/memcached-operator/main.go diff --git a/changelog/fragments/go-v3-alpha.yaml b/changelog/fragments/go-v3-alpha.yaml new file mode 100644 index 00000000000..96542f03461 --- /dev/null +++ b/changelog/fragments/go-v3-alpha.yaml @@ -0,0 +1,8 @@ +entries: + - description: > + (go/v2) bumped controller-runtime from v0.6.3 to v0.6.4 + kind: change + migration: + header: Go projects should update their controller-runtime version to v0.6.4 + body: > + In your go.mod file, update the sigs.k8s.io/controller-runtime version to v0.6.4 diff --git a/go.mod b/go.mod index 75ce83074a8..96e1ac4c81e 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( rsc.io/letsencrypt v0.0.3 // indirect sigs.k8s.io/controller-runtime v0.7.0-alpha.7 sigs.k8s.io/controller-tools v0.3.0 - sigs.k8s.io/kubebuilder/v2 v2.3.2-0.20201111001842-c158f4fa4207 + sigs.k8s.io/kubebuilder/v2 v2.3.2-0.20201204230216-593f2e80cdf6 sigs.k8s.io/yaml v1.2.0 ) diff --git a/go.sum b/go.sum index ae6e707bbf1..0af03fa6990 100644 --- a/go.sum +++ b/go.sum @@ -1361,8 +1361,8 @@ sigs.k8s.io/controller-runtime v0.7.0-alpha.7 h1:KtMmb2Ef/S38GNbf0Jpa+FWXqnxFYeW sigs.k8s.io/controller-runtime v0.7.0-alpha.7/go.mod h1:pJ3YBrJiAqMAZKi6UVGuE98ZrroV1p+pIhoHsMm9wdU= sigs.k8s.io/controller-tools v0.3.0 h1:y3YD99XOyWaXkiF1kd41uRvfp/64teWcrEZFuHxPhJ4= sigs.k8s.io/controller-tools v0.3.0/go.mod h1:enhtKGfxZD1GFEoMgP8Fdbu+uKQ/cq1/WGJhdVChfvI= -sigs.k8s.io/kubebuilder/v2 v2.3.2-0.20201111001842-c158f4fa4207 h1:JtlaBrtWymJbh6ea+TJUZkzBb0x0dMKV+P0+ZPaldxk= -sigs.k8s.io/kubebuilder/v2 v2.3.2-0.20201111001842-c158f4fa4207/go.mod h1:J/D/179LBZhQOhRvmMRNbje/Bk+PjbN0/fzUupmO7+U= +sigs.k8s.io/kubebuilder/v2 v2.3.2-0.20201204230216-593f2e80cdf6 h1:SE+xhj4aauOCSeZKjRizd6VwHgkVfJABJpVk/xqYTiI= +sigs.k8s.io/kubebuilder/v2 v2.3.2-0.20201204230216-593f2e80cdf6/go.mod h1:J/D/179LBZhQOhRvmMRNbje/Bk+PjbN0/fzUupmO7+U= sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0= sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU= sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= diff --git a/hack/generate/samples/generate_testdata.go b/hack/generate/samples/generate_testdata.go index 1f51c257ab2..69125cdcdb0 100644 --- a/hack/generate/samples/generate_testdata.go +++ b/hack/generate/samples/generate_testdata.go @@ -22,7 +22,7 @@ import ( log "github.com/sirupsen/logrus" "github.com/operator-framework/operator-sdk/hack/generate/samples/internal/ansible" - gosamples "github.com/operator-framework/operator-sdk/hack/generate/samples/internal/go" + golang "github.com/operator-framework/operator-sdk/hack/generate/samples/internal/go" "github.com/operator-framework/operator-sdk/hack/generate/samples/internal/helm" "github.com/operator-framework/operator-sdk/internal/testutils" ) @@ -54,5 +54,5 @@ func main() { ansible.GenerateMemcachedAnsibleSample(samplesPath) log.Infof("creating Go Memcached Sample with Webhooks") - gosamples.GenerateMemcachedGoWithWebhooksSample(samplesPath) + golang.GenerateMemcachedGoWithWebhooksSample(samplesPath) } diff --git a/hack/generate/samples/internal/go/generate.go b/hack/generate/samples/internal/go/generate.go new file mode 100644 index 00000000000..2969a04e3f9 --- /dev/null +++ b/hack/generate/samples/internal/go/generate.go @@ -0,0 +1,27 @@ +// Copyright 2020 The Operator-SDK 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. + +package pkg + +import ( + "path/filepath" + + golangv2 "github.com/operator-framework/operator-sdk/hack/generate/samples/internal/go/v2" + golangv3 "github.com/operator-framework/operator-sdk/hack/generate/samples/internal/go/v3" +) + +func GenerateMemcachedGoWithWebhooksSample(rootPath string) { + golangv2.GenerateMemcachedGoWithWebhooksSample(filepath.Join(rootPath, "go", "v2")) + golangv3.GenerateMemcachedGoWithWebhooksSample(filepath.Join(rootPath, "go", "v3")) +} diff --git a/hack/generate/samples/internal/go/memcached_with_webhooks.go b/hack/generate/samples/internal/go/v2/memcached_with_webhooks.go similarity index 98% rename from hack/generate/samples/internal/go/memcached_with_webhooks.go rename to hack/generate/samples/internal/go/v2/memcached_with_webhooks.go index c88d141ef6e..1da17736c03 100644 --- a/hack/generate/samples/internal/go/memcached_with_webhooks.go +++ b/hack/generate/samples/internal/go/v2/memcached_with_webhooks.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package gosamples +package v2 import ( "fmt" @@ -59,6 +59,7 @@ func (mh *MemcachedGoWithWebhooks) Prepare() { func (mh *MemcachedGoWithWebhooks) Run() { log.Infof("creating the project") err := mh.ctx.Init( + "--plugins", "go/v2", "--repo", "github.com/example/memcached-operator", "--domain", mh.ctx.Domain) @@ -92,6 +93,8 @@ func (mh *MemcachedGoWithWebhooks) Run() { mh.ctx.CreateBundle() + pkg.CheckError("formatting project", mh.ctx.Make("fmt")) + // Clean up built binaries, if any. pkg.CheckError("cleaning up", os.RemoveAll(filepath.Join(mh.ctx.Dir, "bin"))) } @@ -410,7 +413,8 @@ const watchCustomizedFragment = `return ctrl.NewControllerManagedBy(mgr). Complete(r) ` -const webhooksFragment = `// TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation. +const webhooksFragment = ` +// TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation. // +kubebuilder:webhook:verbs=create;update,path=/validate-cache-example-com-v1alpha1-memcached,mutating=false,failurePolicy=fail,groups=cache.example.com,resources=memcacheds,versions=v1alpha1,name=vmemcached.kb.io var _ webhook.Validator = &Memcached{} diff --git a/hack/generate/samples/internal/go/v3/memcached_with_webhooks.go b/hack/generate/samples/internal/go/v3/memcached_with_webhooks.go new file mode 100644 index 00000000000..0c518f67aa1 --- /dev/null +++ b/hack/generate/samples/internal/go/v3/memcached_with_webhooks.go @@ -0,0 +1,447 @@ +// Copyright 2020 The Operator-SDK 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. + +package v3 + +import ( + "fmt" + "os" + "path/filepath" + "strings" + + log "github.com/sirupsen/logrus" + kbtestutils "sigs.k8s.io/kubebuilder/v2/test/e2e/utils" + + "github.com/operator-framework/operator-sdk/hack/generate/samples/internal/pkg" + "github.com/operator-framework/operator-sdk/internal/testutils" +) + +// MemcachedGoWithWebhooks defines the Memcached Sample in GO using webhooks +type MemcachedGoWithWebhooks struct { + ctx *pkg.SampleContext +} + +// MemcachedGoWithWebhooks return a MemcachedGoWithWebhooks +func NewMemcachedGoWithWebhooks(ctx *pkg.SampleContext) MemcachedGoWithWebhooks { + return MemcachedGoWithWebhooks{ctx} +} + +// Prepare the Context for the Memcached with WebHooks Go Sample +// Note that sample directory will be re-created and the context data for the sample +// will be set such as the domain and GVK. +func (mh *MemcachedGoWithWebhooks) Prepare() { + log.Infof("destroying directory for Memcached with Webhooks Go samples") + mh.ctx.Destroy() + + log.Infof("creating directory") + err := mh.ctx.Prepare() + pkg.CheckError("creating directory for Go Sample", err) + + log.Infof("setting domain and GVK") + mh.ctx.Domain = "example.com" + mh.ctx.Version = "v1alpha1" + mh.ctx.Group = "cache" + mh.ctx.Kind = "Memcached" +} + +// Run the steps to create the Memcached with Webhooks Go Sample +func (mh *MemcachedGoWithWebhooks) Run() { + log.Infof("creating the project") + err := mh.ctx.Init( + // TODO(estroz): change this to go/v3 is stabilized. + "--plugins", "go/v3-alpha", + "--repo", "github.com/example/memcached-operator", + "--domain", + mh.ctx.Domain) + pkg.CheckError("creating the project", err) + + err = mh.ctx.CreateAPI( + "--group", mh.ctx.Group, + "--version", mh.ctx.Version, + "--kind", mh.ctx.Kind, + "--controller", "true", + "--resource", "true") + pkg.CheckError("scaffolding apis", err) + + log.Infof("implementing the API") + mh.implementingAPI() + + log.Infof("implementing the Controller") + mh.implementingController() + + log.Infof("scaffolding webhook") + err = mh.ctx.CreateWebhook( + "--group", mh.ctx.Group, + "--version", mh.ctx.Version, + "--kind", mh.ctx.Kind, + "--defaulting", + "--defaulting") + pkg.CheckError("scaffolding webhook", err) + + mh.implementingWebhooks() + mh.uncommentKustomizationFile() + + mh.ctx.CreateBundle() + + pkg.CheckError("formatting project", mh.ctx.Make("fmt")) + + // Clean up built binaries, if any. + pkg.CheckError("cleaning up", os.RemoveAll(filepath.Join(mh.ctx.Dir, "bin"))) +} + +// uncommentKustomizationFile will uncomment the file kustomization.yaml +func (mh *MemcachedGoWithWebhooks) uncommentKustomizationFile() { + log.Infof("uncomment kustomization.yaml to enable webhook and ca injection") + err := testutils.UncommentCode( + filepath.Join(mh.ctx.Dir, "config", "default", "kustomization.yaml"), + "#- ../webhook", "#") + pkg.CheckError("uncomment webhook", err) + + err = testutils.UncommentCode( + filepath.Join(mh.ctx.Dir, "config", "default", "kustomization.yaml"), + "#- ../certmanager", "#") + pkg.CheckError("uncomment certmanager", err) + + err = testutils.UncommentCode( + filepath.Join(mh.ctx.Dir, "config", "default", "kustomization.yaml"), + "#- ../prometheus", "#") + pkg.CheckError("uncomment prometheus", err) + + err = testutils.UncommentCode( + filepath.Join(mh.ctx.Dir, "config", "default", "kustomization.yaml"), + "#- manager_webhook_patch.yaml", "#") + pkg.CheckError("uncomment manager_webhook_patch.yaml", err) + + err = testutils.UncommentCode( + filepath.Join(mh.ctx.Dir, "config", "default", "kustomization.yaml"), + "#- webhookcainjection_patch.yaml", "#") + pkg.CheckError("uncomment webhookcainjection_patch.yaml", err) + + err = testutils.UncommentCode(filepath.Join(mh.ctx.Dir, "config", "default", "kustomization.yaml"), + `#- name: CERTIFICATE_NAMESPACE # namespace of the certificate CR +# objref: +# kind: Certificate +# group: cert-manager.io +# version: v1 +# name: serving-cert # this name should match the one in certificate.yaml +# fieldref: +# fieldpath: metadata.namespace +#- name: CERTIFICATE_NAME +# objref: +# kind: Certificate +# group: cert-manager.io +# version: v1 +# name: serving-cert # this name should match the one in certificate.yaml +#- name: SERVICE_NAMESPACE # namespace of the service +# objref: +# kind: Service +# version: v1 +# name: webhook-service +# fieldref: +# fieldpath: metadata.namespace +#- name: SERVICE_NAME +# objref: +# kind: Service +# version: v1 +# name: webhook-service`, "#") + pkg.CheckError("uncommented certificate CR", err) +} + +// implementingWebhooks will customize the kind wekbhok file +func (mh *MemcachedGoWithWebhooks) implementingWebhooks() { + log.Infof("implementing webhooks") + webhookPath := filepath.Join(mh.ctx.Dir, "api", mh.ctx.Version, fmt.Sprintf("%s_webhook.go", + strings.ToLower(mh.ctx.Kind))) + + // Add webhook methods + err := kbtestutils.InsertCode(webhookPath, + "// TODO(user): fill in your defaulting logic.\n}", + webhooksFragment) + pkg.CheckError("replacing reconcile", err) + + err = testutils.ReplaceInFile(webhookPath, + "// TODO(user): fill in your defaulting logic.", "if r.Spec.Size == 0 {\n\t\tr.Spec.Size = 3\n\t}") + pkg.CheckError("replacing default webhook implementation", err) + + // Add imports + err = kbtestutils.InsertCode(webhookPath, + "import (", + // TODO(estroz): remove runtime dep when --programmatic-validation is added to `ccreate webhook` above. + "\"errors\"\n\n\"k8s.io/apimachinery/pkg/runtime\"") + pkg.CheckError("adding imports", err) +} + +// implementingController will customize the Controller +func (mh *MemcachedGoWithWebhooks) implementingController() { + controllerPath := filepath.Join(mh.ctx.Dir, "controllers", fmt.Sprintf("%s_controller.go", + strings.ToLower(mh.ctx.Kind))) + + // Add imports + err := kbtestutils.InsertCode(controllerPath, + "import (", + importsFragment) + pkg.CheckError("adding imports", err) + + // Add RBAC permissions on top of reconcile + err = kbtestutils.InsertCode(controllerPath, + "/finalizers,verbs=update", + rbacFragment) + pkg.CheckError("adding rbac", err) + + // Replace reconcile content + err = testutils.ReplaceInFile(controllerPath, + fmt.Sprintf("_ = r.Log.WithValues(\"%s\", req.NamespacedName)", strings.ToLower(mh.ctx.Kind)), + fmt.Sprintf("log := r.Log.WithValues(\"%s\", req.NamespacedName)", strings.ToLower(mh.ctx.Kind))) + pkg.CheckError("replacing reconcile content", err) + + // Add reconcile implementation + err = testutils.ReplaceInFile(controllerPath, + "// your logic here", reconcileFragment) + pkg.CheckError("replacing reconcile", err) + + // Add helpers funcs to the controller + err = kbtestutils.InsertCode(controllerPath, + "return ctrl.Result{}, nil\n}", controllerFuncsFragment) + pkg.CheckError("adding helpers methods in the controller", err) + + // Add watch for the Kind + err = testutils.ReplaceInFile(controllerPath, + fmt.Sprintf(watchOriginalFragment, mh.ctx.Group, mh.ctx.Version, mh.ctx.Kind), + fmt.Sprintf(watchCustomizedFragment, mh.ctx.Group, mh.ctx.Version, mh.ctx.Kind)) + pkg.CheckError("replacing reconcile", err) +} + +// implementingAPI will customize the API +func (mh *MemcachedGoWithWebhooks) implementingAPI() { + err := kbtestutils.InsertCode( + filepath.Join(mh.ctx.Dir, "api", mh.ctx.Version, fmt.Sprintf("%s_types.go", strings.ToLower(mh.ctx.Kind))), + fmt.Sprintf("type %sSpec struct {\n\t// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster\n\t// Important: Run \"make\" to regenerate code after modifying this file", mh.ctx.Kind), + ` + + // Size defines the number of Memcached instances + Size int32 `+"`"+`json:"size,omitempty"`+"`"+` +`) + pkg.CheckError("inserting spec Status", err) + + log.Infof("implementing MemcachedStatus") + err = kbtestutils.InsertCode( + filepath.Join(mh.ctx.Dir, "api", mh.ctx.Version, fmt.Sprintf("%s_types.go", strings.ToLower(mh.ctx.Kind))), + fmt.Sprintf("type %sStatus struct {\n\t// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster\n\t// Important: Run \"make\" to regenerate code after modifying this file", mh.ctx.Kind), + ` + + // Nodes store the name of the pods which are running Memcached instances + Nodes []string `+"`"+`json:"nodes,omitempty"`+"`"+` +`) + pkg.CheckError("inserting Node Status", err) +} + +// GenerateMemcachedGoWithWebhooksSample will call all actions to create the directory and generate the sample +// Note that it should NOT be called in the e2e tests. +func GenerateMemcachedGoWithWebhooksSample(samplesPath string) { + log.Infof("starting to generate Go memcached sample with webhooks") + path := filepath.Join(samplesPath, "memcached-operator") + ctx, err := pkg.NewSampleContext(testutils.BinaryName, path, "GO111MODULE=on") + pkg.CheckError("generating Go memcached with webhooks context", err) + + memcached := NewMemcachedGoWithWebhooks(&ctx) + memcached.Prepare() + memcached.Run() +} + +const rbacFragment = ` +// +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=core,resources=pods,verbs=get;list;` + +const reconcileFragment = `// Fetch the Memcached instance + memcached := &cachev1alpha1.Memcached{} + err := r.Get(ctx, req.NamespacedName, memcached) + if err != nil { + if errors.IsNotFound(err) { + // Request object not found, could have been deleted after reconcile request. + // Owned objects are automatically garbage collected. For additional cleanup logic use finalizers. + // Return and don't requeue + log.Info("Memcached resource not found. Ignoring since object must be deleted") + return ctrl.Result{}, nil + } + // Error reading the object - requeue the request. + log.Error(err, "Failed to get Memcached") + return ctrl.Result{}, err + } + + // Check if the deployment already exists, if not create a new one + found := &appsv1.Deployment{} + err = r.Get(ctx, types.NamespacedName{Name: memcached.Name, Namespace: memcached.Namespace}, found) + if err != nil && errors.IsNotFound(err) { + // Define a new deployment + dep := r.deploymentForMemcached(memcached) + log.Info("Creating a new Deployment", "Deployment.Namespace", dep.Namespace, "Deployment.Name", dep.Name) + err = r.Create(ctx, dep) + if err != nil { + log.Error(err, "Failed to create new Deployment", "Deployment.Namespace", dep.Namespace, "Deployment.Name", dep.Name) + return ctrl.Result{}, err + } + // Deployment created successfully - return and requeue + return ctrl.Result{Requeue: true}, nil + } else if err != nil { + log.Error(err, "Failed to get Deployment") + return ctrl.Result{}, err + } + + // Ensure the deployment size is the same as the spec + size := memcached.Spec.Size + if *found.Spec.Replicas != size { + found.Spec.Replicas = &size + err = r.Update(ctx, found) + if err != nil { + log.Error(err, "Failed to update Deployment", "Deployment.Namespace", found.Namespace, "Deployment.Name", found.Name) + return ctrl.Result{}, err + } + // Spec updated - return and requeue + return ctrl.Result{Requeue: true}, nil + } + + // Update the Memcached status with the pod names + // List the pods for this memcached's deployment + podList := &corev1.PodList{} + listOpts := []client.ListOption{ + client.InNamespace(memcached.Namespace), + client.MatchingLabels(labelsForMemcached(memcached.Name)), + } + if err = r.List(ctx, podList, listOpts...); err != nil { + log.Error(err, "Failed to list pods", "Memcached.Namespace", memcached.Namespace, "Memcached.Name", memcached.Name) + return ctrl.Result{}, err + } + podNames := getPodNames(podList.Items) + + // Update status.Nodes if needed + if !reflect.DeepEqual(podNames, memcached.Status.Nodes) { + memcached.Status.Nodes = podNames + err := r.Status().Update(ctx, memcached) + if err != nil { + log.Error(err, "Failed to update Memcached status") + return ctrl.Result{}, err + } + } +` + +const controllerFuncsFragment = ` + +// deploymentForMemcached returns a memcached Deployment object +func (r *MemcachedReconciler) deploymentForMemcached(m *cachev1alpha1.Memcached) *appsv1.Deployment { + ls := labelsForMemcached(m.Name) + replicas := m.Spec.Size + + dep := &appsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: m.Name, + Namespace: m.Namespace, + }, + Spec: appsv1.DeploymentSpec{ + Replicas: &replicas, + Selector: &metav1.LabelSelector{ + MatchLabels: ls, + }, + Template: corev1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: ls, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{{ + Image: "memcached:1.4.36-alpine", + Name: "memcached", + Command: []string{"memcached", "-m=64", "-o", "modern", "-v"}, + Ports: []corev1.ContainerPort{{ + ContainerPort: 11211, + Name: "memcached", + }}, + }}, + }, + }, + }, + } + // Set Memcached instance as the owner and controller + ctrl.SetControllerReference(m, dep, r.Scheme) + return dep +} + +// labelsForMemcached returns the labels for selecting the resources +// belonging to the given memcached CR name. +func labelsForMemcached(name string) map[string]string { + return map[string]string{"app": "memcached", "memcached_cr": name} +} + +// getPodNames returns the pod names of the array of pods passed in +func getPodNames(pods []corev1.Pod) []string { + var podNames []string + for _, pod := range pods { + podNames = append(podNames, pod.Name) + } + return podNames +} +` + +const importsFragment = ` + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "reflect" + +` + +const watchOriginalFragment = `return ctrl.NewControllerManagedBy(mgr). + For(&%s%s.%s{}). + Complete(r) +` + +const watchCustomizedFragment = `return ctrl.NewControllerManagedBy(mgr). + For(&%s%s.%s{}). + Owns(&appsv1.Deployment{}). + Complete(r) +` + +const webhooksFragment = ` +// TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation. +// +kubebuilder:webhook:path=/validate-cache-example-com-v1alpha1-memcached,mutating=false,failurePolicy=fail,sideEffects=None,groups=cache.example.com,resources=memcacheds,verbs=create;update,versions=v1alpha1,name=vmemcached.kb.io,admissionReviewVersions={v1beta1} + +var _ webhook.Validator = &Memcached{} + +// ValidateCreate implements webhook.Validator so a webhook will be registered for the type +func (r *Memcached) ValidateCreate() error { + memcachedlog.Info("validate create", "name", r.Name) + + return validateOdd(r.Spec.Size) +} + +// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type +func (r *Memcached) ValidateUpdate(old runtime.Object) error { + memcachedlog.Info("validate update", "name", r.Name) + + return validateOdd(r.Spec.Size) +} + +// ValidateDelete implements webhook.Validator so a webhook will be registered for the type +func (r *Memcached) ValidateDelete() error { + memcachedlog.Info("validate delete", "name", r.Name) + + return nil +} +func validateOdd(n int32) error { + if n%2 == 0 { + return errors.New("Cluster size must be an odd number") + } + return nil +} +` diff --git a/hack/generate/samples/internal/pkg/context.go b/hack/generate/samples/internal/pkg/context.go index 5cd8a47c1b9..c746f3a2e60 100644 --- a/hack/generate/samples/internal/pkg/context.go +++ b/hack/generate/samples/internal/pkg/context.go @@ -15,10 +15,6 @@ package pkg import ( - "fmt" - "path/filepath" - "strings" - "github.com/operator-framework/operator-sdk/internal/testutils" ) @@ -29,18 +25,6 @@ type SampleContext struct { // NewSampleContext returns a SampleContext containing a new kubebuilder TestContext. func NewSampleContext(binary string, path string, env ...string) (s SampleContext, err error) { - s.TestContext, err = testutils.NewTestContext(binary, env...) - // If the path was informed then this should be the dir used - if strings.TrimSpace(path) != "" { - path, err = filepath.Abs(path) - if err != nil { - return s, err - } - s.CmdContext.Dir = path - s.ProjectName = strings.ToLower(filepath.Base(s.Dir)) - s.ImageName = fmt.Sprintf("quay.io/example/%s:v0.0.1", s.ProjectName) - s.BundleImageName = fmt.Sprintf("quay.io/example/%s-bundle:v0.0.1", s.ProjectName) - } - + s.TestContext, err = testutils.NewPartialTestContext(binary, path, env...) return s, err } diff --git a/internal/cmd/operator-sdk/cli/cli.go b/internal/cmd/operator-sdk/cli/cli.go index 453c2648c46..8b8641858da 100644 --- a/internal/cmd/operator-sdk/cli/cli.go +++ b/internal/cmd/operator-sdk/cli/cli.go @@ -22,10 +22,10 @@ import ( "github.com/operator-framework/operator-sdk/internal/cmd/operator-sdk/olm" "github.com/operator-framework/operator-sdk/internal/cmd/operator-sdk/run" "github.com/operator-framework/operator-sdk/internal/cmd/operator-sdk/scorecard" - "github.com/operator-framework/operator-sdk/internal/cmd/operator-sdk/version" "github.com/operator-framework/operator-sdk/internal/flags" ansiblev1 "github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1" golangv2 "github.com/operator-framework/operator-sdk/internal/plugins/golang/v2" + golangv3 "github.com/operator-framework/operator-sdk/internal/plugins/golang/v3" helmv1 "github.com/operator-framework/operator-sdk/internal/plugins/helm/v1" "github.com/operator-framework/operator-sdk/internal/util/projutil" @@ -33,6 +33,7 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" "sigs.k8s.io/kubebuilder/v2/pkg/cli" + "sigs.k8s.io/kubebuilder/v2/pkg/model/config" ) var commands = []*cobra.Command{ @@ -43,7 +44,6 @@ var commands = []*cobra.Command{ olm.NewCmd(), run.NewCmd(), scorecard.NewCmd(), - version.NewCmd(), } func Run() error { @@ -57,14 +57,17 @@ func Run() error { func GetPluginsCLIAndRoot() (cli.CLI, *cobra.Command) { c, err := cli.New( cli.WithCommandName("operator-sdk"), + cli.WithVersion(makeVersionString()), + cli.WithDefaultProjectVersion(config.Version3Alpha), cli.WithPlugins( &golangv2.Plugin{}, + &golangv3.Plugin{}, &helmv1.Plugin{}, &ansiblev1.Plugin{}, ), - cli.WithDefaultPlugins( - &golangv2.Plugin{}, - ), + cli.WithDefaultPlugins(config.Version2, &golangv2.Plugin{}), + // TODO(estroz): make go/v3-alpha plugin the default once stabilized. + cli.WithDefaultPlugins(config.Version3Alpha, &golangv2.Plugin{}), cli.WithExtraCommands(commands...), ) if err != nil { diff --git a/internal/cmd/operator-sdk/version/version_suite_test.go b/internal/cmd/operator-sdk/cli/cli_suite_test.go similarity index 93% rename from internal/cmd/operator-sdk/version/version_suite_test.go rename to internal/cmd/operator-sdk/cli/cli_suite_test.go index 67474ae8074..ecd7c636ab7 100644 --- a/internal/cmd/operator-sdk/version/version_suite_test.go +++ b/internal/cmd/operator-sdk/cli/cli_suite_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package version_test +package cli import ( "testing" @@ -23,5 +23,5 @@ import ( func TestVersion(t *testing.T) { RegisterFailHandler(Fail) - RunSpecs(t, "Version Cmd Suite") + RunSpecs(t, "CLI Suite") } diff --git a/internal/cmd/operator-sdk/version/cmd.go b/internal/cmd/operator-sdk/cli/version.go similarity index 67% rename from internal/cmd/operator-sdk/version/cmd.go rename to internal/cmd/operator-sdk/cli/version.go index ca4684a23f9..f7bce4d3d1c 100644 --- a/internal/cmd/operator-sdk/version/cmd.go +++ b/internal/cmd/operator-sdk/cli/version.go @@ -12,29 +12,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -package version +package cli import ( "fmt" "runtime" - "github.com/spf13/cobra" - ver "github.com/operator-framework/operator-sdk/internal/version" ) -func NewCmd() *cobra.Command { - versionCmd := &cobra.Command{ - Use: "version", - Short: "Prints the version of operator-sdk", - Run: func(cmd *cobra.Command, args []string) { - run() - }, - } - return versionCmd -} - -func run() { - fmt.Printf("operator-sdk version: %q, commit: %q, kubernetes version: %q, go version: %q, GOOS: %q, GOARCH: %q\n", +func makeVersionString() string { + return fmt.Sprintf("operator-sdk version: %q, commit: %q, kubernetes version: %q, go version: %q, GOOS: %q, GOARCH: %q", ver.GitVersion, ver.GitCommit, ver.KubernetesVersion, runtime.Version(), runtime.GOOS, runtime.GOARCH) } diff --git a/internal/cmd/operator-sdk/cli/version_test.go b/internal/cmd/operator-sdk/cli/version_test.go new file mode 100644 index 00000000000..ba57c469ff8 --- /dev/null +++ b/internal/cmd/operator-sdk/cli/version_test.go @@ -0,0 +1,41 @@ +// Copyright 2020 The Operator-SDK 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. + +package cli + +import ( + "fmt" + "runtime" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + ver "github.com/operator-framework/operator-sdk/internal/version" +) + +var _ = Describe("printVersion", func() { + It("prints the correct version info", func() { + expVersion := makeVersionString() + version := ver.GitVersion + if version == "unknown" { + version = ver.Version + } + Expect(expVersion).To(ContainSubstring(fmt.Sprintf("version: %q", version))) + Expect(expVersion).To(ContainSubstring(fmt.Sprintf("commit: %q", ver.GitCommit))) + Expect(expVersion).To(ContainSubstring(fmt.Sprintf("kubernetes version: %q", ver.KubernetesVersion))) + Expect(expVersion).To(ContainSubstring(fmt.Sprintf("go version: %q", runtime.Version()))) + Expect(expVersion).To(ContainSubstring(fmt.Sprintf("GOOS: %q", runtime.GOOS))) + Expect(expVersion).To(ContainSubstring(fmt.Sprintf("GOARCH: %q", runtime.GOARCH))) + }) +}) diff --git a/internal/cmd/operator-sdk/version/cmd_test.go b/internal/cmd/operator-sdk/version/cmd_test.go deleted file mode 100644 index 8def44ddd9a..00000000000 --- a/internal/cmd/operator-sdk/version/cmd_test.go +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2020 The Operator-SDK 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. - -package version - -import ( - "fmt" - "io/ioutil" - "os" - "runtime" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - - ver "github.com/operator-framework/operator-sdk/internal/version" -) - -var _ = Describe("Running a version command", func() { - Describe("NewCmd", func() { - It("builds a cobra command", func() { - cmd := NewCmd() - Expect(cmd).NotTo(BeNil()) - Expect(cmd.Use).NotTo(Equal("")) - Expect(cmd.Short).NotTo(Equal("")) - }) - }) - Describe("run", func() { - It("prints the correct version info", func() { - r, w, _ := os.Pipe() - tmp := os.Stdout - defer func() { - os.Stdout = tmp - }() - os.Stdout = w - go func() { - run() - w.Close() - }() - stdout, err := ioutil.ReadAll(r) - Expect(err).To(BeNil()) - stdoutString := string(stdout) - version := ver.GitVersion - if version == "unknown" { - version = ver.Version - } - Expect(stdoutString).To(ContainSubstring(fmt.Sprintf("version: %q", version))) - Expect(stdoutString).To(ContainSubstring(fmt.Sprintf("commit: %q", ver.GitCommit))) - Expect(stdoutString).To(ContainSubstring(fmt.Sprintf("kubernetes version: %q", ver.KubernetesVersion))) - Expect(stdoutString).To(ContainSubstring(fmt.Sprintf("go version: %q", runtime.Version()))) - Expect(stdoutString).To(ContainSubstring(fmt.Sprintf("GOOS: %q", runtime.GOOS))) - Expect(stdoutString).To(ContainSubstring(fmt.Sprintf("GOARCH: %q", runtime.GOARCH))) - }) - }) -}) diff --git a/internal/kubebuilder/cmdutil/cmdutil.go b/internal/kubebuilder/cmdutil/cmdutil.go index 1999b912974..aa3e7f4a9e9 100644 --- a/internal/kubebuilder/cmdutil/cmdutil.go +++ b/internal/kubebuilder/cmdutil/cmdutil.go @@ -16,14 +16,18 @@ limitations under the License. package cmdutil -import "sigs.k8s.io/kubebuilder/v2/pkg/plugin/scaffold" +// Scaffolder interface creates files to set up a controller manager +type Scaffolder interface { + // Scaffold performs the scaffolding + Scaffold() error +} // RunOptions represent the types used to implement the different commands type RunOptions interface { // - Step 1: verify that the command can be run (e.g., go version, project version, arguments, ...) Validate() error // - Step 2: create the Scaffolder instance - GetScaffolder() (scaffold.Scaffolder, error) + GetScaffolder() (Scaffolder, error) // - Step 3: call the Scaffold method of the Scaffolder instance. Doesn't need any method // - Step 4: finish the command execution PostScaffold() error diff --git a/internal/plugins/ansible/v1/api.go b/internal/plugins/ansible/v1/api.go index 96cfdbc5b47..6fa7f33c6a2 100644 --- a/internal/plugins/ansible/v1/api.go +++ b/internal/plugins/ansible/v1/api.go @@ -22,7 +22,6 @@ import ( "sigs.k8s.io/kubebuilder/v2/pkg/model/config" "sigs.k8s.io/kubebuilder/v2/pkg/model/resource" "sigs.k8s.io/kubebuilder/v2/pkg/plugin" - "sigs.k8s.io/kubebuilder/v2/pkg/plugin/scaffold" "github.com/operator-framework/operator-sdk/internal/kubebuilder/cmdutil" "github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/scaffolds" @@ -152,7 +151,7 @@ func (p *createAPIPSubcommand) Validate() error { return nil } -func (p *createAPIPSubcommand) GetScaffolder() (scaffold.Scaffolder, error) { +func (p *createAPIPSubcommand) GetScaffolder() (cmdutil.Scaffolder, error) { return scaffolds.NewCreateAPIScaffolder(p.config, p.createOptions), nil } diff --git a/internal/plugins/ansible/v1/init.go b/internal/plugins/ansible/v1/init.go index 7e26f7310dc..48eb1390967 100644 --- a/internal/plugins/ansible/v1/init.go +++ b/internal/plugins/ansible/v1/init.go @@ -24,7 +24,6 @@ import ( "k8s.io/apimachinery/pkg/util/validation" "sigs.k8s.io/kubebuilder/v2/pkg/model/config" "sigs.k8s.io/kubebuilder/v2/pkg/plugin" - "sigs.k8s.io/kubebuilder/v2/pkg/plugin/scaffold" "github.com/operator-framework/operator-sdk/internal/kubebuilder/cmdutil" "github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/scaffolds" @@ -63,34 +62,30 @@ Optionally creates a new API, using the same flags as "create api" ` ctx.Examples = fmt.Sprintf(` # Scaffold a project with no API - $ %s init --plugins=%s --domain=my.domain \ + $ %[1]s init --plugins=%[2]s --domain=my.domain \ # Invokes "create api" - $ %s init --plugins=%s \ + $ %[1]s init --plugins=%[2]s \ --domain=my.domain \ --group=apps --version=v1alpha1 --kind=AppService - $ %s init --plugins=%s \ + $ %[1]s init --plugins=%[2]s \ --domain=my.domain \ --group=apps --version=v1alpha1 --kind=AppService \ --generate-role - $ %s init --plugins=%s \ + $ %[1]s init --plugins=%[2]s \ --domain=my.domain \ --group=apps --version=v1alpha1 --kind=AppService \ --generate-playbook - $ %s init --plugins=%s \ + $ %[1]s init --plugins=%[2]s \ --domain=my.domain \ --group=apps --version=v1alpha1 --kind=AppService \ --generate-playbook \ --generate-role `, ctx.CommandName, pluginKey, - ctx.CommandName, pluginKey, - ctx.CommandName, pluginKey, - ctx.CommandName, pluginKey, - ctx.CommandName, pluginKey, ) p.commandName = ctx.CommandName } @@ -160,9 +155,9 @@ func (p *initSubcommand) Validate() error { return nil } -func (p *initSubcommand) GetScaffolder() (scaffold.Scaffolder, error) { +func (p *initSubcommand) GetScaffolder() (cmdutil.Scaffolder, error) { var ( - apiScaffolder scaffold.Scaffolder + apiScaffolder cmdutil.Scaffolder err error ) if p.doCreateAPI { diff --git a/internal/plugins/ansible/v1/scaffolds/api.go b/internal/plugins/ansible/v1/scaffolds/api.go index 334b52f412c..57a727a9e58 100644 --- a/internal/plugins/ansible/v1/scaffolds/api.go +++ b/internal/plugins/ansible/v1/scaffolds/api.go @@ -25,8 +25,8 @@ import ( "sigs.k8s.io/kubebuilder/v2/pkg/model/config" "sigs.k8s.io/kubebuilder/v2/pkg/model/file" "sigs.k8s.io/kubebuilder/v2/pkg/model/resource" - "sigs.k8s.io/kubebuilder/v2/pkg/plugin/scaffold" + "github.com/operator-framework/operator-sdk/internal/kubebuilder/cmdutil" "github.com/operator-framework/operator-sdk/internal/kubebuilder/machinery" "github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/constants" "github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/scaffolds/internal/templates" @@ -38,7 +38,7 @@ import ( ansibleroles "github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/scaffolds/internal/templates/roles" ) -var _ scaffold.Scaffolder = &apiScaffolder{} +var _ cmdutil.Scaffolder = &apiScaffolder{} type CreateOptions struct { GVK schema.GroupVersionKind @@ -54,7 +54,7 @@ type apiScaffolder struct { } // NewCreateAPIScaffolder returns a new Scaffolder for project initialization operations -func NewCreateAPIScaffolder(config *config.Config, opts CreateOptions) scaffold.Scaffolder { +func NewCreateAPIScaffolder(config *config.Config, opts CreateOptions) cmdutil.Scaffolder { return &apiScaffolder{ config: config, opts: opts, @@ -91,7 +91,7 @@ func (s *apiScaffolder) scaffold() error { } resource := resourceOptions.NewResource(s.config, true) - s.config.AddResource(resource.GVK()) + s.config.UpdateResources(resource.GVK()) var createAPITemplates []file.Builder createAPITemplates = append(createAPITemplates, diff --git a/internal/plugins/ansible/v1/scaffolds/init.go b/internal/plugins/ansible/v1/scaffolds/init.go index b0947daeda4..09e1c006359 100644 --- a/internal/plugins/ansible/v1/scaffolds/init.go +++ b/internal/plugins/ansible/v1/scaffolds/init.go @@ -20,8 +20,8 @@ package scaffolds import ( "sigs.k8s.io/kubebuilder/v2/pkg/model" "sigs.k8s.io/kubebuilder/v2/pkg/model/config" - "sigs.k8s.io/kubebuilder/v2/pkg/plugin/scaffold" + "github.com/operator-framework/operator-sdk/internal/kubebuilder/cmdutil" "github.com/operator-framework/operator-sdk/internal/kubebuilder/machinery" "github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/scaffolds/internal/templates" "github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/scaffolds/internal/templates/config/kdefault" @@ -47,15 +47,15 @@ const ( // ansibleOperatorVersion is set to the version of ansible-operator at compile-time. var ansibleOperatorVersion = version.ImageVersion -var _ scaffold.Scaffolder = &initScaffolder{} +var _ cmdutil.Scaffolder = &initScaffolder{} type initScaffolder struct { config *config.Config - apiScaffolder scaffold.Scaffolder + apiScaffolder cmdutil.Scaffolder } // NewInitScaffolder returns a new Scaffolder for project initialization operations -func NewInitScaffolder(config *config.Config, apiScaffolder scaffold.Scaffolder) scaffold.Scaffolder { +func NewInitScaffolder(config *config.Config, apiScaffolder cmdutil.Scaffolder) cmdutil.Scaffolder { return &initScaffolder{ config: config, apiScaffolder: apiScaffolder, diff --git a/internal/plugins/golang/v2/plugin.go b/internal/plugins/golang/v2/plugin.go index a4dbffe6de7..ec7b7f511f4 100644 --- a/internal/plugins/golang/v2/plugin.go +++ b/internal/plugins/golang/v2/plugin.go @@ -18,7 +18,7 @@ import ( "github.com/operator-framework/operator-sdk/internal/plugins" "sigs.k8s.io/kubebuilder/v2/pkg/plugin" - kbgov2 "sigs.k8s.io/kubebuilder/v2/pkg/plugin/v2" + kbgov2 "sigs.k8s.io/kubebuilder/v2/pkg/plugins/golang/v2" ) // Plugin name/version used in this file will also be used in phase 2 plugins when we can diff --git a/internal/plugins/golang/v3/api.go b/internal/plugins/golang/v3/api.go new file mode 100644 index 00000000000..6f625d315c4 --- /dev/null +++ b/internal/plugins/golang/v3/api.go @@ -0,0 +1,70 @@ +// Copyright 2020 The Operator-SDK 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. + +package v3 + +import ( + "github.com/spf13/pflag" + "sigs.k8s.io/kubebuilder/v2/pkg/model/config" + "sigs.k8s.io/kubebuilder/v2/pkg/plugin" + + manifestsv2 "github.com/operator-framework/operator-sdk/internal/plugins/manifests/v2" +) + +type createAPISubcommand struct { + plugin.CreateAPISubcommand + + config *config.Config +} + +var _ plugin.CreateAPISubcommand = &createAPISubcommand{} + +func (p *createAPISubcommand) UpdateContext(ctx *plugin.Context) { + p.CreateAPISubcommand.UpdateContext(ctx) +} +func (p *createAPISubcommand) BindFlags(fs *pflag.FlagSet) { p.CreateAPISubcommand.BindFlags(fs) } + +func (p *createAPISubcommand) InjectConfig(c *config.Config) { + p.CreateAPISubcommand.InjectConfig(c) + p.config = c +} + +func (p *createAPISubcommand) Run() error { + // Run() may add a new resource to the config, so we can compare resources before/after to get the new resource. + oldResources := make(map[config.GVK]struct{}, len(p.config.Resources)) + for _, r := range p.config.Resources { + oldResources[r] = struct{}{} + } + if err := p.CreateAPISubcommand.Run(); err != nil { + return err + } + + // Find the new resource. Here we shouldn't worry about checking if one was found, + // since downstream plugins will do so. + var newResource config.GVK + for _, r := range p.config.Resources { + if _, hasResource := oldResources[r]; !hasResource { + newResource = r + break + } + } + + // Run SDK phase 2 plugins. + return p.runPhase2(newResource) +} + +// SDK phase 2 plugins. +func (p *createAPISubcommand) runPhase2(gvk config.GVK) error { + return manifestsv2.RunCreateAPI(p.config, gvk) +} diff --git a/internal/plugins/golang/v3/init.go b/internal/plugins/golang/v3/init.go new file mode 100644 index 00000000000..eed75977605 --- /dev/null +++ b/internal/plugins/golang/v3/init.go @@ -0,0 +1,64 @@ +// Copyright 2020 The Operator-SDK 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. + +package v3 + +import ( + "github.com/spf13/pflag" + "sigs.k8s.io/kubebuilder/v2/pkg/model/config" + "sigs.k8s.io/kubebuilder/v2/pkg/plugin" + + manifestsv2 "github.com/operator-framework/operator-sdk/internal/plugins/manifests/v2" + scorecardv2 "github.com/operator-framework/operator-sdk/internal/plugins/scorecard/v2" +) + +type initSubcommand struct { + plugin.InitSubcommand + + config *config.Config +} + +var _ plugin.InitSubcommand = &initSubcommand{} + +func (p *initSubcommand) UpdateContext(ctx *plugin.Context) { p.InitSubcommand.UpdateContext(ctx) } +func (p *initSubcommand) BindFlags(fs *pflag.FlagSet) { p.InitSubcommand.BindFlags(fs) } + +func (p *initSubcommand) InjectConfig(c *config.Config) { + p.InitSubcommand.InjectConfig(c) + p.config = c +} + +func (p *initSubcommand) Run() error { + if err := p.InitSubcommand.Run(); err != nil { + return err + } + + // Run SDK phase 2 plugins. + if err := p.runPhase2(); err != nil { + return err + } + + return nil +} + +// SDK phase 2 plugins. +func (p *initSubcommand) runPhase2() error { + if err := manifestsv2.RunInit(p.config); err != nil { + return err + } + if err := scorecardv2.RunInit(p.config); err != nil { + return err + } + return nil +} diff --git a/internal/plugins/golang/v3/plugin.go b/internal/plugins/golang/v3/plugin.go new file mode 100644 index 00000000000..a6be68a5a03 --- /dev/null +++ b/internal/plugins/golang/v3/plugin.go @@ -0,0 +1,55 @@ +// Copyright 2020 The Operator-SDK 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. + +package v3 + +import ( + "sigs.k8s.io/kubebuilder/v2/pkg/plugin" + kbgov3 "sigs.k8s.io/kubebuilder/v2/pkg/plugins/golang/v3" +) + +var ( + _ plugin.Plugin = Plugin{} + _ plugin.Full = Plugin{} +) + +// Plugin defines an Operator SDK Go scaffold and CLI plugin. Its current purpose is to +// add operator-framework features to the base kubebuilder Go scaffold and CLI. +type Plugin struct{} + +func (Plugin) Name() string { return (kbgov3.Plugin{}).Name() } +func (Plugin) Version() plugin.Version { return (kbgov3.Plugin{}).Version() } +func (Plugin) SupportedProjectVersions() []string { + return (kbgov3.Plugin{}).SupportedProjectVersions() +} + +func (p Plugin) GetInitSubcommand() plugin.InitSubcommand { + return &initSubcommand{ + InitSubcommand: (kbgov3.Plugin{}).GetInitSubcommand(), + } +} + +func (p Plugin) GetCreateAPISubcommand() plugin.CreateAPISubcommand { + return &createAPISubcommand{ + CreateAPISubcommand: (kbgov3.Plugin{}).GetCreateAPISubcommand(), + } +} + +func (p Plugin) GetCreateWebhookSubcommand() plugin.CreateWebhookSubcommand { + return (kbgov3.Plugin{}).GetCreateWebhookSubcommand() +} + +func (p Plugin) GetEditSubcommand() plugin.EditSubcommand { + return (kbgov3.Plugin{}).GetEditSubcommand() +} diff --git a/internal/plugins/helm/v1/api.go b/internal/plugins/helm/v1/api.go index 179ba7d8d56..4f9ece79428 100644 --- a/internal/plugins/helm/v1/api.go +++ b/internal/plugins/helm/v1/api.go @@ -22,7 +22,6 @@ import ( "sigs.k8s.io/kubebuilder/v2/pkg/model/config" "sigs.k8s.io/kubebuilder/v2/pkg/model/resource" "sigs.k8s.io/kubebuilder/v2/pkg/plugin" - "sigs.k8s.io/kubebuilder/v2/pkg/plugin/scaffold" "github.com/operator-framework/operator-sdk/internal/kubebuilder/cmdutil" "github.com/operator-framework/operator-sdk/internal/plugins/helm/v1/chartutil" @@ -181,8 +180,8 @@ func (p *createAPISubcommand) Validate() error { return nil } -// GetScaffolder returns scaffold.Scaffolder which will be executed due the RunOptions interface implementation -func (p *createAPISubcommand) GetScaffolder() (scaffold.Scaffolder, error) { +// GetScaffolder returns cmdutil.Scaffolder which will be executed due the RunOptions interface implementation +func (p *createAPISubcommand) GetScaffolder() (cmdutil.Scaffolder, error) { return scaffolds.NewAPIScaffolder(p.config, p.createOptions), nil } diff --git a/internal/plugins/helm/v1/init.go b/internal/plugins/helm/v1/init.go index 312b9434915..0729fc70edf 100644 --- a/internal/plugins/helm/v1/init.go +++ b/internal/plugins/helm/v1/init.go @@ -24,7 +24,6 @@ import ( "k8s.io/apimachinery/pkg/util/validation" "sigs.k8s.io/kubebuilder/v2/pkg/model/config" "sigs.k8s.io/kubebuilder/v2/pkg/plugin" - "sigs.k8s.io/kubebuilder/v2/pkg/plugin/scaffold" "github.com/operator-framework/operator-sdk/internal/kubebuilder/cmdutil" "github.com/operator-framework/operator-sdk/internal/plugins/helm/v1/chartutil" @@ -62,63 +61,55 @@ Writes the following files: - a Patch file for customizing image for manager manifests - a Patch file for enabling prometheus metrics ` - ctx.Examples = fmt.Sprintf(` $ %s init --plugins=%s \ + ctx.Examples = fmt.Sprintf(` $ %[1]s init --plugins=%[2]s \ --domain=example.com \ --group=apps \ --version=v1alpha1 \ --kind=AppService - $ %s init --plugins=%s \ + $ %[1]s init --plugins=%[2]s \ --project-name=myapp --domain=example.com \ --group=apps \ --version=v1alpha1 \ --kind=AppService - $ %s init --plugins=%s \ + $ %[1]s init --plugins=%[2]s \ --domain=example.com \ --group=apps \ --version=v1alpha1 \ --kind=AppService \ --helm-chart=myrepo/app - $ %s init --plugins=%s \ + $ %[1]s init --plugins=%[2]s \ --domain=example.com \ --helm-chart=myrepo/app - $ %s init --plugins=%s \ + $ %[1]s init --plugins=%[2]s \ --domain=example.com \ --helm-chart=myrepo/app \ --helm-chart-version=1.2.3 - $ %s init --plugins=%s \ + $ %[1]s init --plugins=%[2]s \ --domain=example.com \ --helm-chart=app \ --helm-chart-repo=https://charts.mycompany.com/ - $ %s init --plugins=%s \ + $ %[1]s init --plugins=%[2]s \ --domain=example.com \ --helm-chart=app \ --helm-chart-repo=https://charts.mycompany.com/ \ --helm-chart-version=1.2.3 - $ %s init --plugins=%s \ + $ %[1]s init --plugins=%[2]s \ --domain=example.com \ --helm-chart=/path/to/local/chart-directories/app/ - $ %s init --plugins=%s \ + $ %[1]s init --plugins=%[2]s \ --domain=example.com \ --helm-chart=/path/to/local/chart-archives/app-1.2.3.tgz `, ctx.CommandName, pluginKey, - ctx.CommandName, pluginKey, - ctx.CommandName, pluginKey, - ctx.CommandName, pluginKey, - ctx.CommandName, pluginKey, - ctx.CommandName, pluginKey, - ctx.CommandName, pluginKey, - ctx.CommandName, pluginKey, - ctx.CommandName, pluginKey, ) p.commandName = ctx.CommandName @@ -196,10 +187,10 @@ func (p *initSubcommand) Validate() error { return nil } -// GetScaffolder returns scaffold.Scaffolder which will be executed due the RunOptions interface implementation -func (p *initSubcommand) GetScaffolder() (scaffold.Scaffolder, error) { +// GetScaffolder returns cmdutil.Scaffolder which will be executed due the RunOptions interface implementation +func (p *initSubcommand) GetScaffolder() (cmdutil.Scaffolder, error) { var ( - apiScaffolder scaffold.Scaffolder + apiScaffolder cmdutil.Scaffolder err error ) if p.doCreateAPI { diff --git a/internal/plugins/helm/v1/scaffolds/api.go b/internal/plugins/helm/v1/scaffolds/api.go index 7f653373702..de44383043b 100644 --- a/internal/plugins/helm/v1/scaffolds/api.go +++ b/internal/plugins/helm/v1/scaffolds/api.go @@ -26,8 +26,8 @@ import ( "sigs.k8s.io/kubebuilder/v2/pkg/model" "sigs.k8s.io/kubebuilder/v2/pkg/model/config" "sigs.k8s.io/kubebuilder/v2/pkg/model/resource" - "sigs.k8s.io/kubebuilder/v2/pkg/plugin/scaffold" + "github.com/operator-framework/operator-sdk/internal/kubebuilder/cmdutil" "github.com/operator-framework/operator-sdk/internal/kubebuilder/machinery" "github.com/operator-framework/operator-sdk/internal/plugins/helm/v1/chartutil" "github.com/operator-framework/operator-sdk/internal/plugins/helm/v1/scaffolds/internal/templates" @@ -36,7 +36,7 @@ import ( "github.com/operator-framework/operator-sdk/internal/plugins/helm/v1/scaffolds/internal/templates/config/samples" ) -var _ scaffold.Scaffolder = &apiScaffolder{} +var _ cmdutil.Scaffolder = &apiScaffolder{} // apiScaffolder contains configuration for generating scaffolding for Go type // representing the API and controller that implements the behavior for the API. @@ -46,7 +46,7 @@ type apiScaffolder struct { } // NewAPIScaffolder returns a new Scaffolder for API/controller creation operations -func NewAPIScaffolder(config *config.Config, opts chartutil.CreateOptions) scaffold.Scaffolder { +func NewAPIScaffolder(config *config.Config, opts chartutil.CreateOptions) cmdutil.Scaffolder { return &apiScaffolder{ config: config, opts: opts, @@ -85,7 +85,7 @@ func (s *apiScaffolder) scaffold() error { } res := r.NewResource(s.config, true) - s.config.AddResource(res.GVK()) + s.config.UpdateResources(res.GVK()) chartPath := filepath.Join(chartutil.HelmChartsDir, chrt.Metadata.Name) if err := machinery.NewScaffold().Execute( diff --git a/internal/plugins/helm/v1/scaffolds/init.go b/internal/plugins/helm/v1/scaffolds/init.go index 2fedbaf1a48..f9b1e6d496a 100644 --- a/internal/plugins/helm/v1/scaffolds/init.go +++ b/internal/plugins/helm/v1/scaffolds/init.go @@ -22,8 +22,8 @@ import ( "sigs.k8s.io/kubebuilder/v2/pkg/model" "sigs.k8s.io/kubebuilder/v2/pkg/model/config" - "sigs.k8s.io/kubebuilder/v2/pkg/plugin/scaffold" + "github.com/operator-framework/operator-sdk/internal/kubebuilder/cmdutil" "github.com/operator-framework/operator-sdk/internal/kubebuilder/machinery" "github.com/operator-framework/operator-sdk/internal/plugins/helm/v1/chartutil" "github.com/operator-framework/operator-sdk/internal/plugins/helm/v1/scaffolds/internal/templates" @@ -44,15 +44,15 @@ const ( // helmOperatorVersion is set to the version of helm-operator at compile-time. var helmOperatorVersion = version.ImageVersion -var _ scaffold.Scaffolder = &initScaffolder{} +var _ cmdutil.Scaffolder = &initScaffolder{} type initScaffolder struct { config *config.Config - apiScaffolder scaffold.Scaffolder + apiScaffolder cmdutil.Scaffolder } // NewInitScaffolder returns a new Scaffolder for project initialization operations -func NewInitScaffolder(config *config.Config, apiScaffolder scaffold.Scaffolder) scaffold.Scaffolder { +func NewInitScaffolder(config *config.Config, apiScaffolder cmdutil.Scaffolder) cmdutil.Scaffolder { return &initScaffolder{ config: config, apiScaffolder: apiScaffolder, diff --git a/internal/plugins/manifests/v2/plugin.go b/internal/plugins/manifests/v2/plugin.go new file mode 100644 index 00000000000..7e06f492d54 --- /dev/null +++ b/internal/plugins/manifests/v2/plugin.go @@ -0,0 +1,70 @@ +// Copyright 2020 The Operator-SDK 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. + +package v2 + +import ( + "fmt" + + "github.com/operator-framework/operator-sdk/internal/plugins" + "github.com/operator-framework/operator-sdk/internal/plugins/manifests" + + "sigs.k8s.io/kubebuilder/v2/pkg/model/config" + "sigs.k8s.io/kubebuilder/v2/pkg/plugin" +) + +const ( + pluginName = "manifests" + plugins.DefaultNameQualifier +) + +var ( + pluginVersion = plugin.Version{Number: 2} + pluginConfigKey = plugin.Key(pluginName, pluginVersion.String()) +) + +// Config configures this plugin, and is saved in the project config file. +type Config struct{} + +// hasPluginConfig returns true if cfg.Plugins contains an exact match for this plugin's key. +func hasPluginConfig(cfg *config.Config) bool { + if !cfg.IsV3() || len(cfg.Plugins) == 0 { + return false + } + _, hasKey := cfg.Plugins[pluginConfigKey] + return hasKey +} + +// RunInit modifies the project scaffolded by kubebuilder's Init plugin. +func RunInit(cfg *config.Config) error { + // Only run these if project version is v3. + if err := manifests.RunInit(cfg); err != nil { + return err + } + + // Update the plugin config section with this plugin's configuration. + mCfg := Config{} + if err := cfg.EncodePluginConfig(pluginConfigKey, mCfg); err != nil { + return fmt.Errorf("error writing plugin config for %s: %v", pluginConfigKey, err) + } + + return nil +} + +// RunCreateAPI runs the manifests SDK phase 2 plugin. +func RunCreateAPI(cfg *config.Config, gvk config.GVK) error { + if !hasPluginConfig(cfg) { + return nil + } + return manifests.RunCreateAPI(cfg, gvk) +} diff --git a/internal/plugins/scorecard/v2/plugin.go b/internal/plugins/scorecard/v2/plugin.go new file mode 100644 index 00000000000..80147698a13 --- /dev/null +++ b/internal/plugins/scorecard/v2/plugin.go @@ -0,0 +1,53 @@ +// Copyright 2020 The Operator-SDK 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. + +package v2 + +import ( + "fmt" + + "github.com/operator-framework/operator-sdk/internal/plugins" + "github.com/operator-framework/operator-sdk/internal/plugins/scorecard" + + "sigs.k8s.io/kubebuilder/v2/pkg/model/config" + "sigs.k8s.io/kubebuilder/v2/pkg/plugin" +) + +const ( + pluginName = "scorecard" + plugins.DefaultNameQualifier +) + +var ( + pluginVersion = plugin.Version{Number: 2} + pluginConfigKey = plugin.Key(pluginName, pluginVersion.String()) +) + +// Config configures this plugin, and is saved in the project config file. +type Config struct{} + +// RunInit scaffolds kustomize files for kustomizing a scorecard componentconfig. +func RunInit(cfg *config.Config) error { + + if err := scorecard.RunInit(cfg); err != nil { + return err + } + + // Update the plugin config section with this plugin's configuration. + mCfg := Config{} + if err := cfg.EncodePluginConfig(pluginConfigKey, mCfg); err != nil { + return fmt.Errorf("error writing plugin config for %s: %v", pluginConfigKey, err) + } + + return nil +} diff --git a/internal/testutils/utils.go b/internal/testutils/utils.go index ae7199f39a9..4c63da1236f 100644 --- a/internal/testutils/utils.go +++ b/internal/testutils/utils.go @@ -49,14 +49,48 @@ type TestContext struct { } // NewTestContext returns a TestContext containing a new kubebuilder TestContext. -func NewTestContext(binary string, env ...string) (tc TestContext, err error) { - tc.TestContext, err = kbtestutils.NewTestContext(binary, env...) +// Construct if your environment is connected to a live cluster, ex. for e2e tests. +func NewTestContext(binaryName string, env ...string) (tc TestContext, err error) { + if tc.TestContext, err = kbtestutils.NewTestContext(binaryName, env...); err != nil { + return tc, err + } tc.ProjectName = strings.ToLower(filepath.Base(tc.Dir)) - tc.ImageName = fmt.Sprintf("quay.io/example/%s:v0.0.1", tc.ProjectName) - tc.BundleImageName = fmt.Sprintf("quay.io/example/%s-bundle:v0.0.1", tc.ProjectName) + tc.ImageName = makeImageName(tc.ProjectName) + tc.BundleImageName = makeBundleImageName(tc.ProjectName) tc.isOLMManagedBySuite = true tc.isPrometheusManagedBySuite = true - return tc, err + return tc, nil +} + +// NewPartialTestContext returns a TestContext containing a partial kubebuilder TestContext. +// This object needs to be populated with GVK information. The underlying TestContext is +// created directly rather than through a constructor so cluster-based setup is skipped. +func NewPartialTestContext(binaryName, dir string, env ...string) (tc TestContext, err error) { + cc := &kbtestutils.CmdContext{ + Env: env, + } + if cc.Dir, err = filepath.Abs(dir); err != nil { + return tc, err + } + projectName := strings.ToLower(filepath.Base(dir)) + + return TestContext{ + TestContext: &kbtestutils.TestContext{ + CmdContext: cc, + BinaryName: binaryName, + ImageName: makeImageName(projectName), + }, + ProjectName: projectName, + BundleImageName: makeBundleImageName(projectName), + }, nil +} + +func makeImageName(projectName string) string { + return fmt.Sprintf("quay.io/example/%s:v0.0.1", projectName) +} + +func makeBundleImageName(projectName string) string { + return fmt.Sprintf("quay.io/example/%s-bundle:v0.0.1", projectName) } // InstallOLM runs 'operator-sdk olm install' for specific version @@ -75,11 +109,6 @@ func (tc TestContext) UninstallOLM() { } } -// KustomizeBuild runs 'kustomize build ' and returns its output and an error if any. -func (tc TestContext) KustomizeBuild(dir string) ([]byte, error) { - return tc.Run(exec.Command("kustomize", "build", dir)) -} - // ReplaceInFile replaces all instances of old with new in the file at path. // todo(camilamacedo86): this func can be pushed to upstream/kb func ReplaceInFile(path, old, new string) error { diff --git a/test/e2e-go/e2e_go_cluster_test.go b/test/e2e-go/e2e_go_cluster_test.go index 126cce378eb..cb87d68f046 100644 --- a/test/e2e-go/e2e_go_cluster_test.go +++ b/test/e2e-go/e2e_go_cluster_test.go @@ -43,20 +43,11 @@ var _ = Describe("operator-sdk", func() { Expect(err).NotTo(HaveOccurred()) }) AfterEach(func() { - By("cleaning up the operator and resources") - defaultOutput, err := tc.KustomizeBuild(filepath.Join("config", "default")) - Expect(err).NotTo(HaveOccurred()) - _, err = tc.Kubectl.WithInput(string(defaultOutput)).Command("delete", "-f", "-") - Expect(err).NotTo(HaveOccurred()) - - By("deleting Curl Pod created") - _, _ = tc.Kubectl.Delete(true, "pod", "curl") - By("cleaning up permissions") _, _ = tc.Kubectl.Command("delete", "clusterrolebinding", fmt.Sprintf("metrics-%s", tc.TestSuffix)) - By("undeploy project") + By("cleaning up the operator and resources") _ = tc.Make("undeploy") By("ensuring that the namespace was deleted") @@ -131,14 +122,6 @@ var _ = Describe("operator-sdk", func() { return err }, time.Minute, time.Second).Should(Succeed()) - By("ensuring the created resource object gets reconciled in controller") - managerContainerLogs := func() string { - logOutput, err := tc.Kubectl.Logs(controllerPodName, "-c", "manager") - Expect(err).NotTo(HaveOccurred()) - return logOutput - } - Eventually(managerContainerLogs, time.Minute, time.Second).Should(ContainSubstring("Successfully Reconciled")) - By("granting permissions to access the metrics and read the token") _, err = tc.Kubectl.Command( "create", @@ -148,7 +131,7 @@ var _ = Describe("operator-sdk", func() { fmt.Sprintf("--serviceaccount=%s:default", tc.Kubectl.Namespace)) Expect(err).NotTo(HaveOccurred()) - By("getting the token") + By("reading the token") b64Token, err := tc.Kubectl.Get( true, "secrets", @@ -156,12 +139,12 @@ var _ = Describe("operator-sdk", func() { Expect(err).NotTo(HaveOccurred()) token, err := base64.StdEncoding.DecodeString(strings.TrimSpace(b64Token)) Expect(err).NotTo(HaveOccurred()) - Expect(token).NotTo(HaveLen(0)) + Expect(len(token)).To(BeNumerically(">", 0)) - By("creating a pod with curl image") - // todo: the flag --generator=run-pod/v1 is deprecated, however, shows that besides + By("creating a curl pod") + // TODO: the flag --generator=run-pod/v1 is deprecated, however, shows that besides // it should not make any difference and work locally successfully when the flag is removed - // travis has been failing and the curl pod is not found when the flag is not used + // the test will fail and the curl pod is not found when the flag is not used cmdOpts := []string{ "run", "--generator=run-pod/v1", "curl", "--image=curlimages/curl:7.68.0", "--restart=OnFailure", "--", "curl", "-v", "-k", "-H", fmt.Sprintf(`Authorization: Bearer %s`, token), @@ -171,27 +154,38 @@ var _ = Describe("operator-sdk", func() { _, err = tc.Kubectl.CommandInNamespace(cmdOpts...) Expect(err).NotTo(HaveOccurred()) - By("validating the curl pod running as expected") + By("validating that the curl pod is running as expected") verifyCurlUp := func() error { // Validate pod status status, err := tc.Kubectl.Get( true, "pods", "curl", "-o", "jsonpath={.status.phase}") - Expect(err).NotTo(HaveOccurred()) + ExpectWithOffset(1, err).NotTo(HaveOccurred()) if status != "Completed" && status != "Succeeded" { return fmt.Errorf("curl pod in %s status", status) } return nil } - Eventually(verifyCurlUp, 4*time.Minute, time.Second).Should(Succeed()) + Eventually(verifyCurlUp, 2*time.Minute, time.Second).Should(Succeed()) - By("checking metrics endpoint serving as expected") + By("validating that the metrics endpoint is serving as expected") + var metricsOutput string getCurlLogs := func() string { - logOutput, err := tc.Kubectl.Logs("curl") - Expect(err).NotTo(HaveOccurred()) - return logOutput + metricsOutput, err = tc.Kubectl.Logs("curl") + ExpectWithOffset(1, err).NotTo(HaveOccurred()) + return metricsOutput } Eventually(getCurlLogs, time.Minute, time.Second).Should(ContainSubstring("< HTTP/2 200")) + + By("cleaning up the curl pod") + _, err = tc.Kubectl.Delete(true, "pods", "curl") + Expect(err).NotTo(HaveOccurred()) + + By("validating that the created resource object gets reconciled in the controller") + Expect(metricsOutput).To(ContainSubstring(fmt.Sprintf( + `controller_runtime_reconcile_total{controller="%s",result="success"} 1`, + strings.ToLower(tc.Kind), + ))) }) }) }) diff --git a/test/e2e-go/e2e_go_suite_test.go b/test/e2e-go/e2e_go_suite_test.go index 49e923db4ca..56678801e44 100644 --- a/test/e2e-go/e2e_go_suite_test.go +++ b/test/e2e-go/e2e_go_suite_test.go @@ -62,6 +62,8 @@ var _ = BeforeSuite(func() { By("initializing a project") err = tc.Init( "--project-version", "3-alpha", + // TODO(estroz): remove this once go/v3-alpha is stabilized and the default plugin. + "--plugins", "go/v3-alpha", "--repo", path.Join("github.com", "example", tc.ProjectName), "--domain", tc.Domain, "--fetch-deps=false") diff --git a/testdata/go/memcached-operator/.gitignore b/testdata/go/v2/go/memcached-operator/.gitignore similarity index 100% rename from testdata/go/memcached-operator/.gitignore rename to testdata/go/v2/go/memcached-operator/.gitignore diff --git a/testdata/go/memcached-operator/Dockerfile b/testdata/go/v2/go/memcached-operator/Dockerfile similarity index 100% rename from testdata/go/memcached-operator/Dockerfile rename to testdata/go/v2/go/memcached-operator/Dockerfile diff --git a/testdata/go/memcached-operator/Makefile b/testdata/go/v2/go/memcached-operator/Makefile similarity index 100% rename from testdata/go/memcached-operator/Makefile rename to testdata/go/v2/go/memcached-operator/Makefile diff --git a/testdata/go/memcached-operator/PROJECT b/testdata/go/v2/go/memcached-operator/PROJECT similarity index 100% rename from testdata/go/memcached-operator/PROJECT rename to testdata/go/v2/go/memcached-operator/PROJECT diff --git a/testdata/go/memcached-operator/api/v1alpha1/groupversion_info.go b/testdata/go/v2/go/memcached-operator/api/v1alpha1/groupversion_info.go similarity index 100% rename from testdata/go/memcached-operator/api/v1alpha1/groupversion_info.go rename to testdata/go/v2/go/memcached-operator/api/v1alpha1/groupversion_info.go diff --git a/testdata/go/memcached-operator/api/v1alpha1/memcached_types.go b/testdata/go/v2/go/memcached-operator/api/v1alpha1/memcached_types.go similarity index 99% rename from testdata/go/memcached-operator/api/v1alpha1/memcached_types.go rename to testdata/go/v2/go/memcached-operator/api/v1alpha1/memcached_types.go index f9a4c16774b..4ed5052101e 100644 --- a/testdata/go/memcached-operator/api/v1alpha1/memcached_types.go +++ b/testdata/go/v2/go/memcached-operator/api/v1alpha1/memcached_types.go @@ -31,7 +31,6 @@ type MemcachedSpec struct { // Size defines the number of Memcached instances Size int32 `json:"size,omitempty"` - // Foo is an example field of Memcached. Edit Memcached_types.go to remove/update Foo string `json:"foo,omitempty"` } @@ -43,7 +42,6 @@ type MemcachedStatus struct { // Nodes store the name of the pods which are running Memcached instances Nodes []string `json:"nodes,omitempty"` - } // +kubebuilder:object:root=true diff --git a/testdata/go/memcached-operator/api/v1alpha1/memcached_webhook.go b/testdata/go/v2/go/memcached-operator/api/v1alpha1/memcached_webhook.go similarity index 95% rename from testdata/go/memcached-operator/api/v1alpha1/memcached_webhook.go rename to testdata/go/v2/go/memcached-operator/api/v1alpha1/memcached_webhook.go index cdf24233311..d3b41a9f963 100644 --- a/testdata/go/memcached-operator/api/v1alpha1/memcached_webhook.go +++ b/testdata/go/v2/go/memcached-operator/api/v1alpha1/memcached_webhook.go @@ -16,7 +16,8 @@ limitations under the License. package v1alpha1 -import ("errors" +import ( + "errors" ctrl "sigs.k8s.io/controller-runtime" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/webhook" @@ -44,7 +45,9 @@ func (r *Memcached) Default() { if r.Spec.Size == 0 { r.Spec.Size = 3 } -}// TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation. +} + +// TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation. // +kubebuilder:webhook:verbs=create;update,path=/validate-cache-example-com-v1alpha1-memcached,mutating=false,failurePolicy=fail,groups=cache.example.com,resources=memcacheds,versions=v1alpha1,name=vmemcached.kb.io var _ webhook.Validator = &Memcached{} @@ -75,4 +78,3 @@ func validateOdd(n int32) error { } return nil } - diff --git a/testdata/go/memcached-operator/api/v1alpha1/zz_generated.deepcopy.go b/testdata/go/v2/go/memcached-operator/api/v1alpha1/zz_generated.deepcopy.go similarity index 100% rename from testdata/go/memcached-operator/api/v1alpha1/zz_generated.deepcopy.go rename to testdata/go/v2/go/memcached-operator/api/v1alpha1/zz_generated.deepcopy.go diff --git a/testdata/go/memcached-operator/bundle.Dockerfile b/testdata/go/v2/go/memcached-operator/bundle.Dockerfile similarity index 100% rename from testdata/go/memcached-operator/bundle.Dockerfile rename to testdata/go/v2/go/memcached-operator/bundle.Dockerfile diff --git a/testdata/go/memcached-operator/bundle/manifests/cache.example.com_memcacheds.yaml b/testdata/go/v2/go/memcached-operator/bundle/manifests/cache.example.com_memcacheds.yaml similarity index 100% rename from testdata/go/memcached-operator/bundle/manifests/cache.example.com_memcacheds.yaml rename to testdata/go/v2/go/memcached-operator/bundle/manifests/cache.example.com_memcacheds.yaml diff --git a/testdata/go/memcached-operator/bundle/manifests/memcached-operator-controller-manager-metrics-monitor_monitoring.coreos.com_v1_servicemonitor.yaml b/testdata/go/v2/go/memcached-operator/bundle/manifests/memcached-operator-controller-manager-metrics-monitor_monitoring.coreos.com_v1_servicemonitor.yaml similarity index 100% rename from testdata/go/memcached-operator/bundle/manifests/memcached-operator-controller-manager-metrics-monitor_monitoring.coreos.com_v1_servicemonitor.yaml rename to testdata/go/v2/go/memcached-operator/bundle/manifests/memcached-operator-controller-manager-metrics-monitor_monitoring.coreos.com_v1_servicemonitor.yaml diff --git a/testdata/go/memcached-operator/bundle/manifests/memcached-operator-controller-manager-metrics-service_v1_service.yaml b/testdata/go/v2/go/memcached-operator/bundle/manifests/memcached-operator-controller-manager-metrics-service_v1_service.yaml similarity index 100% rename from testdata/go/memcached-operator/bundle/manifests/memcached-operator-controller-manager-metrics-service_v1_service.yaml rename to testdata/go/v2/go/memcached-operator/bundle/manifests/memcached-operator-controller-manager-metrics-service_v1_service.yaml diff --git a/testdata/go/memcached-operator/bundle/manifests/memcached-operator-metrics-reader_rbac.authorization.k8s.io_v1_clusterrole.yaml b/testdata/go/v2/go/memcached-operator/bundle/manifests/memcached-operator-metrics-reader_rbac.authorization.k8s.io_v1_clusterrole.yaml similarity index 100% rename from testdata/go/memcached-operator/bundle/manifests/memcached-operator-metrics-reader_rbac.authorization.k8s.io_v1_clusterrole.yaml rename to testdata/go/v2/go/memcached-operator/bundle/manifests/memcached-operator-metrics-reader_rbac.authorization.k8s.io_v1_clusterrole.yaml diff --git a/testdata/go/memcached-operator/bundle/manifests/memcached-operator-webhook-service_v1_service.yaml b/testdata/go/v2/go/memcached-operator/bundle/manifests/memcached-operator-webhook-service_v1_service.yaml similarity index 100% rename from testdata/go/memcached-operator/bundle/manifests/memcached-operator-webhook-service_v1_service.yaml rename to testdata/go/v2/go/memcached-operator/bundle/manifests/memcached-operator-webhook-service_v1_service.yaml diff --git a/testdata/go/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml b/testdata/go/v2/go/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml similarity index 100% rename from testdata/go/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml rename to testdata/go/v2/go/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml diff --git a/testdata/go/memcached-operator/bundle/metadata/annotations.yaml b/testdata/go/v2/go/memcached-operator/bundle/metadata/annotations.yaml similarity index 100% rename from testdata/go/memcached-operator/bundle/metadata/annotations.yaml rename to testdata/go/v2/go/memcached-operator/bundle/metadata/annotations.yaml diff --git a/testdata/go/memcached-operator/bundle/tests/scorecard/config.yaml b/testdata/go/v2/go/memcached-operator/bundle/tests/scorecard/config.yaml similarity index 100% rename from testdata/go/memcached-operator/bundle/tests/scorecard/config.yaml rename to testdata/go/v2/go/memcached-operator/bundle/tests/scorecard/config.yaml diff --git a/testdata/go/memcached-operator/config/certmanager/certificate.yaml b/testdata/go/v2/go/memcached-operator/config/certmanager/certificate.yaml similarity index 100% rename from testdata/go/memcached-operator/config/certmanager/certificate.yaml rename to testdata/go/v2/go/memcached-operator/config/certmanager/certificate.yaml diff --git a/testdata/go/memcached-operator/config/certmanager/kustomization.yaml b/testdata/go/v2/go/memcached-operator/config/certmanager/kustomization.yaml similarity index 100% rename from testdata/go/memcached-operator/config/certmanager/kustomization.yaml rename to testdata/go/v2/go/memcached-operator/config/certmanager/kustomization.yaml diff --git a/testdata/go/memcached-operator/config/certmanager/kustomizeconfig.yaml b/testdata/go/v2/go/memcached-operator/config/certmanager/kustomizeconfig.yaml similarity index 100% rename from testdata/go/memcached-operator/config/certmanager/kustomizeconfig.yaml rename to testdata/go/v2/go/memcached-operator/config/certmanager/kustomizeconfig.yaml diff --git a/testdata/go/memcached-operator/config/crd/bases/cache.example.com_memcacheds.yaml b/testdata/go/v2/go/memcached-operator/config/crd/bases/cache.example.com_memcacheds.yaml similarity index 100% rename from testdata/go/memcached-operator/config/crd/bases/cache.example.com_memcacheds.yaml rename to testdata/go/v2/go/memcached-operator/config/crd/bases/cache.example.com_memcacheds.yaml diff --git a/testdata/go/memcached-operator/config/crd/kustomization.yaml b/testdata/go/v2/go/memcached-operator/config/crd/kustomization.yaml similarity index 100% rename from testdata/go/memcached-operator/config/crd/kustomization.yaml rename to testdata/go/v2/go/memcached-operator/config/crd/kustomization.yaml diff --git a/testdata/go/memcached-operator/config/crd/kustomizeconfig.yaml b/testdata/go/v2/go/memcached-operator/config/crd/kustomizeconfig.yaml similarity index 100% rename from testdata/go/memcached-operator/config/crd/kustomizeconfig.yaml rename to testdata/go/v2/go/memcached-operator/config/crd/kustomizeconfig.yaml diff --git a/testdata/go/memcached-operator/config/crd/patches/cainjection_in_memcacheds.yaml b/testdata/go/v2/go/memcached-operator/config/crd/patches/cainjection_in_memcacheds.yaml similarity index 100% rename from testdata/go/memcached-operator/config/crd/patches/cainjection_in_memcacheds.yaml rename to testdata/go/v2/go/memcached-operator/config/crd/patches/cainjection_in_memcacheds.yaml diff --git a/testdata/go/memcached-operator/config/crd/patches/webhook_in_memcacheds.yaml b/testdata/go/v2/go/memcached-operator/config/crd/patches/webhook_in_memcacheds.yaml similarity index 100% rename from testdata/go/memcached-operator/config/crd/patches/webhook_in_memcacheds.yaml rename to testdata/go/v2/go/memcached-operator/config/crd/patches/webhook_in_memcacheds.yaml diff --git a/testdata/go/memcached-operator/config/default/kustomization.yaml b/testdata/go/v2/go/memcached-operator/config/default/kustomization.yaml similarity index 100% rename from testdata/go/memcached-operator/config/default/kustomization.yaml rename to testdata/go/v2/go/memcached-operator/config/default/kustomization.yaml diff --git a/testdata/go/memcached-operator/config/default/manager_auth_proxy_patch.yaml b/testdata/go/v2/go/memcached-operator/config/default/manager_auth_proxy_patch.yaml similarity index 100% rename from testdata/go/memcached-operator/config/default/manager_auth_proxy_patch.yaml rename to testdata/go/v2/go/memcached-operator/config/default/manager_auth_proxy_patch.yaml diff --git a/testdata/go/memcached-operator/config/default/manager_webhook_patch.yaml b/testdata/go/v2/go/memcached-operator/config/default/manager_webhook_patch.yaml similarity index 100% rename from testdata/go/memcached-operator/config/default/manager_webhook_patch.yaml rename to testdata/go/v2/go/memcached-operator/config/default/manager_webhook_patch.yaml diff --git a/testdata/go/memcached-operator/config/default/webhookcainjection_patch.yaml b/testdata/go/v2/go/memcached-operator/config/default/webhookcainjection_patch.yaml similarity index 100% rename from testdata/go/memcached-operator/config/default/webhookcainjection_patch.yaml rename to testdata/go/v2/go/memcached-operator/config/default/webhookcainjection_patch.yaml diff --git a/testdata/go/memcached-operator/config/manager/kustomization.yaml b/testdata/go/v2/go/memcached-operator/config/manager/kustomization.yaml similarity index 100% rename from testdata/go/memcached-operator/config/manager/kustomization.yaml rename to testdata/go/v2/go/memcached-operator/config/manager/kustomization.yaml diff --git a/testdata/go/memcached-operator/config/manager/manager.yaml b/testdata/go/v2/go/memcached-operator/config/manager/manager.yaml similarity index 100% rename from testdata/go/memcached-operator/config/manager/manager.yaml rename to testdata/go/v2/go/memcached-operator/config/manager/manager.yaml diff --git a/testdata/go/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml b/testdata/go/v2/go/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml similarity index 100% rename from testdata/go/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml rename to testdata/go/v2/go/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml diff --git a/testdata/go/memcached-operator/config/manifests/kustomization.yaml b/testdata/go/v2/go/memcached-operator/config/manifests/kustomization.yaml similarity index 100% rename from testdata/go/memcached-operator/config/manifests/kustomization.yaml rename to testdata/go/v2/go/memcached-operator/config/manifests/kustomization.yaml diff --git a/testdata/go/memcached-operator/config/prometheus/kustomization.yaml b/testdata/go/v2/go/memcached-operator/config/prometheus/kustomization.yaml similarity index 100% rename from testdata/go/memcached-operator/config/prometheus/kustomization.yaml rename to testdata/go/v2/go/memcached-operator/config/prometheus/kustomization.yaml diff --git a/testdata/go/memcached-operator/config/prometheus/monitor.yaml b/testdata/go/v2/go/memcached-operator/config/prometheus/monitor.yaml similarity index 100% rename from testdata/go/memcached-operator/config/prometheus/monitor.yaml rename to testdata/go/v2/go/memcached-operator/config/prometheus/monitor.yaml diff --git a/testdata/go/memcached-operator/config/rbac/auth_proxy_client_clusterrole.yaml b/testdata/go/v2/go/memcached-operator/config/rbac/auth_proxy_client_clusterrole.yaml similarity index 100% rename from testdata/go/memcached-operator/config/rbac/auth_proxy_client_clusterrole.yaml rename to testdata/go/v2/go/memcached-operator/config/rbac/auth_proxy_client_clusterrole.yaml diff --git a/testdata/go/memcached-operator/config/rbac/auth_proxy_role.yaml b/testdata/go/v2/go/memcached-operator/config/rbac/auth_proxy_role.yaml similarity index 100% rename from testdata/go/memcached-operator/config/rbac/auth_proxy_role.yaml rename to testdata/go/v2/go/memcached-operator/config/rbac/auth_proxy_role.yaml diff --git a/testdata/go/memcached-operator/config/rbac/auth_proxy_role_binding.yaml b/testdata/go/v2/go/memcached-operator/config/rbac/auth_proxy_role_binding.yaml similarity index 100% rename from testdata/go/memcached-operator/config/rbac/auth_proxy_role_binding.yaml rename to testdata/go/v2/go/memcached-operator/config/rbac/auth_proxy_role_binding.yaml diff --git a/testdata/go/memcached-operator/config/rbac/auth_proxy_service.yaml b/testdata/go/v2/go/memcached-operator/config/rbac/auth_proxy_service.yaml similarity index 100% rename from testdata/go/memcached-operator/config/rbac/auth_proxy_service.yaml rename to testdata/go/v2/go/memcached-operator/config/rbac/auth_proxy_service.yaml diff --git a/testdata/go/memcached-operator/config/rbac/kustomization.yaml b/testdata/go/v2/go/memcached-operator/config/rbac/kustomization.yaml similarity index 100% rename from testdata/go/memcached-operator/config/rbac/kustomization.yaml rename to testdata/go/v2/go/memcached-operator/config/rbac/kustomization.yaml diff --git a/testdata/go/memcached-operator/config/rbac/leader_election_role.yaml b/testdata/go/v2/go/memcached-operator/config/rbac/leader_election_role.yaml similarity index 100% rename from testdata/go/memcached-operator/config/rbac/leader_election_role.yaml rename to testdata/go/v2/go/memcached-operator/config/rbac/leader_election_role.yaml diff --git a/testdata/go/memcached-operator/config/rbac/leader_election_role_binding.yaml b/testdata/go/v2/go/memcached-operator/config/rbac/leader_election_role_binding.yaml similarity index 100% rename from testdata/go/memcached-operator/config/rbac/leader_election_role_binding.yaml rename to testdata/go/v2/go/memcached-operator/config/rbac/leader_election_role_binding.yaml diff --git a/testdata/go/memcached-operator/config/rbac/memcached_editor_role.yaml b/testdata/go/v2/go/memcached-operator/config/rbac/memcached_editor_role.yaml similarity index 100% rename from testdata/go/memcached-operator/config/rbac/memcached_editor_role.yaml rename to testdata/go/v2/go/memcached-operator/config/rbac/memcached_editor_role.yaml diff --git a/testdata/go/memcached-operator/config/rbac/memcached_viewer_role.yaml b/testdata/go/v2/go/memcached-operator/config/rbac/memcached_viewer_role.yaml similarity index 100% rename from testdata/go/memcached-operator/config/rbac/memcached_viewer_role.yaml rename to testdata/go/v2/go/memcached-operator/config/rbac/memcached_viewer_role.yaml diff --git a/testdata/go/memcached-operator/config/rbac/role.yaml b/testdata/go/v2/go/memcached-operator/config/rbac/role.yaml similarity index 100% rename from testdata/go/memcached-operator/config/rbac/role.yaml rename to testdata/go/v2/go/memcached-operator/config/rbac/role.yaml diff --git a/testdata/go/memcached-operator/config/rbac/role_binding.yaml b/testdata/go/v2/go/memcached-operator/config/rbac/role_binding.yaml similarity index 100% rename from testdata/go/memcached-operator/config/rbac/role_binding.yaml rename to testdata/go/v2/go/memcached-operator/config/rbac/role_binding.yaml diff --git a/testdata/go/memcached-operator/config/samples/cache_v1alpha1_memcached.yaml b/testdata/go/v2/go/memcached-operator/config/samples/cache_v1alpha1_memcached.yaml similarity index 100% rename from testdata/go/memcached-operator/config/samples/cache_v1alpha1_memcached.yaml rename to testdata/go/v2/go/memcached-operator/config/samples/cache_v1alpha1_memcached.yaml diff --git a/testdata/go/memcached-operator/config/samples/kustomization.yaml b/testdata/go/v2/go/memcached-operator/config/samples/kustomization.yaml similarity index 100% rename from testdata/go/memcached-operator/config/samples/kustomization.yaml rename to testdata/go/v2/go/memcached-operator/config/samples/kustomization.yaml diff --git a/testdata/go/memcached-operator/config/scorecard/bases/config.yaml b/testdata/go/v2/go/memcached-operator/config/scorecard/bases/config.yaml similarity index 100% rename from testdata/go/memcached-operator/config/scorecard/bases/config.yaml rename to testdata/go/v2/go/memcached-operator/config/scorecard/bases/config.yaml diff --git a/testdata/go/memcached-operator/config/scorecard/kustomization.yaml b/testdata/go/v2/go/memcached-operator/config/scorecard/kustomization.yaml similarity index 100% rename from testdata/go/memcached-operator/config/scorecard/kustomization.yaml rename to testdata/go/v2/go/memcached-operator/config/scorecard/kustomization.yaml diff --git a/testdata/go/memcached-operator/config/scorecard/patches/basic.config.yaml b/testdata/go/v2/go/memcached-operator/config/scorecard/patches/basic.config.yaml similarity index 100% rename from testdata/go/memcached-operator/config/scorecard/patches/basic.config.yaml rename to testdata/go/v2/go/memcached-operator/config/scorecard/patches/basic.config.yaml diff --git a/testdata/go/memcached-operator/config/scorecard/patches/olm.config.yaml b/testdata/go/v2/go/memcached-operator/config/scorecard/patches/olm.config.yaml similarity index 100% rename from testdata/go/memcached-operator/config/scorecard/patches/olm.config.yaml rename to testdata/go/v2/go/memcached-operator/config/scorecard/patches/olm.config.yaml diff --git a/testdata/go/memcached-operator/config/webhook/kustomization.yaml b/testdata/go/v2/go/memcached-operator/config/webhook/kustomization.yaml similarity index 100% rename from testdata/go/memcached-operator/config/webhook/kustomization.yaml rename to testdata/go/v2/go/memcached-operator/config/webhook/kustomization.yaml diff --git a/testdata/go/memcached-operator/config/webhook/kustomizeconfig.yaml b/testdata/go/v2/go/memcached-operator/config/webhook/kustomizeconfig.yaml similarity index 100% rename from testdata/go/memcached-operator/config/webhook/kustomizeconfig.yaml rename to testdata/go/v2/go/memcached-operator/config/webhook/kustomizeconfig.yaml diff --git a/testdata/go/memcached-operator/config/webhook/manifests.yaml b/testdata/go/v2/go/memcached-operator/config/webhook/manifests.yaml similarity index 100% rename from testdata/go/memcached-operator/config/webhook/manifests.yaml rename to testdata/go/v2/go/memcached-operator/config/webhook/manifests.yaml diff --git a/testdata/go/memcached-operator/config/webhook/service.yaml b/testdata/go/v2/go/memcached-operator/config/webhook/service.yaml similarity index 100% rename from testdata/go/memcached-operator/config/webhook/service.yaml rename to testdata/go/v2/go/memcached-operator/config/webhook/service.yaml diff --git a/testdata/go/memcached-operator/controllers/memcached_controller.go b/testdata/go/v2/go/memcached-operator/controllers/memcached_controller.go similarity index 99% rename from testdata/go/memcached-operator/controllers/memcached_controller.go rename to testdata/go/v2/go/memcached-operator/controllers/memcached_controller.go index 56b2340d0bd..14ee7006471 100644 --- a/testdata/go/memcached-operator/controllers/memcached_controller.go +++ b/testdata/go/v2/go/memcached-operator/controllers/memcached_controller.go @@ -24,7 +24,6 @@ import ( "k8s.io/apimachinery/pkg/types" "reflect" - "context" "github.com/go-logr/logr" @@ -123,7 +122,6 @@ func (r *MemcachedReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { } } - return ctrl.Result{}, nil } @@ -180,7 +178,6 @@ func getPodNames(pods []corev1.Pod) []string { return podNames } - func (r *MemcachedReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). For(&cachev1alpha1.Memcached{}). diff --git a/testdata/go/memcached-operator/controllers/suite_test.go b/testdata/go/v2/go/memcached-operator/controllers/suite_test.go similarity index 100% rename from testdata/go/memcached-operator/controllers/suite_test.go rename to testdata/go/v2/go/memcached-operator/controllers/suite_test.go diff --git a/testdata/go/memcached-operator/go.mod b/testdata/go/v2/go/memcached-operator/go.mod similarity index 85% rename from testdata/go/memcached-operator/go.mod rename to testdata/go/v2/go/memcached-operator/go.mod index 8ba3d87d653..009ec6f67dc 100644 --- a/testdata/go/memcached-operator/go.mod +++ b/testdata/go/v2/go/memcached-operator/go.mod @@ -9,5 +9,5 @@ require ( k8s.io/api v0.18.6 k8s.io/apimachinery v0.18.6 k8s.io/client-go v0.18.6 - sigs.k8s.io/controller-runtime v0.6.3 + sigs.k8s.io/controller-runtime v0.6.4 ) diff --git a/testdata/go/memcached-operator/go.sum b/testdata/go/v2/go/memcached-operator/go.sum similarity index 99% rename from testdata/go/memcached-operator/go.sum rename to testdata/go/v2/go/memcached-operator/go.sum index d37c4f4180b..99be6d9c769 100644 --- a/testdata/go/memcached-operator/go.sum +++ b/testdata/go/v2/go/memcached-operator/go.sum @@ -465,8 +465,8 @@ k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl k8s.io/utils v0.0.0-20200603063816-c1c6865ac451 h1:v8ud2Up6QK1lNOKFgiIVrZdMg7MpmSnvtrOieolJKoE= k8s.io/utils v0.0.0-20200603063816-c1c6865ac451/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0= -sigs.k8s.io/controller-runtime v0.6.3 h1:SBbr+inLPEKhvlJtrvDcwIpm+uhDvp63Bl72xYJtoOE= -sigs.k8s.io/controller-runtime v0.6.3/go.mod h1:WlZNXcM0++oyaQt4B7C2lEE5JYRs8vJUzRP4N4JpdAY= +sigs.k8s.io/controller-runtime v0.6.4 h1:4013CKsBs5bEqo+LevzDett+LLxag/FjQWG94nVZ/9g= +sigs.k8s.io/controller-runtime v0.6.4/go.mod h1:WlZNXcM0++oyaQt4B7C2lEE5JYRs8vJUzRP4N4JpdAY= sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= sigs.k8s.io/structured-merge-diff/v3 v3.0.0 h1:dOmIZBMfhcHS09XZkMyUgkq5trg3/jRyJYFZUiaOp8E= sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= diff --git a/testdata/go/memcached-operator/hack/boilerplate.go.txt b/testdata/go/v2/go/memcached-operator/hack/boilerplate.go.txt similarity index 100% rename from testdata/go/memcached-operator/hack/boilerplate.go.txt rename to testdata/go/v2/go/memcached-operator/hack/boilerplate.go.txt diff --git a/testdata/go/memcached-operator/main.go b/testdata/go/v2/go/memcached-operator/main.go similarity index 100% rename from testdata/go/memcached-operator/main.go rename to testdata/go/v2/go/memcached-operator/main.go diff --git a/testdata/go/v3/memcached-operator/.dockerignore b/testdata/go/v3/memcached-operator/.dockerignore new file mode 100644 index 00000000000..243f81a5080 --- /dev/null +++ b/testdata/go/v3/memcached-operator/.dockerignore @@ -0,0 +1,5 @@ +# More info: https://docs.docker.com/engine/reference/builder/#dockerignore-file +# Ignore all files which are not go type +!**/*.go +!**/*.mod +!**/*.sum diff --git a/testdata/go/v3/memcached-operator/.gitignore b/testdata/go/v3/memcached-operator/.gitignore new file mode 100644 index 00000000000..c0a7a54cac5 --- /dev/null +++ b/testdata/go/v3/memcached-operator/.gitignore @@ -0,0 +1,25 @@ + +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib +bin +testbin/* + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Kubernetes Generated files - skip generated files, except for vendored files + +!vendor/**/zz_generated.* + +# editor and IDE paraphernalia +.idea +*.swp +*.swo +*~ diff --git a/testdata/go/v3/memcached-operator/Dockerfile b/testdata/go/v3/memcached-operator/Dockerfile new file mode 100644 index 00000000000..ce816f3b0e7 --- /dev/null +++ b/testdata/go/v3/memcached-operator/Dockerfile @@ -0,0 +1,27 @@ +# Build the manager binary +FROM golang:1.15 as builder + +WORKDIR /workspace +# Copy the Go Modules manifests +COPY go.mod go.mod +COPY go.sum go.sum +# cache deps before building and copying source so that we don't need to re-download as much +# and so that source changes don't invalidate our downloaded layer +RUN go mod download + +# Copy the go source +COPY main.go main.go +COPY api/ api/ +COPY controllers/ controllers/ + +# Build +RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GO111MODULE=on go build -a -o manager main.go + +# 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 --from=builder /workspace/manager . +USER 65532:65532 + +ENTRYPOINT ["/manager"] diff --git a/testdata/go/v3/memcached-operator/Makefile b/testdata/go/v3/memcached-operator/Makefile new file mode 100644 index 00000000000..482fa7aebe7 --- /dev/null +++ b/testdata/go/v3/memcached-operator/Makefile @@ -0,0 +1,119 @@ +# Current Operator version +VERSION ?= 0.0.1 +# Default bundle image tag +BUNDLE_IMG ?= controller-bundle:$(VERSION) +# Options for 'bundle-build' +ifneq ($(origin CHANNELS), undefined) +BUNDLE_CHANNELS := --channels=$(CHANNELS) +endif +ifneq ($(origin DEFAULT_CHANNEL), undefined) +BUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL) +endif +BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL) + +# Image URL to use all building/pushing image targets +IMG ?= controller:latest +# Produce CRDs that work back to Kubernetes 1.11 (no version conversion) +CRD_OPTIONS ?= "crd:trivialVersions=true,preserveUnknownFields=false" + +# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set) +ifeq (,$(shell go env GOBIN)) +GOBIN=$(shell go env GOPATH)/bin +else +GOBIN=$(shell go env GOBIN) +endif + +all: manager + +# Run tests +ENVTEST_ASSETS_DIR=$(shell pwd)/testbin +test: generate fmt vet manifests + mkdir -p ${ENVTEST_ASSETS_DIR} + test -f ${ENVTEST_ASSETS_DIR}/setup-envtest.sh || curl -sSLo ${ENVTEST_ASSETS_DIR}/setup-envtest.sh https://raw.githubusercontent.com/kubernetes-sigs/controller-runtime/v0.7.0-alpha.8/hack/setup-envtest.sh + source ${ENVTEST_ASSETS_DIR}/setup-envtest.sh; fetch_envtest_tools $(ENVTEST_ASSETS_DIR); setup_envtest_env $(ENVTEST_ASSETS_DIR); go test ./... -coverprofile cover.out + +# Build manager binary +manager: generate fmt vet + go build -o bin/manager main.go + +# Run against the configured Kubernetes cluster in ~/.kube/config +run: generate fmt vet manifests + go run ./main.go + +# Install CRDs into a cluster +install: manifests kustomize + $(KUSTOMIZE) build config/crd | kubectl apply -f - + +# Uninstall CRDs from a cluster +uninstall: manifests kustomize + $(KUSTOMIZE) build config/crd | kubectl delete -f - + +# Deploy controller in the configured Kubernetes cluster in ~/.kube/config +deploy: manifests kustomize + cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG} + $(KUSTOMIZE) build config/default | kubectl apply -f - + +# UnDeploy controller from the configured Kubernetes cluster in ~/.kube/config +undeploy: + $(KUSTOMIZE) build config/default | kubectl delete -f - + +# Generate manifests e.g. CRD, RBAC etc. +manifests: controller-gen + $(CONTROLLER_GEN) $(CRD_OPTIONS) rbac:roleName=manager-role webhook paths="./..." output:crd:artifacts:config=config/crd/bases + +# Run go fmt against code +fmt: + go fmt ./... + +# Run go vet against code +vet: + go vet ./... + +# Generate code +generate: controller-gen + $(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..." + +# Build the docker image +docker-build: test + docker build -t ${IMG} . + +# Push the docker image +docker-push: + docker push ${IMG} + +# Download controller-gen locally if necessary +CONTROLLER_GEN = $(shell pwd)/bin/controller-gen +controller-gen: + $(call go-get-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@v0.4.1) + +# Download kustomize locally if necessary +KUSTOMIZE = $(shell pwd)/bin/kustomize +kustomize: + $(call go-get-tool,$(KUSTOMIZE),sigs.k8s.io/kustomize/kustomize/v3@v3.8.7) + +# go-get-tool will 'go get' any package $2 and install it to $1. +PROJECT_DIR := $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST)))) +define go-get-tool +@[ -f $(1) ] || { \ +set -e ;\ +TMP_DIR=$$(mktemp -d) ;\ +cd $$TMP_DIR ;\ +go mod init tmp ;\ +echo "Downloading $(2)" ;\ +GOBIN=$(PROJECT_DIR)/bin go get $(2) ;\ +rm -rf $$TMP_DIR ;\ +} +endef + +# Generate bundle manifests and metadata, then validate generated files. +.PHONY: bundle +bundle: manifests kustomize + operator-sdk generate kustomize manifests --interactive=false -q + cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG) + $(KUSTOMIZE) build config/manifests | operator-sdk generate bundle -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS) + operator-sdk bundle validate ./bundle + +# Build the bundle image. +.PHONY: bundle-build +bundle-build: + docker build -f bundle.Dockerfile -t $(BUNDLE_IMG) . diff --git a/testdata/go/v3/memcached-operator/PROJECT b/testdata/go/v3/memcached-operator/PROJECT new file mode 100644 index 00000000000..f968692d2db --- /dev/null +++ b/testdata/go/v3/memcached-operator/PROJECT @@ -0,0 +1,14 @@ +domain: example.com +layout: go.kubebuilder.io/v3-alpha +projectName: memcached-operator +repo: github.com/example/memcached-operator +resources: +- crdVersion: v1 + group: cache + kind: Memcached + version: v1alpha1 + webhookVersion: v1 +version: 3-alpha +plugins: + manifests.sdk.operatorframework.io/v2: {} + scorecard.sdk.operatorframework.io/v2: {} diff --git a/testdata/go/v3/memcached-operator/api/v1alpha1/groupversion_info.go b/testdata/go/v3/memcached-operator/api/v1alpha1/groupversion_info.go new file mode 100644 index 00000000000..cd34e142a1d --- /dev/null +++ b/testdata/go/v3/memcached-operator/api/v1alpha1/groupversion_info.go @@ -0,0 +1,36 @@ +/* +Copyright 2020. + +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 v1alpha1 contains API Schema definitions for the cache v1alpha1 API group +// +kubebuilder:object:generate=true +// +groupName=cache.example.com +package v1alpha1 + +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: "cache.example.com", Version: "v1alpha1"} + + // 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/testdata/go/v3/memcached-operator/api/v1alpha1/memcached_types.go b/testdata/go/v3/memcached-operator/api/v1alpha1/memcached_types.go new file mode 100644 index 00000000000..4ed5052101e --- /dev/null +++ b/testdata/go/v3/memcached-operator/api/v1alpha1/memcached_types.go @@ -0,0 +1,70 @@ +/* +Copyright 2020. + +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 v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! +// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. + +// MemcachedSpec defines the desired state of Memcached +type MemcachedSpec struct { + // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster + // Important: Run "make" to regenerate code after modifying this file + + // Size defines the number of Memcached instances + Size int32 `json:"size,omitempty"` + + // Foo is an example field of Memcached. Edit Memcached_types.go to remove/update + Foo string `json:"foo,omitempty"` +} + +// MemcachedStatus defines the observed state of Memcached +type MemcachedStatus struct { + // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster + // Important: Run "make" to regenerate code after modifying this file + + // Nodes store the name of the pods which are running Memcached instances + Nodes []string `json:"nodes,omitempty"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status + +// Memcached is the Schema for the memcacheds API +type Memcached struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec MemcachedSpec `json:"spec,omitempty"` + Status MemcachedStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// MemcachedList contains a list of Memcached +type MemcachedList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Memcached `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Memcached{}, &MemcachedList{}) +} diff --git a/testdata/go/v3/memcached-operator/api/v1alpha1/memcached_webhook.go b/testdata/go/v3/memcached-operator/api/v1alpha1/memcached_webhook.go new file mode 100644 index 00000000000..65cafb56d07 --- /dev/null +++ b/testdata/go/v3/memcached-operator/api/v1alpha1/memcached_webhook.go @@ -0,0 +1,82 @@ +/* +Copyright 2020. + +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 v1alpha1 + +import ( + "errors" + + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/webhook" +) + +// log is for logging in this package. +var memcachedlog = logf.Log.WithName("memcached-resource") + +func (r *Memcached) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} + +// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! + +// +kubebuilder:webhook:path=/mutate-cache-example-com-v1alpha1-memcached,mutating=true,failurePolicy=fail,sideEffects=None,groups=cache.example.com,resources=memcacheds,verbs=create;update,versions=v1alpha1,name=mmemcached.kb.io,admissionReviewVersions={v1beta1} + +var _ webhook.Defaulter = &Memcached{} + +// Default implements webhook.Defaulter so a webhook will be registered for the type +func (r *Memcached) Default() { + memcachedlog.Info("default", "name", r.Name) + + if r.Spec.Size == 0 { + r.Spec.Size = 3 + } +} + +// TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation. +// +kubebuilder:webhook:path=/validate-cache-example-com-v1alpha1-memcached,mutating=false,failurePolicy=fail,sideEffects=None,groups=cache.example.com,resources=memcacheds,verbs=create;update,versions=v1alpha1,name=vmemcached.kb.io,admissionReviewVersions={v1beta1} + +var _ webhook.Validator = &Memcached{} + +// ValidateCreate implements webhook.Validator so a webhook will be registered for the type +func (r *Memcached) ValidateCreate() error { + memcachedlog.Info("validate create", "name", r.Name) + + return validateOdd(r.Spec.Size) +} + +// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type +func (r *Memcached) ValidateUpdate(old runtime.Object) error { + memcachedlog.Info("validate update", "name", r.Name) + + return validateOdd(r.Spec.Size) +} + +// ValidateDelete implements webhook.Validator so a webhook will be registered for the type +func (r *Memcached) ValidateDelete() error { + memcachedlog.Info("validate delete", "name", r.Name) + + return nil +} +func validateOdd(n int32) error { + if n%2 == 0 { + return errors.New("Cluster size must be an odd number") + } + return nil +} diff --git a/testdata/go/v3/memcached-operator/api/v1alpha1/webhook_suite_test.go b/testdata/go/v3/memcached-operator/api/v1alpha1/webhook_suite_test.go new file mode 100644 index 00000000000..d122eacf445 --- /dev/null +++ b/testdata/go/v3/memcached-operator/api/v1alpha1/webhook_suite_test.go @@ -0,0 +1,133 @@ +/* +Copyright 2020. + +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 v1alpha1 + +import ( + "context" + "crypto/tls" + "fmt" + "net" + "path/filepath" + "testing" + "time" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + admissionv1beta1 "k8s.io/api/admission/v1beta1" + // +kubebuilder:scaffold:imports + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/rest" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/envtest" + "sigs.k8s.io/controller-runtime/pkg/envtest/printer" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/log/zap" +) + +// These tests use Ginkgo (BDD-style Go testing framework). Refer to +// http://onsi.github.io/ginkgo/ to learn more about Ginkgo. + +var cfg *rest.Config +var k8sClient client.Client +var testEnv *envtest.Environment +var ctx context.Context +var cancel context.CancelFunc + +func TestAPIs(t *testing.T) { + RegisterFailHandler(Fail) + + RunSpecsWithDefaultAndCustomReporters(t, + "Webhook Suite", + []Reporter{printer.NewlineReporter{}}) +} + +var _ = BeforeSuite(func() { + logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) + + ctx, cancel = context.WithCancel(context.TODO()) + + By("bootstrapping test environment") + testEnv = &envtest.Environment{ + CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")}, + WebhookInstallOptions: envtest.WebhookInstallOptions{ + Paths: []string{filepath.Join("..", "..", "config", "webhook")}, + }, + } + + cfg, err := testEnv.Start() + Expect(err).NotTo(HaveOccurred()) + Expect(cfg).NotTo(BeNil()) + + scheme := runtime.NewScheme() + err = AddToScheme(scheme) + Expect(err).NotTo(HaveOccurred()) + + err = admissionv1beta1.AddToScheme(scheme) + Expect(err).NotTo(HaveOccurred()) + + // +kubebuilder:scaffold:scheme + + k8sClient, err = client.New(cfg, client.Options{Scheme: scheme}) + Expect(err).NotTo(HaveOccurred()) + Expect(k8sClient).NotTo(BeNil()) + + // start webhook server using Manager + webhookInstallOptions := &testEnv.WebhookInstallOptions + mgr, err := ctrl.NewManager(cfg, ctrl.Options{ + Scheme: scheme, + Host: webhookInstallOptions.LocalServingHost, + Port: webhookInstallOptions.LocalServingPort, + CertDir: webhookInstallOptions.LocalServingCertDir, + LeaderElection: false, + MetricsBindAddress: "0", + }) + Expect(err).NotTo(HaveOccurred()) + + err = (&Memcached{}).SetupWebhookWithManager(mgr) + Expect(err).NotTo(HaveOccurred()) + + // +kubebuilder:scaffold:webhook + + go func() { + err = mgr.Start(ctx) + if err != nil { + Expect(err).NotTo(HaveOccurred()) + } + }() + + // wait for the webhook server to get ready + dialer := &net.Dialer{Timeout: time.Second} + addrPort := fmt.Sprintf("%s:%d", webhookInstallOptions.LocalServingHost, webhookInstallOptions.LocalServingPort) + Eventually(func() error { + conn, err := tls.DialWithDialer(dialer, "tcp", addrPort, &tls.Config{InsecureSkipVerify: true}) + if err != nil { + return err + } + conn.Close() + return nil + }).Should(Succeed()) + +}, 60) + +var _ = AfterSuite(func() { + cancel() + By("tearing down the test environment") + err := testEnv.Stop() + Expect(err).NotTo(HaveOccurred()) +}) diff --git a/testdata/go/v3/memcached-operator/api/v1alpha1/zz_generated.deepcopy.go b/testdata/go/v3/memcached-operator/api/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 00000000000..c9b4e97a164 --- /dev/null +++ b/testdata/go/v3/memcached-operator/api/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,119 @@ +// +build !ignore_autogenerated + +/* +Copyright 2020. + +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 v1alpha1 + +import ( + 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 *Memcached) DeepCopyInto(out *Memcached) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Memcached. +func (in *Memcached) DeepCopy() *Memcached { + if in == nil { + return nil + } + out := new(Memcached) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Memcached) 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 *MemcachedList) DeepCopyInto(out *MemcachedList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Memcached, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MemcachedList. +func (in *MemcachedList) DeepCopy() *MemcachedList { + if in == nil { + return nil + } + out := new(MemcachedList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *MemcachedList) 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 *MemcachedSpec) DeepCopyInto(out *MemcachedSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MemcachedSpec. +func (in *MemcachedSpec) DeepCopy() *MemcachedSpec { + if in == nil { + return nil + } + out := new(MemcachedSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MemcachedStatus) DeepCopyInto(out *MemcachedStatus) { + *out = *in + if in.Nodes != nil { + in, out := &in.Nodes, &out.Nodes + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MemcachedStatus. +func (in *MemcachedStatus) DeepCopy() *MemcachedStatus { + if in == nil { + return nil + } + out := new(MemcachedStatus) + in.DeepCopyInto(out) + return out +} diff --git a/testdata/go/v3/memcached-operator/bundle.Dockerfile b/testdata/go/v3/memcached-operator/bundle.Dockerfile new file mode 100644 index 00000000000..4f7ff821ae5 --- /dev/null +++ b/testdata/go/v3/memcached-operator/bundle.Dockerfile @@ -0,0 +1,12 @@ +FROM scratch + +LABEL operators.operatorframework.io.bundle.mediatype.v1=registry+v1 +LABEL operators.operatorframework.io.bundle.manifests.v1=manifests/ +LABEL operators.operatorframework.io.bundle.metadata.v1=metadata/ +LABEL operators.operatorframework.io.bundle.package.v1=memcached-operator +LABEL operators.operatorframework.io.bundle.channels.v1=alpha +LABEL operators.operatorframework.io.test.config.v1=tests/scorecard/ +LABEL operators.operatorframework.io.test.mediatype.v1=scorecard+v1 +COPY bundle/manifests /manifests/ +COPY bundle/metadata /metadata/ +COPY bundle/tests/scorecard /tests/scorecard/ diff --git a/testdata/go/v3/memcached-operator/bundle/manifests/cache.example.com_memcacheds.yaml b/testdata/go/v3/memcached-operator/bundle/manifests/cache.example.com_memcacheds.yaml new file mode 100644 index 00000000000..3af607fe5c2 --- /dev/null +++ b/testdata/go/v3/memcached-operator/bundle/manifests/cache.example.com_memcacheds.yaml @@ -0,0 +1,60 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.4.1 + creationTimestamp: null + name: memcacheds.cache.example.com +spec: + group: cache.example.com + names: + kind: Memcached + listKind: MemcachedList + plural: memcacheds + singular: memcached + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: Memcached is the Schema for the memcacheds API + 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: MemcachedSpec defines the desired state of Memcached + properties: + foo: + description: Foo is an example field of Memcached. Edit Memcached_types.go to remove/update + type: string + size: + description: Size defines the number of Memcached instances + format: int32 + type: integer + type: object + status: + description: MemcachedStatus defines the observed state of Memcached + properties: + nodes: + description: Nodes store the name of the pods which are running Memcached instances + items: + type: string + type: array + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/testdata/go/v3/memcached-operator/bundle/manifests/memcached-operator-controller-manager-metrics-monitor_monitoring.coreos.com_v1_servicemonitor.yaml b/testdata/go/v3/memcached-operator/bundle/manifests/memcached-operator-controller-manager-metrics-monitor_monitoring.coreos.com_v1_servicemonitor.yaml new file mode 100644 index 00000000000..f9e131b08de --- /dev/null +++ b/testdata/go/v3/memcached-operator/bundle/manifests/memcached-operator-controller-manager-metrics-monitor_monitoring.coreos.com_v1_servicemonitor.yaml @@ -0,0 +1,13 @@ +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + labels: + control-plane: controller-manager + name: memcached-operator-controller-manager-metrics-monitor +spec: + endpoints: + - path: /metrics + port: https + selector: + matchLabels: + control-plane: controller-manager diff --git a/testdata/go/v3/memcached-operator/bundle/manifests/memcached-operator-controller-manager-metrics-service_v1_service.yaml b/testdata/go/v3/memcached-operator/bundle/manifests/memcached-operator-controller-manager-metrics-service_v1_service.yaml new file mode 100644 index 00000000000..157a0cefa11 --- /dev/null +++ b/testdata/go/v3/memcached-operator/bundle/manifests/memcached-operator-controller-manager-metrics-service_v1_service.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Service +metadata: + creationTimestamp: null + labels: + control-plane: controller-manager + name: memcached-operator-controller-manager-metrics-service +spec: + ports: + - name: https + port: 8443 + targetPort: https + selector: + control-plane: controller-manager +status: + loadBalancer: {} diff --git a/testdata/go/v3/memcached-operator/bundle/manifests/memcached-operator-manager-config_v1_configmap.yaml b/testdata/go/v3/memcached-operator/bundle/manifests/memcached-operator-manager-config_v1_configmap.yaml new file mode 100644 index 00000000000..ea42c599454 --- /dev/null +++ b/testdata/go/v3/memcached-operator/bundle/manifests/memcached-operator-manager-config_v1_configmap.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +data: + controller_manager_config.yaml: | + apiVersion: controller-runtime.sigs.k8s.io/v1alpha1 + kind: ControllerManagerConfig + health: + healthProbeBindAddress: :8081 + metrics: + bindAddress: 127.0.0.1:8080 + webhook: + port: 9443 + leaderElection: + leaderElect: true + resourceName: 86f835c3.example.com +kind: ConfigMap +metadata: + name: memcached-operator-manager-config diff --git a/testdata/go/v3/memcached-operator/bundle/manifests/memcached-operator-metrics-reader_rbac.authorization.k8s.io_v1_clusterrole.yaml b/testdata/go/v3/memcached-operator/bundle/manifests/memcached-operator-metrics-reader_rbac.authorization.k8s.io_v1_clusterrole.yaml new file mode 100644 index 00000000000..42a2ae6ac4d --- /dev/null +++ b/testdata/go/v3/memcached-operator/bundle/manifests/memcached-operator-metrics-reader_rbac.authorization.k8s.io_v1_clusterrole.yaml @@ -0,0 +1,10 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + creationTimestamp: null + name: memcached-operator-metrics-reader +rules: +- nonResourceURLs: + - /metrics + verbs: + - get diff --git a/testdata/go/v3/memcached-operator/bundle/manifests/memcached-operator-webhook-service_v1_service.yaml b/testdata/go/v3/memcached-operator/bundle/manifests/memcached-operator-webhook-service_v1_service.yaml new file mode 100644 index 00000000000..4c9ef443f09 --- /dev/null +++ b/testdata/go/v3/memcached-operator/bundle/manifests/memcached-operator-webhook-service_v1_service.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + creationTimestamp: null + name: memcached-operator-webhook-service +spec: + ports: + - port: 443 + targetPort: 9443 + selector: + control-plane: controller-manager +status: + loadBalancer: {} diff --git a/testdata/go/v3/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml b/testdata/go/v3/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml new file mode 100644 index 00000000000..b58e2903ca7 --- /dev/null +++ b/testdata/go/v3/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml @@ -0,0 +1,254 @@ +apiVersion: operators.coreos.com/v1alpha1 +kind: ClusterServiceVersion +metadata: + annotations: + alm-examples: |- + [ + { + "apiVersion": "cache.example.com/v1alpha1", + "kind": "Memcached", + "metadata": { + "name": "memcached-sample" + }, + "spec": { + "foo": "bar" + } + } + ] + capabilities: Basic Install + name: memcached-operator.v0.0.1 + namespace: placeholder +spec: + apiservicedefinitions: {} + customresourcedefinitions: + owned: + - description: Memcached is the Schema for the memcacheds API + displayName: Memcached + kind: Memcached + name: memcacheds.cache.example.com + version: v1alpha1 + description: Memcached Operator description. TODO. + displayName: Memcached Operator + icon: + - base64data: "" + mediatype: "" + install: + spec: + clusterPermissions: + - rules: + - apiGroups: + - apps + resources: + - deployments + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - cache.example.com + resources: + - memcacheds + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - cache.example.com + resources: + - memcacheds/finalizers + verbs: + - update + - apiGroups: + - cache.example.com + resources: + - memcacheds/status + verbs: + - get + - patch + - update + - apiGroups: + - "" + resources: + - pods + verbs: + - get + - list + - apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create + - apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create + serviceAccountName: default + deployments: + - name: memcached-operator-controller-manager + spec: + replicas: 1 + selector: + matchLabels: + control-plane: controller-manager + strategy: {} + template: + metadata: + labels: + control-plane: controller-manager + spec: + containers: + - args: + - --secure-listen-address=0.0.0.0:8443 + - --upstream=http://127.0.0.1:8080/ + - --logtostderr=true + - --v=10 + image: gcr.io/kubebuilder/kube-rbac-proxy:v0.5.0 + name: kube-rbac-proxy + ports: + - containerPort: 8443 + name: https + resources: {} + - args: + - --health-probe-bind-address=:8081 + - --metrics-bind-address=127.0.0.1:8080 + - --leader-elect + command: + - /manager + image: quay.io/example/memcached-operator:v0.0.1 + livenessProbe: + httpGet: + path: /readyz + port: 8081 + initialDelaySeconds: 15 + periodSeconds: 20 + name: manager + ports: + - containerPort: 9443 + name: webhook-server + protocol: TCP + readinessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 5 + periodSeconds: 10 + resources: + limits: + cpu: 100m + memory: 30Mi + requests: + cpu: 100m + memory: 20Mi + securityContext: + allowPrivilegeEscalation: false + volumeMounts: + - mountPath: /tmp/k8s-webhook-server/serving-certs + name: cert + readOnly: true + securityContext: + runAsUser: 65532 + terminationGracePeriodSeconds: 10 + volumes: + - name: cert + secret: + defaultMode: 420 + secretName: webhook-server-cert + permissions: + - rules: + - apiGroups: + - "" + - coordination.k8s.io + resources: + - configmaps + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete + - apiGroups: + - "" + resources: + - events + verbs: + - create + - patch + serviceAccountName: default + strategy: deployment + installModes: + - supported: false + type: OwnNamespace + - supported: false + type: SingleNamespace + - supported: false + type: MultiNamespace + - supported: true + type: AllNamespaces + keywords: + - memcached-operator + links: + - name: Memcached Operator + url: https://memcached-operator.domain + maintainers: + - email: your@email.com + name: Maintainer Name + maturity: alpha + provider: + name: Provider Name + url: https://your.domain + version: 0.0.1 + webhookdefinitions: + - admissionReviewVersions: + - v1beta1 + containerPort: 443 + deploymentName: memcached-operator-controller-manager + failurePolicy: Fail + generateName: vmemcached.kb.io + rules: + - apiGroups: + - cache.example.com + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - memcacheds + sideEffects: None + targetPort: 9443 + type: ValidatingAdmissionWebhook + webhookPath: /validate-cache-example-com-v1alpha1-memcached + - admissionReviewVersions: + - v1beta1 + containerPort: 443 + deploymentName: memcached-operator-controller-manager + failurePolicy: Fail + generateName: mmemcached.kb.io + rules: + - apiGroups: + - cache.example.com + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - memcacheds + sideEffects: None + targetPort: 9443 + type: MutatingAdmissionWebhook + webhookPath: /mutate-cache-example-com-v1alpha1-memcached diff --git a/testdata/go/v3/memcached-operator/bundle/metadata/annotations.yaml b/testdata/go/v3/memcached-operator/bundle/metadata/annotations.yaml new file mode 100644 index 00000000000..9c65a477b22 --- /dev/null +++ b/testdata/go/v3/memcached-operator/bundle/metadata/annotations.yaml @@ -0,0 +1,8 @@ +annotations: + operators.operatorframework.io.bundle.channels.v1: alpha + operators.operatorframework.io.bundle.manifests.v1: manifests/ + operators.operatorframework.io.bundle.mediatype.v1: registry+v1 + operators.operatorframework.io.bundle.metadata.v1: metadata/ + operators.operatorframework.io.bundle.package.v1: memcached-operator + operators.operatorframework.io.test.config.v1: tests/scorecard/ + operators.operatorframework.io.test.mediatype.v1: scorecard+v1 diff --git a/testdata/go/v3/memcached-operator/bundle/tests/scorecard/config.yaml b/testdata/go/v3/memcached-operator/bundle/tests/scorecard/config.yaml new file mode 100644 index 00000000000..e39a5d88b57 --- /dev/null +++ b/testdata/go/v3/memcached-operator/bundle/tests/scorecard/config.yaml @@ -0,0 +1,49 @@ +apiVersion: scorecard.operatorframework.io/v1alpha3 +kind: Configuration +metadata: + name: config +stages: +- parallel: true + tests: + - entrypoint: + - scorecard-test + - basic-check-spec + image: quay.io/operator-framework/scorecard-test:v1.2.0 + labels: + suite: basic + test: basic-check-spec-test + - entrypoint: + - scorecard-test + - olm-bundle-validation + image: quay.io/operator-framework/scorecard-test:v1.2.0 + labels: + suite: olm + test: olm-bundle-validation-test + - entrypoint: + - scorecard-test + - olm-crds-have-validation + image: quay.io/operator-framework/scorecard-test:v1.2.0 + labels: + suite: olm + test: olm-crds-have-validation-test + - entrypoint: + - scorecard-test + - olm-crds-have-resources + image: quay.io/operator-framework/scorecard-test:v1.2.0 + labels: + suite: olm + test: olm-crds-have-resources-test + - entrypoint: + - scorecard-test + - olm-spec-descriptors + image: quay.io/operator-framework/scorecard-test:v1.2.0 + labels: + suite: olm + test: olm-spec-descriptors-test + - entrypoint: + - scorecard-test + - olm-status-descriptors + image: quay.io/operator-framework/scorecard-test:v1.2.0 + labels: + suite: olm + test: olm-status-descriptors-test diff --git a/testdata/go/v3/memcached-operator/config/certmanager/certificate.yaml b/testdata/go/v3/memcached-operator/config/certmanager/certificate.yaml new file mode 100644 index 00000000000..52d866183c7 --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/certmanager/certificate.yaml @@ -0,0 +1,25 @@ +# The following manifests contain a self-signed issuer CR and a certificate CR. +# More document can be found at https://docs.cert-manager.io +# WARNING: Targets CertManager v1.0. Check https://cert-manager.io/docs/installation/upgrading/ for breaking changes. +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: selfsigned-issuer + namespace: system +spec: + selfSigned: {} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: serving-cert # this name should match the one appeared in kustomizeconfig.yaml + namespace: system +spec: + # $(SERVICE_NAME) and $(SERVICE_NAMESPACE) will be substituted by kustomize + dnsNames: + - $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc + - $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc.cluster.local + issuerRef: + kind: Issuer + name: selfsigned-issuer + secretName: webhook-server-cert # this secret will not be prefixed, since it's not managed by kustomize diff --git a/testdata/go/v3/memcached-operator/config/certmanager/kustomization.yaml b/testdata/go/v3/memcached-operator/config/certmanager/kustomization.yaml new file mode 100644 index 00000000000..bebea5a595e --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/certmanager/kustomization.yaml @@ -0,0 +1,5 @@ +resources: +- certificate.yaml + +configurations: +- kustomizeconfig.yaml diff --git a/testdata/go/v3/memcached-operator/config/certmanager/kustomizeconfig.yaml b/testdata/go/v3/memcached-operator/config/certmanager/kustomizeconfig.yaml new file mode 100644 index 00000000000..90d7c313ca1 --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/certmanager/kustomizeconfig.yaml @@ -0,0 +1,16 @@ +# This configuration is for teaching kustomize how to update name ref and var substitution +nameReference: +- kind: Issuer + group: cert-manager.io + fieldSpecs: + - kind: Certificate + group: cert-manager.io + path: spec/issuerRef/name + +varReference: +- kind: Certificate + group: cert-manager.io + path: spec/commonName +- kind: Certificate + group: cert-manager.io + path: spec/dnsNames diff --git a/testdata/go/v3/memcached-operator/config/crd/bases/cache.example.com_memcacheds.yaml b/testdata/go/v3/memcached-operator/config/crd/bases/cache.example.com_memcacheds.yaml new file mode 100644 index 00000000000..af219aaff23 --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/crd/bases/cache.example.com_memcacheds.yaml @@ -0,0 +1,68 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.4.1 + creationTimestamp: null + name: memcacheds.cache.example.com +spec: + group: cache.example.com + names: + kind: Memcached + listKind: MemcachedList + plural: memcacheds + singular: memcached + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: Memcached is the Schema for the memcacheds API + 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: MemcachedSpec defines the desired state of Memcached + properties: + foo: + description: Foo is an example field of Memcached. Edit Memcached_types.go + to remove/update + type: string + size: + description: Size defines the number of Memcached instances + format: int32 + type: integer + type: object + status: + description: MemcachedStatus defines the observed state of Memcached + properties: + nodes: + description: Nodes store the name of the pods which are running Memcached + instances + items: + type: string + type: array + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/testdata/go/v3/memcached-operator/config/crd/kustomization.yaml b/testdata/go/v3/memcached-operator/config/crd/kustomization.yaml new file mode 100644 index 00000000000..4acd9f4b810 --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/crd/kustomization.yaml @@ -0,0 +1,21 @@ +# 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/cache.example.com_memcacheds.yaml +# +kubebuilder:scaffold:crdkustomizeresource + +patchesStrategicMerge: +# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix. +# patches here are for enabling the conversion webhook for each CRD +#- patches/webhook_in_memcacheds.yaml +# +kubebuilder:scaffold:crdkustomizewebhookpatch + +# [CERTMANAGER] To enable webhook, uncomment all the sections with [CERTMANAGER] prefix. +# patches here are for enabling the CA injection for each CRD +#- patches/cainjection_in_memcacheds.yaml +# +kubebuilder:scaffold:crdkustomizecainjectionpatch + +# the following config is for teaching kustomize how to do kustomization for CRDs. +configurations: +- kustomizeconfig.yaml diff --git a/testdata/go/v3/memcached-operator/config/crd/kustomizeconfig.yaml b/testdata/go/v3/memcached-operator/config/crd/kustomizeconfig.yaml new file mode 100644 index 00000000000..ec5c150a9df --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/crd/kustomizeconfig.yaml @@ -0,0 +1,19 @@ +# This file is for teaching kustomize how to substitute name and namespace reference in CRD +nameReference: +- kind: Service + version: v1 + fieldSpecs: + - kind: CustomResourceDefinition + version: v1 + group: apiextensions.k8s.io + path: spec/conversion/webhook/clientConfig/service/name + +namespace: +- kind: CustomResourceDefinition + version: v1 + group: apiextensions.k8s.io + path: spec/conversion/webhook/clientConfig/service/namespace + create: false + +varReference: +- path: metadata/annotations diff --git a/testdata/go/v3/memcached-operator/config/crd/patches/cainjection_in_memcacheds.yaml b/testdata/go/v3/memcached-operator/config/crd/patches/cainjection_in_memcacheds.yaml new file mode 100644 index 00000000000..809a2aad8b7 --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/crd/patches/cainjection_in_memcacheds.yaml @@ -0,0 +1,7 @@ +# The following patch adds a directive for certmanager to inject CA into the CRD +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) + name: memcacheds.cache.example.com diff --git a/testdata/go/v3/memcached-operator/config/crd/patches/webhook_in_memcacheds.yaml b/testdata/go/v3/memcached-operator/config/crd/patches/webhook_in_memcacheds.yaml new file mode 100644 index 00000000000..844a0c493f8 --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/crd/patches/webhook_in_memcacheds.yaml @@ -0,0 +1,14 @@ +# The following patch enables a conversion webhook for the CRD +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: memcacheds.cache.example.com +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + service: + namespace: system + name: webhook-service + path: /convert diff --git a/testdata/go/v3/memcached-operator/config/default/kustomization.yaml b/testdata/go/v3/memcached-operator/config/default/kustomization.yaml new file mode 100644 index 00000000000..a92983c82e9 --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/default/kustomization.yaml @@ -0,0 +1,80 @@ +# Adds namespace to all resources. +namespace: memcached-operator-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: memcached-operator- + +# Labels to add to all resources and selectors. +#commonLabels: +# someName: someValue + +bases: +- ../crd +- ../rbac +- ../manager +# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in +# crd/kustomization.yaml +- ../webhook + +# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required. +- ../certmanager + +# [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'. +- ../prometheus + + +patchesStrategicMerge: +# Protect the /metrics endpoint by putting it behind auth. +# If you want your controller-manager to expose the /metrics +# endpoint w/o any authn/z, please comment the following line. +- manager_auth_proxy_patch.yaml + +# Mount the controller config file for loading manager configurations +# through a ComponentConfig type +#- manager_config_patch.yaml + +# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in +# crd/kustomization.yaml +- manager_webhook_patch.yaml + + +# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. +# Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks. +# 'CERTMANAGER' needs to be enabled to use ca injection +- webhookcainjection_patch.yaml + + +# the following config is for teaching kustomize how to do var substitution +vars: +# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix. +- name: CERTIFICATE_NAMESPACE # namespace of the certificate CR + objref: + kind: Certificate + group: cert-manager.io + version: v1 + name: serving-cert # this name should match the one in certificate.yaml + fieldref: + fieldpath: metadata.namespace +- name: CERTIFICATE_NAME + objref: + kind: Certificate + group: cert-manager.io + version: v1 + name: serving-cert # this name should match the one in certificate.yaml +- name: SERVICE_NAMESPACE # namespace of the service + objref: + kind: Service + version: v1 + name: webhook-service + fieldref: + fieldpath: metadata.namespace +- name: SERVICE_NAME + objref: + kind: Service + version: v1 + name: webhook-service + diff --git a/testdata/go/v3/memcached-operator/config/default/manager_auth_proxy_patch.yaml b/testdata/go/v3/memcached-operator/config/default/manager_auth_proxy_patch.yaml new file mode 100644 index 00000000000..49b1f1ab36e --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/default/manager_auth_proxy_patch.yaml @@ -0,0 +1,26 @@ +# This patch inject a sidecar container which is a HTTP proxy for the +# controller manager, it performs RBAC authorization against the Kubernetes API using SubjectAccessReviews. +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system +spec: + template: + spec: + containers: + - name: kube-rbac-proxy + image: gcr.io/kubebuilder/kube-rbac-proxy:v0.5.0 + args: + - "--secure-listen-address=0.0.0.0:8443" + - "--upstream=http://127.0.0.1:8080/" + - "--logtostderr=true" + - "--v=10" + ports: + - containerPort: 8443 + name: https + - name: manager + args: + - "--health-probe-bind-address=:8081" + - "--metrics-bind-address=127.0.0.1:8080" + - "--leader-elect" diff --git a/testdata/go/v3/memcached-operator/config/default/manager_config_patch.yaml b/testdata/go/v3/memcached-operator/config/default/manager_config_patch.yaml new file mode 100644 index 00000000000..6c400155cfb --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/default/manager_config_patch.yaml @@ -0,0 +1,20 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system +spec: + template: + spec: + containers: + - name: manager + args: + - "--config=controller_manager_config.yaml" + volumeMounts: + - name: manager-config + mountPath: /controller_manager_config.yaml + subPath: controller_manager_config.yaml + volumes: + - name: manager-config + configMap: + name: manager-config diff --git a/testdata/go/v3/memcached-operator/config/default/manager_webhook_patch.yaml b/testdata/go/v3/memcached-operator/config/default/manager_webhook_patch.yaml new file mode 100644 index 00000000000..738de350b71 --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/default/manager_webhook_patch.yaml @@ -0,0 +1,23 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system +spec: + template: + spec: + containers: + - name: manager + ports: + - containerPort: 9443 + name: webhook-server + protocol: TCP + volumeMounts: + - mountPath: /tmp/k8s-webhook-server/serving-certs + name: cert + readOnly: true + volumes: + - name: cert + secret: + defaultMode: 420 + secretName: webhook-server-cert diff --git a/testdata/go/v3/memcached-operator/config/default/webhookcainjection_patch.yaml b/testdata/go/v3/memcached-operator/config/default/webhookcainjection_patch.yaml new file mode 100644 index 00000000000..02ab515d428 --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/default/webhookcainjection_patch.yaml @@ -0,0 +1,15 @@ +# This patch add annotation to admission webhook config and +# the variables $(CERTIFICATE_NAMESPACE) and $(CERTIFICATE_NAME) will be substituted by kustomize. +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + name: mutating-webhook-configuration + annotations: + cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: validating-webhook-configuration + annotations: + cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) diff --git a/testdata/go/v3/memcached-operator/config/manager/controller_manager_config.yaml b/testdata/go/v3/memcached-operator/config/manager/controller_manager_config.yaml new file mode 100644 index 00000000000..9cb0ff302e4 --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/manager/controller_manager_config.yaml @@ -0,0 +1,11 @@ +apiVersion: controller-runtime.sigs.k8s.io/v1alpha1 +kind: ControllerManagerConfig +health: + healthProbeBindAddress: :8081 +metrics: + bindAddress: 127.0.0.1:8080 +webhook: + port: 9443 +leaderElection: + leaderElect: true + resourceName: 86f835c3.example.com diff --git a/testdata/go/v3/memcached-operator/config/manager/kustomization.yaml b/testdata/go/v3/memcached-operator/config/manager/kustomization.yaml new file mode 100644 index 00000000000..9d957eced1c --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/manager/kustomization.yaml @@ -0,0 +1,16 @@ +resources: +- manager.yaml + +generatorOptions: + disableNameSuffixHash: true + +configMapGenerator: +- files: + - controller_manager_config.yaml + name: manager-config +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +images: +- name: controller + newName: quay.io/example/memcached-operator + newTag: v0.0.1 diff --git a/testdata/go/v3/memcached-operator/config/manager/manager.yaml b/testdata/go/v3/memcached-operator/config/manager/manager.yaml new file mode 100644 index 00000000000..11cf9f6af38 --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/manager/manager.yaml @@ -0,0 +1,55 @@ +apiVersion: v1 +kind: Namespace +metadata: + labels: + control-plane: controller-manager + name: system +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system + labels: + control-plane: controller-manager +spec: + selector: + matchLabels: + control-plane: controller-manager + replicas: 1 + template: + metadata: + labels: + control-plane: controller-manager + spec: + securityContext: + runAsUser: 65532 + containers: + - command: + - /manager + args: + - --leader-elect + image: controller:latest + name: manager + securityContext: + allowPrivilegeEscalation: false + livenessProbe: + httpGet: + path: /readyz + port: 8081 + initialDelaySeconds: 15 + periodSeconds: 20 + readinessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 5 + periodSeconds: 10 + resources: + limits: + cpu: 100m + memory: 30Mi + requests: + cpu: 100m + memory: 20Mi + terminationGracePeriodSeconds: 10 diff --git a/testdata/go/v3/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml b/testdata/go/v3/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml new file mode 100644 index 00000000000..bcfeaa4015d --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml @@ -0,0 +1,48 @@ +apiVersion: operators.coreos.com/v1alpha1 +kind: ClusterServiceVersion +metadata: + annotations: + alm-examples: '[]' + capabilities: Basic Install + name: memcached-operator.v0.0.0 + namespace: placeholder +spec: + apiservicedefinitions: {} + customresourcedefinitions: + owned: + - description: Memcached is the Schema for the memcacheds API + displayName: Memcached + kind: Memcached + name: memcacheds.cache.example.com + version: v1alpha1 + description: Memcached Operator description. TODO. + displayName: Memcached Operator + icon: + - base64data: "" + mediatype: "" + install: + spec: + deployments: null + strategy: "" + installModes: + - supported: false + type: OwnNamespace + - supported: false + type: SingleNamespace + - supported: false + type: MultiNamespace + - supported: true + type: AllNamespaces + keywords: + - memcached-operator + links: + - name: Memcached Operator + url: https://memcached-operator.domain + maintainers: + - email: your@email.com + name: Maintainer Name + maturity: alpha + provider: + name: Provider Name + url: https://your.domain + version: 0.0.0 diff --git a/testdata/go/v3/memcached-operator/config/manifests/kustomization.yaml b/testdata/go/v3/memcached-operator/config/manifests/kustomization.yaml new file mode 100644 index 00000000000..63ca74d72a3 --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/manifests/kustomization.yaml @@ -0,0 +1,4 @@ +resources: +- ../default +- ../samples +- ../scorecard diff --git a/testdata/go/v3/memcached-operator/config/prometheus/kustomization.yaml b/testdata/go/v3/memcached-operator/config/prometheus/kustomization.yaml new file mode 100644 index 00000000000..ed137168a1d --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/prometheus/kustomization.yaml @@ -0,0 +1,2 @@ +resources: +- monitor.yaml diff --git a/testdata/go/v3/memcached-operator/config/prometheus/monitor.yaml b/testdata/go/v3/memcached-operator/config/prometheus/monitor.yaml new file mode 100644 index 00000000000..9b8047b760f --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/prometheus/monitor.yaml @@ -0,0 +1,16 @@ + +# Prometheus Monitor Service (Metrics) +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + labels: + control-plane: controller-manager + name: controller-manager-metrics-monitor + namespace: system +spec: + endpoints: + - path: /metrics + port: https + selector: + matchLabels: + control-plane: controller-manager diff --git a/testdata/go/v3/memcached-operator/config/rbac/auth_proxy_client_clusterrole.yaml b/testdata/go/v3/memcached-operator/config/rbac/auth_proxy_client_clusterrole.yaml new file mode 100644 index 00000000000..bd4af137a9f --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/rbac/auth_proxy_client_clusterrole.yaml @@ -0,0 +1,7 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: metrics-reader +rules: +- nonResourceURLs: ["/metrics"] + verbs: ["get"] diff --git a/testdata/go/v3/memcached-operator/config/rbac/auth_proxy_role.yaml b/testdata/go/v3/memcached-operator/config/rbac/auth_proxy_role.yaml new file mode 100644 index 00000000000..618f5e4177c --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/rbac/auth_proxy_role.yaml @@ -0,0 +1,13 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: proxy-role +rules: +- apiGroups: ["authentication.k8s.io"] + resources: + - tokenreviews + verbs: ["create"] +- apiGroups: ["authorization.k8s.io"] + resources: + - subjectaccessreviews + verbs: ["create"] diff --git a/testdata/go/v3/memcached-operator/config/rbac/auth_proxy_role_binding.yaml b/testdata/go/v3/memcached-operator/config/rbac/auth_proxy_role_binding.yaml new file mode 100644 index 00000000000..48ed1e4b85c --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/rbac/auth_proxy_role_binding.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: proxy-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: proxy-role +subjects: +- kind: ServiceAccount + name: default + namespace: system diff --git a/testdata/go/v3/memcached-operator/config/rbac/auth_proxy_service.yaml b/testdata/go/v3/memcached-operator/config/rbac/auth_proxy_service.yaml new file mode 100644 index 00000000000..6cf656be149 --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/rbac/auth_proxy_service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + control-plane: controller-manager + name: controller-manager-metrics-service + namespace: system +spec: + ports: + - name: https + port: 8443 + targetPort: https + selector: + control-plane: controller-manager diff --git a/testdata/go/v3/memcached-operator/config/rbac/kustomization.yaml b/testdata/go/v3/memcached-operator/config/rbac/kustomization.yaml new file mode 100644 index 00000000000..66c28338fe0 --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/rbac/kustomization.yaml @@ -0,0 +1,12 @@ +resources: +- role.yaml +- role_binding.yaml +- leader_election_role.yaml +- leader_election_role_binding.yaml +# Comment the following 4 lines if you want to disable +# the auth proxy (https://github.com/brancz/kube-rbac-proxy) +# which protects your /metrics endpoint. +- auth_proxy_service.yaml +- auth_proxy_role.yaml +- auth_proxy_role_binding.yaml +- auth_proxy_client_clusterrole.yaml diff --git a/testdata/go/v3/memcached-operator/config/rbac/leader_election_role.yaml b/testdata/go/v3/memcached-operator/config/rbac/leader_election_role.yaml new file mode 100644 index 00000000000..6334cc51c83 --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/rbac/leader_election_role.yaml @@ -0,0 +1,27 @@ +# permissions to do leader election. +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: leader-election-role +rules: +- apiGroups: + - "" + - coordination.k8s.io + resources: + - configmaps + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch diff --git a/testdata/go/v3/memcached-operator/config/rbac/leader_election_role_binding.yaml b/testdata/go/v3/memcached-operator/config/rbac/leader_election_role_binding.yaml new file mode 100644 index 00000000000..eed16906f4d --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/rbac/leader_election_role_binding.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: leader-election-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: leader-election-role +subjects: +- kind: ServiceAccount + name: default + namespace: system diff --git a/testdata/go/v3/memcached-operator/config/rbac/memcached_editor_role.yaml b/testdata/go/v3/memcached-operator/config/rbac/memcached_editor_role.yaml new file mode 100644 index 00000000000..459afe748d5 --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/rbac/memcached_editor_role.yaml @@ -0,0 +1,24 @@ +# permissions for end users to edit memcacheds. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: memcached-editor-role +rules: +- apiGroups: + - cache.example.com + resources: + - memcacheds + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - cache.example.com + resources: + - memcacheds/status + verbs: + - get diff --git a/testdata/go/v3/memcached-operator/config/rbac/memcached_viewer_role.yaml b/testdata/go/v3/memcached-operator/config/rbac/memcached_viewer_role.yaml new file mode 100644 index 00000000000..861669c343f --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/rbac/memcached_viewer_role.yaml @@ -0,0 +1,20 @@ +# permissions for end users to view memcacheds. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: memcached-viewer-role +rules: +- apiGroups: + - cache.example.com + resources: + - memcacheds + verbs: + - get + - list + - watch +- apiGroups: + - cache.example.com + resources: + - memcacheds/status + verbs: + - get diff --git a/testdata/go/v3/memcached-operator/config/rbac/role.yaml b/testdata/go/v3/memcached-operator/config/rbac/role.yaml new file mode 100644 index 00000000000..e32a4510071 --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/rbac/role.yaml @@ -0,0 +1,53 @@ + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + creationTimestamp: null + name: manager-role +rules: +- apiGroups: + - apps + resources: + - deployments + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - cache.example.com + resources: + - memcacheds + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - cache.example.com + resources: + - memcacheds/finalizers + verbs: + - update +- apiGroups: + - cache.example.com + resources: + - memcacheds/status + verbs: + - get + - patch + - update +- apiGroups: + - "" + resources: + - pods + verbs: + - get + - list diff --git a/testdata/go/v3/memcached-operator/config/rbac/role_binding.yaml b/testdata/go/v3/memcached-operator/config/rbac/role_binding.yaml new file mode 100644 index 00000000000..8f2658702c8 --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/rbac/role_binding.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: manager-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: manager-role +subjects: +- kind: ServiceAccount + name: default + namespace: system diff --git a/testdata/go/v3/memcached-operator/config/samples/cache_v1alpha1_memcached.yaml b/testdata/go/v3/memcached-operator/config/samples/cache_v1alpha1_memcached.yaml new file mode 100644 index 00000000000..3ea15eed5cd --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/samples/cache_v1alpha1_memcached.yaml @@ -0,0 +1,7 @@ +apiVersion: cache.example.com/v1alpha1 +kind: Memcached +metadata: + name: memcached-sample +spec: + # Add fields here + foo: bar diff --git a/testdata/go/v3/memcached-operator/config/samples/kustomization.yaml b/testdata/go/v3/memcached-operator/config/samples/kustomization.yaml new file mode 100644 index 00000000000..62e56248418 --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/samples/kustomization.yaml @@ -0,0 +1,4 @@ +## Append samples you want in your CSV to this file as resources ## +resources: +- cache_v1alpha1_memcached.yaml +# +kubebuilder:scaffold:manifestskustomizesamples diff --git a/testdata/go/v3/memcached-operator/config/scorecard/bases/config.yaml b/testdata/go/v3/memcached-operator/config/scorecard/bases/config.yaml new file mode 100644 index 00000000000..c77047841ed --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/scorecard/bases/config.yaml @@ -0,0 +1,7 @@ +apiVersion: scorecard.operatorframework.io/v1alpha3 +kind: Configuration +metadata: + name: config +stages: +- parallel: true + tests: [] diff --git a/testdata/go/v3/memcached-operator/config/scorecard/kustomization.yaml b/testdata/go/v3/memcached-operator/config/scorecard/kustomization.yaml new file mode 100644 index 00000000000..d73509ee73f --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/scorecard/kustomization.yaml @@ -0,0 +1,16 @@ +resources: +- bases/config.yaml +patchesJson6902: +- path: patches/basic.config.yaml + target: + group: scorecard.operatorframework.io + version: v1alpha3 + kind: Configuration + name: config +- path: patches/olm.config.yaml + target: + group: scorecard.operatorframework.io + version: v1alpha3 + kind: Configuration + name: config +# +kubebuilder:scaffold:patchesJson6902 diff --git a/testdata/go/v3/memcached-operator/config/scorecard/patches/basic.config.yaml b/testdata/go/v3/memcached-operator/config/scorecard/patches/basic.config.yaml new file mode 100644 index 00000000000..f80c746f9e7 --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/scorecard/patches/basic.config.yaml @@ -0,0 +1,10 @@ +- op: add + path: /stages/0/tests/- + value: + entrypoint: + - scorecard-test + - basic-check-spec + image: quay.io/operator-framework/scorecard-test:v1.2.0 + labels: + suite: basic + test: basic-check-spec-test diff --git a/testdata/go/v3/memcached-operator/config/scorecard/patches/olm.config.yaml b/testdata/go/v3/memcached-operator/config/scorecard/patches/olm.config.yaml new file mode 100644 index 00000000000..ef6834b1e3d --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/scorecard/patches/olm.config.yaml @@ -0,0 +1,50 @@ +- op: add + path: /stages/0/tests/- + value: + entrypoint: + - scorecard-test + - olm-bundle-validation + image: quay.io/operator-framework/scorecard-test:v1.2.0 + labels: + suite: olm + test: olm-bundle-validation-test +- op: add + path: /stages/0/tests/- + value: + entrypoint: + - scorecard-test + - olm-crds-have-validation + image: quay.io/operator-framework/scorecard-test:v1.2.0 + labels: + suite: olm + test: olm-crds-have-validation-test +- op: add + path: /stages/0/tests/- + value: + entrypoint: + - scorecard-test + - olm-crds-have-resources + image: quay.io/operator-framework/scorecard-test:v1.2.0 + labels: + suite: olm + test: olm-crds-have-resources-test +- op: add + path: /stages/0/tests/- + value: + entrypoint: + - scorecard-test + - olm-spec-descriptors + image: quay.io/operator-framework/scorecard-test:v1.2.0 + labels: + suite: olm + test: olm-spec-descriptors-test +- op: add + path: /stages/0/tests/- + value: + entrypoint: + - scorecard-test + - olm-status-descriptors + image: quay.io/operator-framework/scorecard-test:v1.2.0 + labels: + suite: olm + test: olm-status-descriptors-test diff --git a/testdata/go/v3/memcached-operator/config/webhook/kustomization.yaml b/testdata/go/v3/memcached-operator/config/webhook/kustomization.yaml new file mode 100644 index 00000000000..9cf26134e4d --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/webhook/kustomization.yaml @@ -0,0 +1,6 @@ +resources: +- manifests.yaml +- service.yaml + +configurations: +- kustomizeconfig.yaml diff --git a/testdata/go/v3/memcached-operator/config/webhook/kustomizeconfig.yaml b/testdata/go/v3/memcached-operator/config/webhook/kustomizeconfig.yaml new file mode 100644 index 00000000000..25e21e3c963 --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/webhook/kustomizeconfig.yaml @@ -0,0 +1,25 @@ +# the following config is for teaching kustomize where to look at when substituting vars. +# It requires kustomize v2.1.0 or newer to work properly. +nameReference: +- kind: Service + version: v1 + fieldSpecs: + - kind: MutatingWebhookConfiguration + group: admissionregistration.k8s.io + path: webhooks/clientConfig/service/name + - kind: ValidatingWebhookConfiguration + group: admissionregistration.k8s.io + path: webhooks/clientConfig/service/name + +namespace: +- kind: MutatingWebhookConfiguration + group: admissionregistration.k8s.io + path: webhooks/clientConfig/service/namespace + create: true +- kind: ValidatingWebhookConfiguration + group: admissionregistration.k8s.io + path: webhooks/clientConfig/service/namespace + create: true + +varReference: +- path: metadata/annotations diff --git a/testdata/go/v3/memcached-operator/config/webhook/manifests.yaml b/testdata/go/v3/memcached-operator/config/webhook/manifests.yaml new file mode 100644 index 00000000000..0ac58a1bd25 --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/webhook/manifests.yaml @@ -0,0 +1,56 @@ + +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + creationTimestamp: null + name: mutating-webhook-configuration +webhooks: +- admissionReviewVersions: + - v1beta1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /mutate-cache-example-com-v1alpha1-memcached + failurePolicy: Fail + name: mmemcached.kb.io + rules: + - apiGroups: + - cache.example.com + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - memcacheds + sideEffects: None + +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + creationTimestamp: null + name: validating-webhook-configuration +webhooks: +- admissionReviewVersions: + - v1beta1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /validate-cache-example-com-v1alpha1-memcached + failurePolicy: Fail + name: vmemcached.kb.io + rules: + - apiGroups: + - cache.example.com + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - memcacheds + sideEffects: None diff --git a/testdata/go/v3/memcached-operator/config/webhook/service.yaml b/testdata/go/v3/memcached-operator/config/webhook/service.yaml new file mode 100644 index 00000000000..31e0f829591 --- /dev/null +++ b/testdata/go/v3/memcached-operator/config/webhook/service.yaml @@ -0,0 +1,12 @@ + +apiVersion: v1 +kind: Service +metadata: + name: webhook-service + namespace: system +spec: + ports: + - port: 443 + targetPort: 9443 + selector: + control-plane: controller-manager diff --git a/testdata/go/v3/memcached-operator/controllers/memcached_controller.go b/testdata/go/v3/memcached-operator/controllers/memcached_controller.go new file mode 100644 index 00000000000..4ed03157281 --- /dev/null +++ b/testdata/go/v3/memcached-operator/controllers/memcached_controller.go @@ -0,0 +1,195 @@ +/* +Copyright 2020. + +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 controllers + +import ( + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "reflect" + + "context" + + "github.com/go-logr/logr" + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + + cachev1alpha1 "github.com/example/memcached-operator/api/v1alpha1" +) + +// MemcachedReconciler reconciles a Memcached object +type MemcachedReconciler struct { + client.Client + Log logr.Logger + Scheme *runtime.Scheme +} + +// +kubebuilder:rbac:groups=cache.example.com,resources=memcacheds,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=cache.example.com,resources=memcacheds/status,verbs=get;update;patch +// +kubebuilder:rbac:groups=cache.example.com,resources=memcacheds/finalizers,verbs=update +// +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=core,resources=pods,verbs=get;list; + +// Reconcile is part of the main kubernetes reconciliation loop which aims to +// move the current state of the cluster closer to the desired state. +// TODO(user): Modify the Reconcile function to compare the state specified by +// the Memcached object against the actual cluster state, and then +// perform operations to make the cluster state reflect the state specified by +// the user. +// +// For more details, check Reconcile and its Result here: +// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.7.0-alpha.8/pkg/reconcile +func (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + log := r.Log.WithValues("memcached", req.NamespacedName) + + // Fetch the Memcached instance + memcached := &cachev1alpha1.Memcached{} + err := r.Get(ctx, req.NamespacedName, memcached) + if err != nil { + if errors.IsNotFound(err) { + // Request object not found, could have been deleted after reconcile request. + // Owned objects are automatically garbage collected. For additional cleanup logic use finalizers. + // Return and don't requeue + log.Info("Memcached resource not found. Ignoring since object must be deleted") + return ctrl.Result{}, nil + } + // Error reading the object - requeue the request. + log.Error(err, "Failed to get Memcached") + return ctrl.Result{}, err + } + + // Check if the deployment already exists, if not create a new one + found := &appsv1.Deployment{} + err = r.Get(ctx, types.NamespacedName{Name: memcached.Name, Namespace: memcached.Namespace}, found) + if err != nil && errors.IsNotFound(err) { + // Define a new deployment + dep := r.deploymentForMemcached(memcached) + log.Info("Creating a new Deployment", "Deployment.Namespace", dep.Namespace, "Deployment.Name", dep.Name) + err = r.Create(ctx, dep) + if err != nil { + log.Error(err, "Failed to create new Deployment", "Deployment.Namespace", dep.Namespace, "Deployment.Name", dep.Name) + return ctrl.Result{}, err + } + // Deployment created successfully - return and requeue + return ctrl.Result{Requeue: true}, nil + } else if err != nil { + log.Error(err, "Failed to get Deployment") + return ctrl.Result{}, err + } + + // Ensure the deployment size is the same as the spec + size := memcached.Spec.Size + if *found.Spec.Replicas != size { + found.Spec.Replicas = &size + err = r.Update(ctx, found) + if err != nil { + log.Error(err, "Failed to update Deployment", "Deployment.Namespace", found.Namespace, "Deployment.Name", found.Name) + return ctrl.Result{}, err + } + // Spec updated - return and requeue + return ctrl.Result{Requeue: true}, nil + } + + // Update the Memcached status with the pod names + // List the pods for this memcached's deployment + podList := &corev1.PodList{} + listOpts := []client.ListOption{ + client.InNamespace(memcached.Namespace), + client.MatchingLabels(labelsForMemcached(memcached.Name)), + } + if err = r.List(ctx, podList, listOpts...); err != nil { + log.Error(err, "Failed to list pods", "Memcached.Namespace", memcached.Namespace, "Memcached.Name", memcached.Name) + return ctrl.Result{}, err + } + podNames := getPodNames(podList.Items) + + // Update status.Nodes if needed + if !reflect.DeepEqual(podNames, memcached.Status.Nodes) { + memcached.Status.Nodes = podNames + err := r.Status().Update(ctx, memcached) + if err != nil { + log.Error(err, "Failed to update Memcached status") + return ctrl.Result{}, err + } + } + + return ctrl.Result{}, nil +} + +// deploymentForMemcached returns a memcached Deployment object +func (r *MemcachedReconciler) deploymentForMemcached(m *cachev1alpha1.Memcached) *appsv1.Deployment { + ls := labelsForMemcached(m.Name) + replicas := m.Spec.Size + + dep := &appsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: m.Name, + Namespace: m.Namespace, + }, + Spec: appsv1.DeploymentSpec{ + Replicas: &replicas, + Selector: &metav1.LabelSelector{ + MatchLabels: ls, + }, + Template: corev1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: ls, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{{ + Image: "memcached:1.4.36-alpine", + Name: "memcached", + Command: []string{"memcached", "-m=64", "-o", "modern", "-v"}, + Ports: []corev1.ContainerPort{{ + ContainerPort: 11211, + Name: "memcached", + }}, + }}, + }, + }, + }, + } + // Set Memcached instance as the owner and controller + ctrl.SetControllerReference(m, dep, r.Scheme) + return dep +} + +// labelsForMemcached returns the labels for selecting the resources +// belonging to the given memcached CR name. +func labelsForMemcached(name string) map[string]string { + return map[string]string{"app": "memcached", "memcached_cr": name} +} + +// getPodNames returns the pod names of the array of pods passed in +func getPodNames(pods []corev1.Pod) []string { + var podNames []string + for _, pod := range pods { + podNames = append(podNames, pod.Name) + } + return podNames +} + +// SetupWithManager sets up the controller with the Manager. +func (r *MemcachedReconciler) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr). + For(&cachev1alpha1.Memcached{}). + Owns(&appsv1.Deployment{}). + Complete(r) +} diff --git a/testdata/go/v3/memcached-operator/controllers/suite_test.go b/testdata/go/v3/memcached-operator/controllers/suite_test.go new file mode 100644 index 00000000000..03618e8b33f --- /dev/null +++ b/testdata/go/v3/memcached-operator/controllers/suite_test.go @@ -0,0 +1,79 @@ +/* +Copyright 2020. + +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 controllers + +import ( + "path/filepath" + "testing" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/envtest" + "sigs.k8s.io/controller-runtime/pkg/envtest/printer" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/log/zap" + + cachev1alpha1 "github.com/example/memcached-operator/api/v1alpha1" + // +kubebuilder:scaffold:imports +) + +// These tests use Ginkgo (BDD-style Go testing framework). Refer to +// http://onsi.github.io/ginkgo/ to learn more about Ginkgo. + +var cfg *rest.Config +var k8sClient client.Client +var testEnv *envtest.Environment + +func TestAPIs(t *testing.T) { + RegisterFailHandler(Fail) + + RunSpecsWithDefaultAndCustomReporters(t, + "Controller Suite", + []Reporter{printer.NewlineReporter{}}) +} + +var _ = BeforeSuite(func() { + logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) + + By("bootstrapping test environment") + testEnv = &envtest.Environment{ + CRDDirectoryPaths: []string{filepath.Join("..", "config", "crd", "bases")}, + } + + cfg, err := testEnv.Start() + Expect(err).NotTo(HaveOccurred()) + Expect(cfg).NotTo(BeNil()) + + err = cachev1alpha1.AddToScheme(scheme.Scheme) + Expect(err).NotTo(HaveOccurred()) + + // +kubebuilder:scaffold:scheme + + k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) + Expect(err).NotTo(HaveOccurred()) + Expect(k8sClient).NotTo(BeNil()) + +}, 60) + +var _ = AfterSuite(func() { + By("tearing down the test environment") + err := testEnv.Stop() + Expect(err).NotTo(HaveOccurred()) +}) diff --git a/testdata/go/v3/memcached-operator/go.mod b/testdata/go/v3/memcached-operator/go.mod new file mode 100644 index 00000000000..8ea59968a61 --- /dev/null +++ b/testdata/go/v3/memcached-operator/go.mod @@ -0,0 +1,13 @@ +module github.com/example/memcached-operator + +go 1.15 + +require ( + github.com/go-logr/logr v0.3.0 + github.com/onsi/ginkgo v1.14.1 + github.com/onsi/gomega v1.10.2 + k8s.io/api v0.19.2 + k8s.io/apimachinery v0.19.2 + k8s.io/client-go v0.19.2 + sigs.k8s.io/controller-runtime v0.7.0-alpha.8 +) diff --git a/testdata/go/v3/memcached-operator/go.sum b/testdata/go/v3/memcached-operator/go.sum new file mode 100644 index 00000000000..843c9201519 --- /dev/null +++ b/testdata/go/v3/memcached-operator/go.sum @@ -0,0 +1,638 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.51.0 h1:PvKAVQWCtlGUSlZkGW3QLelKaWq7KYv/MW1EboG8bfM= +cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= +github.com/Azure/go-autorest/autorest v0.9.6 h1:5YWtOnckcudzIw8lPPBcWOnmIFWMtHci1ZWAZulMSx0= +github.com/Azure/go-autorest/autorest v0.9.6/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630= +github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= +github.com/Azure/go-autorest/autorest/adal v0.8.2 h1:O1X4oexUxnZCaEUGsvMnr8ZGj8HI37tNezwY4npRqA0= +github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= +github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= +github.com/Azure/go-autorest/autorest/date v0.2.0 h1:yW+Zlqf26583pE43KhfnhFcdmSWlm5Ew6bxipnr/tbM= +github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= +github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.3.0 h1:qJumjCaCudz+OcqE9/XtEPfvtOjOmKaui4EOpFI6zZc= +github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= +github.com/Azure/go-autorest/logger v0.1.0 h1:ruG4BSDXONFRrZZJ2GUXDiUyVpayPmb1GnWeHDdaNKY= +github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= +github.com/Azure/go-autorest/tracing v0.5.0 h1:TRn4WjSnkcSy5AEG3pnbtFSwNtwzjr4VYyQflFE619k= +github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= +github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v4.9.0+incompatible h1:kLcOMZeuLAJvL2BPWLMIj5oaZQobrkAqrL+WFZwQses= +github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= +github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= +github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-logr/logr v0.3.0 h1:q4c+kbcR0d5rSurhBR8dIgieOaYpXtsdTYfx22Cu6rs= +github.com/go-logr/logr v0.3.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-logr/zapr v0.2.0 h1:v6Ji8yBW77pva6NkJKQdHLAJKrIJKRHz0RXwPqCHSR4= +github.com/go-logr/zapr v0.2.0/go.mod h1:qhKdvif7YF5GI9NWEpyxTSSBdGmzkNguibrdCNVPunU= +github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= +github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= +github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= +github.com/go-openapi/analysis v0.19.2/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk= +github.com/go-openapi/analysis v0.19.5/go.mod h1:hkEAkxagaIvIP7VTn8ygJNkd4kAYON2rCu0v0ObL0AU= +github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= +github.com/go-openapi/errors v0.18.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= +github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= +github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= +github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= +github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= +github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= +github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= +github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= +github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= +github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= +github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= +github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= +github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= +github.com/go-openapi/loads v0.19.2/go.mod h1:QAskZPMX5V0C2gvfkGZzJlINuP7Hx/4+ix5jWFxsNPs= +github.com/go-openapi/loads v0.19.4/go.mod h1:zZVHonKd8DXyxyw4yfnVjPzBjIQcLt0CCsn0N0ZrQsk= +github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA= +github.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt4sK4FXt0O64= +github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29gLDlFGtJ8NL4= +github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= +github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= +github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= +github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY= +github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= +github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= +github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= +github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY= +github.com/go-openapi/strfmt v0.19.3/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU= +github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= +github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= +github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= +github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= +github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= +github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7 h1:5ZkaAPbicIKTF2I64qf5Fh8Aa83Q/dnOafMYV0OMwjA= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= +github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= +github.com/googleapis/gnostic v0.5.1 h1:A8Yhf6EtqTv9RMsU6MQTyrtV1TjWlR6xU9BsZIwuTCM= +github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.10 h1:6q5mVkdH/vYmqngx7kZQTjJ5HRsx+ImorDIEQ+beJgc= +github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.1 h1:jMU0WaQrP0a/YAEq8eJmJKjBoMs+pClEr1vDMlM/Do4= +github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +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= +github.com/onsi/gomega v1.10.2 h1:aY/nuoWlKJud2J6U0E3NWsjlg+0GtwXxgEqthRdzlcs= +github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.7.1 h1:NTGy1Ja9pByO+xAeH/qiWnLrKtr3hJPNjaVUwnjpdpA= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= +github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= +go.etcd.io/etcd v0.5.0-alpha.5.0.20200819165624-17cef6e3e9d5/go.mod h1:skWido08r9w6Lq/w70DO5XYIKMu4QFu1+4VsqLQuJy8= +go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk= +go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A= +go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.8.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.15.0 h1:ZZCA22JRF2gQE5FoNmhmrf7jeJJ2uhqDUNRYKm8dvmM= +go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f h1:J5lckAjkw6qYlOZNj90mLYNTEKDvWeuc1yieZ8qUzUE= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6 h1:pE8b58s1HRDMi8RDc79m0HISf9D4TzseP40cEA6IGfs= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4 h1:5/PjkGUjvEU5Gl6BxmvKRPpqo2uNMv4rcHBMwzk/st8= +golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s= +golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200616133436-c1934b75d054 h1:HHeAlu5H9b71C+Fx0K+1dGgVFN1DM1/wz4aoGOA5qS8= +golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gomodules.xyz/jsonpatch/v2 v2.1.0 h1:Phva6wqu+xR//Njw6iorylFFgn/z547tw5Ne3HZPQ+k= +gomodules.xyz/jsonpatch/v2 v2.1.0/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEGA= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +k8s.io/api v0.19.2 h1:q+/krnHWKsL7OBZg/rxnycsl9569Pud76UJ77MvKXms= +k8s.io/api v0.19.2/go.mod h1:IQpK0zFQ1xc5iNIQPqzgoOwuFugaYHK4iCknlAQP9nI= +k8s.io/apiextensions-apiserver v0.19.2 h1:oG84UwiDsVDu7dlsGQs5GySmQHCzMhknfhFExJMz9tA= +k8s.io/apiextensions-apiserver v0.19.2/go.mod h1:EYNjpqIAvNZe+svXVx9j4uBaVhTB4C94HkY3w058qcg= +k8s.io/apimachinery v0.19.2 h1:5Gy9vQpAGTKHPVOh5c4plE274X8D/6cuEiTO2zve7tc= +k8s.io/apimachinery v0.19.2/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= +k8s.io/apiserver v0.19.2/go.mod h1:FreAq0bJ2vtZFj9Ago/X0oNGC51GfubKK/ViOKfVAOA= +k8s.io/client-go v0.19.2 h1:gMJuU3xJZs86L1oQ99R4EViAADUPMHHtS9jFshasHSc= +k8s.io/client-go v0.19.2/go.mod h1:S5wPhCqyDNAlzM9CnEdgTGV4OqhsW3jGO1UM1epwfJA= +k8s.io/code-generator v0.19.2/go.mod h1:moqLn7w0t9cMs4+5CQyxnfA/HV8MF6aAVENF+WZZhgk= +k8s.io/component-base v0.19.2 h1:jW5Y9RcZTb79liEhW3XDVTW7MuvEGP0tQZnfSX6/+gs= +k8s.io/component-base v0.19.2/go.mod h1:g5LrsiTiabMLZ40AR6Hl45f088DevyGY+cCE2agEIVo= +k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= +k8s.io/klog/v2 v2.2.0 h1:XRvcwJozkgZ1UQJmfMGpvRthQHOvihEhYtDfAaxMz/A= +k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6 h1:+WnxoVtG8TMiudHBSEtrVL1egv36TkkJm+bA8AxicmQ= +k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= +k8s.io/utils v0.0.0-20200729134348-d5654de09c73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20200912215256-4140de9c8800 h1:9ZNvfPvVIEsp/T1ez4GQuzCcCTEQWhovSofhqR73A6g= +k8s.io/utils v0.0.0-20200912215256-4140de9c8800/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.9/go.mod h1:dzAXnQbTRyDlZPJX2SUPEqvnB+j7AJjtlox7PEwigU0= +sigs.k8s.io/controller-runtime v0.7.0-alpha.8 h1:l8I2KO3xLuNaT0yPP6mtWLw5NuMG3dY2YiaQXEGApXg= +sigs.k8s.io/controller-runtime v0.7.0-alpha.8/go.mod h1:pJ3YBrJiAqMAZKi6UVGuE98ZrroV1p+pIhoHsMm9wdU= +sigs.k8s.io/structured-merge-diff/v4 v4.0.1 h1:YXTMot5Qz/X1iBRJhAt+vI+HVttY0WkSqqhKxQ0xVbA= +sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= +sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/testdata/go/v3/memcached-operator/hack/boilerplate.go.txt b/testdata/go/v3/memcached-operator/hack/boilerplate.go.txt new file mode 100644 index 00000000000..606681a693e --- /dev/null +++ b/testdata/go/v3/memcached-operator/hack/boilerplate.go.txt @@ -0,0 +1,15 @@ +/* +Copyright 2020. + +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. +*/ \ No newline at end of file diff --git a/testdata/go/v3/memcached-operator/main.go b/testdata/go/v3/memcached-operator/main.go new file mode 100644 index 00000000000..bfd085027e7 --- /dev/null +++ b/testdata/go/v3/memcached-operator/main.go @@ -0,0 +1,109 @@ +/* +Copyright 2020. + +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 ( + "flag" + "os" + + // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) + // to ensure that exec-entrypoint and run can make use of them. + _ "k8s.io/client-go/plugin/pkg/client/auth" + + "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + clientgoscheme "k8s.io/client-go/kubernetes/scheme" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/healthz" + "sigs.k8s.io/controller-runtime/pkg/log/zap" + + cachev1alpha1 "github.com/example/memcached-operator/api/v1alpha1" + "github.com/example/memcached-operator/controllers" + // +kubebuilder:scaffold:imports +) + +var ( + scheme = runtime.NewScheme() + setupLog = ctrl.Log.WithName("setup") +) + +func init() { + utilruntime.Must(clientgoscheme.AddToScheme(scheme)) + + utilruntime.Must(cachev1alpha1.AddToScheme(scheme)) + // +kubebuilder:scaffold:scheme +} + +func main() { + var metricsAddr string + var enableLeaderElection bool + var probeAddr string + flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.") + flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.") + flag.BoolVar(&enableLeaderElection, "leader-elect", false, + "Enable leader election for controller manager. "+ + "Enabling this will ensure there is only one active controller manager.") + opts := zap.Options{ + Development: true, + } + opts.BindFlags(flag.CommandLine) + flag.Parse() + + ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts))) + + mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ + Scheme: scheme, + MetricsBindAddress: metricsAddr, + Port: 9443, + HealthProbeBindAddress: probeAddr, + LeaderElection: enableLeaderElection, + LeaderElectionID: "86f835c3.example.com", + }) + if err != nil { + setupLog.Error(err, "unable to start manager") + os.Exit(1) + } + + if err = (&controllers.MemcachedReconciler{ + Client: mgr.GetClient(), + Log: ctrl.Log.WithName("controllers").WithName("Memcached"), + Scheme: mgr.GetScheme(), + }).SetupWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create controller", "controller", "Memcached") + os.Exit(1) + } + if err = (&cachev1alpha1.Memcached{}).SetupWebhookWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create webhook", "webhook", "Memcached") + os.Exit(1) + } + // +kubebuilder:scaffold:builder + + if err := mgr.AddHealthzCheck("health", healthz.Ping); err != nil { + setupLog.Error(err, "unable to set up health check") + os.Exit(1) + } + if err := mgr.AddReadyzCheck("check", healthz.Ping); err != nil { + setupLog.Error(err, "unable to set up ready check") + os.Exit(1) + } + + setupLog.Info("starting manager") + if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil { + setupLog.Error(err, "problem running manager") + os.Exit(1) + } +} diff --git a/website/content/en/docs/cli/operator-sdk.md b/website/content/en/docs/cli/operator-sdk.md index 2a934bb72d3..2a8e1d75b7f 100644 --- a/website/content/en/docs/cli/operator-sdk.md +++ b/website/content/en/docs/cli/operator-sdk.md @@ -76,5 +76,5 @@ operator-sdk [flags] * [operator-sdk olm](../operator-sdk_olm) - Manage the Operator Lifecycle Manager installation in your cluster * [operator-sdk run](../operator-sdk_run) - Run an Operator in a variety of environments * [operator-sdk scorecard](../operator-sdk_scorecard) - Runs scorecard -* [operator-sdk version](../operator-sdk_version) - Prints the version of operator-sdk +* [operator-sdk version](../operator-sdk_version) - Print the operator-sdk version diff --git a/website/content/en/docs/cli/operator-sdk_create_api.md b/website/content/en/docs/cli/operator-sdk_create_api.md index d88451973ac..009e523f71c 100644 --- a/website/content/en/docs/cli/operator-sdk_create_api.md +++ b/website/content/en/docs/cli/operator-sdk_create_api.md @@ -9,9 +9,6 @@ Scaffold a Kubernetes API Scaffold a Kubernetes API. -For project-specific information, run this command in the root directory of a -project. - Note: unable to find configuration file, project must be initialized ``` diff --git a/website/content/en/docs/cli/operator-sdk_create_webhook.md b/website/content/en/docs/cli/operator-sdk_create_webhook.md index 7eebb950236..60983e33d6a 100644 --- a/website/content/en/docs/cli/operator-sdk_create_webhook.md +++ b/website/content/en/docs/cli/operator-sdk_create_webhook.md @@ -9,9 +9,6 @@ Scaffold a webhook for an API resource Scaffold a webhook for an API resource. -For project-specific information, run this command in the root directory of a -project. - Note: unable to find configuration file, project must be initialized ``` diff --git a/website/content/en/docs/cli/operator-sdk_init.md b/website/content/en/docs/cli/operator-sdk_init.md index eeb9acaafa9..b018748f815 100644 --- a/website/content/en/docs/cli/operator-sdk_init.md +++ b/website/content/en/docs/cli/operator-sdk_init.md @@ -42,7 +42,7 @@ operator-sdk init [flags] -h, --help help for init --license string license to use to boilerplate, may be one of 'apache2', 'none' (default "apache2") --owner string owner to add to the copyright - --plugins strings Name and optionally version of the plugin to initialize the project with. Available plugins: ("ansible.sdk.operatorframework.io/v1", "go.kubebuilder.io/v2", "helm.sdk.operatorframework.io/v1") + --plugins strings Name and optionally version of the plugin to initialize the project with. Available plugins: ("ansible.sdk.operatorframework.io/v1", "go.kubebuilder.io/v2", "go.kubebuilder.io/v3-alpha", "helm.sdk.operatorframework.io/v1") --project-name string name of this project --project-version string project version, possible values: ("2", "3-alpha") (default "3-alpha") --repo string name to use for go module (e.g., github.com/user/repo), defaults to the go package of the current working directory. diff --git a/website/content/en/docs/cli/operator-sdk_version.md b/website/content/en/docs/cli/operator-sdk_version.md index 027a3a998f1..1ba4c72080b 100644 --- a/website/content/en/docs/cli/operator-sdk_version.md +++ b/website/content/en/docs/cli/operator-sdk_version.md @@ -3,16 +3,22 @@ title: "operator-sdk version" --- ## operator-sdk version -Prints the version of operator-sdk +Print the operator-sdk version ### Synopsis -Prints the version of operator-sdk +Print the operator-sdk version ``` operator-sdk version [flags] ``` +### Examples + +``` +operator-sdk version +``` + ### Options ``` From 3265788939c77bf6d9987c37216dd53357d82151 Mon Sep 17 00:00:00 2001 From: Camila Macedo Date: Mon, 7 Dec 2020 15:32:54 +0000 Subject: [PATCH 234/376] fix: go samples after v3 addtional (#4286) Signed-off-by: reinvantveer --- .gitignore | 5 ++++- .../samples/internal/go/v2/memcached_with_webhooks.go | 2 +- .../samples/internal/go/v3/memcached_with_webhooks.go | 3 +-- testdata/go/v2/{go => }/memcached-operator/.gitignore | 0 testdata/go/v2/{go => }/memcached-operator/Dockerfile | 0 testdata/go/v2/{go => }/memcached-operator/Makefile | 0 testdata/go/v2/{go => }/memcached-operator/PROJECT | 0 .../memcached-operator/api/v1alpha1/groupversion_info.go | 0 .../memcached-operator/api/v1alpha1/memcached_types.go | 0 .../memcached-operator/api/v1alpha1/memcached_webhook.go | 0 .../memcached-operator/api/v1alpha1/zz_generated.deepcopy.go | 0 testdata/go/v2/{go => }/memcached-operator/bundle.Dockerfile | 0 .../bundle/manifests/cache.example.com_memcacheds.yaml | 0 ...rics-monitor_monitoring.coreos.com_v1_servicemonitor.yaml | 0 ...erator-controller-manager-metrics-service_v1_service.yaml | 0 ...rics-reader_rbac.authorization.k8s.io_v1_clusterrole.yaml | 0 .../memcached-operator-webhook-service_v1_service.yaml | 0 .../manifests/memcached-operator.clusterserviceversion.yaml | 0 .../memcached-operator/bundle/metadata/annotations.yaml | 0 .../memcached-operator/bundle/tests/scorecard/config.yaml | 0 .../memcached-operator/config/certmanager/certificate.yaml | 0 .../memcached-operator/config/certmanager/kustomization.yaml | 0 .../config/certmanager/kustomizeconfig.yaml | 0 .../config/crd/bases/cache.example.com_memcacheds.yaml | 0 .../memcached-operator/config/crd/kustomization.yaml | 0 .../memcached-operator/config/crd/kustomizeconfig.yaml | 0 .../config/crd/patches/cainjection_in_memcacheds.yaml | 0 .../config/crd/patches/webhook_in_memcacheds.yaml | 0 .../memcached-operator/config/default/kustomization.yaml | 0 .../config/default/manager_auth_proxy_patch.yaml | 0 .../config/default/manager_webhook_patch.yaml | 0 .../config/default/webhookcainjection_patch.yaml | 0 .../memcached-operator/config/manager/kustomization.yaml | 0 .../{go => }/memcached-operator/config/manager/manager.yaml | 0 .../bases/memcached-operator.clusterserviceversion.yaml | 0 .../memcached-operator/config/manifests/kustomization.yaml | 0 .../memcached-operator/config/prometheus/kustomization.yaml | 0 .../memcached-operator/config/prometheus/monitor.yaml | 0 .../config/rbac/auth_proxy_client_clusterrole.yaml | 0 .../memcached-operator/config/rbac/auth_proxy_role.yaml | 0 .../config/rbac/auth_proxy_role_binding.yaml | 0 .../memcached-operator/config/rbac/auth_proxy_service.yaml | 0 .../memcached-operator/config/rbac/kustomization.yaml | 0 .../memcached-operator/config/rbac/leader_election_role.yaml | 0 .../config/rbac/leader_election_role_binding.yaml | 0 .../config/rbac/memcached_editor_role.yaml | 0 .../config/rbac/memcached_viewer_role.yaml | 0 .../go/v2/{go => }/memcached-operator/config/rbac/role.yaml | 0 .../memcached-operator/config/rbac/role_binding.yaml | 0 .../config/samples/cache_v1alpha1_memcached.yaml | 0 .../memcached-operator/config/samples/kustomization.yaml | 0 .../memcached-operator/config/scorecard/bases/config.yaml | 0 .../memcached-operator/config/scorecard/kustomization.yaml | 0 .../config/scorecard/patches/basic.config.yaml | 0 .../config/scorecard/patches/olm.config.yaml | 0 .../memcached-operator/config/webhook/kustomization.yaml | 0 .../memcached-operator/config/webhook/kustomizeconfig.yaml | 0 .../memcached-operator/config/webhook/manifests.yaml | 0 .../{go => }/memcached-operator/config/webhook/service.yaml | 0 .../memcached-operator/controllers/memcached_controller.go | 0 .../v2/{go => }/memcached-operator/controllers/suite_test.go | 0 testdata/go/v2/{go => }/memcached-operator/go.mod | 0 testdata/go/v2/{go => }/memcached-operator/go.sum | 0 .../v2/{go => }/memcached-operator/hack/boilerplate.go.txt | 0 testdata/go/v2/{go => }/memcached-operator/main.go | 0 65 files changed, 6 insertions(+), 4 deletions(-) rename testdata/go/v2/{go => }/memcached-operator/.gitignore (100%) rename testdata/go/v2/{go => }/memcached-operator/Dockerfile (100%) rename testdata/go/v2/{go => }/memcached-operator/Makefile (100%) rename testdata/go/v2/{go => }/memcached-operator/PROJECT (100%) rename testdata/go/v2/{go => }/memcached-operator/api/v1alpha1/groupversion_info.go (100%) rename testdata/go/v2/{go => }/memcached-operator/api/v1alpha1/memcached_types.go (100%) rename testdata/go/v2/{go => }/memcached-operator/api/v1alpha1/memcached_webhook.go (100%) rename testdata/go/v2/{go => }/memcached-operator/api/v1alpha1/zz_generated.deepcopy.go (100%) rename testdata/go/v2/{go => }/memcached-operator/bundle.Dockerfile (100%) rename testdata/go/v2/{go => }/memcached-operator/bundle/manifests/cache.example.com_memcacheds.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/bundle/manifests/memcached-operator-controller-manager-metrics-monitor_monitoring.coreos.com_v1_servicemonitor.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/bundle/manifests/memcached-operator-controller-manager-metrics-service_v1_service.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/bundle/manifests/memcached-operator-metrics-reader_rbac.authorization.k8s.io_v1_clusterrole.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/bundle/manifests/memcached-operator-webhook-service_v1_service.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/bundle/metadata/annotations.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/bundle/tests/scorecard/config.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/certmanager/certificate.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/certmanager/kustomization.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/certmanager/kustomizeconfig.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/crd/bases/cache.example.com_memcacheds.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/crd/kustomization.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/crd/kustomizeconfig.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/crd/patches/cainjection_in_memcacheds.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/crd/patches/webhook_in_memcacheds.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/default/kustomization.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/default/manager_auth_proxy_patch.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/default/manager_webhook_patch.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/default/webhookcainjection_patch.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/manager/kustomization.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/manager/manager.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/manifests/kustomization.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/prometheus/kustomization.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/prometheus/monitor.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/rbac/auth_proxy_client_clusterrole.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/rbac/auth_proxy_role.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/rbac/auth_proxy_role_binding.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/rbac/auth_proxy_service.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/rbac/kustomization.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/rbac/leader_election_role.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/rbac/leader_election_role_binding.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/rbac/memcached_editor_role.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/rbac/memcached_viewer_role.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/rbac/role.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/rbac/role_binding.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/samples/cache_v1alpha1_memcached.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/samples/kustomization.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/scorecard/bases/config.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/scorecard/kustomization.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/scorecard/patches/basic.config.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/scorecard/patches/olm.config.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/webhook/kustomization.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/webhook/kustomizeconfig.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/webhook/manifests.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/config/webhook/service.yaml (100%) rename testdata/go/v2/{go => }/memcached-operator/controllers/memcached_controller.go (100%) rename testdata/go/v2/{go => }/memcached-operator/controllers/suite_test.go (100%) rename testdata/go/v2/{go => }/memcached-operator/go.mod (100%) rename testdata/go/v2/{go => }/memcached-operator/go.sum (100%) rename testdata/go/v2/{go => }/memcached-operator/hack/boilerplate.go.txt (100%) rename testdata/go/v2/{go => }/memcached-operator/main.go (100%) diff --git a/.gitignore b/.gitignore index 7e83314920d..8a8884325af 100644 --- a/.gitignore +++ b/.gitignore @@ -17,7 +17,10 @@ website/node_modules/ website/tech-doc-hugo # Ensure that will not commit the bin gen in the go sample -testdata/go/memcached-operator/bin/* +testdata/go/v2/memcached-operator/bin/* +testdata/go/v3/memcached-operator/bin/* +testdata/ansible/memcached-operator/bin/* +testdata/helm/memcached-operator/bin/* # Ignore molecule samples testdata if it be generated in the testdata/ diretory testdata/ansible/memcached-molecule-operator diff --git a/hack/generate/samples/internal/go/v2/memcached_with_webhooks.go b/hack/generate/samples/internal/go/v2/memcached_with_webhooks.go index 1da17736c03..c04f94fce8f 100644 --- a/hack/generate/samples/internal/go/v2/memcached_with_webhooks.go +++ b/hack/generate/samples/internal/go/v2/memcached_with_webhooks.go @@ -251,7 +251,7 @@ func (mh *MemcachedGoWithWebhooks) implementingAPI() { // Note that it should NOT be called in the e2e tests. func GenerateMemcachedGoWithWebhooksSample(samplesPath string) { log.Infof("starting to generate Go memcached sample with webhooks") - ctx, err := pkg.NewSampleContext(testutils.BinaryName, filepath.Join(samplesPath, "go/memcached-operator"), "GO111MODULE=on") + ctx, err := pkg.NewSampleContext(testutils.BinaryName, filepath.Join(samplesPath, "memcached-operator"), "GO111MODULE=on") pkg.CheckError("generating Go memcached with webhooks context", err) memcached := NewMemcachedGoWithWebhooks(&ctx) diff --git a/hack/generate/samples/internal/go/v3/memcached_with_webhooks.go b/hack/generate/samples/internal/go/v3/memcached_with_webhooks.go index 0c518f67aa1..81dc52036cf 100644 --- a/hack/generate/samples/internal/go/v3/memcached_with_webhooks.go +++ b/hack/generate/samples/internal/go/v3/memcached_with_webhooks.go @@ -250,8 +250,7 @@ func (mh *MemcachedGoWithWebhooks) implementingAPI() { // Note that it should NOT be called in the e2e tests. func GenerateMemcachedGoWithWebhooksSample(samplesPath string) { log.Infof("starting to generate Go memcached sample with webhooks") - path := filepath.Join(samplesPath, "memcached-operator") - ctx, err := pkg.NewSampleContext(testutils.BinaryName, path, "GO111MODULE=on") + ctx, err := pkg.NewSampleContext(testutils.BinaryName, filepath.Join(samplesPath, "memcached-operator"), "GO111MODULE=on") pkg.CheckError("generating Go memcached with webhooks context", err) memcached := NewMemcachedGoWithWebhooks(&ctx) diff --git a/testdata/go/v2/go/memcached-operator/.gitignore b/testdata/go/v2/memcached-operator/.gitignore similarity index 100% rename from testdata/go/v2/go/memcached-operator/.gitignore rename to testdata/go/v2/memcached-operator/.gitignore diff --git a/testdata/go/v2/go/memcached-operator/Dockerfile b/testdata/go/v2/memcached-operator/Dockerfile similarity index 100% rename from testdata/go/v2/go/memcached-operator/Dockerfile rename to testdata/go/v2/memcached-operator/Dockerfile diff --git a/testdata/go/v2/go/memcached-operator/Makefile b/testdata/go/v2/memcached-operator/Makefile similarity index 100% rename from testdata/go/v2/go/memcached-operator/Makefile rename to testdata/go/v2/memcached-operator/Makefile diff --git a/testdata/go/v2/go/memcached-operator/PROJECT b/testdata/go/v2/memcached-operator/PROJECT similarity index 100% rename from testdata/go/v2/go/memcached-operator/PROJECT rename to testdata/go/v2/memcached-operator/PROJECT diff --git a/testdata/go/v2/go/memcached-operator/api/v1alpha1/groupversion_info.go b/testdata/go/v2/memcached-operator/api/v1alpha1/groupversion_info.go similarity index 100% rename from testdata/go/v2/go/memcached-operator/api/v1alpha1/groupversion_info.go rename to testdata/go/v2/memcached-operator/api/v1alpha1/groupversion_info.go diff --git a/testdata/go/v2/go/memcached-operator/api/v1alpha1/memcached_types.go b/testdata/go/v2/memcached-operator/api/v1alpha1/memcached_types.go similarity index 100% rename from testdata/go/v2/go/memcached-operator/api/v1alpha1/memcached_types.go rename to testdata/go/v2/memcached-operator/api/v1alpha1/memcached_types.go diff --git a/testdata/go/v2/go/memcached-operator/api/v1alpha1/memcached_webhook.go b/testdata/go/v2/memcached-operator/api/v1alpha1/memcached_webhook.go similarity index 100% rename from testdata/go/v2/go/memcached-operator/api/v1alpha1/memcached_webhook.go rename to testdata/go/v2/memcached-operator/api/v1alpha1/memcached_webhook.go diff --git a/testdata/go/v2/go/memcached-operator/api/v1alpha1/zz_generated.deepcopy.go b/testdata/go/v2/memcached-operator/api/v1alpha1/zz_generated.deepcopy.go similarity index 100% rename from testdata/go/v2/go/memcached-operator/api/v1alpha1/zz_generated.deepcopy.go rename to testdata/go/v2/memcached-operator/api/v1alpha1/zz_generated.deepcopy.go diff --git a/testdata/go/v2/go/memcached-operator/bundle.Dockerfile b/testdata/go/v2/memcached-operator/bundle.Dockerfile similarity index 100% rename from testdata/go/v2/go/memcached-operator/bundle.Dockerfile rename to testdata/go/v2/memcached-operator/bundle.Dockerfile diff --git a/testdata/go/v2/go/memcached-operator/bundle/manifests/cache.example.com_memcacheds.yaml b/testdata/go/v2/memcached-operator/bundle/manifests/cache.example.com_memcacheds.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/bundle/manifests/cache.example.com_memcacheds.yaml rename to testdata/go/v2/memcached-operator/bundle/manifests/cache.example.com_memcacheds.yaml diff --git a/testdata/go/v2/go/memcached-operator/bundle/manifests/memcached-operator-controller-manager-metrics-monitor_monitoring.coreos.com_v1_servicemonitor.yaml b/testdata/go/v2/memcached-operator/bundle/manifests/memcached-operator-controller-manager-metrics-monitor_monitoring.coreos.com_v1_servicemonitor.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/bundle/manifests/memcached-operator-controller-manager-metrics-monitor_monitoring.coreos.com_v1_servicemonitor.yaml rename to testdata/go/v2/memcached-operator/bundle/manifests/memcached-operator-controller-manager-metrics-monitor_monitoring.coreos.com_v1_servicemonitor.yaml diff --git a/testdata/go/v2/go/memcached-operator/bundle/manifests/memcached-operator-controller-manager-metrics-service_v1_service.yaml b/testdata/go/v2/memcached-operator/bundle/manifests/memcached-operator-controller-manager-metrics-service_v1_service.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/bundle/manifests/memcached-operator-controller-manager-metrics-service_v1_service.yaml rename to testdata/go/v2/memcached-operator/bundle/manifests/memcached-operator-controller-manager-metrics-service_v1_service.yaml diff --git a/testdata/go/v2/go/memcached-operator/bundle/manifests/memcached-operator-metrics-reader_rbac.authorization.k8s.io_v1_clusterrole.yaml b/testdata/go/v2/memcached-operator/bundle/manifests/memcached-operator-metrics-reader_rbac.authorization.k8s.io_v1_clusterrole.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/bundle/manifests/memcached-operator-metrics-reader_rbac.authorization.k8s.io_v1_clusterrole.yaml rename to testdata/go/v2/memcached-operator/bundle/manifests/memcached-operator-metrics-reader_rbac.authorization.k8s.io_v1_clusterrole.yaml diff --git a/testdata/go/v2/go/memcached-operator/bundle/manifests/memcached-operator-webhook-service_v1_service.yaml b/testdata/go/v2/memcached-operator/bundle/manifests/memcached-operator-webhook-service_v1_service.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/bundle/manifests/memcached-operator-webhook-service_v1_service.yaml rename to testdata/go/v2/memcached-operator/bundle/manifests/memcached-operator-webhook-service_v1_service.yaml diff --git a/testdata/go/v2/go/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml b/testdata/go/v2/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml rename to testdata/go/v2/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml diff --git a/testdata/go/v2/go/memcached-operator/bundle/metadata/annotations.yaml b/testdata/go/v2/memcached-operator/bundle/metadata/annotations.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/bundle/metadata/annotations.yaml rename to testdata/go/v2/memcached-operator/bundle/metadata/annotations.yaml diff --git a/testdata/go/v2/go/memcached-operator/bundle/tests/scorecard/config.yaml b/testdata/go/v2/memcached-operator/bundle/tests/scorecard/config.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/bundle/tests/scorecard/config.yaml rename to testdata/go/v2/memcached-operator/bundle/tests/scorecard/config.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/certmanager/certificate.yaml b/testdata/go/v2/memcached-operator/config/certmanager/certificate.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/certmanager/certificate.yaml rename to testdata/go/v2/memcached-operator/config/certmanager/certificate.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/certmanager/kustomization.yaml b/testdata/go/v2/memcached-operator/config/certmanager/kustomization.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/certmanager/kustomization.yaml rename to testdata/go/v2/memcached-operator/config/certmanager/kustomization.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/certmanager/kustomizeconfig.yaml b/testdata/go/v2/memcached-operator/config/certmanager/kustomizeconfig.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/certmanager/kustomizeconfig.yaml rename to testdata/go/v2/memcached-operator/config/certmanager/kustomizeconfig.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/crd/bases/cache.example.com_memcacheds.yaml b/testdata/go/v2/memcached-operator/config/crd/bases/cache.example.com_memcacheds.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/crd/bases/cache.example.com_memcacheds.yaml rename to testdata/go/v2/memcached-operator/config/crd/bases/cache.example.com_memcacheds.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/crd/kustomization.yaml b/testdata/go/v2/memcached-operator/config/crd/kustomization.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/crd/kustomization.yaml rename to testdata/go/v2/memcached-operator/config/crd/kustomization.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/crd/kustomizeconfig.yaml b/testdata/go/v2/memcached-operator/config/crd/kustomizeconfig.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/crd/kustomizeconfig.yaml rename to testdata/go/v2/memcached-operator/config/crd/kustomizeconfig.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/crd/patches/cainjection_in_memcacheds.yaml b/testdata/go/v2/memcached-operator/config/crd/patches/cainjection_in_memcacheds.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/crd/patches/cainjection_in_memcacheds.yaml rename to testdata/go/v2/memcached-operator/config/crd/patches/cainjection_in_memcacheds.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/crd/patches/webhook_in_memcacheds.yaml b/testdata/go/v2/memcached-operator/config/crd/patches/webhook_in_memcacheds.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/crd/patches/webhook_in_memcacheds.yaml rename to testdata/go/v2/memcached-operator/config/crd/patches/webhook_in_memcacheds.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/default/kustomization.yaml b/testdata/go/v2/memcached-operator/config/default/kustomization.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/default/kustomization.yaml rename to testdata/go/v2/memcached-operator/config/default/kustomization.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/default/manager_auth_proxy_patch.yaml b/testdata/go/v2/memcached-operator/config/default/manager_auth_proxy_patch.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/default/manager_auth_proxy_patch.yaml rename to testdata/go/v2/memcached-operator/config/default/manager_auth_proxy_patch.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/default/manager_webhook_patch.yaml b/testdata/go/v2/memcached-operator/config/default/manager_webhook_patch.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/default/manager_webhook_patch.yaml rename to testdata/go/v2/memcached-operator/config/default/manager_webhook_patch.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/default/webhookcainjection_patch.yaml b/testdata/go/v2/memcached-operator/config/default/webhookcainjection_patch.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/default/webhookcainjection_patch.yaml rename to testdata/go/v2/memcached-operator/config/default/webhookcainjection_patch.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/manager/kustomization.yaml b/testdata/go/v2/memcached-operator/config/manager/kustomization.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/manager/kustomization.yaml rename to testdata/go/v2/memcached-operator/config/manager/kustomization.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/manager/manager.yaml b/testdata/go/v2/memcached-operator/config/manager/manager.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/manager/manager.yaml rename to testdata/go/v2/memcached-operator/config/manager/manager.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml b/testdata/go/v2/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml rename to testdata/go/v2/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/manifests/kustomization.yaml b/testdata/go/v2/memcached-operator/config/manifests/kustomization.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/manifests/kustomization.yaml rename to testdata/go/v2/memcached-operator/config/manifests/kustomization.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/prometheus/kustomization.yaml b/testdata/go/v2/memcached-operator/config/prometheus/kustomization.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/prometheus/kustomization.yaml rename to testdata/go/v2/memcached-operator/config/prometheus/kustomization.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/prometheus/monitor.yaml b/testdata/go/v2/memcached-operator/config/prometheus/monitor.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/prometheus/monitor.yaml rename to testdata/go/v2/memcached-operator/config/prometheus/monitor.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/rbac/auth_proxy_client_clusterrole.yaml b/testdata/go/v2/memcached-operator/config/rbac/auth_proxy_client_clusterrole.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/rbac/auth_proxy_client_clusterrole.yaml rename to testdata/go/v2/memcached-operator/config/rbac/auth_proxy_client_clusterrole.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/rbac/auth_proxy_role.yaml b/testdata/go/v2/memcached-operator/config/rbac/auth_proxy_role.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/rbac/auth_proxy_role.yaml rename to testdata/go/v2/memcached-operator/config/rbac/auth_proxy_role.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/rbac/auth_proxy_role_binding.yaml b/testdata/go/v2/memcached-operator/config/rbac/auth_proxy_role_binding.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/rbac/auth_proxy_role_binding.yaml rename to testdata/go/v2/memcached-operator/config/rbac/auth_proxy_role_binding.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/rbac/auth_proxy_service.yaml b/testdata/go/v2/memcached-operator/config/rbac/auth_proxy_service.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/rbac/auth_proxy_service.yaml rename to testdata/go/v2/memcached-operator/config/rbac/auth_proxy_service.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/rbac/kustomization.yaml b/testdata/go/v2/memcached-operator/config/rbac/kustomization.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/rbac/kustomization.yaml rename to testdata/go/v2/memcached-operator/config/rbac/kustomization.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/rbac/leader_election_role.yaml b/testdata/go/v2/memcached-operator/config/rbac/leader_election_role.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/rbac/leader_election_role.yaml rename to testdata/go/v2/memcached-operator/config/rbac/leader_election_role.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/rbac/leader_election_role_binding.yaml b/testdata/go/v2/memcached-operator/config/rbac/leader_election_role_binding.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/rbac/leader_election_role_binding.yaml rename to testdata/go/v2/memcached-operator/config/rbac/leader_election_role_binding.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/rbac/memcached_editor_role.yaml b/testdata/go/v2/memcached-operator/config/rbac/memcached_editor_role.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/rbac/memcached_editor_role.yaml rename to testdata/go/v2/memcached-operator/config/rbac/memcached_editor_role.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/rbac/memcached_viewer_role.yaml b/testdata/go/v2/memcached-operator/config/rbac/memcached_viewer_role.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/rbac/memcached_viewer_role.yaml rename to testdata/go/v2/memcached-operator/config/rbac/memcached_viewer_role.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/rbac/role.yaml b/testdata/go/v2/memcached-operator/config/rbac/role.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/rbac/role.yaml rename to testdata/go/v2/memcached-operator/config/rbac/role.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/rbac/role_binding.yaml b/testdata/go/v2/memcached-operator/config/rbac/role_binding.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/rbac/role_binding.yaml rename to testdata/go/v2/memcached-operator/config/rbac/role_binding.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/samples/cache_v1alpha1_memcached.yaml b/testdata/go/v2/memcached-operator/config/samples/cache_v1alpha1_memcached.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/samples/cache_v1alpha1_memcached.yaml rename to testdata/go/v2/memcached-operator/config/samples/cache_v1alpha1_memcached.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/samples/kustomization.yaml b/testdata/go/v2/memcached-operator/config/samples/kustomization.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/samples/kustomization.yaml rename to testdata/go/v2/memcached-operator/config/samples/kustomization.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/scorecard/bases/config.yaml b/testdata/go/v2/memcached-operator/config/scorecard/bases/config.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/scorecard/bases/config.yaml rename to testdata/go/v2/memcached-operator/config/scorecard/bases/config.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/scorecard/kustomization.yaml b/testdata/go/v2/memcached-operator/config/scorecard/kustomization.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/scorecard/kustomization.yaml rename to testdata/go/v2/memcached-operator/config/scorecard/kustomization.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/scorecard/patches/basic.config.yaml b/testdata/go/v2/memcached-operator/config/scorecard/patches/basic.config.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/scorecard/patches/basic.config.yaml rename to testdata/go/v2/memcached-operator/config/scorecard/patches/basic.config.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/scorecard/patches/olm.config.yaml b/testdata/go/v2/memcached-operator/config/scorecard/patches/olm.config.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/scorecard/patches/olm.config.yaml rename to testdata/go/v2/memcached-operator/config/scorecard/patches/olm.config.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/webhook/kustomization.yaml b/testdata/go/v2/memcached-operator/config/webhook/kustomization.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/webhook/kustomization.yaml rename to testdata/go/v2/memcached-operator/config/webhook/kustomization.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/webhook/kustomizeconfig.yaml b/testdata/go/v2/memcached-operator/config/webhook/kustomizeconfig.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/webhook/kustomizeconfig.yaml rename to testdata/go/v2/memcached-operator/config/webhook/kustomizeconfig.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/webhook/manifests.yaml b/testdata/go/v2/memcached-operator/config/webhook/manifests.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/webhook/manifests.yaml rename to testdata/go/v2/memcached-operator/config/webhook/manifests.yaml diff --git a/testdata/go/v2/go/memcached-operator/config/webhook/service.yaml b/testdata/go/v2/memcached-operator/config/webhook/service.yaml similarity index 100% rename from testdata/go/v2/go/memcached-operator/config/webhook/service.yaml rename to testdata/go/v2/memcached-operator/config/webhook/service.yaml diff --git a/testdata/go/v2/go/memcached-operator/controllers/memcached_controller.go b/testdata/go/v2/memcached-operator/controllers/memcached_controller.go similarity index 100% rename from testdata/go/v2/go/memcached-operator/controllers/memcached_controller.go rename to testdata/go/v2/memcached-operator/controllers/memcached_controller.go diff --git a/testdata/go/v2/go/memcached-operator/controllers/suite_test.go b/testdata/go/v2/memcached-operator/controllers/suite_test.go similarity index 100% rename from testdata/go/v2/go/memcached-operator/controllers/suite_test.go rename to testdata/go/v2/memcached-operator/controllers/suite_test.go diff --git a/testdata/go/v2/go/memcached-operator/go.mod b/testdata/go/v2/memcached-operator/go.mod similarity index 100% rename from testdata/go/v2/go/memcached-operator/go.mod rename to testdata/go/v2/memcached-operator/go.mod diff --git a/testdata/go/v2/go/memcached-operator/go.sum b/testdata/go/v2/memcached-operator/go.sum similarity index 100% rename from testdata/go/v2/go/memcached-operator/go.sum rename to testdata/go/v2/memcached-operator/go.sum diff --git a/testdata/go/v2/go/memcached-operator/hack/boilerplate.go.txt b/testdata/go/v2/memcached-operator/hack/boilerplate.go.txt similarity index 100% rename from testdata/go/v2/go/memcached-operator/hack/boilerplate.go.txt rename to testdata/go/v2/memcached-operator/hack/boilerplate.go.txt diff --git a/testdata/go/v2/go/memcached-operator/main.go b/testdata/go/v2/memcached-operator/main.go similarity index 100% rename from testdata/go/v2/go/memcached-operator/main.go rename to testdata/go/v2/memcached-operator/main.go From 89bddb626abb76e81103d969318842010d9caf7d Mon Sep 17 00:00:00 2001 From: Mike Ng <58747157+mikeshng@users.noreply.github.com> Date: Mon, 7 Dec 2020 15:06:35 -0500 Subject: [PATCH 235/376] fix: (helm) - prevent a possible nil pointer in the helm uninstall (#4288) Signed-off-by: Mike Ng Signed-off-by: reinvantveer --- internal/helm/controller/reconcile.go | 2 +- internal/helm/release/manager.go | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/internal/helm/controller/reconcile.go b/internal/helm/controller/reconcile.go index edba053458d..fb0e56d692b 100644 --- a/internal/helm/controller/reconcile.go +++ b/internal/helm/controller/reconcile.go @@ -119,7 +119,7 @@ func (r HelmOperatorReconciler) Reconcile(ctx context.Context, request reconcile log.Info("Release not found, removing finalizer") } else { log.Info("Uninstalled release") - if log.V(0).Enabled() { + if log.V(0).Enabled() && uninstalledRelease != nil { fmt.Println(diff.Generate(uninstalledRelease.Manifest, "")) } status.SetCondition(types.HelmAppCondition{ diff --git a/internal/helm/release/manager.go b/internal/helm/release/manager.go index f6b671b9335..d72c2a0c0c5 100644 --- a/internal/helm/release/manager.go +++ b/internal/helm/release/manager.go @@ -370,5 +370,8 @@ func (m manager) UninstallRelease(ctx context.Context, opts ...UninstallOption) } } uninstallResponse, err := uninstall.Run(m.releaseName) + if uninstallResponse == nil { + return nil, err + } return uninstallResponse.Release, err } From 2bff082e5c2785c77b042d57a9898226b2242e3e Mon Sep 17 00:00:00 2001 From: Camila Macedo Date: Tue, 8 Dec 2020 22:55:06 +0000 Subject: [PATCH 236/376] test-e2e/go : using samples (#4056) **Description of the change:** - Use Memcached sample instead of re-generate the project. - Fix/Adjust the e2e tests to work with the sample. **Motivation for the change:** operator-framework/enhancements#47 Signed-off-by: reinvantveer --- .../internal/go/v2/memcached_with_webhooks.go | 25 +++- .../internal/go/v3/memcached_with_webhooks.go | 7 + test/e2e-go/e2e_go_cluster_test.go | 38 +++--- test/e2e-go/e2e_go_olm_test.go | 126 +++++++++++++++--- test/e2e-go/e2e_go_scorecard_test.go | 1 + test/e2e-go/e2e_go_suite_test.go | 79 ++++------- .../api/v1alpha1/memcached_webhook.go | 1 + ...cached-operator.clusterserviceversion.yaml | 2 +- .../samples/cache_v1alpha1_memcached.yaml | 2 +- ...cached-operator.clusterserviceversion.yaml | 2 +- .../samples/cache_v1alpha1_memcached.yaml | 2 +- 11 files changed, 187 insertions(+), 98 deletions(-) diff --git a/hack/generate/samples/internal/go/v2/memcached_with_webhooks.go b/hack/generate/samples/internal/go/v2/memcached_with_webhooks.go index c04f94fce8f..bb0a6fce02c 100644 --- a/hack/generate/samples/internal/go/v2/memcached_with_webhooks.go +++ b/hack/generate/samples/internal/go/v2/memcached_with_webhooks.go @@ -176,8 +176,13 @@ func (mh *MemcachedGoWithWebhooks) implementingWebhooks() { // Add imports err = kbtestutils.InsertCode(webhookPath, "import (", - "\"errors\"") - pkg.CheckError("adding imports", err) + "\n\t\"errors\"") + pkg.CheckError("adding errors import", err) + + err = kbtestutils.InsertCode(webhookPath, + "\n\t\"errors\"", + "\n\t\"k8s.io/apimachinery/pkg/runtime\"") + pkg.CheckError("adding k8s.io/apimachinery/pkg/runtime import", err) } // implementingController will customize the Controller @@ -225,8 +230,11 @@ func (mh *MemcachedGoWithWebhooks) implementingController() { // implementingAPI will customize the API func (mh *MemcachedGoWithWebhooks) implementingAPI() { + typeFilePath := filepath.Join(mh.ctx.Dir, "api", mh.ctx.Version, fmt.Sprintf("%s_types.go", strings.ToLower(mh.ctx.Kind))) + + log.Infof("implementing api spec") err := kbtestutils.InsertCode( - filepath.Join(mh.ctx.Dir, "api", mh.ctx.Version, fmt.Sprintf("%s_types.go", strings.ToLower(mh.ctx.Kind))), + typeFilePath, fmt.Sprintf("type %sSpec struct {\n\t// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster\n\t// Important: Run \"make\" to regenerate code after modifying this file", mh.ctx.Kind), ` @@ -235,9 +243,9 @@ func (mh *MemcachedGoWithWebhooks) implementingAPI() { `) pkg.CheckError("inserting spec Status", err) - log.Infof("implementing MemcachedStatus") + log.Infof("implementing api status") err = kbtestutils.InsertCode( - filepath.Join(mh.ctx.Dir, "api", mh.ctx.Version, fmt.Sprintf("%s_types.go", strings.ToLower(mh.ctx.Kind))), + typeFilePath, fmt.Sprintf("type %sStatus struct {\n\t// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster\n\t// Important: Run \"make\" to regenerate code after modifying this file", mh.ctx.Kind), ` @@ -245,6 +253,13 @@ func (mh *MemcachedGoWithWebhooks) implementingAPI() { Nodes []string `+"`"+`json:"nodes,omitempty"`+"`"+` `) pkg.CheckError("inserting Node Status", err) + + sampleFile := filepath.Join("config", "samples", + fmt.Sprintf("%s_%s_%s.yaml", mh.ctx.Group, mh.ctx.Version, strings.ToLower(mh.ctx.Kind))) + + log.Infof("updating sample to have size attribute") + err = testutils.ReplaceInFile(filepath.Join(mh.ctx.Dir, sampleFile), "foo: bar", "size: 1") + pkg.CheckError("updating sample", err) } // GenerateMemcachedGoWithWebhooksSample will call all actions to create the directory and generate the sample diff --git a/hack/generate/samples/internal/go/v3/memcached_with_webhooks.go b/hack/generate/samples/internal/go/v3/memcached_with_webhooks.go index 81dc52036cf..ec451b8fe36 100644 --- a/hack/generate/samples/internal/go/v3/memcached_with_webhooks.go +++ b/hack/generate/samples/internal/go/v3/memcached_with_webhooks.go @@ -244,6 +244,13 @@ func (mh *MemcachedGoWithWebhooks) implementingAPI() { Nodes []string `+"`"+`json:"nodes,omitempty"`+"`"+` `) pkg.CheckError("inserting Node Status", err) + + sampleFile := filepath.Join("config", "samples", + fmt.Sprintf("%s_%s_%s.yaml", mh.ctx.Group, mh.ctx.Version, strings.ToLower(mh.ctx.Kind))) + + log.Infof("updating sample to have size attribute") + err = testutils.ReplaceInFile(filepath.Join(mh.ctx.Dir, sampleFile), "foo: bar", "size: 1") + pkg.CheckError("updating sample", err) } // GenerateMemcachedGoWithWebhooksSample will call all actions to create the directory and generate the sample diff --git a/test/e2e-go/e2e_go_cluster_test.go b/test/e2e-go/e2e_go_cluster_test.go index cb87d68f046..1ec650c399a 100644 --- a/test/e2e-go/e2e_go_cluster_test.go +++ b/test/e2e-go/e2e_go_cluster_test.go @@ -30,25 +30,27 @@ import ( var _ = Describe("operator-sdk", func() { var controllerPodName string + var metricsClusterRoleBindingName string Context("built with operator-sdk", func() { BeforeEach(func() { - By("enabling Prometheus via the kustomization.yaml") - Expect(kbtestutils.UncommentCode( - filepath.Join(tc.Dir, "config", "default", "kustomization.yaml"), - "#- ../prometheus", "#")).To(Succeed()) - + metricsClusterRoleBindingName = fmt.Sprintf("%s-metrics-reader", tc.ProjectName) + reconcileCount++ By("deploying project on the cluster") err := tc.Make("deploy", "IMG="+tc.ImageName) Expect(err).NotTo(HaveOccurred()) + }) AfterEach(func() { + By("deleting Curl Pod created") + _, _ = tc.Kubectl.Delete(false, "pod", "curl") + By("cleaning up permissions") _, _ = tc.Kubectl.Command("delete", "clusterrolebinding", - fmt.Sprintf("metrics-%s", tc.TestSuffix)) + metricsClusterRoleBindingName) - By("cleaning up the operator and resources") - _ = tc.Make("undeploy") + By("cleaning up created API objects during test process") + tc.CleanupManifests(filepath.Join("config", "default")) By("ensuring that the namespace was deleted") verifyNamespaceDeleted := func() error { @@ -102,14 +104,14 @@ var _ = Describe("operator-sdk", func() { _, err := tc.Kubectl.Get( true, "ServiceMonitor", - fmt.Sprintf("e2e-%s-controller-manager-metrics-monitor", tc.TestSuffix)) + fmt.Sprintf("%s-controller-manager-metrics-monitor", tc.ProjectName)) Expect(err).NotTo(HaveOccurred()) By("ensuring the created metrics Service for the manager") _, err = tc.Kubectl.Get( true, "Service", - fmt.Sprintf("e2e-%s-controller-manager-metrics-service", tc.TestSuffix)) + fmt.Sprintf("%s-controller-manager-metrics-service", tc.ProjectName)) Expect(err).NotTo(HaveOccurred()) By("creating an instance of CR") @@ -125,9 +127,8 @@ var _ = Describe("operator-sdk", func() { By("granting permissions to access the metrics and read the token") _, err = tc.Kubectl.Command( "create", - "clusterrolebinding", - fmt.Sprintf("metrics-%s", tc.TestSuffix), - fmt.Sprintf("--clusterrole=e2e-%s-metrics-reader", tc.TestSuffix), + "clusterrolebinding", metricsClusterRoleBindingName, + fmt.Sprintf("--clusterrole=%s-metrics-reader", tc.ProjectName), fmt.Sprintf("--serviceaccount=%s:default", tc.Kubectl.Namespace)) Expect(err).NotTo(HaveOccurred()) @@ -148,8 +149,7 @@ var _ = Describe("operator-sdk", func() { cmdOpts := []string{ "run", "--generator=run-pod/v1", "curl", "--image=curlimages/curl:7.68.0", "--restart=OnFailure", "--", "curl", "-v", "-k", "-H", fmt.Sprintf(`Authorization: Bearer %s`, token), - fmt.Sprintf("https://e2e-%v-controller-manager-metrics-service.e2e-%v-system.svc:8443/metrics", - tc.TestSuffix, tc.TestSuffix), + fmt.Sprintf("https://%s-controller-manager-metrics-service.%s.svc:8443/metrics", tc.ProjectName, tc.Kubectl.Namespace), } _, err = tc.Kubectl.CommandInNamespace(cmdOpts...) Expect(err).NotTo(HaveOccurred()) @@ -177,14 +177,10 @@ var _ = Describe("operator-sdk", func() { } Eventually(getCurlLogs, time.Minute, time.Second).Should(ContainSubstring("< HTTP/2 200")) - By("cleaning up the curl pod") - _, err = tc.Kubectl.Delete(true, "pods", "curl") - Expect(err).NotTo(HaveOccurred()) - By("validating that the created resource object gets reconciled in the controller") Expect(metricsOutput).To(ContainSubstring(fmt.Sprintf( - `controller_runtime_reconcile_total{controller="%s",result="success"} 1`, - strings.ToLower(tc.Kind), + `controller_runtime_reconcile_total{controller="%s",result="success"} %d`, + strings.ToLower(tc.Kind), reconcileCount, ))) }) }) diff --git a/test/e2e-go/e2e_go_olm_test.go b/test/e2e-go/e2e_go_olm_test.go index f4df883f07e..2111314e985 100644 --- a/test/e2e-go/e2e_go_olm_test.go +++ b/test/e2e-go/e2e_go_olm_test.go @@ -16,36 +16,54 @@ package e2e_go_test import ( "os/exec" + "path/filepath" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + + "github.com/operator-framework/operator-sdk/internal/testutils" ) var _ = Describe("Integrating Go Projects with OLM", func() { - Context("with operator-sdk", func() { - const operatorVersion = "0.0.1" - It("should generate and run a valid OLM bundle and packagemanifests", func() { - By("turning off interactive prompts for all generation tasks.") - err := tc.DisableManifestsInteractiveMode() - Expect(err).NotTo(HaveOccurred()) + // OLM does not work with cert-manager. In this way, we need to generate + // the pkg manifest after we comment cert-manager options into the kustomization file. + // More info: https://olm.operatorframework.io/docs/advanced-tasks/adding-admission-and-conversion-webhooks/#certificate-authority-requirements + BeforeEach(func() { + reconcileCount++ + By("commenting cert-manager") + err := testutils.ReplaceInFile( + filepath.Join(tc.Dir, "config", "default", "kustomization.yaml"), + "- ../certmanager", "#- ../certmanager") + Expect(err).NotTo(HaveOccurred()) - By("building the bundle") - err = tc.Make("bundle", "IMG="+tc.ImageName) - Expect(err).NotTo(HaveOccurred()) + By("commenting cert-manager") + err = testutils.ReplaceInFile( + filepath.Join(tc.Dir, "config", "default", "kustomization.yaml"), + uncommentedCertManagerKustomizeFields, commentedCertManagerKustomizeFields) + Expect(err).NotTo(HaveOccurred()) + }) - By("building the operator bundle image") - err = tc.Make("bundle-build", "BUNDLE_IMG="+tc.BundleImageName) - Expect(err).NotTo(HaveOccurred()) + AfterEach(func() { + By("commenting cert-manager") + err := testutils.ReplaceInFile( + filepath.Join(tc.Dir, "config", "default", "kustomization.yaml"), + "#- ../certmanager", "- ../certmanager") + Expect(err).NotTo(HaveOccurred()) - if tc.IsRunningOnKind() { - By("loading the bundle image into Kind cluster") - err = tc.LoadImageToKindClusterWithName(tc.BundleImageName) - Expect(err).NotTo(HaveOccurred()) - } + By("commenting cert-manager") + err = testutils.ReplaceInFile( + filepath.Join(tc.Dir, "config", "default", "kustomization.yaml"), + commentedCertManagerKustomizeFields, uncommentedCertManagerKustomizeFields) + Expect(err).NotTo(HaveOccurred()) + }) + Context("with operator-sdk", func() { + const operatorVersion = "0.0.1" + + It("should generate and run a valid OLM bundle and packagemanifests", func() { By("adding the 'packagemanifests' rule to the Makefile") - err = tc.AddPackagemanifestsTarget() + err := tc.AddPackagemanifestsTarget() Expect(err).NotTo(HaveOccurred()) By("generating the operator package manifests") @@ -69,3 +87,75 @@ var _ = Describe("Integrating Go Projects with OLM", func() { }) }) }) + +const uncommentedCertManagerKustomizeFields = `# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. +# Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks. +# 'CERTMANAGER' needs to be enabled to use ca injection +- webhookcainjection_patch.yaml + + +# the following config is for teaching kustomize how to do var substitution +vars: +# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix. +- name: CERTIFICATE_NAMESPACE # namespace of the certificate CR + objref: + kind: Certificate + group: cert-manager.io + version: v1alpha2 + name: serving-cert # this name should match the one in certificate.yaml + fieldref: + fieldpath: metadata.namespace +- name: CERTIFICATE_NAME + objref: + kind: Certificate + group: cert-manager.io + version: v1alpha2 + name: serving-cert # this name should match the one in certificate.yaml +- name: SERVICE_NAMESPACE # namespace of the service + objref: + kind: Service + version: v1 + name: webhook-service + fieldref: + fieldpath: metadata.namespace +- name: SERVICE_NAME + objref: + kind: Service + version: v1 + name: webhook-service` + +const commentedCertManagerKustomizeFields = `# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. +# Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks. +# 'CERTMANAGER' needs to be enabled to use ca injection +# - webhookcainjection_patch.yaml + + +# the following config is for teaching kustomize how to do var substitution +vars: +# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix. +#- name: CERTIFICATE_NAMESPACE # namespace of the certificate CR +# objref: +# kind: Certificate +# group: cert-manager.io +# version: v1alpha2 +# name: serving-cert # this name should match the one in certificate.yaml +# fieldref: +# fieldpath: metadata.namespace +#- name: CERTIFICATE_NAME +# objref: +# kind: Certificate +# group: cert-manager.io +# version: v1alpha2 +# name: serving-cert # this name should match the one in certificate.yaml +#- name: SERVICE_NAMESPACE # namespace of the service +# objref: +# kind: Service +# version: v1 +# name: webhook-service +# fieldref: +# fieldpath: metadata.namespace +#- name: SERVICE_NAME +# objref: +# kind: Service +# version: v1 +# name: webhook-service` diff --git a/test/e2e-go/e2e_go_scorecard_test.go b/test/e2e-go/e2e_go_scorecard_test.go index f028c6f12e2..4ed48a60217 100644 --- a/test/e2e-go/e2e_go_scorecard_test.go +++ b/test/e2e-go/e2e_go_scorecard_test.go @@ -26,6 +26,7 @@ import ( var _ = Describe("Testing Go Projects with Scorecard", func() { Context("with operator-sdk", func() { + reconcileCount++ const ( OLMBundleValidationTest = "olm-bundle-validation" OLMCRDsHaveValidationTest = "olm-crds-have-validation" diff --git a/test/e2e-go/e2e_go_suite_test.go b/test/e2e-go/e2e_go_suite_test.go index 56678801e44..4e5ea1955b9 100644 --- a/test/e2e-go/e2e_go_suite_test.go +++ b/test/e2e-go/e2e_go_suite_test.go @@ -16,14 +16,11 @@ package e2e_go_test import ( "fmt" - "path" - "path/filepath" - "strings" + "os/exec" "testing" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - kbtestutils "sigs.k8s.io/kubebuilder/v2/test/e2e/utils" "github.com/operator-framework/operator-sdk/internal/testutils" ) @@ -38,7 +35,8 @@ func TestE2EGo(t *testing.T) { } var ( - tc testutils.TestContext + tc testutils.TestContext + reconcileCount = 0 ) // BeforeSuite run before any specs are run to perform the required actions for all e2e Go tests. @@ -49,8 +47,16 @@ var _ = BeforeSuite(func() { tc, err = testutils.NewTestContext(testutils.BinaryName, "GO111MODULE=on") Expect(err).NotTo(HaveOccurred()) - By("creating a new directory") - Expect(tc.Prepare()).To(Succeed()) + tc.Domain = "example.com" + tc.Group = "cache" + tc.Version = "v1alpha1" + tc.Kind = "Memcached" + tc.Resources = "memcacheds" + tc.ProjectName = "memcached-operator" + tc.Kubectl.Namespace = fmt.Sprintf("%s-system", tc.ProjectName) + + By("copying sample to a temporary e2e directory") + Expect(exec.Command("cp", "-r", "../../testdata/go/v2/memcached-operator", tc.Dir).Run()).To(Succeed()) By("fetching the current-context") tc.Kubectx, err = tc.Kubectl.Command("config", "current-context") @@ -59,16 +65,6 @@ var _ = BeforeSuite(func() { By("preparing the prerequisites on cluster") tc.InstallPrerequisites() - By("initializing a project") - err = tc.Init( - "--project-version", "3-alpha", - // TODO(estroz): remove this once go/v3-alpha is stabilized and the default plugin. - "--plugins", "go/v3-alpha", - "--repo", path.Join("github.com", "example", tc.ProjectName), - "--domain", tc.Domain, - "--fetch-deps=false") - Expect(err).NotTo(HaveOccurred()) - By("by adding scorecard custom patch file") err = tc.AddScorecardCustomPatchFile() Expect(err).NotTo(HaveOccurred()) @@ -77,39 +73,6 @@ var _ = BeforeSuite(func() { err = tc.ReplaceScorecardImagesForDev() Expect(err).NotTo(HaveOccurred()) - By("creating an API definition") - err = tc.CreateAPI( - "--group", tc.Group, - "--version", tc.Version, - "--kind", tc.Kind, - "--namespaced", - "--resource", - "--controller", - "--make=false") - Expect(err).NotTo(HaveOccurred()) - - By("implementing the API") - Expect(kbtestutils.InsertCode( - filepath.Join(tc.Dir, "api", tc.Version, fmt.Sprintf("%s_types.go", strings.ToLower(tc.Kind))), - fmt.Sprintf(`type %sSpec struct { -`, tc.Kind), - ` // +optional - Count int `+"`"+`json:"count,omitempty"`+"`"+` -`)).Should(Succeed()) - - By("enabling Prometheus via the kustomization.yaml") - Expect(kbtestutils.UncommentCode( - filepath.Join(tc.Dir, "config", "default", "kustomization.yaml"), - "#- ../prometheus", "#")).To(Succeed()) - - By("turning off interactive prompts for all generation tasks.") - err = tc.DisableManifestsInteractiveMode() - Expect(err).NotTo(HaveOccurred()) - - By("checking the kustomize setup") - err = tc.Make("kustomize") - Expect(err).NotTo(HaveOccurred()) - By("building the project image") err = tc.Make("docker-build", "IMG="+tc.ImageName) Expect(err).NotTo(HaveOccurred()) @@ -124,11 +87,27 @@ var _ = BeforeSuite(func() { By("generating the operator bundle") err = tc.Make("bundle", "IMG="+tc.ImageName) Expect(err).NotTo(HaveOccurred()) + + By("building the operator bundle image") + err = tc.Make("bundle-build", "BUNDLE_IMG="+tc.BundleImageName) + Expect(err).NotTo(HaveOccurred()) + + if tc.IsRunningOnKind() { + By("loading the bundle image into Kind cluster") + err = tc.LoadImageToKindClusterWithName(tc.BundleImageName) + Expect(err).NotTo(HaveOccurred()) + } + + By("installing cert manager bundle") + Expect(tc.InstallCertManager(true)).To(Succeed()) }) // AfterSuite run after all the specs have run, regardless of whether any tests have failed to ensures that // all be cleaned up var _ = AfterSuite(func() { + By("uninstall cert manager bundle") + tc.UninstallCertManager(true) + By("uninstalling prerequisites") tc.UninstallPrerequisites() diff --git a/testdata/go/v2/memcached-operator/api/v1alpha1/memcached_webhook.go b/testdata/go/v2/memcached-operator/api/v1alpha1/memcached_webhook.go index d3b41a9f963..99a42b91d10 100644 --- a/testdata/go/v2/memcached-operator/api/v1alpha1/memcached_webhook.go +++ b/testdata/go/v2/memcached-operator/api/v1alpha1/memcached_webhook.go @@ -18,6 +18,7 @@ package v1alpha1 import ( "errors" + "k8s.io/apimachinery/pkg/runtime" ctrl "sigs.k8s.io/controller-runtime" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/webhook" diff --git a/testdata/go/v2/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml b/testdata/go/v2/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml index 3f59a770118..2f41e115859 100644 --- a/testdata/go/v2/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml +++ b/testdata/go/v2/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml @@ -11,7 +11,7 @@ metadata: "name": "memcached-sample" }, "spec": { - "foo": "bar" + "size": 1 } } ] diff --git a/testdata/go/v2/memcached-operator/config/samples/cache_v1alpha1_memcached.yaml b/testdata/go/v2/memcached-operator/config/samples/cache_v1alpha1_memcached.yaml index 3ea15eed5cd..9e263db9d91 100644 --- a/testdata/go/v2/memcached-operator/config/samples/cache_v1alpha1_memcached.yaml +++ b/testdata/go/v2/memcached-operator/config/samples/cache_v1alpha1_memcached.yaml @@ -4,4 +4,4 @@ metadata: name: memcached-sample spec: # Add fields here - foo: bar + size: 1 diff --git a/testdata/go/v3/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml b/testdata/go/v3/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml index b58e2903ca7..d6ad1d003da 100644 --- a/testdata/go/v3/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml +++ b/testdata/go/v3/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml @@ -11,7 +11,7 @@ metadata: "name": "memcached-sample" }, "spec": { - "foo": "bar" + "size": 1 } } ] diff --git a/testdata/go/v3/memcached-operator/config/samples/cache_v1alpha1_memcached.yaml b/testdata/go/v3/memcached-operator/config/samples/cache_v1alpha1_memcached.yaml index 3ea15eed5cd..9e263db9d91 100644 --- a/testdata/go/v3/memcached-operator/config/samples/cache_v1alpha1_memcached.yaml +++ b/testdata/go/v3/memcached-operator/config/samples/cache_v1alpha1_memcached.yaml @@ -4,4 +4,4 @@ metadata: name: memcached-sample spec: # Add fields here - foo: bar + size: 1 From 0780a2830e510aa1aebfdbd0f18f62c63dc3d322 Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Thu, 10 Dec 2020 13:57:39 -0800 Subject: [PATCH 237/376] test/e2e-go: fix reconcile check (#4300) Signed-off-by: reinvantveer --- test/e2e-go/e2e_go_cluster_test.go | 15 +++++++++------ test/e2e-go/e2e_go_olm_test.go | 1 - test/e2e-go/e2e_go_scorecard_test.go | 1 - test/e2e-go/e2e_go_suite_test.go | 3 +-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/test/e2e-go/e2e_go_cluster_test.go b/test/e2e-go/e2e_go_cluster_test.go index 1ec650c399a..39ec38775c2 100644 --- a/test/e2e-go/e2e_go_cluster_test.go +++ b/test/e2e-go/e2e_go_cluster_test.go @@ -18,6 +18,7 @@ package e2e_go_test import ( "encoding/base64" + "encoding/json" "fmt" "path/filepath" "strings" @@ -35,7 +36,6 @@ var _ = Describe("operator-sdk", func() { Context("built with operator-sdk", func() { BeforeEach(func() { metricsClusterRoleBindingName = fmt.Sprintf("%s-metrics-reader", tc.ProjectName) - reconcileCount++ By("deploying project on the cluster") err := tc.Make("deploy", "IMG="+tc.ImageName) Expect(err).NotTo(HaveOccurred()) @@ -91,7 +91,7 @@ var _ = Describe("operator-sdk", func() { true, "pods", controllerPodName, "-o", "jsonpath={.status.phase}") if err != nil { - return fmt.Errorf("failed to get pod stauts for %q: %v", controllerPodName, err) + return fmt.Errorf("failed to get pod status for %q: %v", controllerPodName, err) } if status != "Running" { return fmt.Errorf("controller pod in %s status", status) @@ -177,11 +177,14 @@ var _ = Describe("operator-sdk", func() { } Eventually(getCurlLogs, time.Minute, time.Second).Should(ContainSubstring("< HTTP/2 200")) + // The controller updates memcacheds' status.nodes with a list of pods it is replicated across + // on a successful reconcile. By("validating that the created resource object gets reconciled in the controller") - Expect(metricsOutput).To(ContainSubstring(fmt.Sprintf( - `controller_runtime_reconcile_total{controller="%s",result="success"} %d`, - strings.ToLower(tc.Kind), reconcileCount, - ))) + status, err := tc.Kubectl.Get(true, "memcacheds", "memcached-sample", "-o", "jsonpath={.status.nodes}") + Expect(err).NotTo(HaveOccurred()) + var nodes []string + Expect(json.Unmarshal([]byte(status), &nodes)).To(Succeed()) + Expect(len(nodes)).To(BeNumerically(">", 0)) }) }) }) diff --git a/test/e2e-go/e2e_go_olm_test.go b/test/e2e-go/e2e_go_olm_test.go index 2111314e985..ff23faa08b5 100644 --- a/test/e2e-go/e2e_go_olm_test.go +++ b/test/e2e-go/e2e_go_olm_test.go @@ -30,7 +30,6 @@ var _ = Describe("Integrating Go Projects with OLM", func() { // the pkg manifest after we comment cert-manager options into the kustomization file. // More info: https://olm.operatorframework.io/docs/advanced-tasks/adding-admission-and-conversion-webhooks/#certificate-authority-requirements BeforeEach(func() { - reconcileCount++ By("commenting cert-manager") err := testutils.ReplaceInFile( filepath.Join(tc.Dir, "config", "default", "kustomization.yaml"), diff --git a/test/e2e-go/e2e_go_scorecard_test.go b/test/e2e-go/e2e_go_scorecard_test.go index 4ed48a60217..f028c6f12e2 100644 --- a/test/e2e-go/e2e_go_scorecard_test.go +++ b/test/e2e-go/e2e_go_scorecard_test.go @@ -26,7 +26,6 @@ import ( var _ = Describe("Testing Go Projects with Scorecard", func() { Context("with operator-sdk", func() { - reconcileCount++ const ( OLMBundleValidationTest = "olm-bundle-validation" OLMCRDsHaveValidationTest = "olm-crds-have-validation" diff --git a/test/e2e-go/e2e_go_suite_test.go b/test/e2e-go/e2e_go_suite_test.go index 4e5ea1955b9..b3b2831250f 100644 --- a/test/e2e-go/e2e_go_suite_test.go +++ b/test/e2e-go/e2e_go_suite_test.go @@ -35,8 +35,7 @@ func TestE2EGo(t *testing.T) { } var ( - tc testutils.TestContext - reconcileCount = 0 + tc testutils.TestContext ) // BeforeSuite run before any specs are run to perform the required actions for all e2e Go tests. From 159827a6854721426b9c5a36bc1852a4a64afb1c Mon Sep 17 00:00:00 2001 From: Amarnath Valluri Date: Fri, 11 Dec 2020 01:02:39 +0200 Subject: [PATCH 238/376] OLM client: Wait till the deployment appear (#4298) Sometimes OLM installation fails with below error: ``` INFO[0028] Waiting for deployment/packageserver rollout to complete FATA[0028] Failed to install OLM version "latest": deployment/packageserver failed to rollout: deployments.apps "packageserver" not found ``` The reason might be that the deployment object we are waiting for is not yet registered with the API server. So, do not treat this as an error and continue the polling. FIXES: 4293 Signed-off-by: reinvantveer --- internal/olm/client/client.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/internal/olm/client/client.go b/internal/olm/client/client.go index acacb683648..8cfcb443bd0 100644 --- a/internal/olm/client/client.go +++ b/internal/olm/client/client.go @@ -159,6 +159,7 @@ func getName(namespace, name string) string { } func (c Client) DoRolloutWait(ctx context.Context, key types.NamespacedName) error { + onceNotFound := sync.Once{} onceReplicasUpdated := sync.Once{} oncePendingTermination := sync.Once{} onceNotAvailable := sync.Once{} @@ -168,6 +169,12 @@ func (c Client) DoRolloutWait(ctx context.Context, key types.NamespacedName) err deployment := appsv1.Deployment{} err := c.KubeClient.Get(ctx, key, &deployment) if err != nil { + if apierrors.IsNotFound(err) { + onceNotFound.Do(func() { + log.Printf(" Waiting for Deployment %q to appear", key) + }) + return false, nil + } return false, err } if deployment.Generation <= deployment.Status.ObservedGeneration { From 295ffc3bdcd1c8b087e7d15384ff45304c492b09 Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Thu, 10 Dec 2020 15:40:23 -0800 Subject: [PATCH 239/376] e2e/integration: fix flaky OLM integration test (#4301) - Makefile: remove atypical KUBECONFIG - internal/olm/operator/uninstall.go: set CatalogSource GVK before deleting - test/integration/operator_olm_test.go: ensure cleanup after each run Signed-off-by: reinvantveer --- Makefile | 1 - internal/olm/operator/uninstall.go | 2 +- test/integration/operator_olm_test.go | 41 +++++++++++++++------------ 3 files changed, 24 insertions(+), 20 deletions(-) diff --git a/Makefile b/Makefile index 81d3a37805a..5cc1f13b515 100644 --- a/Makefile +++ b/Makefile @@ -141,7 +141,6 @@ e2e_targets := test-e2e $(e2e_tests) .PHONY: test-e2e-setup export KIND_CLUSTER := operator-sdk-e2e -export KUBECONFIG := $(HOME)/.kube/kind-$(KIND_CLUSTER).config export KUBEBUILDER_ASSETS := $(PWD)/$(TOOLS_DIR) test-e2e-setup: build $(SCRIPTS_DIR)/fetch kind 0.9.0 diff --git a/internal/olm/operator/uninstall.go b/internal/olm/operator/uninstall.go index cd21d17ba58..93f1cb66b47 100644 --- a/internal/olm/operator/uninstall.go +++ b/internal/olm/operator/uninstall.go @@ -83,7 +83,6 @@ func (u *Uninstall) Run(ctx context.Context) error { } catsrc := &v1alpha1.CatalogSource{} - catsrc.SetGroupVersionKind(v1alpha1.SchemeGroupVersion.WithKind(v1alpha1.CatalogSourceKind)) if sub != nil { catsrcKey := types.NamespacedName{ Namespace: sub.Spec.CatalogSourceNamespace, @@ -129,6 +128,7 @@ func (u *Uninstall) Run(ctx context.Context) error { // Delete the catalog source. This assumes that all underlying resources related // to this catalog source have an owner reference to this catalog source so that // they are automatically garbage-collected. + catsrc.SetGroupVersionKind(v1alpha1.SchemeGroupVersion.WithKind(v1alpha1.CatalogSourceKind)) if err := u.deleteObjects(ctx, true, catsrc); err != nil { return err } diff --git a/test/integration/operator_olm_test.go b/test/integration/operator_olm_test.go index ec8a55532d6..64385635d2b 100644 --- a/test/integration/operator_olm_test.go +++ b/test/integration/operator_olm_test.go @@ -33,7 +33,6 @@ import ( "github.com/operator-framework/operator-sdk/internal/olm/operator" "github.com/operator-framework/operator-sdk/internal/olm/operator/packagemanifests" - "github.com/operator-framework/operator-sdk/internal/util/k8sutil" ) const ( @@ -43,10 +42,6 @@ const ( defaultOperatorVersion = "0.0.2" ) -var ( - kubeconfigPath = os.Getenv(k8sutil.KubeConfigEnvVar) -) - // TODO(estroz): rewrite these in the style of e2e tests (ginkgo/gomega + scaffold a project for each scenario). func TestOLMIntegration(t *testing.T) { @@ -101,7 +96,7 @@ func PackageManifestsOwnNamespace(t *testing.T) { t.Fatal(err) } - cfg := &operator.Configuration{KubeconfigPath: kubeconfigPath} + cfg := &operator.Configuration{} assert.NoError(t, cfg.Load()) i := packagemanifests.NewInstall(cfg) i.PackageManifestsDirectory = manifestsDir @@ -113,8 +108,8 @@ func PackageManifestsOwnNamespace(t *testing.T) { // Cleanup. defer func() { - if err := doUninstall(t, kubeconfigPath); err != nil { - t.Fatal(err) + if err := doUninstall(cfg); err != nil { + t.Log(err) } }() @@ -163,14 +158,21 @@ func PackageManifestsBasic(t *testing.T) { os.RemoveAll(tmp) t.Fatal(err) } - cfg := &operator.Configuration{KubeconfigPath: kubeconfigPath} + cfg := &operator.Configuration{} assert.NoError(t, cfg.Load()) i := packagemanifests.NewInstall(cfg) i.PackageManifestsDirectory = manifestsDir i.Version = defaultOperatorVersion + // Cleanup. + defer func() { + if err := doUninstall(cfg); err != nil { + t.Log(err) + } + }() + // Remove operator before deploy - assert.Error(t, doUninstall(t, kubeconfigPath)) + assert.Error(t, doUninstall(cfg)) // Deploy operator assert.NoError(t, doInstall(i)) @@ -178,9 +180,9 @@ func PackageManifestsBasic(t *testing.T) { assert.Error(t, doInstall(i)) // Remove operator after deploy - assert.NoError(t, doUninstall(t, kubeconfigPath)) + assert.NoError(t, doUninstall(cfg)) // Remove operator after removal - assert.Error(t, doUninstall(t, kubeconfigPath)) + assert.Error(t, doUninstall(cfg)) } func PackageManifestsMultiplePackages(t *testing.T) { @@ -255,21 +257,24 @@ func PackageManifestsMultiplePackages(t *testing.T) { os.RemoveAll(tmp) t.Fatal(err) } - cfg := &operator.Configuration{KubeconfigPath: kubeconfigPath} + cfg := &operator.Configuration{} assert.NoError(t, cfg.Load()) i := packagemanifests.NewInstall(cfg) i.PackageManifestsDirectory = manifestsDir i.Version = operatorVersion2 + // Cleanup. + defer func() { + if err := doUninstall(cfg); err != nil { + t.Log(err) + } + }() + // Deploy operator assert.NoError(t, doInstall(i)) - // Remove operator after deploy - assert.NoError(t, doUninstall(t, kubeconfigPath)) } -func doUninstall(t *testing.T, kubeconfigPath string) error { - cfg := &operator.Configuration{KubeconfigPath: kubeconfigPath} - assert.NoError(t, cfg.Load()) +func doUninstall(cfg *operator.Configuration) error { uninstall := operator.NewUninstall(cfg) uninstall.DeleteAll = true uninstall.DeleteOperatorGroupNames = []string{operator.SDKOperatorGroupName} From c5abed0ebc1c8b723674d46b88d2a75699daefbd Mon Sep 17 00:00:00 2001 From: Rashmi Gottipati Date: Thu, 10 Dec 2020 19:38:35 -0500 Subject: [PATCH 240/376] Implement run bundle upgrade feature using OLM (#4271) * run bundle-upgrade subcommand for testing operator upgrades * created a new registry pod with the new bundle image and a different pod name * updated existing catalog source with address field and annotations * refactoring to include correct bundle images in the registry pod * cleanup of the previously created registry pod * CLI for run bundle-upgrade subcommand Co-authored-by: Eric Stroczynski Signed-off-by: reinvantveer --- changelog/fragments/run-bundle-upgrade.yaml | 4 + .../cmd/operator-sdk/run/bundleupgrade/cmd.go | 57 ++++ internal/cmd/operator-sdk/run/cmd.go | 2 + internal/cmd/operator-sdk/run/cmd_test.go | 5 +- internal/olm/operator/bundle/install.go | 54 +--- .../olm/operator/bundleupgrade/upgrade.go | 81 ++++++ internal/olm/operator/helpers.go | 35 +++ internal/olm/operator/registry/catalog.go | 4 + .../operator/registry/index/registry_pod.go | 130 +++++---- .../registry/index/registry_pod_test.go | 133 ++++----- internal/olm/operator/registry/index_image.go | 252 +++++++++++++----- .../operator/registry/operator_installer.go | 74 +++++ .../content/en/docs/cli/operator-sdk_run.md | 1 + .../cli/operator-sdk_run_bundle-upgrade.md | 34 +++ 14 files changed, 609 insertions(+), 257 deletions(-) create mode 100644 changelog/fragments/run-bundle-upgrade.yaml create mode 100644 internal/cmd/operator-sdk/run/bundleupgrade/cmd.go create mode 100644 internal/olm/operator/bundleupgrade/upgrade.go create mode 100644 website/content/en/docs/cli/operator-sdk_run_bundle-upgrade.md diff --git a/changelog/fragments/run-bundle-upgrade.yaml b/changelog/fragments/run-bundle-upgrade.yaml new file mode 100644 index 00000000000..35e42a656d9 --- /dev/null +++ b/changelog/fragments/run-bundle-upgrade.yaml @@ -0,0 +1,4 @@ +entries: + - description: > + Added the `run bundle-upgrade` subcommand to automate testing upgrades of an operator from one version to another using OLM. + kind: addition diff --git a/internal/cmd/operator-sdk/run/bundleupgrade/cmd.go b/internal/cmd/operator-sdk/run/bundleupgrade/cmd.go new file mode 100644 index 00000000000..497eb5ff0aa --- /dev/null +++ b/internal/cmd/operator-sdk/run/bundleupgrade/cmd.go @@ -0,0 +1,57 @@ +// Copyright 2020 The Operator-SDK 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. + +package bundleupgrade + +import ( + "context" + "time" + + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + + "github.com/operator-framework/operator-sdk/internal/olm/operator" + "github.com/operator-framework/operator-sdk/internal/olm/operator/bundleupgrade" +) + +func NewCmd(cfg *operator.Configuration) *cobra.Command { + var timeout time.Duration + + u := bundleupgrade.NewUpgrade(cfg) + cmd := &cobra.Command{ + Use: "bundle-upgrade ", + Short: "Upgrade an Operator previously installed in the bundle format with OLM", + Args: cobra.ExactArgs(1), + PersistentPreRunE: func(_ *cobra.Command, _ []string) error { + return cfg.Load() + }, + Run: func(cmd *cobra.Command, args []string) { + ctx, cancel := context.WithTimeout(cmd.Context(), timeout) + defer cancel() + + u.BundleImage = args[0] + + _, err := u.Run(ctx) + if err != nil { + logrus.Fatalf("Failed to run bundle upgrade: %v\n", err) + } + }, + } + cmd.Flags().SortFlags = false + cfg.BindFlags(cmd.PersistentFlags()) + u.BindFlags(cmd.Flags()) + + cmd.Flags().DurationVar(&timeout, "timeout", 2*time.Minute, "upgrade timeout") + return cmd +} diff --git a/internal/cmd/operator-sdk/run/cmd.go b/internal/cmd/operator-sdk/run/cmd.go index 17aecfb236b..5f46845aac1 100644 --- a/internal/cmd/operator-sdk/run/cmd.go +++ b/internal/cmd/operator-sdk/run/cmd.go @@ -18,6 +18,7 @@ import ( "github.com/spf13/cobra" "github.com/operator-framework/operator-sdk/internal/cmd/operator-sdk/run/bundle" + "github.com/operator-framework/operator-sdk/internal/cmd/operator-sdk/run/bundleupgrade" "github.com/operator-framework/operator-sdk/internal/cmd/operator-sdk/run/packagemanifests" "github.com/operator-framework/operator-sdk/internal/olm/operator" ) @@ -33,6 +34,7 @@ func NewCmd() *cobra.Command { cmd.AddCommand( bundle.NewCmd(cfg), + bundleupgrade.NewCmd(cfg), packagemanifests.NewCmd(cfg), ) diff --git a/internal/cmd/operator-sdk/run/cmd_test.go b/internal/cmd/operator-sdk/run/cmd_test.go index ea4d80cc86b..02194836391 100644 --- a/internal/cmd/operator-sdk/run/cmd_test.go +++ b/internal/cmd/operator-sdk/run/cmd_test.go @@ -29,9 +29,10 @@ var _ = Describe("Running a run command", func() { Expect(cmd.Long).NotTo(BeNil()) subcommands := cmd.Commands() - Expect(len(subcommands)).To(Equal(2)) + Expect(len(subcommands)).To(Equal(3)) Expect(subcommands[0].Use).To(Equal("bundle ")) - Expect(subcommands[1].Use).To(Equal("packagemanifests [packagemanifests-root-dir]")) + Expect(subcommands[1].Use).To(Equal("bundle-upgrade ")) + Expect(subcommands[2].Use).To(Equal("packagemanifests [packagemanifests-root-dir]")) }) }) }) diff --git a/internal/olm/operator/bundle/install.go b/internal/olm/operator/bundle/install.go index ad94c2e81d9..fa293c25b54 100644 --- a/internal/olm/operator/bundle/install.go +++ b/internal/olm/operator/bundle/install.go @@ -16,19 +16,15 @@ package bundle import ( "context" - "fmt" - "os" - "path/filepath" "strings" - apimanifests "github.com/operator-framework/api/pkg/manifests" "github.com/operator-framework/api/pkg/operators/v1alpha1" registrybundle "github.com/operator-framework/operator-registry/pkg/lib/bundle" "github.com/spf13/pflag" "github.com/operator-framework/operator-sdk/internal/olm/operator" "github.com/operator-framework/operator-sdk/internal/olm/operator/registry" - registryutil "github.com/operator-framework/operator-sdk/internal/registry" + "github.com/operator-framework/operator-sdk/internal/olm/operator/registry/index" ) type Install struct { @@ -50,12 +46,10 @@ func NewInstall(cfg *operator.Configuration) Install { return i } -const defaultIndexImage = "quay.io/operator-framework/upstream-opm-builder:latest" - func (i *Install) BindFlags(fs *pflag.FlagSet) { - fs.StringVar(&i.IndexImage, "index-image", defaultIndexImage, "index image in which to inject bundle") + fs.StringVar(&i.IndexImage, "index-image", index.DefaultIndexImage, "index image in which to inject bundle") fs.Var(&i.InstallMode, "install-mode", "install mode") - fs.StringVar(&i.InjectBundleMode, "mode", "", "mode to use for adding bundle to index") + fs.StringVar(&i.BundleAddMode, "mode", "", "mode to use for adding bundle to index") _ = fs.MarkHidden("mode") } @@ -67,10 +61,11 @@ func (i Install) Run(ctx context.Context) (*v1alpha1.ClusterServiceVersion, erro } func (i *Install) setup(ctx context.Context) error { - labels, csv, err := loadBundle(ctx, i.BundleImage) + labels, bundle, err := operator.LoadBundle(ctx, i.BundleImage) if err != nil { return err } + csv := bundle.CSV if err := i.InstallMode.CheckCompatibility(csv, i.cfg.Namespace); err != nil { return err @@ -81,40 +76,15 @@ func (i *Install) setup(ctx context.Context) error { i.OperatorInstaller.StartingCSV = csv.Name i.OperatorInstaller.SupportedInstallModes = operator.GetSupportedInstallModes(csv.Spec.InstallModes) i.OperatorInstaller.Channel = strings.Split(labels[registrybundle.ChannelsLabel], ",")[0] - i.IndexImageCatalogCreator.BundleImage = i.BundleImage + i.IndexImageCatalogCreator.PackageName = i.OperatorInstaller.PackageName - i.IndexImageCatalogCreator.InjectBundles = []string{i.BundleImage} - i.IndexImageCatalogCreator.InjectBundleMode = "replaces" - if i.IndexImageCatalogCreator.IndexImage == defaultIndexImage { - i.IndexImageCatalogCreator.InjectBundleMode = "semver" + i.IndexImageCatalogCreator.BundleImage = i.BundleImage + if i.IndexImageCatalogCreator.BundleAddMode == "" { + i.IndexImageCatalogCreator.BundleAddMode = index.ReplacesBundleAddMode + if i.IndexImageCatalogCreator.IndexImage == index.DefaultIndexImage { + i.IndexImageCatalogCreator.BundleAddMode = index.SemverBundleAddMode + } } return nil } - -func loadBundle(ctx context.Context, bundleImage string) (registryutil.Labels, *v1alpha1.ClusterServiceVersion, error) { - bundlePath, err := registryutil.ExtractBundleImage(ctx, nil, bundleImage, false) - if err != nil { - return nil, nil, fmt.Errorf("pull bundle image: %v", err) - } - defer func() { - _ = os.RemoveAll(bundlePath) - }() - - labels, _, err := registryutil.FindBundleMetadata(bundlePath) - if err != nil { - return nil, nil, fmt.Errorf("load bundle metadata: %v", err) - } - - relManifestsDir, ok := labels.GetManifestsDir() - if !ok { - return nil, nil, fmt.Errorf("manifests directory not defined in bundle metadata") - } - manifestsDir := filepath.Join(bundlePath, relManifestsDir) - bundle, err := apimanifests.GetBundleFromDir(manifestsDir) - if err != nil { - return nil, nil, fmt.Errorf("load bundle: %v", err) - } - - return labels, bundle.CSV, nil -} diff --git a/internal/olm/operator/bundleupgrade/upgrade.go b/internal/olm/operator/bundleupgrade/upgrade.go new file mode 100644 index 00000000000..e0b8e3ed8e8 --- /dev/null +++ b/internal/olm/operator/bundleupgrade/upgrade.go @@ -0,0 +1,81 @@ +// Copyright 2020 The Operator-SDK 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. + +package bundleupgrade + +import ( + "context" + "strings" + + "github.com/operator-framework/api/pkg/operators/v1alpha1" + registrybundle "github.com/operator-framework/operator-registry/pkg/lib/bundle" + "github.com/spf13/pflag" + + "github.com/operator-framework/operator-sdk/internal/olm/operator" + "github.com/operator-framework/operator-sdk/internal/olm/operator/registry" + "github.com/operator-framework/operator-sdk/internal/olm/operator/registry/index" +) + +type Upgrade struct { + BundleImage string + + *registry.IndexImageCatalogCreator + *registry.OperatorInstaller + + cfg *operator.Configuration +} + +func NewUpgrade(cfg *operator.Configuration) Upgrade { + u := Upgrade{ + OperatorInstaller: registry.NewOperatorInstaller(cfg), + cfg: cfg, + } + u.IndexImageCatalogCreator = registry.NewIndexImageCatalogCreator(cfg) + u.CatalogUpdater = u.IndexImageCatalogCreator + return u +} + +func (u *Upgrade) BindFlags(fs *pflag.FlagSet) { + fs.StringVar(&u.BundleAddMode, "mode", "", "mode to use for adding new bundle version to index") + _ = fs.MarkHidden("mode") +} + +func (u Upgrade) Run(ctx context.Context) (*v1alpha1.ClusterServiceVersion, error) { + if err := u.setup(ctx); err != nil { + return nil, err + } + return u.UpgradeOperator(ctx) +} + +func (u *Upgrade) setup(ctx context.Context) error { + labels, bundle, err := operator.LoadBundle(ctx, u.BundleImage) + if err != nil { + return err + } + csv := bundle.CSV + + u.OperatorInstaller.PackageName = labels[registrybundle.PackageLabel] + u.OperatorInstaller.CatalogSourceName = operator.CatalogNameForPackage(u.OperatorInstaller.PackageName) + u.OperatorInstaller.StartingCSV = csv.Name + u.OperatorInstaller.SupportedInstallModes = operator.GetSupportedInstallModes(csv.Spec.InstallModes) + u.OperatorInstaller.Channel = strings.Split(labels[registrybundle.ChannelsLabel], ",")[0] + + // Since an existing CatalogSource will have an annotation containing the existing index image, + // defer defaulting the bundle add mode to after the existing CatalogSource is retrieved. + u.IndexImageCatalogCreator.PackageName = u.OperatorInstaller.PackageName + u.IndexImageCatalogCreator.BundleImage = u.BundleImage + u.IndexImageCatalogCreator.IndexImage = index.DefaultIndexImage + + return nil +} diff --git a/internal/olm/operator/helpers.go b/internal/olm/operator/helpers.go index 898f456fa3e..b5b6900c314 100644 --- a/internal/olm/operator/helpers.go +++ b/internal/olm/operator/helpers.go @@ -15,7 +15,14 @@ package operator import ( + "context" "fmt" + "os" + "path/filepath" + + apimanifests "github.com/operator-framework/api/pkg/manifests" + + registryutil "github.com/operator-framework/operator-sdk/internal/registry" ) const ( @@ -25,3 +32,31 @@ const ( func CatalogNameForPackage(pkg string) string { return fmt.Sprintf("%s-catalog", pkg) } + +// LoadBundle returns metadata and manifests from within bundleImage. +func LoadBundle(ctx context.Context, bundleImage string) (registryutil.Labels, *apimanifests.Bundle, error) { + bundlePath, err := registryutil.ExtractBundleImage(ctx, nil, bundleImage, false) + if err != nil { + return nil, nil, fmt.Errorf("pull bundle image: %v", err) + } + defer func() { + _ = os.RemoveAll(bundlePath) + }() + + labels, _, err := registryutil.FindBundleMetadata(bundlePath) + if err != nil { + return nil, nil, fmt.Errorf("load bundle metadata: %v", err) + } + + relManifestsDir, ok := labels.GetManifestsDir() + if !ok { + return nil, nil, fmt.Errorf("manifests directory not defined in bundle metadata") + } + manifestsDir := filepath.Join(bundlePath, relManifestsDir) + bundle, err := apimanifests.GetBundleFromDir(manifestsDir) + if err != nil { + return nil, nil, fmt.Errorf("load bundle: %v", err) + } + + return labels, bundle, nil +} diff --git a/internal/olm/operator/registry/catalog.go b/internal/olm/operator/registry/catalog.go index c12d4b5b3c7..1963ea1c16e 100644 --- a/internal/olm/operator/registry/catalog.go +++ b/internal/olm/operator/registry/catalog.go @@ -23,3 +23,7 @@ import ( type CatalogCreator interface { CreateCatalog(ctx context.Context, name string) (*v1alpha1.CatalogSource, error) } + +type CatalogUpdater interface { + UpdateCatalog(ctx context.Context, cs *v1alpha1.CatalogSource) error +} diff --git a/internal/olm/operator/registry/index/registry_pod.go b/internal/olm/operator/registry/index/registry_pod.go index 5ea9d018850..33f686455e2 100644 --- a/internal/olm/operator/registry/index/registry_pod.go +++ b/internal/olm/operator/registry/index/registry_pod.go @@ -20,7 +20,6 @@ import ( "errors" "fmt" "path" - "strings" "text/template" "time" @@ -36,36 +35,39 @@ import ( "github.com/operator-framework/operator-sdk/internal/util/k8sutil" ) -// BundleAddModeType - type of BundleAddMode in RegistryPod struct -type BundleAddModeType = string +// BundleAddMode - type of BundleAddMode in RegistryPod struct +type BundleAddMode = string const ( // SemverBundleAddMode - bundle add mode for semver - SemverBundleAddMode BundleAddModeType = "semver" + SemverBundleAddMode BundleAddMode = "semver" // ReplacesBundleAddMode - bundle add mode for replaces - ReplacesBundleAddMode BundleAddModeType = "replaces" + ReplacesBundleAddMode BundleAddMode = "replaces" ) const ( + // DefaultIndexImage is the index base image used if none is specified. It contains no bundles. + DefaultIndexImage = "quay.io/operator-framework/upstream-opm-builder:latest" + // defaultGRPCPort is the default grpc container port that the registry pod exposes - defaultGRPCPort = 50051 - defaultIndexImage = "quay.io/operator-framework/upstream-opm-builder:latest" + defaultGRPCPort = 50051 + defaultDBPath = "/database/index.db" + defaultContainerName = "registry-grpc" defaultContainerPortName = "grpc" ) -var ( - // Internal error - errPodNotInit = errors.New("internal error: RegistryPod not initialized") -) +// BundleItem contains the metadata of a bundle image relevant to the registry pod. +type BundleItem struct { + // ImageTag is the bundle image's tag. + ImageTag string `json:"imageTag"` + // AddMode describes how the bundle should be added to an index image. + AddMode BundleAddMode `json:"mode"` +} // RegistryPod holds resources necessary for creation of a registry server type RegistryPod struct { - // BundleAddMode specifies the graph update mode that defines how channel graphs are updated - // It is of the type BundleAddModeType - BundleAddMode BundleAddModeType - - // BundleImage specifies the container image that opm uses to generate and incrementally update the database - BundleImage string + // BundleItems contains all bundles to be added to a registry pod. + BundleItems []BundleItem // Index image contains a database of pointers to operator manifest content that is queriable via an API. // new version of an operator bundle when published can be added to an index image @@ -84,51 +86,40 @@ type RegistryPod struct { cfg *operator.Configuration } -// NewRegistryPod initializes the RegistryPod struct and sets defaults for empty fields -func NewRegistryPod(cfg *operator.Configuration, dbPath, bundleImage string) (*RegistryPod, error) { - rp := &RegistryPod{} - +// init initializes the RegistryPod struct and sets defaults for empty fields +func (rp *RegistryPod) init(cfg *operator.Configuration) error { if rp.GRPCPort == 0 { rp.GRPCPort = defaultGRPCPort } - - if len(strings.TrimSpace(rp.IndexImage)) < 1 { - rp.IndexImage = defaultIndexImage + if rp.DBPath == "" { + rp.DBPath = defaultDBPath } - - if len(strings.TrimSpace(rp.BundleAddMode)) < 1 { - if rp.IndexImage == defaultIndexImage { - rp.BundleAddMode = SemverBundleAddMode - } else { - rp.BundleAddMode = ReplacesBundleAddMode - } + if rp.IndexImage == "" { + rp.IndexImage = DefaultIndexImage } - rp.cfg = cfg - rp.DBPath = dbPath - rp.BundleImage = bundleImage // validate the RegistryPod struct and ensure required fields are set if err := rp.validate(); err != nil { - return nil, fmt.Errorf("error validating registry pod struct: %v", err) + return fmt.Errorf("invalid registry pod: %v", err) } // podForBundleRegistry() to make the pod definition pod, err := rp.podForBundleRegistry() if err != nil { - return nil, fmt.Errorf("error building registry pod definition: %v", err) + return fmt.Errorf("error building registry pod definition: %v", err) } rp.pod = pod - return rp, nil + return nil } // Create creates a bundle registry pod built from an index image, // sets the catalog source as the owner for the pod and verifies that // the pod is running -func (rp *RegistryPod) Create(ctx context.Context, cs *v1alpha1.CatalogSource) (*corev1.Pod, error) { - if rp.pod == nil { - return nil, errPodNotInit +func (rp *RegistryPod) Create(ctx context.Context, cfg *operator.Configuration, cs *v1alpha1.CatalogSource) (*corev1.Pod, error) { + if err := rp.init(cfg); err != nil { + return nil, err } // make catalog source the owner of registry pod object @@ -143,7 +134,7 @@ func (rp *RegistryPod) Create(ctx context.Context, cs *v1alpha1.CatalogSource) ( // get registry pod key podKey := types.NamespacedName{ Namespace: rp.cfg.Namespace, - Name: getPodName(rp.BundleImage), + Name: rp.pod.GetName(), } // poll and verify that pod is running @@ -177,20 +168,20 @@ func (rp *RegistryPod) checkPodStatus(ctx context.Context, podCheck wait.Conditi // validate will ensure that RegistryPod required fields are set // and throws error if not set func (rp *RegistryPod) validate() error { - if len(strings.TrimSpace(rp.BundleImage)) < 1 { - return errors.New("bundle image cannot be empty") - } - if len(strings.TrimSpace(rp.DBPath)) < 1 { - return errors.New("registry database path cannot be empty") + if len(rp.BundleItems) == 0 { + return errors.New("bundle image set cannot be empty") } - - if len(strings.TrimSpace(rp.BundleAddMode)) < 1 { - return errors.New("bundle add mode cannot be empty") - } - - if rp.BundleAddMode != SemverBundleAddMode && rp.BundleAddMode != ReplacesBundleAddMode { - return fmt.Errorf("invalid bundle mode %q: must be one of [%q, %q]", - rp.BundleAddMode, ReplacesBundleAddMode, SemverBundleAddMode) + for _, item := range rp.BundleItems { + if item.ImageTag == "" { + return errors.New("bundle image cannot be empty") + } + if item.AddMode == "" { + return fmt.Errorf("bundle add mode for %q cannot be empty", item.ImageTag) + } + if item.AddMode != SemverBundleAddMode && item.AddMode != ReplacesBundleAddMode { + return fmt.Errorf("invalid bundle mode %q: must be one of [%q, %q]", + item.AddMode, ReplacesBundleAddMode, SemverBundleAddMode) + } } return nil @@ -210,16 +201,19 @@ func getPodName(bundleImage string) string { // podForBundleRegistry constructs and returns the registry pod definition // and throws error when unable to build the pod definition successfully func (rp *RegistryPod) podForBundleRegistry() (*corev1.Pod, error) { + // rp was already validated so len(rp.BundleItems) must be greater than 0. + bundleImage := rp.BundleItems[len(rp.BundleItems)-1].ImageTag + // construct the container command for pod spec containerCmd, err := rp.getContainerCmd() if err != nil { - return nil, fmt.Errorf("error parsing container command: %v", err) + return nil, err } // make the pod definition rp.pod = &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ - Name: getPodName(rp.BundleImage), + Name: getPodName(bundleImage), Namespace: rp.cfg.Namespace, }, Spec: corev1.PodSpec{ @@ -243,21 +237,16 @@ func (rp *RegistryPod) podForBundleRegistry() (*corev1.Pod, error) { return rp.pod, nil } +const containerCommand = `/bin/mkdir -p {{ .DBPath | dirname }} && \ +{{- range $i, $item := .BundleItems }} +/bin/opm registry add -d {{ $.DBPath }} -b {{ $item.ImageTag }} --mode={{ $item.AddMode }} && \ +{{- end }} +/bin/opm registry serve -d {{ .DBPath }} -p {{ .GRPCPort }} +` + // getContainerCmd uses templating to construct the container command // and throws error if unable to parse and execute the container command func (rp *RegistryPod) getContainerCmd() (string, error) { - const containerCommand = "/bin/mkdir -p {{ .DBPath | dirname }} &&" + - "/bin/opm registry add -d {{ .DBPath }} -b {{.BundleImage}} --mode={{.BundleAddMode}} &&" + - "/bin/opm registry serve -d {{ .DBPath }} -p {{.GRPCPort}}" - type bundleCmd struct { - BundleImage, DBPath, BundleAddMode string - GRPCPort int32 - } - - var command = bundleCmd{rp.BundleImage, rp.DBPath, - rp.BundleAddMode, rp.GRPCPort} - - out := &bytes.Buffer{} // create a custom dirname template function funcMap := template.FuncMap{ @@ -266,11 +255,12 @@ func (rp *RegistryPod) getContainerCmd() (string, error) { // add the custom dirname template function to the // template's FuncMap and parse the containerCommand - tmp := template.Must(template.New("containerCommand").Funcs(funcMap).Parse(containerCommand)) + tmp := template.Must(template.New("cmd").Funcs(funcMap).Parse(containerCommand)) // execute the command by applying the parsed tmp to command // and write command output to out - if err := tmp.Execute(out, command); err != nil { + out := &bytes.Buffer{} + if err := tmp.Execute(out, rp); err != nil { return "", fmt.Errorf("parse container command: %w", err) } diff --git a/internal/olm/operator/registry/index/registry_pod_test.go b/internal/olm/operator/registry/index/registry_pod_test.go index 149d7fb5c55..49ea305e5ea 100644 --- a/internal/olm/operator/registry/index/registry_pod_test.go +++ b/internal/olm/operator/registry/index/registry_pod_test.go @@ -17,17 +17,17 @@ package index import ( "context" "fmt" + "strings" "testing" "time" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - "github.com/operator-framework/api/pkg/operators/v1alpha1" - "github.com/operator-framework/operator-sdk/internal/olm/operator" "k8s.io/apimachinery/pkg/util/wait" - "sigs.k8s.io/controller-runtime/pkg/client" fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake" + + "github.com/operator-framework/operator-sdk/internal/olm/operator" ) // newFakeClient() returns a fake controller runtime client @@ -42,34 +42,30 @@ func TestCreateRegistryPod(t *testing.T) { var _ = Describe("RegistryPod", func() { + var defaultBundleItem = BundleItem{ + ImageTag: "quay.io/example/example-operator-bundle:0.2.0", + AddMode: SemverBundleAddMode, + } + Describe("creating registry pod", func() { Context("with valid registry pod values", func() { - expectedPodName := "quay-io-example-example-operator-bundle-0-2-0" - expectedOutput := "/bin/mkdir -p /database &&" + - "/bin/opm registry add -d /database/index.db -b quay.io/example/example-operator-bundle:0.2.0 --mode=semver &&" + - "/bin/opm registry serve -d /database/index.db -p 50051" var rp *RegistryPod var cfg *operator.Configuration - var err error BeforeEach(func() { cfg = &operator.Configuration{ Client: newFakeClient(), Namespace: "test-default", } - rp, err = NewRegistryPod(cfg, "/database/index.db", "quay.io/example/example-operator-bundle:0.2.0") - Expect(err).To(BeNil()) - }) - - It("should validate the RegistryPod successfully", func() { - err := rp.validate() - - Expect(err).To(BeNil()) + rp = &RegistryPod{BundleItems: []BundleItem{defaultBundleItem}} + By("initializing the RegistryPod") + Expect(rp.init(cfg)).To(Succeed()) }) It("should create the RegistryPod successfully", func() { + expectedPodName := "quay-io-example-example-operator-bundle-0-2-0" Expect(rp).NotTo(BeNil()) Expect(rp.pod.Name).To(Equal(expectedPodName)) Expect(rp.pod.Namespace).To(Equal(rp.cfg.Namespace)) @@ -81,25 +77,36 @@ var _ = Describe("RegistryPod", func() { } }) - It("should return a valid container command", func() { - output, err := rp.getContainerCmd() + It("should create a registry pod when database path is not provided", func() { + Expect(rp.DBPath).To(Equal("/database/index.db")) + }) + It("should return a valid container command for one image", func() { + output, err := rp.getContainerCmd() Expect(err).To(BeNil()) - Expect(output).Should(Equal(expectedOutput)) + Expect(output).Should(Equal(containerCommandFor(defaultDBPath, []BundleItem{defaultBundleItem}))) }) - It("should return a pod definition successfully", func() { - rp.pod, err = rp.podForBundleRegistry() - - Expect(rp.pod).NotTo(BeNil()) - Expect(rp.pod.Name).To(Equal(expectedPodName)) - Expect(rp.pod.Namespace).To(Equal(rp.cfg.Namespace)) - Expect(rp.pod.Spec.Containers[0].Name).To(Equal(defaultContainerName)) - if len(rp.pod.Spec.Containers) > 0 { - if len(rp.pod.Spec.Containers[0].Ports) > 0 { - Expect(rp.pod.Spec.Containers[0].Ports[0].ContainerPort).To(Equal(rp.GRPCPort)) - } + It("should return a valid container command for three images", func() { + bundleItems := []BundleItem{ + defaultBundleItem, + { + ImageTag: "quay.io/example/example-operator-bundle:0.3.0", + AddMode: ReplacesBundleAddMode, + }, + { + ImageTag: "quay.io/example/example-operator-bundle:1.0.1", + AddMode: SemverBundleAddMode, + }, + } + rp2 := RegistryPod{ + DBPath: defaultDBPath, + GRPCPort: defaultGRPCPort, + BundleItems: bundleItems, } + output, err := rp2.getContainerCmd() + Expect(err).To(BeNil()) + Expect(output).Should(Equal(containerCommandFor(defaultDBPath, bundleItems))) }) It("check pod status should return successfully when pod check is true", func() { @@ -123,51 +130,28 @@ var _ = Describe("RegistryPod", func() { }) It("should error when bundle image is not provided", func() { - expectedErr := "bundle image cannot be empty" - - _, err := NewRegistryPod(cfg, "/database/index.db", "") - - Expect(err).NotTo(BeNil()) - Expect(err.Error()).Should(ContainSubstring(expectedErr)) - }) - - It("should not create a registry pod when database path is not provided", func() { - expectedErr := "registry database path cannot be empty" - - _, err := NewRegistryPod(cfg, "", - "quay.io/example/example-operator-bundle:0.2.0") - - Expect(err).NotTo(BeNil()) - Expect(err.Error()).Should(ContainSubstring(expectedErr)) - }) - - It("should not create a registry pod when bundle add mode is empty", func() { - expectedErr := "bundle add mode cannot be empty" - - rp, _ := NewRegistryPod(cfg, "/database/index.db", - "quay.io/example/example-operator-bundle:0.2.0") - rp.BundleAddMode = "" - - err := rp.validate() + expectedErr := "bundle image set cannot be empty" + rp := &RegistryPod{} + err := rp.init(cfg) Expect(err).NotTo(BeNil()) Expect(err.Error()).Should(ContainSubstring(expectedErr)) }) It("should not accept any other bundle add mode other than semver or replaces", func() { expectedErr := "invalid bundle mode" - - rp, _ := NewRegistryPod(cfg, "/database/index.db", - "quay.io/example/example-operator-bundle:0.2.0") - rp.BundleAddMode = "invalid" - - err := rp.validate() + rp := &RegistryPod{ + BundleItems: []BundleItem{{ImageTag: "quay.io/example/example-operator-bundle:0.2.0", AddMode: "invalid"}}, + } + err := rp.init(cfg) Expect(err).NotTo(BeNil()) Expect(err.Error()).Should(ContainSubstring(expectedErr)) }) It("checkPodStatus should return error when pod check is false and context is done", func() { - rp, _ := NewRegistryPod(cfg, "/database/index.db", - "quay.io/example/example-operator-bundle:0.2.0") + rp := &RegistryPod{ + BundleItems: []BundleItem{defaultBundleItem}, + } + Expect(rp.init(cfg)).To(Succeed()) mockBadPodCheck := wait.ConditionFunc(func() (done bool, err error) { return false, fmt.Errorf("error waiting for registry pod") @@ -179,21 +163,18 @@ var _ = Describe("RegistryPod", func() { cancel() err := rp.checkPodStatus(ctx, mockBadPodCheck) - Expect(err).NotTo(BeNil()) Expect(err.Error()).Should(ContainSubstring(expectedErr)) }) - - It("Create should fail when registry pod is not initialized", func() { - rp := RegistryPod{} - cs := &v1alpha1.CatalogSource{} - pod, err := rp.Create(context.Background(), cs) - - Expect(err).NotTo(BeNil()) - Expect(pod).To(BeNil()) - Expect(err).To(MatchError(errPodNotInit)) - }) - }) }) }) + +// containerCommandFor returns the expected container command for a db path and set of bundle items. +func containerCommandFor(dbPath string, items []BundleItem) string { + additions := &strings.Builder{} + for _, item := range items { + additions.WriteString(fmt.Sprintf("/bin/opm registry add -d %s -b %s --mode=%s && \\\n", dbPath, item.ImageTag, item.AddMode)) + } + return fmt.Sprintf("/bin/mkdir -p /database && \\\n%s/bin/opm registry serve -d /database/index.db -p 50051\n", additions.String()) +} diff --git a/internal/olm/operator/registry/index_image.go b/internal/olm/operator/registry/index_image.go index 704afc83b0a..831821474fd 100644 --- a/internal/olm/operator/registry/index_image.go +++ b/internal/olm/operator/registry/index_image.go @@ -18,10 +18,14 @@ import ( "context" "encoding/json" "fmt" + "time" "github.com/operator-framework/api/pkg/operators/v1alpha1" + log "github.com/sirupsen/logrus" corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/util/retry" "github.com/operator-framework/operator-sdk/internal/olm/operator" @@ -29,16 +33,30 @@ import ( registryutil "github.com/operator-framework/operator-sdk/internal/registry" ) +// Internal CatalogSource annotations. +const ( + operatorFrameworkGroup = "operators.operatorframework.io" + + // Holds the base index image tag used to create a catalog. + indexImageAnnotation = operatorFrameworkGroup + "/index-image" + // Holds all bundle image and add mode pairs in the current catalog. + injectedBundlesAnnotation = operatorFrameworkGroup + "/injected-bundles" + // Holds the name of the existing registry pod associated with a catalog. + registryPodNameAnnotation = operatorFrameworkGroup + "/registry-pod-name" +) + type IndexImageCatalogCreator struct { - PackageName string - IndexImage string - InjectBundles []string - InjectBundleMode string - BundleImage string + PackageName string + IndexImage string + BundleImage string + BundleAddMode index.BundleAddMode cfg *operator.Configuration } +var _ CatalogCreator = &IndexImageCatalogCreator{} +var _ CatalogUpdater = &IndexImageCatalogCreator{} + func NewIndexImageCatalogCreator(cfg *operator.Configuration) *IndexImageCatalogCreator { return &IndexImageCatalogCreator{ cfg: cfg, @@ -46,11 +64,6 @@ func NewIndexImageCatalogCreator(cfg *operator.Configuration) *IndexImageCatalog } func (c IndexImageCatalogCreator) CreateCatalog(ctx context.Context, name string) (*v1alpha1.CatalogSource, error) { - dbPath, err := c.getDBPath(ctx) - if err != nil { - return nil, fmt.Errorf("get database path: %v", err) - } - // create a basic catalog source type cs := newCatalogSource(name, c.cfg.Namespace, withSDKPublisher(c.PackageName)) @@ -60,91 +73,196 @@ func (c IndexImageCatalogCreator) CreateCatalog(ctx context.Context, name string return nil, fmt.Errorf("error creating catalog source: %v", err) } - // create registry pod - pod, err := c.createRegistryPod(ctx, dbPath, cs) - if err != nil { + newItems := []index.BundleItem{{ImageTag: c.BundleImage, AddMode: c.BundleAddMode}} + if err := c.createAnnotatedRegistry(ctx, cs, newItems, updateFeildsNoOp); err != nil { return nil, fmt.Errorf("error creating registry pod: %v", err) } - // update catalog source with source type, address and annotations - if err := c.updateCatalogSource(ctx, pod.Status.PodIP, cs); err != nil { - return nil, fmt.Errorf("error updating catalog source: %v", err) - } - return cs, nil } -const defaultDBPath = "/database/index.db" - -func (c IndexImageCatalogCreator) getDBPath(ctx context.Context) (string, error) { - labels, err := registryutil.GetImageLabels(ctx, nil, c.IndexImage, false) - if err != nil { - return "", fmt.Errorf("get index image labels: %v", err) +// UpdateCatalog links a new registry pod in catalog source by updating the address and annotations, +// then deletes existing registry pod based on annotation name found in catalog source object +func (c IndexImageCatalogCreator) UpdateCatalog(ctx context.Context, cs *v1alpha1.CatalogSource) error { + var prevRegistryPodName string + if annotations := cs.GetAnnotations(); len(annotations) != 0 { + if value, hasAnnotation := annotations[indexImageAnnotation]; hasAnnotation && value != "" { + c.IndexImage = value + } + prevRegistryPodName = annotations[registryPodNameAnnotation] } - if dbPath, ok := labels["operators.operatorframework.io.index.database.v1"]; ok { - return dbPath, nil + // Default add mode here since it depends on an existing annotation. + if c.BundleAddMode == "" { + if c.IndexImage == index.DefaultIndexImage { + c.BundleAddMode = index.SemverBundleAddMode + } else { + c.BundleAddMode = index.ReplacesBundleAddMode + } } - return defaultDBPath, nil -} -func (c IndexImageCatalogCreator) createRegistryPod(ctx context.Context, dbPath string, cs *v1alpha1.CatalogSource) (*corev1.Pod, error) { - // Initialize registry pod - registryPod, err := index.NewRegistryPod(c.cfg, dbPath, c.BundleImage) + existingItems, err := getExistingBundleItems(cs.GetAnnotations()) if err != nil { - return nil, fmt.Errorf("error initializing registry pod: %v", err) + return fmt.Errorf("error getting existing bundles from CatalogSource %s annotations: %v", cs.GetName(), err) } + imageReferenceExists := len(existingItems) == 0 - var pod *corev1.Pod - // Create registry pod - if pod, err = registryPod.Create(ctx, cs); err != nil { - return nil, fmt.Errorf("error creating registry pod: %v", err) + newItem := index.BundleItem{ImageTag: c.BundleImage, AddMode: c.BundleAddMode} + existingItems = append(existingItems, newItem) + + updateFields := func(*v1alpha1.CatalogSource) { + // set `spec.Image` field to empty as we will be setting the address field in + // catalog source to point to the new new registry pod + if imageReferenceExists { + cs.Spec.Image = "" + } } + if err := c.createAnnotatedRegistry(ctx, cs, existingItems, updateFields); err != nil { + return fmt.Errorf("error creating registry pod: %v", err) + } + + log.Infof("Updated catalog source %s with address and annotations", cs.GetName()) - return pod, nil + if prevRegistryPodName != "" { + if err = c.deleteRegistryPod(ctx, prevRegistryPodName); err != nil { + return fmt.Errorf("error cleaning up previous registry pod: %v", err) + } + } + + return nil } -func (c IndexImageCatalogCreator) updateCatalogSource(ctx context.Context, podAddr string, cs *v1alpha1.CatalogSource) error { - // JSON marshal injected bundles - injectedBundlesJSON, err := json.Marshal(c.InjectBundles) +// createAnnotatedRegistry creates a registry pod and updates cs with annotations constructed +// from items and that pod, then applies updateFields. +func (c IndexImageCatalogCreator) createAnnotatedRegistry(ctx context.Context, cs *v1alpha1.CatalogSource, + items []index.BundleItem, updateFields func(*v1alpha1.CatalogSource)) (err error) { + + // Initialize and create registry pod + registryPod := index.RegistryPod{ + BundleItems: items, + IndexImage: c.IndexImage, + } + if registryPod.DBPath, err = c.getDBPath(ctx); err != nil { + return fmt.Errorf("get database path: %v", err) + } + pod, err := registryPod.Create(ctx, c.cfg, cs) if err != nil { - return fmt.Errorf("error marshaling injected bundles: %v", err) + return fmt.Errorf("error creating registry pod: %v", err) } - // Get catalog source key - catsrcKey := types.NamespacedName{ - Namespace: cs.GetNamespace(), - Name: cs.GetName(), + // JSON marshal injected bundles + injectedBundlesJSON, err := json.Marshal(items) + if err != nil { + return fmt.Errorf("error marshaling added bundles: %v", err) } - // Annotations for catalog source - annotationMapping := map[string]string{ - "operators.operatorframework.io/index-image": c.IndexImage, - "operators.operatorframework.io/inject-bundle-mode": c.InjectBundleMode, - "operators.operatorframework.io/injected-bundles": string(injectedBundlesJSON), + updatedAnnotations := map[string]string{ + indexImageAnnotation: c.IndexImage, + injectedBundlesAnnotation: string(injectedBundlesJSON), + registryPodNameAnnotation: pod.GetName(), } - // Update catalog source with source type as grpc and address as the pod IP, - // and annotations for index image, injected bundles, and registry bundle add mode + + // Update catalog source with source type as grpc, new registry pod address as the pod IP, + // and annotations from items and the pod. + key := types.NamespacedName{Namespace: cs.GetNamespace(), Name: cs.GetName()} if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error { - if err := c.cfg.Client.Get(ctx, catsrcKey, cs); err != nil { - return fmt.Errorf("error getting catalog source: %v", err) + if err := c.cfg.Client.Get(ctx, key, cs); err != nil { + return fmt.Errorf("error getting catalog source: %w", err) } - cs.Spec.Address = index.GetRegistryPodHost(podAddr) - cs.Spec.SourceType = v1alpha1.SourceTypeGrpc - annotations := cs.GetAnnotations() - if annotations == nil { - annotations = make(map[string]string, len(annotationMapping)) - } - for k, v := range annotationMapping { - annotations[k] = v - } - cs.SetAnnotations(annotations) - + updateCatalogSourceFields(cs, pod, updatedAnnotations) + updateFields(cs) if err := c.cfg.Client.Update(ctx, cs); err != nil { - return err + return fmt.Errorf("error updating catalog source: %w", err) } return nil }); err != nil { - return fmt.Errorf("error setting grpc source type and address for catalog source: %v", err) + return err + } + + return nil +} + +// Use if no extra updates need to be made to an annotated CatalogSource. +func updateFeildsNoOp(*v1alpha1.CatalogSource) {} + +// getDBPath returns the database path from the index image's labels. +func (c IndexImageCatalogCreator) getDBPath(ctx context.Context) (string, error) { + labels, err := registryutil.GetImageLabels(ctx, nil, c.IndexImage, false) + if err != nil { + return "", fmt.Errorf("get index image labels: %v", err) + } + return labels["operators.operatorframework.io.index.database.v1"], nil +} + +// updateCatalogSourceFields updates cs's spec to reference targetPod's IP address for a gRPC connection +// and overwrites all annotations with keys matching those in newAnnotations. +func updateCatalogSourceFields(cs *v1alpha1.CatalogSource, targetPod *corev1.Pod, newAnnotations map[string]string) { + // set `spec.Address` and `spec.SourceType` as grpc + cs.Spec.Address = index.GetRegistryPodHost(targetPod.Status.PodIP) + cs.Spec.SourceType = v1alpha1.SourceTypeGrpc + + // set annotations + annotations := cs.GetAnnotations() + if annotations == nil { + annotations = make(map[string]string, len(newAnnotations)) + } + for k, v := range newAnnotations { + annotations[k] = v + } + cs.SetAnnotations(annotations) +} + +// getExistingBundleItems reads and decodes the value of injectedBundlesAnnotation +// if it exists. len(items) == 0 if no annotation is found or is empty. +func getExistingBundleItems(annotations map[string]string) (items []index.BundleItem, err error) { + if len(annotations) == 0 { + return items, nil + } + existingBundleItems, hasItems := annotations[injectedBundlesAnnotation] + if !hasItems || existingBundleItems == "" { + return items, nil + } + if err = json.Unmarshal([]byte(existingBundleItems), &items); err != nil { + return items, fmt.Errorf("error unmarshaling existing bundles: %v", err) + } + return items, nil +} + +func (c IndexImageCatalogCreator) deleteRegistryPod(ctx context.Context, podName string) error { + // get registry pod key + podKey := types.NamespacedName{ + Namespace: c.cfg.Namespace, + Name: podName, + } + + pod := corev1.Pod{} + podCheck := wait.ConditionFunc(func() (done bool, err error) { + if err := c.cfg.Client.Get(ctx, podKey, &pod); err != nil { + return false, fmt.Errorf("error getting previous registry pod %s: %w", podName, err) + } + return true, nil + }) + + if err := wait.PollImmediateUntil(200*time.Millisecond, podCheck, ctx.Done()); err != nil { + return fmt.Errorf("error getting previous registry pod: %v", err) + } + + if err := c.cfg.Client.Delete(ctx, &pod); err != nil && !apierrors.IsNotFound(err) { + return fmt.Errorf("delete %q: %v", pod.GetName(), err) + } else if err == nil { + log.Infof("Deleted previous registry pod with name %q", pod.GetName()) + } + + // Failure of the old pod to clean up should block and cause the caller to error out if it fails, + // since the old pod may still be connected to OLM. + if err := wait.PollImmediateUntil(200*time.Millisecond, func() (bool, error) { + if err := c.cfg.Client.Get(ctx, podKey, &pod); apierrors.IsNotFound(err) { + return true, nil + } else if err != nil { + return false, err + } + return false, nil + }, ctx.Done()); err != nil { + return fmt.Errorf("old registry pod %q failed to delete (%v), requires manual cleanup", pod.GetName(), err) } return nil diff --git a/internal/olm/operator/registry/operator_installer.go b/internal/olm/operator/registry/operator_installer.go index f49d71078ee..acb8ae5ea57 100644 --- a/internal/olm/operator/registry/operator_installer.go +++ b/internal/olm/operator/registry/operator_installer.go @@ -39,6 +39,7 @@ type OperatorInstaller struct { Channel string InstallMode operator.InstallMode CatalogCreator CatalogCreator + CatalogUpdater CatalogUpdater SupportedInstallModes sets.String cfg *operator.Configuration @@ -97,6 +98,79 @@ func (o OperatorInstaller) InstallOperator(ctx context.Context) (*v1alpha1.Clust return csv, nil } +func (o OperatorInstaller) UpgradeOperator(ctx context.Context) (*v1alpha1.ClusterServiceVersion, error) { + subList := &v1alpha1.SubscriptionList{} + + options := client.ListOptions{ + Namespace: o.cfg.Namespace, + } + if err := o.cfg.Client.List(ctx, subList, &options); err != nil { + return nil, fmt.Errorf("error getting list of subscriptions: %v", err) + } + + var subscription *v1alpha1.Subscription + for i := range subList.Items { + s := subList.Items[i] + if o.PackageName == s.Spec.Package { + subscription = &s + break + } + } + + log.Infof("Found existing subscription with name %s and namespace %s", subscription.Name, subscription.Namespace) + + // todo: attempt #1 to trigger install plan for the subscription and + // to make it detect catalog changes, as per OLM suggestion + if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error { + // set the startingCSV to empty + subscription.Spec.StartingCSV = "" + if err := o.cfg.Client.Update(ctx, subscription); err != nil { + return fmt.Errorf("error updating subscription: %v", err) + } + return nil + }); err != nil { + return nil, err + } + + // Get existing catalog source from the subsription + catsrcKey := types.NamespacedName{ + Namespace: subscription.Spec.CatalogSourceNamespace, + Name: subscription.Spec.CatalogSource, + } + + cs := &v1alpha1.CatalogSource{} + if err := o.cfg.Client.Get(ctx, catsrcKey, cs); err != nil { + return nil, fmt.Errorf("error getting catalog source matching the existing subscription: %w", err) + } + log.Infof("Found existing catalog source with name %s and namespace %s", cs.Name, cs.Namespace) + + // Update catalog source + err := o.CatalogUpdater.UpdateCatalog(ctx, cs) + if err != nil { + return nil, fmt.Errorf("update catalog error: %v", err) + } + + // Wait for the Install Plan to be generated + if err = o.waitForInstallPlan(ctx, subscription); err != nil { + return nil, err + } + + // Approve Install Plan for the subscription + if err = o.approveInstallPlan(ctx, subscription); err != nil { + return nil, err + } + + // Wait for successfully installed CSV + csv, err := o.getInstalledCSV(ctx) + if err != nil { + return nil, err + } + + log.Infof("Successfully upgraded to %q", o.StartingCSV) + + return csv, nil +} + //nolint:unused func (o OperatorInstaller) waitForCatalogSource(ctx context.Context, cs *v1alpha1.CatalogSource) error { catSrcKey := client.ObjectKeyFromObject(cs) diff --git a/website/content/en/docs/cli/operator-sdk_run.md b/website/content/en/docs/cli/operator-sdk_run.md index 7b667d29552..c69634897df 100644 --- a/website/content/en/docs/cli/operator-sdk_run.md +++ b/website/content/en/docs/cli/operator-sdk_run.md @@ -25,5 +25,6 @@ This command has subcommands that will deploy your Operator with OLM. * [operator-sdk](../operator-sdk) - Development kit for building Kubernetes extensions and tools. * [operator-sdk run bundle](../operator-sdk_run_bundle) - Deploy an Operator in the bundle format with OLM +* [operator-sdk run bundle-upgrade](../operator-sdk_run_bundle-upgrade) - Upgrade an Operator previously installed in the bundle format with OLM * [operator-sdk run packagemanifests](../operator-sdk_run_packagemanifests) - Deploy an Operator in the package manifests format with OLM diff --git a/website/content/en/docs/cli/operator-sdk_run_bundle-upgrade.md b/website/content/en/docs/cli/operator-sdk_run_bundle-upgrade.md new file mode 100644 index 00000000000..05dcbb8bd0b --- /dev/null +++ b/website/content/en/docs/cli/operator-sdk_run_bundle-upgrade.md @@ -0,0 +1,34 @@ +--- +title: "operator-sdk run bundle-upgrade" +--- +## operator-sdk run bundle-upgrade + +Upgrade an Operator previously installed in the bundle format with OLM + +### Synopsis + +Upgrade an Operator previously installed in the bundle format with OLM + +``` +operator-sdk run bundle-upgrade [flags] +``` + +### Options + +``` + --timeout duration upgrade timeout (default 2m0s) + --kubeconfig string Path to the kubeconfig file to use for CLI requests. + -n, --namespace string If present, namespace scope for this CLI request + -h, --help help for bundle-upgrade +``` + +### Options inherited from parent commands + +``` + --verbose Enable verbose logging +``` + +### SEE ALSO + +* [operator-sdk run](../operator-sdk_run) - Run an Operator in a variety of environments + From 3aa4ca509eb8cb5d00fa4cda1853c2008a2d0ab4 Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Fri, 11 Dec 2020 10:57:37 -0800 Subject: [PATCH 241/376] test/integration: rewrite in BDD style, fixup `cleanup` command (#4303) Signed-off-by: reinvantveer --- Makefile | 2 +- .../fragments/cleanup-all-resources.yaml | 13 + hack/tests/integration.sh | 46 --- .../clusterserviceversion.go | 2 +- internal/olm/operator/uninstall.go | 165 +++++---- internal/testutils/olm.go | 2 +- test/e2e-go/e2e_go_olm_test.go | 160 --------- test/integration/integration_helpers.go | 293 ---------------- test/integration/integration_suite_test.go | 219 ++++++++++++ test/integration/operator_olm_test.go | 316 ------------------ test/integration/packagemanifests_test.go | 87 +++++ .../en/docs/olm-integration/generation.md | 4 +- 12 files changed, 416 insertions(+), 893 deletions(-) create mode 100644 changelog/fragments/cleanup-all-resources.yaml delete mode 100755 hack/tests/integration.sh delete mode 100644 test/e2e-go/e2e_go_olm_test.go delete mode 100644 test/integration/integration_helpers.go create mode 100644 test/integration/integration_suite_test.go delete mode 100644 test/integration/operator_olm_test.go create mode 100644 test/integration/packagemanifests_test.go diff --git a/Makefile b/Makefile index 5cc1f13b515..e3563d70ec6 100644 --- a/Makefile +++ b/Makefile @@ -169,7 +169,7 @@ test-e2e-ansible-molecule:: image/ansible-operator ## Run molecule-based Ansible test-e2e-helm:: image/helm-operator ## Run Helm e2e tests go test ./test/e2e-helm -v -ginkgo.v test-e2e-integration:: ## Run integration tests - ./hack/tests/integration.sh + go test ./test/integration -v -ginkgo.v ./hack/tests/subcommand-olm-install.sh .DEFAULT_GOAL := help diff --git a/changelog/fragments/cleanup-all-resources.yaml b/changelog/fragments/cleanup-all-resources.yaml new file mode 100644 index 00000000000..ff50fb13bcf --- /dev/null +++ b/changelog/fragments/cleanup-all-resources.yaml @@ -0,0 +1,13 @@ +entries: + - description: > + Made the `cleanup` command's error handling more robust on deletion and "not found" events. + kind: bugfix + - description: > + Fixed the documented `packagemanifests` make recipe. + kind: bugfix + migration: + header: Update `packagemanifests` make recipe variable `PKG_MAN_OPTS` + body: > + If your project uses the `packagemanifests` make recipe, update your `PKG_MAN_OPTS` + variable to include `PKG_FROM_VERSION` instead of `FROM_VERSION`, ex. + `PKG_MAN_OPTS ?= $(PKG_FROM_VERSION) $(PKG_CHANNELS) $(PKG_IS_DEFAULT_CHANNEL)`. diff --git a/hack/tests/integration.sh b/hack/tests/integration.sh deleted file mode 100755 index b0be6164bdf..00000000000 --- a/hack/tests/integration.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env bash - -set -eu - -source hack/lib/common.sh -source hack/lib/image_lib.sh - -TMPDIR="$(mktemp -d -p /tmp memcached-operator-XXXX)" -trap_add 'rm -rf $TMPDIR' EXIT -pushd "$TMPDIR" - -header_text "Initializing test project" - -# Initialize a basic memcached-operator project -operator-sdk init --repo github.com/example/memcached-operator --domain example.com --fetch-deps=false -operator-sdk create api --group cache --version v1alpha1 --kind Memcached --controller --resource -sed -i 's@Foo string `json:"foo,omitempty"`@// +optional\ - Count int `json:"count,omitempty"`@' api/v1alpha1/memcached_types.go - -# Build the operator's image. -export OSDK_INTEGRATION_IMAGE="quay.io/example/memcached-operator:integration" -make docker-build IMG="$OSDK_INTEGRATION_IMAGE" -load_image_if_kind "$OSDK_INTEGRATION_IMAGE" - -popd - -# todo: upgrade to use the 0.17.0 when the issue https://github.com/operator-framework/operator-sdk/issues/4284 be solved -# Install OLM on the cluster if not installed. -olm_latest_exists=0 -if ! operator-sdk olm status > /dev/null 2>&1; then - operator-sdk olm install --version=0.15.1 - olm_latest_exists=1 -fi - -header_text "Running integration tests" - -# Integration tests will use default loading rules for the kubeconfig if KUBECONFIG is not set. -go test -v ./test/integration - -header_text "Integration tests succeeded" - -# todo: upgrade to use the 0.17.0 when the issue https://github.com/operator-framework/operator-sdk/issues/4284 be solved -# Uninstall OLM if it was installed for test purposes. -if eval "(( $olm_latest_exists ))"; then - operator-sdk olm uninstall --version=0.15.1 -fi diff --git a/internal/generate/clusterserviceversion/clusterserviceversion.go b/internal/generate/clusterserviceversion/clusterserviceversion.go index d0225a7a214..f921e752857 100644 --- a/internal/generate/clusterserviceversion/clusterserviceversion.go +++ b/internal/generate/clusterserviceversion/clusterserviceversion.go @@ -160,7 +160,7 @@ func (g *Generator) generate() (base *operatorsv1alpha1.ClusterServiceVersion, e } } if g.FromVersion != "" { - base.Spec.Replaces = genutil.MakeCSVName(g.OperatorName, g.Version) + base.Spec.Replaces = genutil.MakeCSVName(g.OperatorName, g.FromVersion) } if err := ApplyTo(g.Collector, base); err != nil { diff --git a/internal/olm/operator/uninstall.go b/internal/olm/operator/uninstall.go index 93f1cb66b47..4020eb25e8d 100644 --- a/internal/olm/operator/uninstall.go +++ b/internal/olm/operator/uninstall.go @@ -32,7 +32,6 @@ import ( ) const ( - csvKind = "ClusterServiceVersion" crdKind = "CustomResourceDefinition" ) @@ -73,7 +72,15 @@ func (u *Uninstall) Run(ctx context.Context) error { return fmt.Errorf("list subscriptions: %v", err) } + // Use nil objects to determine if the underlying was found. + // If it was, the object will != nil. + var subObj, csvObj, csObj client.Object var sub *v1alpha1.Subscription + var crds []client.Object + catsrc := &v1alpha1.CatalogSource{} + catsrc.SetNamespace(u.config.Namespace) + catsrc.SetName(CatalogNameForPackage(u.Package)) + for i := range subs.Items { s := subs.Items[i] if u.Package == s.Spec.Package { @@ -82,88 +89,116 @@ func (u *Uninstall) Run(ctx context.Context) error { } } - catsrc := &v1alpha1.CatalogSource{} + catsrcKey := client.ObjectKeyFromObject(catsrc) if sub != nil { - catsrcKey := types.NamespacedName{ + subObj = sub + // Use the subscription's catalog source data only if available. + keyFromSpec := types.NamespacedName{ Namespace: sub.Spec.CatalogSourceNamespace, Name: sub.Spec.CatalogSource, } - if err := u.config.Client.Get(ctx, catsrcKey, catsrc); err != nil { - return fmt.Errorf("get catalog source: %v", err) + if catsrcKey.Name != "" && catsrcKey.Namespace != "" { + catsrcKey = keyFromSpec } - csv, err := u.getInstalledCSV(ctx, sub) - if err != nil { - return fmt.Errorf("get installed CSV %q: %v", sub.Status.InstalledCSV, err) + // CSV name may either be the installed or current name in a subscription's status, + // depending on installation state. + csvKey := types.NamespacedName{ + Name: sub.Status.InstalledCSV, + Namespace: u.config.Namespace, } - - crds := getCRDs(csv) - - // Delete the subscription first, so that no further installs or upgrades - // of the operator occur while we're cleaning up. - if err := u.deleteObjects(ctx, false, sub); err != nil { - return err + if csvKey.Name == "" { + csvKey.Name = sub.Status.CurrentCSV } - - if u.DeleteCRDs { - // Ensure CustomResourceDefinitions are deleted next, so that the operator - // has a chance to handle CRs that have finalizers. - if err := u.deleteObjects(ctx, true, crds...); err != nil { - return err + // This value can be empty which will cause errors. + if csvKey.Name != "" { + csv := &v1alpha1.ClusterServiceVersion{} + if err := u.config.Client.Get(ctx, csvKey, csv); err != nil && !apierrors.IsNotFound(err) { + return fmt.Errorf("error getting installed CSV %q: %v", csvKey.Name, err) + } else if err == nil { + crds = getCRDs(csv) } + csvObj = csv } + } - // OLM puts an ownerref on every namespaced resource to the CSV, - // and an owner label on every cluster scoped resource. When CSV is deleted - // kube and olm gc will remove all the referenced resources. - if err := u.deleteObjects(ctx, true, csv); err != nil { - return err - } - - } else { - catsrc.SetNamespace(u.config.Namespace) - catsrc.SetName(CatalogNameForPackage(u.Package)) + // Get the catalog source to make sure the correct error is returned. + if err := u.config.Client.Get(ctx, catsrcKey, catsrc); err == nil { + csObj = catsrc + } else if !apierrors.IsNotFound(err) { + return fmt.Errorf("error get catalog source: %v", err) } - // Delete the catalog source. This assumes that all underlying resources related - // to this catalog source have an owner reference to this catalog source so that - // they are automatically garbage-collected. - catsrc.SetGroupVersionKind(v1alpha1.SchemeGroupVersion.WithKind(v1alpha1.CatalogSourceKind)) - if err := u.deleteObjects(ctx, true, catsrc); err != nil { + // Deletion order: + // + // 1. Subscription to prevent further installs or upgrades of the operator while cleaning up. + // 2. CustomResourceDefinitions so the operator has a chance to handle CRs that have finalizers. + // 3. ClusterServiceVersion. OLM puts an ownerref on every namespaced resource to the CSV, + // and an owner label on every cluster scoped resource so they get gc'd on deletion. + // 4. CatalogSource. All other resources installed by OLM or operator-sdk related to this + // package will be gc'd. + + // Subscriptions can be deleted asynchronously. + if err := u.deleteObjects(ctx, false, subObj); err != nil { + return err + } + var objs []client.Object + if u.DeleteCRDs { + objs = append(objs, crds...) + } + objs = append(objs, csvObj, csObj) + // These objects may have owned resources/finalizers, so block on deletion. + if err := u.deleteObjects(ctx, true, objs...); err != nil { return err } - // If this was the last subscription in the namespace and the operator group is - // the one we created, delete it + // If the last subscription in the namespace was deleted and the operator group is + // the one operator-sdk created, delete it. if u.DeleteOperatorGroups { - if err := u.config.Client.List(ctx, &subs, client.InNamespace(u.config.Namespace)); err != nil { - return fmt.Errorf("list subscriptions: %v", err) - } - if len(subs.Items) == 0 { - ogs := v1.OperatorGroupList{} - if err := u.config.Client.List(ctx, &ogs, client.InNamespace(u.config.Namespace)); err != nil { - return fmt.Errorf("list operatorgroups: %v", err) - } - for _, og := range ogs.Items { - og := og - if len(u.DeleteOperatorGroupNames) == 0 || slice.ContainsString(u.DeleteOperatorGroupNames, og.GetName(), nil) { - if err := u.deleteObjects(ctx, false, &og); err != nil { - return err - } - } - } + if err := u.deleteOperatorGroup(ctx); err != nil { + return err } } - if sub == nil { + + // If no objects were cleaned up, the package was not found. + if subObj == nil && csObj == nil && csvObj == nil && len(crds) == 0 { return &ErrPackageNotFound{u.Package} } return nil } +func (u *Uninstall) deleteOperatorGroup(ctx context.Context) error { + subs := v1alpha1.SubscriptionList{} + if err := u.config.Client.List(ctx, &subs, client.InNamespace(u.config.Namespace)); err != nil { + return fmt.Errorf("list subscriptions: %v", err) + } + if len(subs.Items) != 0 { + return nil + } + ogs := v1.OperatorGroupList{} + if err := u.config.Client.List(ctx, &ogs, client.InNamespace(u.config.Namespace)); err != nil { + return fmt.Errorf("list operatorgroups: %v", err) + } + for _, og := range ogs.Items { + if len(u.DeleteOperatorGroupNames) == 0 || slice.ContainsString(u.DeleteOperatorGroupNames, og.GetName(), nil) { + if err := u.deleteObjects(ctx, false, &og); err != nil { + return err + } + } + } + return nil +} + func (u *Uninstall) deleteObjects(ctx context.Context, waitForDelete bool, objs ...client.Object) error { for _, obj := range objs { - obj := obj - lowerKind := strings.ToLower(obj.GetObjectKind().GroupVersionKind().Kind) + if obj == nil { + continue + } + gvks, _, err := u.config.Scheme.ObjectKinds(obj) + if err != nil { + return err + } + lowerKind := strings.ToLower(gvks[0].Kind) if err := u.config.Client.Delete(ctx, obj); err != nil && !apierrors.IsNotFound(err) { return fmt.Errorf("delete %s %q: %v", lowerKind, obj.GetName(), err) } else if err == nil { @@ -186,22 +221,6 @@ func (u *Uninstall) deleteObjects(ctx context.Context, waitForDelete bool, objs return nil } -// getInstalledCSV looks up the installed CSV name from the provided subscription and fetches it. -func (u *Uninstall) getInstalledCSV(ctx context.Context, subscription *v1alpha1.Subscription) (*v1alpha1.ClusterServiceVersion, error) { - key := types.NamespacedName{ - Name: subscription.Status.InstalledCSV, - Namespace: subscription.GetNamespace(), - } - - installedCSV := &v1alpha1.ClusterServiceVersion{} - if err := u.config.Client.Get(ctx, key, installedCSV); err != nil { - return nil, err - } - - installedCSV.SetGroupVersionKind(v1alpha1.SchemeGroupVersion.WithKind(csvKind)) - return installedCSV, nil -} - // getCRDs returns the list of CRDs required by a CSV. func getCRDs(csv *v1alpha1.ClusterServiceVersion) (crds []client.Object) { for _, resource := range csv.Status.RequirementStatus { diff --git a/internal/testutils/olm.go b/internal/testutils/olm.go index 2d3b3213f0d..59ebed81627 100644 --- a/internal/testutils/olm.go +++ b/internal/testutils/olm.go @@ -38,7 +38,7 @@ endif ifeq ($(IS_CHANNEL_DEFAULT), 1) PKG_IS_DEFAULT_CHANNEL := --default-channel endif -PKG_MAN_OPTS ?= $(FROM_VERSION) $(PKG_CHANNELS) $(PKG_IS_DEFAULT_CHANNEL) +PKG_MAN_OPTS ?= $(PKG_FROM_VERSION) $(PKG_CHANNELS) $(PKG_IS_DEFAULT_CHANNEL) # Generate package manifests. packagemanifests: kustomize %s diff --git a/test/e2e-go/e2e_go_olm_test.go b/test/e2e-go/e2e_go_olm_test.go deleted file mode 100644 index ff23faa08b5..00000000000 --- a/test/e2e-go/e2e_go_olm_test.go +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright 2020 The Operator-SDK 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. - -package e2e_go_test - -import ( - "os/exec" - "path/filepath" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - - "github.com/operator-framework/operator-sdk/internal/testutils" -) - -var _ = Describe("Integrating Go Projects with OLM", func() { - - // OLM does not work with cert-manager. In this way, we need to generate - // the pkg manifest after we comment cert-manager options into the kustomization file. - // More info: https://olm.operatorframework.io/docs/advanced-tasks/adding-admission-and-conversion-webhooks/#certificate-authority-requirements - BeforeEach(func() { - By("commenting cert-manager") - err := testutils.ReplaceInFile( - filepath.Join(tc.Dir, "config", "default", "kustomization.yaml"), - "- ../certmanager", "#- ../certmanager") - Expect(err).NotTo(HaveOccurred()) - - By("commenting cert-manager") - err = testutils.ReplaceInFile( - filepath.Join(tc.Dir, "config", "default", "kustomization.yaml"), - uncommentedCertManagerKustomizeFields, commentedCertManagerKustomizeFields) - Expect(err).NotTo(HaveOccurred()) - }) - - AfterEach(func() { - By("commenting cert-manager") - err := testutils.ReplaceInFile( - filepath.Join(tc.Dir, "config", "default", "kustomization.yaml"), - "#- ../certmanager", "- ../certmanager") - Expect(err).NotTo(HaveOccurred()) - - By("commenting cert-manager") - err = testutils.ReplaceInFile( - filepath.Join(tc.Dir, "config", "default", "kustomization.yaml"), - commentedCertManagerKustomizeFields, uncommentedCertManagerKustomizeFields) - Expect(err).NotTo(HaveOccurred()) - }) - - Context("with operator-sdk", func() { - const operatorVersion = "0.0.1" - - It("should generate and run a valid OLM bundle and packagemanifests", func() { - By("adding the 'packagemanifests' rule to the Makefile") - err := tc.AddPackagemanifestsTarget() - Expect(err).NotTo(HaveOccurred()) - - By("generating the operator package manifests") - err = tc.Make("packagemanifests", "IMG="+tc.ImageName) - Expect(err).NotTo(HaveOccurred()) - - By("running the package manifests-formatted operator") - Expect(err).NotTo(HaveOccurred()) - runPkgManCmd := exec.Command(tc.BinaryName, "run", "packagemanifests", - "--install-mode", "AllNamespaces", - "--version", operatorVersion, - "--timeout", "4m") - _, err = tc.Run(runPkgManCmd) - Expect(err).NotTo(HaveOccurred()) - - By("destroying the deployed package manifests-formatted operator") - cleanupPkgManCmd := exec.Command(tc.BinaryName, "cleanup", tc.ProjectName, - "--timeout", "4m") - _, err = tc.Run(cleanupPkgManCmd) - Expect(err).NotTo(HaveOccurred()) - }) - }) -}) - -const uncommentedCertManagerKustomizeFields = `# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. -# Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks. -# 'CERTMANAGER' needs to be enabled to use ca injection -- webhookcainjection_patch.yaml - - -# the following config is for teaching kustomize how to do var substitution -vars: -# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix. -- name: CERTIFICATE_NAMESPACE # namespace of the certificate CR - objref: - kind: Certificate - group: cert-manager.io - version: v1alpha2 - name: serving-cert # this name should match the one in certificate.yaml - fieldref: - fieldpath: metadata.namespace -- name: CERTIFICATE_NAME - objref: - kind: Certificate - group: cert-manager.io - version: v1alpha2 - name: serving-cert # this name should match the one in certificate.yaml -- name: SERVICE_NAMESPACE # namespace of the service - objref: - kind: Service - version: v1 - name: webhook-service - fieldref: - fieldpath: metadata.namespace -- name: SERVICE_NAME - objref: - kind: Service - version: v1 - name: webhook-service` - -const commentedCertManagerKustomizeFields = `# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. -# Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks. -# 'CERTMANAGER' needs to be enabled to use ca injection -# - webhookcainjection_patch.yaml - - -# the following config is for teaching kustomize how to do var substitution -vars: -# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix. -#- name: CERTIFICATE_NAMESPACE # namespace of the certificate CR -# objref: -# kind: Certificate -# group: cert-manager.io -# version: v1alpha2 -# name: serving-cert # this name should match the one in certificate.yaml -# fieldref: -# fieldpath: metadata.namespace -#- name: CERTIFICATE_NAME -# objref: -# kind: Certificate -# group: cert-manager.io -# version: v1alpha2 -# name: serving-cert # this name should match the one in certificate.yaml -#- name: SERVICE_NAMESPACE # namespace of the service -# objref: -# kind: Service -# version: v1 -# name: webhook-service -# fieldref: -# fieldpath: metadata.namespace -#- name: SERVICE_NAME -# objref: -# kind: Service -# version: v1 -# name: webhook-service` diff --git a/test/integration/integration_helpers.go b/test/integration/integration_helpers.go deleted file mode 100644 index ecf397506da..00000000000 --- a/test/integration/integration_helpers.go +++ /dev/null @@ -1,293 +0,0 @@ -// Copyright 2018 The Operator-SDK 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. - -package e2e - -import ( - "fmt" - "html/template" - "io/ioutil" - "os" - "path/filepath" - "strings" - "testing" - - apimanifests "github.com/operator-framework/api/pkg/manifests" - operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1" - "github.com/operator-framework/operator-registry/pkg/lib/bundle" - apiextv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "sigs.k8s.io/yaml" -) - -const ( - imageEnvVar = "OSDK_INTEGRATION_IMAGE" -) - -var ( - // Set with OSDK_INTEGRATION_IMAGE in CI. - testImageTag = "memcached-operator" -) - -type definitionKey struct { - Kind string - Name string - Group string - Versions []apiextv1beta1.CustomResourceDefinitionVersion -} - -type csvTemplateConfig struct { - OperatorName string - Version string - TestImageTag string - ReplacesCSVName string - CRDKeys []definitionKey - InstallModes []operatorsv1alpha1.InstallMode - - IsBundle bool -} - -// TODO(estroz): devise a way for "make bundle" to be called, then update the generated bundle with correct -// install modes within integration tests themselves. - -const csvTmpl = `apiVersion: operators.coreos.com/v1alpha1 -kind: ClusterServiceVersion -metadata: - annotations: - capabilities: Basic Install - name: {{ .OperatorName }}.v{{ .Version }} - namespace: placeholder -spec: - apiservicedefinitions: {} - customresourcedefinitions: - owned: -{{- range $i, $crd := .CRDKeys }}{{- range $j, $version := $crd.Versions }} - - description: Represents a cluster of {{ $crd.Kind }} apps - displayName: {{ $crd.Kind }} App - kind: {{ $crd.Kind }} - name: {{ $crd.Name }} - version: {{ $version.Name }} -{{- end }}{{- end }} - description: Big ol' Operator. - displayName: {{ .OperatorName }} Application - install: - spec: - clusterPermissions: - - rules: - {{- range $i, $crd := .CRDKeys }} - - apiGroups: - - {{ $crd.Group }} - resources: - - {{ $crd.Kind | tolower }}s - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - apiGroups: - - {{ $crd.Group }} - resources: - - {{ $crd.Kind | tolower }}s/status - verbs: - - get - - patch - - update - {{- end}} - serviceAccountName: default - - rules: - - apiGroups: - - authentication.k8s.io - resources: - - tokenreviews - verbs: - - create - - apiGroups: - - authorization.k8s.io - resources: - - subjectaccessreviews - verbs: - - create - serviceAccountName: default - deployments: - - name: {{ .OperatorName }}-controller-manager - spec: - replicas: 1 - selector: - matchLabels: - control-plane: controller-manager - strategy: {} - template: - metadata: - labels: - control-plane: controller-manager - spec: - containers: - - args: - - --secure-listen-address=0.0.0.0:8443 - - --upstream=http://127.0.0.1:8080/ - - --logtostderr=true - - --v=10 - image: gcr.io/kubebuilder/kube-rbac-proxy:v0.5.0 - name: kube-rbac-proxy - ports: - - containerPort: 8443 - name: https - resources: {} - - args: - - --metrics-addr=127.0.0.1:8080 - - --enable-leader-election - command: - - /manager - image: {{ .TestImageTag }} - name: manager - resources: - limits: - cpu: 100m - memory: 30Mi - requests: - cpu: 100m - memory: 20Mi - terminationGracePeriodSeconds: 10 - permissions: - - rules: - - apiGroups: - - "" - resources: - - configmaps - verbs: - - get - - list - - watch - - create - - update - - patch - - delete - - apiGroups: - - "" - resources: - - events - verbs: - - create - - patch - serviceAccountName: default - strategy: deployment - installModes: -{{- range $i, $mode := .InstallModes }} - - supported: {{ $mode.Supported }} - type: {{ $mode.Type }} -{{- end }} -{{- if .ReplacesCSVName }} - replaces: {{ .ReplacesCSVName }} -{{- end }} - version: {{ .Version }} -` - -func writeOperatorManifests(dir string, csvConfig csvTemplateConfig) error { - manifestDir := "" - if csvConfig.IsBundle { - manifestDir = filepath.Join(dir, bundle.ManifestsDir) - } else { - manifestDir = filepath.Join(dir, csvConfig.Version) - } - for _, key := range csvConfig.CRDKeys { - crd := apiextv1beta1.CustomResourceDefinition{ - TypeMeta: metav1.TypeMeta{ - APIVersion: apiextv1beta1.SchemeGroupVersion.String(), - Kind: "CustomResourceDefinition", - }, - ObjectMeta: metav1.ObjectMeta{Name: key.Name}, - Spec: apiextv1beta1.CustomResourceDefinitionSpec{ - Names: apiextv1beta1.CustomResourceDefinitionNames{ - Kind: key.Kind, - ListKind: key.Kind + "List", - Singular: strings.ToLower(key.Kind), - Plural: strings.ToLower(key.Kind) + "s", - }, - Group: key.Group, - Scope: "Namespaced", - Versions: key.Versions, - }, - } - crdPath := filepath.Join(manifestDir, fmt.Sprintf("%s_%ss.yaml", key.Name, strings.ToLower(key.Kind))) - if err := writeManifest(crdPath, crd); err != nil { - return err - } - } - csvPath := filepath.Join(manifestDir, fmt.Sprintf("%s.clusterserviceversion.yaml", csvConfig.OperatorName)) - if err := execTemplateOnFile(csvPath, csvTmpl, csvConfig); err != nil { - return err - } - return nil -} - -func writePackageManifest(dir, pkgName string, channels []apimanifests.PackageChannel) error { - pkg := apimanifests.PackageManifest{ - PackageName: pkgName, - DefaultChannelName: channels[0].Name, - Channels: channels, - } - pkgPath := filepath.Join(dir, fmt.Sprintf("%s.package.yaml", pkgName)) - return writeManifest(pkgPath, pkg) -} - -func writeManifest(path string, o interface{}) error { - if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil { - return err - } - b, err := yaml.Marshal(o) - if err != nil { - return err - } - return ioutil.WriteFile(path, b, 0644) -} - -func execTemplateOnFile(path, tmplStr string, o interface{}) error { - if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil { - return err - } - w, err := os.Create(path) - if err != nil { - return err - } - defer w.Close() - - tmpl := template.New(path).Funcs(map[string]interface{}{ - "tolower": strings.ToLower, - }) - if tmpl, err = tmpl.Parse(tmplStr); err != nil { - return err - } - return tmpl.Execute(w, o) -} - -//nolint:unparam -func mkTempDirWithCleanup(t *testing.T, prefix string) (dir string, f func()) { - var err error - if prefix == "" { - prefix = "sdk-integration-" - } - if dir, err = ioutil.TempDir("", prefix); err != nil { - t.Fatalf("Failed to create tmp dir: %v", err) - } - f = func() { - if err := os.RemoveAll(dir); err != nil { - // Not a test failure since files in /tmp will eventually get deleted - t.Logf("Failed to remove tmp dir %s: %v", dir, err) - } - } - return -} diff --git a/test/integration/integration_suite_test.go b/test/integration/integration_suite_test.go new file mode 100644 index 00000000000..3b6a98f162f --- /dev/null +++ b/test/integration/integration_suite_test.go @@ -0,0 +1,219 @@ +// Copyright 2020 The Operator-SDK 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. + +package integration + +import ( + "fmt" + "io/ioutil" + "os/exec" + "path/filepath" + "testing" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "github.com/operator-framework/api/pkg/operators/v1alpha1" + "github.com/operator-framework/operator-registry/pkg/lib/bundle" + "sigs.k8s.io/kubebuilder/v2/test/e2e/utils" + "sigs.k8s.io/yaml" + + "github.com/operator-framework/operator-sdk/internal/testutils" +) + +// TestIntegration tests operator-sdk projects with OLM. +func TestIntegration(t *testing.T) { + if testing.Short() { + t.Skip("skipping Integration Suite in short mode") + } + RegisterFailHandler(Fail) + RunSpecs(t, "Integration") +} + +var ( + tc testutils.TestContext +) + +var _ = BeforeSuite(func() { + var err error + + By("creating a new test context") + tc, err = testutils.NewTestContext(testutils.BinaryName, "GO111MODULE=on") + Expect(err).NotTo(HaveOccurred()) + + tc.Domain = "example.com" + tc.Group = "cache" + tc.Version = "v1alpha1" + tc.Kind = "Memcached" + tc.Resources = "memcacheds" + tc.ProjectName = "memcached-operator" + tc.ImageName = fmt.Sprintf("quay.io/integration/%s:0.0.1", tc.ProjectName) + tc.BundleImageName = fmt.Sprintf("quay.io/integration/%s-bundle:0.0.1", tc.ProjectName) + + By("copying sample to a temporary e2e directory") + Expect(exec.Command("cp", "-r", "../../testdata/go/v3/memcached-operator", tc.Dir).Run()).To(Succeed()) + + By("updating the project configuration") + updateProjectConfigs(tc) + + By("installing OLM") + Expect(tc.InstallOLMVersion("0.15.1")).To(Succeed()) + + By("installing prometheus-operator") + Expect(tc.InstallPrometheusOperManager()).To(Succeed()) + + By("building the manager image") + Expect(tc.Make("docker-build", "IMG="+tc.ImageName)).To(Succeed()) + + if tc.IsRunningOnKind() { + By("loading the required images into Kind cluster") + Expect(tc.LoadImageToKindCluster()).To(Succeed()) + } + + By("generating the operator package manifests") + err = tc.Make("packagemanifests", "IMG="+tc.ImageName) + Expect(err).NotTo(HaveOccurred()) + + // TODO(estroz): enable when bundles can be tested locally. + // + // By("generating the operator bundle") + // err = tc.Make("bundle", "IMG="+tc.ImageName) + // Expect(err).NotTo(HaveOccurred()) + // + // By("building the operator bundle image") + // err = tc.Make("bundle-build", "BUNDLE_IMG="+tc.BundleImageName) + // Expect(err).NotTo(HaveOccurred()) + + By("creating the test namespace") + _, err = tc.Kubectl.Command("create", "namespace", tc.Kubectl.Namespace) + Expect(err).NotTo(HaveOccurred()) +}) + +var _ = AfterSuite(func() { + By("uninstalling OLM") + tc.UninstallOLM() + + By("uninstalling prometheus-operator") + tc.UninstallPrometheusOperManager() + + By("deleting the test namespace") + warn(tc.Kubectl.Delete(false, "namespace", tc.Kubectl.Namespace)) + + By("cleaning up the project") + tc.Destroy() +}) + +func warn(output string, err error) { + if err != nil { + fmt.Fprintf(GinkgoWriter, "warning: %s", err) + } +} + +func runPackageManifestsFor(tc *testutils.TestContext) func(...string) error { + return func(args ...string) error { + allArgs := []string{"run", "packagemanifests", "--timeout", "4m", "--namespace", tc.Kubectl.Namespace} + output, err := tc.Run(exec.Command(tc.BinaryName, append(allArgs, args...)...)) + if err == nil { + fmt.Fprintln(GinkgoWriter, string(output)) + } + return err + } +} + +func cleanupFor(tc *testutils.TestContext) func() (string, error) { + return func() (string, error) { + allArgs := []string{"cleanup", tc.ProjectName, "--timeout", "4m", "--namespace", tc.Kubectl.Namespace} + output, err := tc.Run(exec.Command(tc.BinaryName, allArgs...)) + if err == nil { + fmt.Fprintln(GinkgoWriter, string(output)) + } + return string(output), err + } +} + +func readCSVFor(tc *testutils.TestContext, isBundle bool) func(string) (*v1alpha1.ClusterServiceVersion, error) { + return func(version string) (*v1alpha1.ClusterServiceVersion, error) { + b, err := ioutil.ReadFile(csvPath(tc, version, isBundle)) + if err != nil { + return nil, err + } + csv := &v1alpha1.ClusterServiceVersion{} + if err := yaml.Unmarshal(b, csv); err != nil { + return nil, err + } + return csv, nil + } +} + +func writeCSVFor(tc *testutils.TestContext, isBundle bool) func(*v1alpha1.ClusterServiceVersion) error { + return func(csv *v1alpha1.ClusterServiceVersion) error { + b, err := yaml.Marshal(csv) + if err != nil { + return err + } + return ioutil.WriteFile(csvPath(tc, csv.Spec.Version.String(), isBundle), b, 0644) + } +} + +func csvPath(tc *testutils.TestContext, version string, isBundle bool) string { + fileName := fmt.Sprintf("%s.clusterserviceversion.yaml", tc.ProjectName) + if isBundle { + return filepath.Join(tc.Dir, "bundle", bundle.ManifestsDir, fileName) + } + return filepath.Join(tc.Dir, "packagemanifests", version, fileName) +} + +func updateProjectConfigs(tc testutils.TestContext) { + defaultKustomization := filepath.Join(tc.Dir, "config", "default", "kustomization.yaml") + ExpectWithOffset(1, testutils.ReplaceInFile(defaultKustomization, + "- ../certmanager", + "#- ../certmanager", + )).To(Succeed()) + ExpectWithOffset(1, testutils.ReplaceInFile(defaultKustomization, + "- manager_webhook_patch.yaml", + "#- manager_webhook_patch.yaml", + )).To(Succeed()) + + olmManagerWebhookPatchFile := filepath.Join(tc.Dir, "config", "default", "olm_manager_webhook_patch.yaml") + ExpectWithOffset(1, ioutil.WriteFile(olmManagerWebhookPatchFile, []byte(olmManagerWebhookPatch), 0644)).To(Succeed()) + + ExpectWithOffset(1, utils.InsertCode(filepath.Join(tc.Dir, "config", "manifests", "kustomization.yaml"), + "- ../scorecard", + defaultKustomizationOLMWebhookPatch, + )).To(Succeed()) + + ExpectWithOffset(1, tc.AddPackagemanifestsTarget()).To(Succeed()) +} + +// Exposes port 9443 for the OLM-managed webhook server. +const defaultKustomizationOLMWebhookPatch = ` +patchesStrategicMerge: +- olm_manager_webhook_patch.yaml +` + +const olmManagerWebhookPatch = ` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system +spec: + template: + spec: + containers: + - name: manager + ports: + - containerPort: 9443 + name: webhook-server + protocol: TCP +` diff --git a/test/integration/operator_olm_test.go b/test/integration/operator_olm_test.go deleted file mode 100644 index 64385635d2b..00000000000 --- a/test/integration/operator_olm_test.go +++ /dev/null @@ -1,316 +0,0 @@ -// Copyright 2018 The Operator-SDK 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. - -package e2e - -import ( - "context" - "fmt" - "os" - "path/filepath" - "testing" - "time" - - apimanifests "github.com/operator-framework/api/pkg/manifests" - operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1" - "github.com/sirupsen/logrus" - "github.com/stretchr/testify/assert" - corev1 "k8s.io/api/core/v1" - apiextv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" - "k8s.io/apimachinery/pkg/util/wait" - "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/operator-framework/operator-sdk/internal/olm/operator" - "github.com/operator-framework/operator-sdk/internal/olm/operator/packagemanifests" -) - -const ( - defaultTimeout = 2 * time.Minute - - defaultOperatorName = "memcached-operator" - defaultOperatorVersion = "0.0.2" -) - -// TODO(estroz): rewrite these in the style of e2e tests (ginkgo/gomega + scaffold a project for each scenario). - -func TestOLMIntegration(t *testing.T) { - if image, ok := os.LookupEnv(imageEnvVar); ok && image != "" { - testImageTag = image - } - - t.Run("PackageManifestsBasic", PackageManifestsBasic) - t.Run("PackageManifestsOwnNamespace", PackageManifestsOwnNamespace) - t.Run("PackageManifestsMultiplePackages", PackageManifestsMultiplePackages) -} - -func PackageManifestsOwnNamespace(t *testing.T) { - - csvConfig := csvTemplateConfig{ - OperatorName: defaultOperatorName, - Version: defaultOperatorVersion, - TestImageTag: testImageTag, - ReplacesCSVName: "", - CRDKeys: []definitionKey{ - { - Kind: "Memcached", - Name: "memcacheds.cache.example.com", - Group: "cache.example.com", - Versions: []apiextv1beta1.CustomResourceDefinitionVersion{ - {Name: "v1alpha1", Storage: true, Served: true}, - }, - }, - }, - InstallModes: []operatorsv1alpha1.InstallMode{ - {Type: operatorsv1alpha1.InstallModeTypeOwnNamespace, Supported: true}, - {Type: operatorsv1alpha1.InstallModeTypeSingleNamespace, Supported: false}, - {Type: operatorsv1alpha1.InstallModeTypeMultiNamespace, Supported: false}, - {Type: operatorsv1alpha1.InstallModeTypeAllNamespaces, Supported: false}, - }, - } - tmp, cleanup := mkTempDirWithCleanup(t, "") - defer cleanup() - - channels := []apimanifests.PackageChannel{ - {Name: "alpha", CurrentCSVName: fmt.Sprintf("%s.v%s", defaultOperatorName, defaultOperatorVersion)}, - } - manifestsDir := filepath.Join(tmp, defaultOperatorName) - err := writeOperatorManifests(manifestsDir, csvConfig) - if err != nil { - os.RemoveAll(tmp) - t.Fatal(err) - } - err = writePackageManifest(manifestsDir, defaultOperatorName, channels) - if err != nil { - os.RemoveAll(tmp) - t.Fatal(err) - } - - cfg := &operator.Configuration{} - assert.NoError(t, cfg.Load()) - i := packagemanifests.NewInstall(cfg) - i.PackageManifestsDirectory = manifestsDir - i.Version = defaultOperatorVersion - i.InstallMode = operator.InstallMode{ - InstallModeType: operatorsv1alpha1.InstallModeTypeOwnNamespace, - TargetNamespaces: []string{"default"}, - } - - // Cleanup. - defer func() { - if err := doUninstall(cfg); err != nil { - t.Log(err) - } - }() - - // Deploy operator. - assert.NoError(t, doInstall(i)) -} - -func PackageManifestsBasic(t *testing.T) { - - csvConfig := csvTemplateConfig{ - OperatorName: defaultOperatorName, - Version: defaultOperatorVersion, - TestImageTag: testImageTag, - ReplacesCSVName: "", - CRDKeys: []definitionKey{ - { - Kind: "Memcached", - Name: "memcacheds.cache.example.com", - Group: "cache.example.com", - Versions: []apiextv1beta1.CustomResourceDefinitionVersion{ - {Name: "v1alpha1", Storage: true, Served: true}, - }, - }, - }, - InstallModes: []operatorsv1alpha1.InstallMode{ - {Type: operatorsv1alpha1.InstallModeTypeOwnNamespace, Supported: false}, - {Type: operatorsv1alpha1.InstallModeTypeSingleNamespace, Supported: false}, - {Type: operatorsv1alpha1.InstallModeTypeMultiNamespace, Supported: false}, - {Type: operatorsv1alpha1.InstallModeTypeAllNamespaces, Supported: true}, - }, - } - tmp, cleanup := mkTempDirWithCleanup(t, "") - defer cleanup() - - channels := []apimanifests.PackageChannel{ - {Name: "alpha", CurrentCSVName: fmt.Sprintf("%s.v%s", defaultOperatorName, defaultOperatorVersion)}, - } - manifestsDir := filepath.Join(tmp, defaultOperatorName) - err := writeOperatorManifests(manifestsDir, csvConfig) - if err != nil { - os.RemoveAll(tmp) - t.Fatal(err) - } - err = writePackageManifest(manifestsDir, defaultOperatorName, channels) - if err != nil { - os.RemoveAll(tmp) - t.Fatal(err) - } - cfg := &operator.Configuration{} - assert.NoError(t, cfg.Load()) - i := packagemanifests.NewInstall(cfg) - i.PackageManifestsDirectory = manifestsDir - i.Version = defaultOperatorVersion - - // Cleanup. - defer func() { - if err := doUninstall(cfg); err != nil { - t.Log(err) - } - }() - - // Remove operator before deploy - assert.Error(t, doUninstall(cfg)) - - // Deploy operator - assert.NoError(t, doInstall(i)) - // Fail to deploy operator after deploy - assert.Error(t, doInstall(i)) - - // Remove operator after deploy - assert.NoError(t, doUninstall(cfg)) - // Remove operator after removal - assert.Error(t, doUninstall(cfg)) -} - -func PackageManifestsMultiplePackages(t *testing.T) { - - operatorVersion1 := defaultOperatorVersion - operatorVersion2 := "0.0.3" - csvConfigs := []csvTemplateConfig{ - { - OperatorName: defaultOperatorName, - Version: operatorVersion1, - TestImageTag: testImageTag, - ReplacesCSVName: "", - CRDKeys: []definitionKey{ - { - Kind: "Memcached", - Name: "memcacheds.cache.example.com", - Group: "cache.example.com", - Versions: []apiextv1beta1.CustomResourceDefinitionVersion{ - {Name: "v1alpha1", Storage: true, Served: true}, - }, - }, - }, - InstallModes: []operatorsv1alpha1.InstallMode{ - {Type: operatorsv1alpha1.InstallModeTypeOwnNamespace, Supported: false}, - {Type: operatorsv1alpha1.InstallModeTypeSingleNamespace, Supported: false}, - {Type: operatorsv1alpha1.InstallModeTypeMultiNamespace, Supported: false}, - {Type: operatorsv1alpha1.InstallModeTypeAllNamespaces, Supported: true}, - }, - }, - { - OperatorName: defaultOperatorName, - Version: operatorVersion2, - TestImageTag: testImageTag, - ReplacesCSVName: fmt.Sprintf("%s.v%s", defaultOperatorName, operatorVersion1), - CRDKeys: []definitionKey{ - { - Kind: "Memcached", - Name: "memcacheds.cache.example.com", - Group: "cache.example.com", - Versions: []apiextv1beta1.CustomResourceDefinitionVersion{ - {Name: "v1alpha1", Storage: false, Served: true}, - {Name: "v1alpha2", Storage: true, Served: true}, - }, - }, - }, - InstallModes: []operatorsv1alpha1.InstallMode{ - {Type: operatorsv1alpha1.InstallModeTypeOwnNamespace, Supported: false}, - {Type: operatorsv1alpha1.InstallModeTypeSingleNamespace, Supported: false}, - {Type: operatorsv1alpha1.InstallModeTypeMultiNamespace, Supported: false}, - {Type: operatorsv1alpha1.InstallModeTypeAllNamespaces, Supported: true}, - }, - }, - } - - tmp, cleanup := mkTempDirWithCleanup(t, "") - defer cleanup() - - channels := []apimanifests.PackageChannel{ - {Name: "stable", CurrentCSVName: fmt.Sprintf("%s.v%s", defaultOperatorName, operatorVersion2)}, - {Name: "alpha", CurrentCSVName: fmt.Sprintf("%s.v%s", defaultOperatorName, operatorVersion1)}, - } - manifestsDir := filepath.Join(tmp, defaultOperatorName) - for _, config := range csvConfigs { - err := writeOperatorManifests(manifestsDir, config) - if err != nil { - os.RemoveAll(tmp) - t.Fatal(err) - } - } - err := writePackageManifest(manifestsDir, defaultOperatorName, channels) - if err != nil { - os.RemoveAll(tmp) - t.Fatal(err) - } - cfg := &operator.Configuration{} - assert.NoError(t, cfg.Load()) - i := packagemanifests.NewInstall(cfg) - i.PackageManifestsDirectory = manifestsDir - i.Version = operatorVersion2 - - // Cleanup. - defer func() { - if err := doUninstall(cfg); err != nil { - t.Log(err) - } - }() - - // Deploy operator - assert.NoError(t, doInstall(i)) -} - -func doUninstall(cfg *operator.Configuration) error { - uninstall := operator.NewUninstall(cfg) - uninstall.DeleteAll = true - uninstall.DeleteOperatorGroupNames = []string{operator.SDKOperatorGroupName} - uninstall.Package = defaultOperatorName - uninstall.Logf = logrus.Infof - - ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout) - defer cancel() - if err := uninstall.Run(ctx); err != nil { - return err - } - return waitForPackageManifestConfigMapDeletion(ctx, cfg, defaultOperatorName) -} - -type installer interface { - Run(context.Context) (*operatorsv1alpha1.ClusterServiceVersion, error) -} - -func doInstall(i installer) error { - ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout) - defer cancel() - - _, err := i.Run(ctx) - return err -} - -func waitForPackageManifestConfigMapDeletion(ctx context.Context, cfg *operator.Configuration, packageName string) error { - cfgmaps := corev1.ConfigMapList{} - opts := []client.ListOption{ - client.InNamespace(cfg.Namespace), - client.MatchingLabels{"owner": "operator-sdk", "package-name": packageName}, - } - return wait.PollImmediateUntil(250*time.Millisecond, func() (bool, error) { - if err := cfg.Client.List(ctx, &cfgmaps, opts...); err != nil { - return false, err - } - return len(cfgmaps.Items) == 0, nil - }, ctx.Done()) -} diff --git a/test/integration/packagemanifests_test.go b/test/integration/packagemanifests_test.go new file mode 100644 index 00000000000..5e30c42dc71 --- /dev/null +++ b/test/integration/packagemanifests_test.go @@ -0,0 +1,87 @@ +// Copyright 2020 The Operator-SDK 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. + +package integration + +import ( + "fmt" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "github.com/operator-framework/api/pkg/operators/v1alpha1" +) + +var _ = Describe("run packagemanifests", func() { + + var ( + err error + output string + ) + + runPackageManifests := runPackageManifestsFor(&tc) + cleanup := cleanupFor(&tc) + isBundle := false + readCSV, writeCSV := readCSVFor(&tc, isBundle), writeCSVFor(&tc, isBundle) + + AfterEach(func() { + By("cleaning up") + _, err = cleanup() + Expect(err).NotTo(HaveOccurred()) + }) + + It("should handle existing operator deployments correctly", func() { + output, err = cleanup() + Expect(err).NotTo(HaveOccurred()) + Expect(output).To(ContainSubstring(`package \"memcached-operator\" not found`)) + Expect(runPackageManifests("--version", "0.0.1")).To(Succeed()) + Expect(runPackageManifests("--version", "0.0.1")).NotTo(Succeed()) + _, err = cleanup() + Expect(err).NotTo(HaveOccurred()) + output, err = cleanup() + Expect(err).NotTo(HaveOccurred()) + Expect(output).To(ContainSubstring(`package \"memcached-operator\" not found`)) + }) + + It("should succeed with a single operator version in OwnNamespace mode", func() { + csv, err := readCSV("0.0.1") + Expect(err).NotTo(HaveOccurred()) + for i, mode := range csv.Spec.InstallModes { + if mode.Type == v1alpha1.InstallModeTypeOwnNamespace { + csv.Spec.InstallModes[i].Supported = true + break + } + } + Expect(writeCSV(csv)).To(Succeed()) + Expect(runPackageManifests("--install-mode", "OwnNamespace", "--version", "0.0.1")).To(Succeed()) + }) + + It("should successfully deploy the second of two operator versions", func() { + versions := []string{"0.0.1", "0.2.0"} + channels := []string{"alpha", "stable"} + for i, version := range versions { + imageTag := fmt.Sprintf("integration/%s:%s", tc.ProjectName, version) + By("building the manager image " + imageTag) + Expect(tc.Make("docker-build", "IMG="+imageTag)).To(Succeed()) + if tc.IsRunningOnKind() { + Expect(tc.LoadImageToKindClusterWithName(imageTag)).To(Succeed()) + } + makeArgs := []string{"packagemanifests", "IMG=" + imageTag, "VERSION=" + version, "CHANNEL=" + channels[i]} + if i != 0 { + makeArgs = append(makeArgs, "FROM_VERSION="+versions[i-1]) + } + Expect(tc.Make(makeArgs...)).To(Succeed()) + } + Expect(runPackageManifests("--version", versions[len(versions)-1])).To(Succeed()) + }) +}) diff --git a/website/content/en/docs/olm-integration/generation.md b/website/content/en/docs/olm-integration/generation.md index 8a67a52b295..99cac09ae9f 100644 --- a/website/content/en/docs/olm-integration/generation.md +++ b/website/content/en/docs/olm-integration/generation.md @@ -186,7 +186,7 @@ endif ifeq ($(IS_CHANNEL_DEFAULT), 1) PKG_IS_DEFAULT_CHANNEL := --default-channel endif -PKG_MAN_OPTS ?= $(FROM_VERSION) $(PKG_CHANNELS) $(PKG_IS_DEFAULT_CHANNEL) +PKG_MAN_OPTS ?= $(PKG_FROM_VERSION) $(PKG_CHANNELS) $(PKG_IS_DEFAULT_CHANNEL) # Generate package manifests. packagemanifests: kustomize manifests @@ -208,7 +208,7 @@ endif ifeq ($(IS_CHANNEL_DEFAULT), 1) PKG_IS_DEFAULT_CHANNEL := --default-channel endif -PKG_MAN_OPTS ?= $(FROM_VERSION) $(PKG_CHANNELS) $(PKG_IS_DEFAULT_CHANNEL) +PKG_MAN_OPTS ?= $(PKG_FROM_VERSION) $(PKG_CHANNELS) $(PKG_IS_DEFAULT_CHANNEL) # Generate package manifests. packagemanifests: kustomize From 03597e13f23e8188ddcb5ce5ad9128d5f1f2ddfa Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Fri, 11 Dec 2020 15:30:07 -0800 Subject: [PATCH 242/376] deps: bump operator-sdk deps to k8s v1.19 (#4294) This commit bumps operator-sdk binary dependencies to k8s v1.19 go.mod,go.sum: update controller-runtime, controller-tools, api, operator-lib, and operator-registry to their k8s v1.19 equivalents *: make API changes Signed-off-by: reinvantveer --- .../fragments/operator-sdk-binary-v1.19.yaml | 4 +++ go.mod | 12 +++---- go.sum | 35 ++++++++----------- .../internal/go/v2/memcached_with_webhooks.go | 11 +++--- .../internal/go/v3/memcached_with_webhooks.go | 10 +++--- internal/ansible/controller/reconcile_test.go | 34 +++++++++--------- internal/olm/client/client_test.go | 17 +++++---- .../registry/configmap/configmap_test.go | 4 +-- .../registry/configmap/registry_test.go | 26 +++++++------- .../olm/operator/registry/configmap_test.go | 6 ++-- .../registry/index/registry_pod_test.go | 2 +- .../registry/operator_installer_test.go | 22 ++++++------ .../api/v1alpha1/memcached_webhook.go | 1 + testdata/go/v3/memcached-operator/Makefile | 2 +- .../api/v1alpha1/memcached_webhook.go | 4 +-- ...cached-operator.clusterserviceversion.yaml | 2 ++ .../config/webhook/manifests.yaml | 2 ++ .../controllers/memcached_controller.go | 2 +- testdata/go/v3/memcached-operator/go.mod | 2 +- testdata/go/v3/memcached-operator/go.sum | 4 +-- 20 files changed, 102 insertions(+), 100 deletions(-) create mode 100644 changelog/fragments/operator-sdk-binary-v1.19.yaml diff --git a/changelog/fragments/operator-sdk-binary-v1.19.yaml b/changelog/fragments/operator-sdk-binary-v1.19.yaml new file mode 100644 index 00000000000..fc2abf0ef19 --- /dev/null +++ b/changelog/fragments/operator-sdk-binary-v1.19.yaml @@ -0,0 +1,4 @@ +entries: + - description: > + Bumped `operator-sdk` binary dependencies to their k8s v1.19 equivalents. + kind: change diff --git a/go.mod b/go.mod index 96e1ac4c81e..b0a0f336604 100644 --- a/go.mod +++ b/go.mod @@ -11,9 +11,9 @@ require ( github.com/markbates/inflect v1.0.4 github.com/onsi/ginkgo v1.14.1 github.com/onsi/gomega v1.10.2 - github.com/operator-framework/api v0.3.20 - github.com/operator-framework/operator-lib v0.2.1-0.20201119204525-6700ae54da56 - github.com/operator-framework/operator-registry v1.14.3 + github.com/operator-framework/api v0.4.0 + github.com/operator-framework/operator-lib v0.3.0 + github.com/operator-framework/operator-registry v1.15.3 github.com/prometheus/client_golang v1.7.1 github.com/sergi/go-diff v1.0.0 github.com/sirupsen/logrus v1.7.0 @@ -32,9 +32,9 @@ require ( k8s.io/client-go v0.19.4 k8s.io/kubectl v0.19.4 rsc.io/letsencrypt v0.0.3 // indirect - sigs.k8s.io/controller-runtime v0.7.0-alpha.7 - sigs.k8s.io/controller-tools v0.3.0 - sigs.k8s.io/kubebuilder/v2 v2.3.2-0.20201204230216-593f2e80cdf6 + sigs.k8s.io/controller-runtime v0.7.0 + sigs.k8s.io/controller-tools v0.4.1 + sigs.k8s.io/kubebuilder/v2 v2.3.2-0.20201211222127-503ba3b7e4ad sigs.k8s.io/yaml v1.2.0 ) diff --git a/go.sum b/go.sum index 0af03fa6990..c80021a92c1 100644 --- a/go.sum +++ b/go.sum @@ -295,8 +295,6 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG github.com/go-logr/logr v0.1.0 h1:M1Tv3VzNlEHg6uyACnRdtrploV2P7wZqH8BoQMtz0cg= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/logr v0.2.1 h1:fV3MLmabKIZ383XifUjFSwcoGee0v9qgPp8wy5svibE= -github.com/go-logr/logr v0.2.1/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v0.3.0 h1:q4c+kbcR0d5rSurhBR8dIgieOaYpXtsdTYfx22Cu6rs= github.com/go-logr/logr v0.3.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/zapr v0.1.0 h1:h+WVe9j6HAA01niTJPA/kKH0i7e0rLZBCwauQFcRE54= @@ -709,13 +707,13 @@ github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxS github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/operator-framework/api v0.3.7-0.20200602203552-431198de9fc2/go.mod h1:Xbje9x0SHmh0nihE21kpesB38vk3cyxnE6JdDS8Jo1Q= -github.com/operator-framework/api v0.3.20 h1:2Ks8GXXl/H2sV9ll2iQBUO65ABQ5VuzN3IKEZCJWljo= -github.com/operator-framework/api v0.3.20/go.mod h1:Xbje9x0SHmh0nihE21kpesB38vk3cyxnE6JdDS8Jo1Q= -github.com/operator-framework/operator-lib v0.2.1-0.20201119204525-6700ae54da56 h1:RFuLAujDg2trSdvasocuc4MM/QS8eKRYmTerKQxIrv0= -github.com/operator-framework/operator-lib v0.2.1-0.20201119204525-6700ae54da56/go.mod h1:7JYMD1tU8z+dvtttqwPC59lOTEGAQRdGr+VlxkGJW2k= -github.com/operator-framework/operator-registry v1.14.3 h1:WiIYJy9cfnbzvlwoO5ikgqHnj/WwKLqItJlTz5EeEzQ= -github.com/operator-framework/operator-registry v1.14.3/go.mod h1:0x4Kkl/1LaK5g/6XgEiJrHF/jEAW3QKYg91M4sYuN0o= +github.com/operator-framework/api v0.3.22/go.mod h1:GVNiB6AQucwdZz3ZFXNv9HtcLOzcFnr6O/QldzKG93g= +github.com/operator-framework/api v0.4.0 h1:OeuGMXScjwosNKXttH3uorywr7APT5luTNPWy3zvqXs= +github.com/operator-framework/api v0.4.0/go.mod h1:xXYReW8+PpSBHMxsf0e7uhtfQTLqIM1iz4X6zUs20+c= +github.com/operator-framework/operator-lib v0.3.0 h1:eGJv0k7dEHIT9vfArWPo6U4eVurAOqhYUzXiHEaZq9g= +github.com/operator-framework/operator-lib v0.3.0/go.mod h1:LTp5UQd8ivq4MXqm/W/XHulHQ0RRoZXsAj73sNMAQxc= +github.com/operator-framework/operator-registry v1.15.3 h1:C+u+zjDh6yQAKN+DbUvPeLjojZtJftvp/J28rRqiWWU= +github.com/operator-framework/operator-registry v1.15.3/go.mod h1:CI7cu5ANoSQB54XWr/hXefm1PbKNJztSrhGBEDLCNCg= github.com/otiai10/copy v1.2.0 h1:HvG945u96iNadPoG2/Ja2+AUJeW5YuFQMixq9yirC+k= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= @@ -830,7 +828,6 @@ github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/cobra v0.0.6/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/cobra v0.0.7/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= @@ -898,8 +895,6 @@ github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wK gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.4 h1:hi1bXHMVrlQh6WwxAy+qZCV/SYIlqo+Ushwdpa4tAKg= -go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= @@ -1015,13 +1010,10 @@ golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191021144547-ec77196f6094/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191028085509-fe3aa8a45271/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= @@ -1141,6 +1133,7 @@ golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200403190813-44a64ad78b9b h1:AFZdJUT7jJYXQEC29hYH/WZkoV7+KhwxQGmdZ19yYoY= golang.org/x/tools v0.0.0-20200403190813-44a64ad78b9b/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200616195046-dc31b401abb5/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20201014231627-1610a49f37af h1:VIUWFyOgzG3c0t9KYop5Ybp4m56LupfOnFYX7Ipnz+I= golang.org/x/tools v0.0.0-20201014231627-1610a49f37af/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1355,14 +1348,14 @@ sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.9 h1:rusRLrDhjBp6aYtl9sGEvQJr6faoHoDLd0YcUBTZguI= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.9/go.mod h1:dzAXnQbTRyDlZPJX2SUPEqvnB+j7AJjtlox7PEwigU0= sigs.k8s.io/controller-runtime v0.6.0/go.mod h1:CpYf5pdNY/B352A1TFLAS2JVSlnGQ5O2cftPHndTroo= -sigs.k8s.io/controller-runtime v0.7.0-alpha.6 h1:ieFqEijQyDEZVIGwI5sYkk7VTa8Itim0kU/TCOnCkto= -sigs.k8s.io/controller-runtime v0.7.0-alpha.6/go.mod h1:03b1n6EtlDvuBPPEOHadJUusruwLWgoT4BDCybMibnA= -sigs.k8s.io/controller-runtime v0.7.0-alpha.7 h1:KtMmb2Ef/S38GNbf0Jpa+FWXqnxFYeWAyhipMmmPCcQ= -sigs.k8s.io/controller-runtime v0.7.0-alpha.7/go.mod h1:pJ3YBrJiAqMAZKi6UVGuE98ZrroV1p+pIhoHsMm9wdU= +sigs.k8s.io/controller-runtime v0.7.0 h1:bU20IBBEPccWz5+zXpLnpVsgBYxqclaHu1pVDl/gEt8= +sigs.k8s.io/controller-runtime v0.7.0/go.mod h1:pJ3YBrJiAqMAZKi6UVGuE98ZrroV1p+pIhoHsMm9wdU= sigs.k8s.io/controller-tools v0.3.0 h1:y3YD99XOyWaXkiF1kd41uRvfp/64teWcrEZFuHxPhJ4= sigs.k8s.io/controller-tools v0.3.0/go.mod h1:enhtKGfxZD1GFEoMgP8Fdbu+uKQ/cq1/WGJhdVChfvI= -sigs.k8s.io/kubebuilder/v2 v2.3.2-0.20201204230216-593f2e80cdf6 h1:SE+xhj4aauOCSeZKjRizd6VwHgkVfJABJpVk/xqYTiI= -sigs.k8s.io/kubebuilder/v2 v2.3.2-0.20201204230216-593f2e80cdf6/go.mod h1:J/D/179LBZhQOhRvmMRNbje/Bk+PjbN0/fzUupmO7+U= +sigs.k8s.io/controller-tools v0.4.1 h1:VkuV0MxlRPmRu5iTgBZU4UxUX2LiR99n3sdQGRxZF4w= +sigs.k8s.io/controller-tools v0.4.1/go.mod h1:G9rHdZMVlBDocIxGkK3jHLWqcTMNvveypYJwrvYKjWU= +sigs.k8s.io/kubebuilder/v2 v2.3.2-0.20201211222127-503ba3b7e4ad h1:QCCQLxLLZsNKgp49jG0rErcSz9oa/4J5WU7lnaEA99A= +sigs.k8s.io/kubebuilder/v2 v2.3.2-0.20201211222127-503ba3b7e4ad/go.mod h1:J/D/179LBZhQOhRvmMRNbje/Bk+PjbN0/fzUupmO7+U= sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0= sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU= sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= diff --git a/hack/generate/samples/internal/go/v2/memcached_with_webhooks.go b/hack/generate/samples/internal/go/v2/memcached_with_webhooks.go index bb0a6fce02c..9c1afcb68e1 100644 --- a/hack/generate/samples/internal/go/v2/memcached_with_webhooks.go +++ b/hack/generate/samples/internal/go/v2/memcached_with_webhooks.go @@ -59,6 +59,8 @@ func (mh *MemcachedGoWithWebhooks) Prepare() { func (mh *MemcachedGoWithWebhooks) Run() { log.Infof("creating the project") err := mh.ctx.Init( + // TODO(estroz): change this to 3 when stabilized. + "--project-version", "3-alpha", "--plugins", "go/v2", "--repo", "github.com/example/memcached-operator", "--domain", @@ -176,13 +178,8 @@ func (mh *MemcachedGoWithWebhooks) implementingWebhooks() { // Add imports err = kbtestutils.InsertCode(webhookPath, "import (", - "\n\t\"errors\"") - pkg.CheckError("adding errors import", err) - - err = kbtestutils.InsertCode(webhookPath, - "\n\t\"errors\"", - "\n\t\"k8s.io/apimachinery/pkg/runtime\"") - pkg.CheckError("adding k8s.io/apimachinery/pkg/runtime import", err) + "\"errors\"\n\n\"k8s.io/apimachinery/pkg/runtime\"") + pkg.CheckError("adding webhook imports", err) } // implementingController will customize the Controller diff --git a/hack/generate/samples/internal/go/v3/memcached_with_webhooks.go b/hack/generate/samples/internal/go/v3/memcached_with_webhooks.go index ec451b8fe36..57c7ac51ab6 100644 --- a/hack/generate/samples/internal/go/v3/memcached_with_webhooks.go +++ b/hack/generate/samples/internal/go/v3/memcached_with_webhooks.go @@ -59,7 +59,9 @@ func (mh *MemcachedGoWithWebhooks) Prepare() { func (mh *MemcachedGoWithWebhooks) Run() { log.Infof("creating the project") err := mh.ctx.Init( - // TODO(estroz): change this to go/v3 is stabilized. + // TODO(estroz): change this to 3 when stabilized. + "--project-version", "3-alpha", + // TODO(estroz): change this to go/v3 when stabilized. "--plugins", "go/v3-alpha", "--repo", "github.com/example/memcached-operator", "--domain", @@ -168,11 +170,11 @@ func (mh *MemcachedGoWithWebhooks) implementingWebhooks() { err := kbtestutils.InsertCode(webhookPath, "// TODO(user): fill in your defaulting logic.\n}", webhooksFragment) - pkg.CheckError("replacing reconcile", err) + pkg.CheckError("replacing webhook validate implementation", err) err = testutils.ReplaceInFile(webhookPath, "// TODO(user): fill in your defaulting logic.", "if r.Spec.Size == 0 {\n\t\tr.Spec.Size = 3\n\t}") - pkg.CheckError("replacing default webhook implementation", err) + pkg.CheckError("replacing webhook default implementation", err) // Add imports err = kbtestutils.InsertCode(webhookPath, @@ -420,7 +422,7 @@ const watchCustomizedFragment = `return ctrl.NewControllerManagedBy(mgr). const webhooksFragment = ` // TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation. -// +kubebuilder:webhook:path=/validate-cache-example-com-v1alpha1-memcached,mutating=false,failurePolicy=fail,sideEffects=None,groups=cache.example.com,resources=memcacheds,verbs=create;update,versions=v1alpha1,name=vmemcached.kb.io,admissionReviewVersions={v1beta1} +// +kubebuilder:webhook:path=/validate-cache-example-com-v1alpha1-memcached,mutating=false,failurePolicy=fail,sideEffects=None,groups=cache.example.com,resources=memcacheds,verbs=create;update,versions=v1alpha1,name=vmemcached.kb.io,admissionReviewVersions={v1,v1beta1} var _ webhook.Validator = &Memcached{} diff --git a/internal/ansible/controller/reconcile_test.go b/internal/ansible/controller/reconcile_test.go index a697aac2839..e60a40bc5fb 100644 --- a/internal/ansible/controller/reconcile_test.go +++ b/internal/ansible/controller/reconcile_test.go @@ -62,7 +62,7 @@ func TestReconcile(t *testing.T) { Runner: &fake.Runner{ JobEvents: []eventapi.JobEvent{}, }, - Client: fakeclient.NewFakeClient(), + Client: fakeclient.NewClientBuilder().Build(), Result: reconcile.Result{}, Request: reconcile.Request{ NamespacedName: types.NamespacedName{ @@ -84,7 +84,7 @@ func TestReconcile(t *testing.T) { }, }, }, - Client: fakeclient.NewFakeClient(&unstructured.Unstructured{ + Client: fakeclient.NewClientBuilder().WithObjects(&unstructured.Unstructured{ Object: map[string]interface{}{ "metadata": map[string]interface{}{ "name": "reconcile", @@ -93,7 +93,7 @@ func TestReconcile(t *testing.T) { "apiVersion": "operator-sdk/v1beta1", "kind": "Testing", }, - }), + }).Build(), Result: reconcile.Result{ RequeueAfter: 5 * time.Second, }, @@ -153,7 +153,7 @@ func TestReconcile(t *testing.T) { }, }, }, - Client: fakeclient.NewFakeClient(&unstructured.Unstructured{ + Client: fakeclient.NewClientBuilder().WithObjects(&unstructured.Unstructured{ Object: map[string]interface{}{ "metadata": map[string]interface{}{ "name": "reconcile", @@ -163,7 +163,7 @@ func TestReconcile(t *testing.T) { "kind": "Testing", "spec": map[string]interface{}{}, }, - }), + }).Build(), Request: reconcile.Request{ NamespacedName: types.NamespacedName{ Name: "reconcile", @@ -227,7 +227,7 @@ func TestReconcile(t *testing.T) { }, }, }, - Client: fakeclient.NewFakeClient(&unstructured.Unstructured{ + Client: fakeclient.NewClientBuilder().WithObjects(&unstructured.Unstructured{ Object: map[string]interface{}{ "metadata": map[string]interface{}{ "name": "reconcile", @@ -237,7 +237,7 @@ func TestReconcile(t *testing.T) { "kind": "Testing", "spec": map[string]interface{}{}, }, - }), + }).Build(), Request: reconcile.Request{ NamespacedName: types.NamespacedName{ Name: "reconcile", @@ -260,7 +260,7 @@ func TestReconcile(t *testing.T) { }, Finalizer: "testing.io", }, - Client: fakeclient.NewFakeClient(&unstructured.Unstructured{ + Client: fakeclient.NewClientBuilder().WithObjects(&unstructured.Unstructured{ Object: map[string]interface{}{ "metadata": map[string]interface{}{ "name": "reconcile", @@ -273,7 +273,7 @@ func TestReconcile(t *testing.T) { "kind": "Testing", "spec": map[string]interface{}{}, }, - }), + }).Build(), Result: reconcile.Result{ RequeueAfter: 3 * time.Second, }, @@ -331,7 +331,7 @@ func TestReconcile(t *testing.T) { }, Finalizer: "testing.io", }, - Client: fakeclient.NewFakeClient(&unstructured.Unstructured{ + Client: fakeclient.NewClientBuilder().WithObjects(&unstructured.Unstructured{ Object: map[string]interface{}{ "metadata": map[string]interface{}{ "name": "reconcile", @@ -345,7 +345,7 @@ func TestReconcile(t *testing.T) { "kind": "Testing", "spec": map[string]interface{}{}, }, - }), + }).Build(), Result: reconcile.Result{}, Request: reconcile.Request{ NamespacedName: types.NamespacedName{ @@ -368,7 +368,7 @@ func TestReconcile(t *testing.T) { }, Finalizer: "testing.io", }, - Client: fakeclient.NewFakeClient(&unstructured.Unstructured{ + Client: fakeclient.NewClientBuilder().WithObjects(&unstructured.Unstructured{ Object: map[string]interface{}{ "metadata": map[string]interface{}{ "name": "reconcile", @@ -399,7 +399,7 @@ func TestReconcile(t *testing.T) { }, }, }, - }), + }).Build(), Result: reconcile.Result{ RequeueAfter: 5 * time.Second, }, @@ -449,7 +449,7 @@ func TestReconcile(t *testing.T) { }, }, }, - Client: fakeclient.NewFakeClient(&unstructured.Unstructured{ + Client: fakeclient.NewClientBuilder().WithObjects(&unstructured.Unstructured{ Object: map[string]interface{}{ "metadata": map[string]interface{}{ "name": "reconcile", @@ -475,7 +475,7 @@ func TestReconcile(t *testing.T) { }, }, }, - }), + }).Build(), Result: reconcile.Result{ RequeueAfter: 5 * time.Second, }, @@ -500,7 +500,7 @@ func TestReconcile(t *testing.T) { }, }, }, - Client: fakeclient.NewFakeClient(&unstructured.Unstructured{ + Client: fakeclient.NewClientBuilder().WithObjects(&unstructured.Unstructured{ Object: map[string]interface{}{ "metadata": map[string]interface{}{ "name": "reconcile", @@ -509,7 +509,7 @@ func TestReconcile(t *testing.T) { "apiVersion": "operator-sdk/v1beta1", "kind": "Testing", }, - }), + }).Build(), Result: reconcile.Result{ RequeueAfter: 5 * time.Second, }, diff --git a/internal/olm/client/client_test.go b/internal/olm/client/client_test.go index b5f0a170ed2..c513f2bb9be 100644 --- a/internal/olm/client/client_test.go +++ b/internal/olm/client/client_test.go @@ -74,8 +74,7 @@ var _ = Describe("Client", func() { }) Context("with a valid csv", func() { It("check error string for pod errors", func() { - fakeClient = fake.NewFakeClient( - + fakeClient = fake.NewClientBuilder().WithObjects( &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: "test-operator-kc44t", @@ -119,7 +118,7 @@ var _ = Describe("Client", func() { }, }, }, - ) + ).Build() key := types.NamespacedName{ Name: "test.operator", Namespace: "test-operator-system", @@ -130,7 +129,7 @@ var _ = Describe("Client", func() { }) It("check error string for multiple pod failures", func() { - fakeClt := fake.NewFakeClient( + fakeClt := fake.NewClientBuilder().WithObjects( &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: "test-operator-jjj", @@ -196,7 +195,7 @@ var _ = Describe("Client", func() { }, }, }, - ) + ).Build() key := types.NamespacedName{ Name: "test.operator", Namespace: "test-operator-system", @@ -208,7 +207,7 @@ var _ = Describe("Client", func() { }) It("check error string for deployment errors,when no pods exist", func() { - fakeClient = fake.NewFakeClient( + fakeClient = fake.NewClientBuilder().WithObjects( &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: "test-operator-controller-manager", @@ -227,7 +226,7 @@ var _ = Describe("Client", func() { }, }, }, - ) + ).Build() key := types.NamespacedName{ Name: "test-operator", Namespace: "test-operator-system", @@ -238,7 +237,7 @@ var _ = Describe("Client", func() { }) It("check error string,when no deployments exist for given CSV", func() { - fakeClient = fake.NewFakeClient() + fakeClient = fake.NewClientBuilder().Build() olmclient := Client{KubeClient: fakeClient} key := types.NamespacedName{ Name: "test-operator", @@ -249,7 +248,7 @@ var _ = Describe("Client", func() { Expect(err.Error()).To(ContainSubstring("\"dummy-operator\" not found")) }) It("check error string,when no namespace provided", func() { - fakeClient = fake.NewFakeClient() + fakeClient = fake.NewClientBuilder().Build() olmclient := Client{KubeClient: fakeClient} key := types.NamespacedName{ Name: "test-operator", diff --git a/internal/olm/operator/registry/configmap/configmap_test.go b/internal/olm/operator/registry/configmap/configmap_test.go index b54c86222b3..434e4855555 100644 --- a/internal/olm/operator/registry/configmap/configmap_test.go +++ b/internal/olm/operator/registry/configmap/configmap_test.go @@ -243,7 +243,7 @@ var _ = Describe("ConfigMap", func() { e error ) BeforeEach(func() { - fakeclient := fake.NewFakeClient( + fakeclient := fake.NewClientBuilder().WithObjects( &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Namespace: "testns", @@ -256,7 +256,7 @@ var _ = Describe("ConfigMap", func() { Labels: makeRegistryLabels("test"), }, }, - ) + ).Build() rr = RegistryResources{ Client: &client.Client{ KubeClient: fakeclient, diff --git a/internal/olm/operator/registry/configmap/registry_test.go b/internal/olm/operator/registry/configmap/registry_test.go index e1436c01ae3..7ca7c3d0a02 100644 --- a/internal/olm/operator/registry/configmap/registry_test.go +++ b/internal/olm/operator/registry/configmap/registry_test.go @@ -61,7 +61,7 @@ var _ = Describe("Registry", func() { Describe("DeletePackageManifestsRegistry", func() { It("should delete the package manifest registry", func() { - fakeclient := fake.NewFakeClient( + fakeclient := fake.NewClientBuilder().WithObjects( &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Namespace: "testns", @@ -70,7 +70,7 @@ var _ = Describe("Registry", func() { }, newRegistryDeployment("pkgName", "testns"), newRegistryService("pkgName", "testns"), - ) + ).Build() rr := RegistryResources{ Pkg: &manifests.PackageManifest{ PackageName: "pkgName", @@ -123,7 +123,7 @@ var _ = Describe("Registry", func() { ) BeforeEach(func() { testns = "testns" - fakeclient := fake.NewFakeClient( + fakeclient := fake.NewClientBuilder().WithObjects( &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Namespace: testns, @@ -132,7 +132,7 @@ var _ = Describe("Registry", func() { }, newRegistryDeployment("pkgName", testns), newRegistryService("pkgName", testns), - ) + ).Build() rr = RegistryResources{ Pkg: &manifests.PackageManifest{ PackageName: "pkgName", @@ -196,7 +196,7 @@ var _ = Describe("Registry", func() { ) BeforeEach(func() { testns = "testns" - fakeclient := fake.NewFakeClient( + fakeclient := fake.NewClientBuilder().WithObjects( &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: "config1", @@ -213,7 +213,7 @@ var _ = Describe("Registry", func() { }, newRegistryDeployment("pkgName", testns), newRegistryService("pkgName", testns), - ) + ).Build() rr = RegistryResources{ Pkg: &manifests.PackageManifest{ PackageName: "pkgName", @@ -251,7 +251,7 @@ var _ = Describe("Registry", func() { }) It("should return true if there are no registry configmaps", func() { - rr.Client.KubeClient = fake.NewFakeClient() + rr.Client.KubeClient = fake.NewClientBuilder().Build() temp, err := rr.IsRegistryDataStale(context.TODO(), testns) Expect(err).Should(BeNil()) @@ -266,7 +266,7 @@ var _ = Describe("Registry", func() { }) It("should return true if the number of files to be added to the registry don't match the numberof files currently in the registry", func() { - rr.Client.KubeClient = fake.NewFakeClient( + rr.Client.KubeClient = fake.NewClientBuilder().WithObjects( &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: getRegistryConfigMapName("pkgName") + "-package", @@ -283,7 +283,7 @@ var _ = Describe("Registry", func() { }, newRegistryDeployment("pkgName", testns), newRegistryService("pkgName", testns), - ) + ).Build() temp, err := rr.IsRegistryDataStale(context.TODO(), testns) Expect(err).Should(BeNil()) @@ -298,7 +298,7 @@ var _ = Describe("Registry", func() { val1: "val1", val2: "val2", }, "userInput") - rr.Client.KubeClient = fake.NewFakeClient( + rr.Client.KubeClient = fake.NewClientBuilder().WithObjects( &corev1.ConfigMap{ BinaryData: binarydata, ObjectMeta: metav1.ObjectMeta{ @@ -316,7 +316,7 @@ var _ = Describe("Registry", func() { }, newRegistryDeployment("pkgName", testns), newRegistryService("pkgName", testns), - ) + ).Build() temp, err := rr.IsRegistryDataStale(context.TODO(), testns) Expect(err).Should(BeNil()) @@ -332,7 +332,7 @@ var _ = Describe("Registry", func() { }, }, }) - rr.Client.KubeClient = fake.NewFakeClient( + rr.Client.KubeClient = fake.NewClientBuilder().WithObjects( &corev1.ConfigMap{ BinaryData: binarydata, ObjectMeta: metav1.ObjectMeta{ @@ -350,7 +350,7 @@ var _ = Describe("Registry", func() { }, newRegistryDeployment("pkgName", testns), newRegistryService("pkgName", testns), - ) + ).Build() temp, err := rr.IsRegistryDataStale(context.TODO(), testns) Expect(err).Should(BeNil()) diff --git a/internal/olm/operator/registry/configmap_test.go b/internal/olm/operator/registry/configmap_test.go index 871cc2ed508..95be3c02642 100644 --- a/internal/olm/operator/registry/configmap_test.go +++ b/internal/olm/operator/registry/configmap_test.go @@ -42,7 +42,9 @@ var _ = Describe("Configmap", func() { ctlog := &ConfigMapCatalogCreator{ cfg: &operator.Configuration{ Namespace: "testns", - Client: fake.NewFakeClient(newCatalogSource("pkgName", "testns", withSDKPublisher("pkgName"))), + Client: fake.NewClientBuilder().WithObjects( + newCatalogSource("pkgName", "testns", withSDKPublisher("pkgName")), + ).Build(), }, Package: &apimanifests.PackageManifest{ PackageName: "pkgName", @@ -61,7 +63,7 @@ var _ = Describe("Configmap", func() { ctlog := &ConfigMapCatalogCreator{ cfg: &operator.Configuration{ Namespace: "testns", - Client: fake.NewFakeClient(cs), + Client: fake.NewClientBuilder().WithObjects(cs).Build(), }, Package: &apimanifests.PackageManifest{ PackageName: "pkgName", diff --git a/internal/olm/operator/registry/index/registry_pod_test.go b/internal/olm/operator/registry/index/registry_pod_test.go index 49ea305e5ea..c306a34d38d 100644 --- a/internal/olm/operator/registry/index/registry_pod_test.go +++ b/internal/olm/operator/registry/index/registry_pod_test.go @@ -32,7 +32,7 @@ import ( // newFakeClient() returns a fake controller runtime client func newFakeClient() client.Client { - return fakeclient.NewFakeClient() + return fakeclient.NewClientBuilder().Build() } func TestCreateRegistryPod(t *testing.T) { diff --git a/internal/olm/operator/registry/operator_installer_test.go b/internal/olm/operator/registry/operator_installer_test.go index 0719600ed99..5d5357d2f0c 100644 --- a/internal/olm/operator/registry/operator_installer_test.go +++ b/internal/olm/operator/registry/operator_installer_test.go @@ -52,7 +52,7 @@ var _ = Describe("OperatorInstaller", func() { sch = runtime.NewScheme() Expect(v1.AddToScheme(sch)).To(Succeed()) Expect(v1alpha1.AddToScheme(sch)).To(Succeed()) - cfg.Client = fake.NewFakeClientWithScheme(sch) + cfg.Client = fake.NewClientBuilder().WithScheme(sch).Build() oi = NewOperatorInstaller(cfg) oi.StartingCSV = "fakeName" @@ -77,7 +77,7 @@ var _ = Describe("OperatorInstaller", func() { It("should pass through any client errors (duplicate)", func() { sub := newSubscription(oi.StartingCSV, oi.cfg.Namespace, withCatalogSource("duplicate", oi.cfg.Namespace)) - oi.cfg.Client = fake.NewFakeClientWithScheme(sch, sub) + oi.cfg.Client = fake.NewClientBuilder().WithScheme(sch).WithObjects(sub).Build() _, err := oi.createSubscription(context.TODO(), "duplicate") Expect(err).To(HaveOccurred()) @@ -98,14 +98,14 @@ var _ = Describe("OperatorInstaller", func() { }) It("should update the install plan", func() { - oi.cfg.Client = fake.NewFakeClientWithScheme(sch, + oi.cfg.Client = fake.NewClientBuilder().WithScheme(sch).WithObjects( &v1alpha1.InstallPlan{ ObjectMeta: metav1.ObjectMeta{ Name: "fakeName", Namespace: "fakeNS", }, }, - ) + ).Build() ip := &v1alpha1.InstallPlan{} ipKey := types.NamespacedName{ @@ -136,7 +136,7 @@ var _ = Describe("OperatorInstaller", func() { Expect(ip.Spec.Approved).To(Equal(true)) }) It("should return an error if the install plan does not exist.", func() { - oi.cfg.Client = fake.NewFakeClientWithScheme(sch) + oi.cfg.Client = fake.NewClientBuilder().WithScheme(sch).Build() sub := &v1alpha1.Subscription{ Status: v1alpha1.SubscriptionStatus{ InstallPlanRef: &corev1.ObjectReference{ @@ -161,7 +161,7 @@ var _ = Describe("OperatorInstaller", func() { cfg := &operator.Configuration{} sch = runtime.NewScheme() Expect(v1alpha1.AddToScheme(sch)).To(Succeed()) - cfg.Client = fake.NewFakeClientWithScheme(sch) + cfg.Client = fake.NewClientBuilder().WithScheme(sch).Build() oi = NewOperatorInstaller(cfg) oi.StartingCSV = "fakeName" @@ -204,7 +204,7 @@ var _ = Describe("OperatorInstaller", func() { BeforeEach(func() { sch := runtime.NewScheme() Expect(v1.AddToScheme(sch)).To(Succeed()) - client = fake.NewFakeClientWithScheme(sch) + client = fake.NewClientBuilder().WithScheme(sch).Build() oi = OperatorInstaller{ cfg: &operator.Configuration{ Scheme: sch, @@ -231,7 +231,7 @@ var _ = Describe("OperatorInstaller", func() { oi.SupportedInstallModes = operator.GetSupportedInstallModes(modes) }) It("should return an error when problems finding OperatorGroup", func() { - oi.cfg.Client = fake.NewFakeClient() + oi.cfg.Client = fake.NewClientBuilder().Build() err := oi.ensureOperatorGroup(context.TODO()) Expect(err).To(HaveOccurred()) }) @@ -382,7 +382,7 @@ var _ = Describe("OperatorInstaller", func() { BeforeEach(func() { sch := runtime.NewScheme() Expect(v1.AddToScheme(sch)).To(Succeed()) - client = fake.NewFakeClientWithScheme(sch) + client = fake.NewClientBuilder().WithScheme(sch).Build() oi = OperatorInstaller{ cfg: &operator.Configuration{ Scheme: sch, @@ -453,7 +453,7 @@ var _ = Describe("OperatorInstaller", func() { BeforeEach(func() { sch := runtime.NewScheme() Expect(v1.AddToScheme(sch)).To(Succeed()) - client = fake.NewFakeClientWithScheme(sch) + client = fake.NewClientBuilder().WithScheme(sch).Build() oi = OperatorInstaller{ cfg: &operator.Configuration{ Scheme: sch, @@ -463,7 +463,7 @@ var _ = Describe("OperatorInstaller", func() { } }) It("should return an error if no OperatorGroups exist", func() { - oi.cfg.Client = fake.NewFakeClient() + oi.cfg.Client = fake.NewClientBuilder().Build() grp, found, err := oi.getOperatorGroup(context.TODO()) Expect(grp).To(BeNil()) Expect(found).To(BeFalse()) diff --git a/testdata/go/v2/memcached-operator/api/v1alpha1/memcached_webhook.go b/testdata/go/v2/memcached-operator/api/v1alpha1/memcached_webhook.go index 99a42b91d10..e2063a6fc66 100644 --- a/testdata/go/v2/memcached-operator/api/v1alpha1/memcached_webhook.go +++ b/testdata/go/v2/memcached-operator/api/v1alpha1/memcached_webhook.go @@ -18,6 +18,7 @@ package v1alpha1 import ( "errors" + "k8s.io/apimachinery/pkg/runtime" ctrl "sigs.k8s.io/controller-runtime" logf "sigs.k8s.io/controller-runtime/pkg/log" diff --git a/testdata/go/v3/memcached-operator/Makefile b/testdata/go/v3/memcached-operator/Makefile index 482fa7aebe7..4a517477bf3 100644 --- a/testdata/go/v3/memcached-operator/Makefile +++ b/testdata/go/v3/memcached-operator/Makefile @@ -29,7 +29,7 @@ all: manager ENVTEST_ASSETS_DIR=$(shell pwd)/testbin test: generate fmt vet manifests mkdir -p ${ENVTEST_ASSETS_DIR} - test -f ${ENVTEST_ASSETS_DIR}/setup-envtest.sh || curl -sSLo ${ENVTEST_ASSETS_DIR}/setup-envtest.sh https://raw.githubusercontent.com/kubernetes-sigs/controller-runtime/v0.7.0-alpha.8/hack/setup-envtest.sh + test -f ${ENVTEST_ASSETS_DIR}/setup-envtest.sh || curl -sSLo ${ENVTEST_ASSETS_DIR}/setup-envtest.sh https://raw.githubusercontent.com/kubernetes-sigs/controller-runtime/v0.7.0/hack/setup-envtest.sh source ${ENVTEST_ASSETS_DIR}/setup-envtest.sh; fetch_envtest_tools $(ENVTEST_ASSETS_DIR); setup_envtest_env $(ENVTEST_ASSETS_DIR); go test ./... -coverprofile cover.out # Build manager binary diff --git a/testdata/go/v3/memcached-operator/api/v1alpha1/memcached_webhook.go b/testdata/go/v3/memcached-operator/api/v1alpha1/memcached_webhook.go index 65cafb56d07..b9189aa44af 100644 --- a/testdata/go/v3/memcached-operator/api/v1alpha1/memcached_webhook.go +++ b/testdata/go/v3/memcached-operator/api/v1alpha1/memcached_webhook.go @@ -36,7 +36,7 @@ func (r *Memcached) SetupWebhookWithManager(mgr ctrl.Manager) error { // EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! -// +kubebuilder:webhook:path=/mutate-cache-example-com-v1alpha1-memcached,mutating=true,failurePolicy=fail,sideEffects=None,groups=cache.example.com,resources=memcacheds,verbs=create;update,versions=v1alpha1,name=mmemcached.kb.io,admissionReviewVersions={v1beta1} +// +kubebuilder:webhook:path=/mutate-cache-example-com-v1alpha1-memcached,mutating=true,failurePolicy=fail,sideEffects=None,groups=cache.example.com,resources=memcacheds,verbs=create;update,versions=v1alpha1,name=mmemcached.kb.io,admissionReviewVersions={v1,v1beta1} var _ webhook.Defaulter = &Memcached{} @@ -50,7 +50,7 @@ func (r *Memcached) Default() { } // TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation. -// +kubebuilder:webhook:path=/validate-cache-example-com-v1alpha1-memcached,mutating=false,failurePolicy=fail,sideEffects=None,groups=cache.example.com,resources=memcacheds,verbs=create;update,versions=v1alpha1,name=vmemcached.kb.io,admissionReviewVersions={v1beta1} +// +kubebuilder:webhook:path=/validate-cache-example-com-v1alpha1-memcached,mutating=false,failurePolicy=fail,sideEffects=None,groups=cache.example.com,resources=memcacheds,verbs=create;update,versions=v1alpha1,name=vmemcached.kb.io,admissionReviewVersions={v1,v1beta1} var _ webhook.Validator = &Memcached{} diff --git a/testdata/go/v3/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml b/testdata/go/v3/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml index d6ad1d003da..44ab0a69513 100644 --- a/testdata/go/v3/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml +++ b/testdata/go/v3/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml @@ -213,6 +213,7 @@ spec: version: 0.0.1 webhookdefinitions: - admissionReviewVersions: + - v1 - v1beta1 containerPort: 443 deploymentName: memcached-operator-controller-manager @@ -233,6 +234,7 @@ spec: type: ValidatingAdmissionWebhook webhookPath: /validate-cache-example-com-v1alpha1-memcached - admissionReviewVersions: + - v1 - v1beta1 containerPort: 443 deploymentName: memcached-operator-controller-manager diff --git a/testdata/go/v3/memcached-operator/config/webhook/manifests.yaml b/testdata/go/v3/memcached-operator/config/webhook/manifests.yaml index 0ac58a1bd25..2dcfac150f8 100644 --- a/testdata/go/v3/memcached-operator/config/webhook/manifests.yaml +++ b/testdata/go/v3/memcached-operator/config/webhook/manifests.yaml @@ -7,6 +7,7 @@ metadata: name: mutating-webhook-configuration webhooks: - admissionReviewVersions: + - v1 - v1beta1 clientConfig: service: @@ -35,6 +36,7 @@ metadata: name: validating-webhook-configuration webhooks: - admissionReviewVersions: + - v1 - v1beta1 clientConfig: service: diff --git a/testdata/go/v3/memcached-operator/controllers/memcached_controller.go b/testdata/go/v3/memcached-operator/controllers/memcached_controller.go index 4ed03157281..0978d43bd4c 100644 --- a/testdata/go/v3/memcached-operator/controllers/memcached_controller.go +++ b/testdata/go/v3/memcached-operator/controllers/memcached_controller.go @@ -55,7 +55,7 @@ type MemcachedReconciler struct { // the user. // // For more details, check Reconcile and its Result here: -// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.7.0-alpha.8/pkg/reconcile +// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.7.0/pkg/reconcile func (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { log := r.Log.WithValues("memcached", req.NamespacedName) diff --git a/testdata/go/v3/memcached-operator/go.mod b/testdata/go/v3/memcached-operator/go.mod index 8ea59968a61..64a36fc9214 100644 --- a/testdata/go/v3/memcached-operator/go.mod +++ b/testdata/go/v3/memcached-operator/go.mod @@ -9,5 +9,5 @@ require ( k8s.io/api v0.19.2 k8s.io/apimachinery v0.19.2 k8s.io/client-go v0.19.2 - sigs.k8s.io/controller-runtime v0.7.0-alpha.8 + sigs.k8s.io/controller-runtime v0.7.0 ) diff --git a/testdata/go/v3/memcached-operator/go.sum b/testdata/go/v3/memcached-operator/go.sum index 843c9201519..ed5f385e5f3 100644 --- a/testdata/go/v3/memcached-operator/go.sum +++ b/testdata/go/v3/memcached-operator/go.sum @@ -629,8 +629,8 @@ k8s.io/utils v0.0.0-20200912215256-4140de9c8800 h1:9ZNvfPvVIEsp/T1ez4GQuzCcCTEQW k8s.io/utils v0.0.0-20200912215256-4140de9c8800/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.9/go.mod h1:dzAXnQbTRyDlZPJX2SUPEqvnB+j7AJjtlox7PEwigU0= -sigs.k8s.io/controller-runtime v0.7.0-alpha.8 h1:l8I2KO3xLuNaT0yPP6mtWLw5NuMG3dY2YiaQXEGApXg= -sigs.k8s.io/controller-runtime v0.7.0-alpha.8/go.mod h1:pJ3YBrJiAqMAZKi6UVGuE98ZrroV1p+pIhoHsMm9wdU= +sigs.k8s.io/controller-runtime v0.7.0 h1:bU20IBBEPccWz5+zXpLnpVsgBYxqclaHu1pVDl/gEt8= +sigs.k8s.io/controller-runtime v0.7.0/go.mod h1:pJ3YBrJiAqMAZKi6UVGuE98ZrroV1p+pIhoHsMm9wdU= sigs.k8s.io/structured-merge-diff/v4 v4.0.1 h1:YXTMot5Qz/X1iBRJhAt+vI+HVttY0WkSqqhKxQ0xVbA= sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= From 4fe75ed09217ddf9f8f5ae47fda0e555abd892e0 Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Mon, 14 Dec 2020 13:06:41 -0800 Subject: [PATCH 243/376] netlify.toml: pin postcss dependency to ^8.0.0, recursive submodule update (#4313) Signed-off-by: reinvantveer --- hack/ci/check-doc-only-update.sh | 1 + netlify.toml | 4 +- website/assets/scss/_styles_project.scss | 2 - website/package-lock.json | 300 ++++++++++------------- 4 files changed, 139 insertions(+), 168 deletions(-) diff --git a/hack/ci/check-doc-only-update.sh b/hack/ci/check-doc-only-update.sh index 82540f97cc4..c768227a8c4 100755 --- a/hack/ci/check-doc-only-update.sh +++ b/hack/ci/check-doc-only-update.sh @@ -14,6 +14,7 @@ DOC_PATTERNS=( "(\.MD)" "(\.png)" "(\.pdf)" + "(netlify\.toml)" "^(doc/)" "^(website/)" "^(changelog/)" diff --git a/netlify.toml b/netlify.toml index cf743111880..26d0105a430 100644 --- a/netlify.toml +++ b/netlify.toml @@ -6,8 +6,8 @@ publish = "public" base = "website" command = """ -git submodule update -f --init themes/docsy && \ -npm install postcss-cli autoprefixer@^9.0.0 && \ +git submodule update -f --init --recursive themes/docsy && \ +npm install postcss@^8.0.0 postcss-cli@^8.0.0 autoprefixer@^9.0.0 && \ ./scripts/set_menu_version.sh && \ hugo version && \ hugo diff --git a/website/assets/scss/_styles_project.scss b/website/assets/scss/_styles_project.scss index e06d2d6c228..4d42bf6cd59 100644 --- a/website/assets/scss/_styles_project.scss +++ b/website/assets/scss/_styles_project.scss @@ -72,5 +72,3 @@ footer { //global @import "global"; - - diff --git a/website/package-lock.json b/website/package-lock.json index 15838aa675c..830f0465a2a 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -97,6 +97,50 @@ "num2fraction": "^1.2.2", "postcss": "^7.0.32", "postcss-value-parser": "^4.1.0" + }, + "dependencies": { + "browserslist": { + "version": "4.16.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.0.tgz", + "integrity": "sha512-/j6k8R0p3nxOC6kx5JGAxsnhc9ixaWJfYc+TNTzxg6+ARaESAvQGV7h0uNOB4t+pLQJZWzcrMxXOxjgsCj3dqQ==", + "requires": { + "caniuse-lite": "^1.0.30001165", + "colorette": "^1.2.1", + "electron-to-chromium": "^1.3.621", + "escalade": "^3.1.1", + "node-releases": "^1.1.67" + } + }, + "caniuse-lite": { + "version": "1.0.30001166", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001166.tgz", + "integrity": "sha512-nCL4LzYK7F4mL0TjEMeYavafOGnBa98vTudH5c8lW9izUjnB99InG6pmC1ElAI1p0GlyZajv4ltUdFXvOHIl1A==" + }, + "electron-to-chromium": { + "version": "1.3.626", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.626.tgz", + "integrity": "sha512-7CanEvJx74EnvjHu1X8gf93KieyxvFLnqOXAH/ddjWD4RrUZYqdg3pykrQ/7t6SLI7DTsp4tfQXEfzeK5t6oAw==" + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + }, + "node-releases": { + "version": "1.1.67", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.67.tgz", + "integrity": "sha512-V5QF9noGFl3EymEwUYzO+3NTDpGfQB4ve6Qfnzf3UNydMhjQRVPR1DZTuvWiLzaFJYw2fmDwAfnRNEVb64hSIg==" + }, + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + } } }, "binary-extensions": { @@ -112,27 +156,11 @@ "fill-range": "^7.0.1" } }, - "browserslist": { - "version": "4.14.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.5.tgz", - "integrity": "sha512-Z+vsCZIvCBvqLoYkBFTwEYH3v5MCQbsAjp50ERycpOjnPmolg1Gjy4+KaWWpm8QOJt9GHkhdqAl14NpCX73CWA==", - "requires": { - "caniuse-lite": "^1.0.30001135", - "electron-to-chromium": "^1.3.571", - "escalade": "^3.1.0", - "node-releases": "^1.1.61" - } - }, "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" }, - "caniuse-lite": { - "version": "1.0.30001146", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001146.tgz", - "integrity": "sha512-VAy5RHDfTJhpxnDdp2n40GPPLp3KqNrXz1QqFv4J64HvArKs8nuNMOWkB3ICOaBTU/Aj4rYAo/ytdQDDFF/Pug==" - }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -153,31 +181,6 @@ } } }, - "chokidar": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", - "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==", - "requires": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "fsevents": "~2.1.2", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.4.0" - } - }, - "cliui": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.1.tgz", - "integrity": "sha512-rcvHOWyGyid6I1WjT/3NatKj2kDt9OdSHSXpyLXaMWFbKpGACNW8pRhhdPUq9MWUOdwn8Rz9AVETjF4105rZZQ==", - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -221,11 +224,6 @@ "path-type": "^4.0.0" } }, - "electron-to-chromium": { - "version": "1.3.578", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.578.tgz", - "integrity": "sha512-z4gU6dA1CbBJsAErW5swTGAaU2TBzc2mPAonJb00zqW1rOraDo2zfBMDRvaz9cVic+0JEZiYbHWPw/fTaZlG2Q==" - }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -239,11 +237,6 @@ "is-arrayish": "^0.2.1" } }, - "escalade": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.0.tgz", - "integrity": "sha512-mAk+hPSO8fLDkhV7V0dXazH5pDc6MrjBTPyD3VeKzxnVFjH1MIxbCdqGZB9O8+EwWakZs3ZCbDS4IpRt79V1ig==" - }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -458,59 +451,6 @@ "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" }, - "log-symbols": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", - "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", - "requires": { - "chalk": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, "merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -525,11 +465,6 @@ "picomatch": "^2.0.5" } }, - "node-releases": { - "version": "1.1.61", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.61.tgz", - "integrity": "sha512-DD5vebQLg8jLCOzwupn954fbIiZht05DAZs0k2u8NStSe6h9XdsuIQL8hSRKYiU8WUQRznmSDrKGbv3ObOmC7g==" - }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -580,19 +515,26 @@ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" }, "postcss": { - "version": "7.0.35", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", - "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.1.tgz", + "integrity": "sha512-RhsqOOAQzTgh1UB/IZdca7F9WDb7SUCR2Vnv1x7DbvuuggQIpoDwjK+q0rzoPffhYvWNKX5JSwS4so4K3UC6vA==", "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" + "colorette": "^1.2.1", + "nanoid": "^3.1.20", + "source-map": "^0.6.1" + }, + "dependencies": { + "nanoid": { + "version": "3.1.20", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", + "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==" + } } }, "postcss-cli": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/postcss-cli/-/postcss-cli-8.1.0.tgz", - "integrity": "sha512-FYuV5zyYX53X5RywInxjWLqHZ4oCBC3nDwrHYU3Z75mFqUo5IHfbeY593heWSagG90nPnXq3tXCck8+2CUl8EA==", + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/postcss-cli/-/postcss-cli-8.3.1.tgz", + "integrity": "sha512-leHXsQRq89S3JC9zw/tKyiVV2jAhnfQe0J8VI4eQQbUjwIe0XxVqLrR+7UsahF1s9wi4GlqP6SJ8ydf44cgF2Q==", "requires": { "chalk": "^4.0.0", "chokidar": "^3.3.0", @@ -604,6 +546,7 @@ "postcss-reporter": "^7.0.0", "pretty-hrtime": "^1.0.3", "read-cache": "^1.0.0", + "slash": "^3.0.0", "yargs": "^16.0.0" }, "dependencies": { @@ -624,6 +567,31 @@ "supports-color": "^7.1.0" } }, + "chokidar": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", + "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + } + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -637,11 +605,37 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, + "postcss-reporter": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-7.0.2.tgz", + "integrity": "sha512-JyQ96NTQQsso42y6L1H1RqHfWH1C3Jr0pt91mVv5IdYddZAE9DUZxuferNgk6q0o6vBVOrfVJb10X1FgDzjmDw==", + "requires": { + "colorette": "^1.2.1", + "lodash.difference": "^4.5.0", + "lodash.forown": "^4.4.0", + "lodash.get": "^4.4.2", + "lodash.groupby": "^4.6.0", + "lodash.sortby": "^4.7.0" + } + }, + "readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "requires": { + "picomatch": "^2.2.1" + } + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -649,6 +643,30 @@ "requires": { "has-flag": "^4.0.0" } + }, + "y18n": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz", + "integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==" + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==" } } }, @@ -661,20 +679,6 @@ "import-cwd": "^3.0.0" } }, - "postcss-reporter": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-7.0.1.tgz", - "integrity": "sha512-R9AK80KIqqMb+lwGRBcRkXS7r96VCTxrZvvrfibyA/dWjqctwx7leHMCC05A9HbW8PnChwOWwrmISwp5HQu5wg==", - "requires": { - "colorette": "^1.2.1", - "lodash.difference": "^4.5.0", - "lodash.forown": "^4.4.0", - "lodash.get": "^4.4.2", - "lodash.groupby": "^4.6.0", - "lodash.sortby": "^4.7.0", - "log-symbols": "^4.0.0" - } - }, "postcss-value-parser": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", @@ -693,14 +697,6 @@ "pify": "^2.3.0" } }, - "readdirp": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", - "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", - "requires": { - "picomatch": "^2.2.1" - } - }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -803,34 +799,10 @@ } } }, - "y18n": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.2.tgz", - "integrity": "sha512-CkwaeZw6dQgqgPGeTWKMXCRmMcBgETFlTml1+ZOO+q7kGst8NREJ+eWwFNPVUQ4QGdAaklbqCZHH6Zuep1RjiA==" - }, "yaml": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.0.tgz", "integrity": "sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==" - }, - "yargs": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.0.3.tgz", - "integrity": "sha512-6+nLw8xa9uK1BOEOykaiYAJVh6/CjxWXK/q9b5FpRgNslt8s22F2xMBqVIKgCRjNgGvGPBy8Vog7WN7yh4amtA==", - "requires": { - "cliui": "^7.0.0", - "escalade": "^3.0.2", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.1", - "yargs-parser": "^20.0.0" - } - }, - "yargs-parser": { - "version": "20.2.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.1.tgz", - "integrity": "sha512-yYsjuSkjbLMBp16eaOt7/siKTjNVjMm3SoJnIg3sEh/JsvqVVDyjRKmaJV4cl+lNIgq6QEco2i3gDebJl7/vLA==" } } } From 4e9c48ceefc8942cb6e600e6f28ef6188feb7896 Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Tue, 15 Dec 2020 00:39:44 -0800 Subject: [PATCH 244/376] test/: clean up some e2e setup code (#4315) Signed-off-by: reinvantveer --- internal/testutils/utils.go | 12 ++++ test/e2e-ansible/e2e_ansible_cluster_test.go | 70 ++++++++------------ test/e2e-go/e2e_go_cluster_test.go | 28 +++----- test/e2e-helm/e2e_helm_cluster_test.go | 36 +++++----- 4 files changed, 67 insertions(+), 79 deletions(-) diff --git a/internal/testutils/utils.go b/internal/testutils/utils.go index 4c63da1236f..81b39c7e49b 100644 --- a/internal/testutils/utils.go +++ b/internal/testutils/utils.go @@ -278,3 +278,15 @@ func (tc TestContext) AllowProjectBeMultiGroup() error { } return nil } + +// WrapWarnOutput is a one-liner to wrap an error from a command that returns (string, error) in a warning. +func WrapWarnOutput(_ string, err error) { + if err != nil { + fmt.Fprintf(GinkgoWriter, "warning: %s", err) + } +} + +// WrapWarn is a one-liner to wrap an error from a command that returns (error) in a warning. +func WrapWarn(err error) { + WrapWarnOutput("", err) +} diff --git a/test/e2e-ansible/e2e_ansible_cluster_test.go b/test/e2e-ansible/e2e_ansible_cluster_test.go index 8a2e639c9a0..60e4d861c63 100644 --- a/test/e2e-ansible/e2e_ansible_cluster_test.go +++ b/test/e2e-ansible/e2e_ansible_cluster_test.go @@ -29,54 +29,42 @@ import ( ) var _ = Describe("Running ansible projects", func() { - var controllerPodName string - var memcachedSampleFile string - var fooSampleFile string - var memfinSampleFile string - var memcachedDeployment string - var metricsClusterRoleBindingName string + + var ( + controllerPodName, memcachedDeploymentName, metricsClusterRoleBindingName string + fooSampleFile, memfinSampleFile, memcachedSampleFile string + ) Context("built with operator-sdk", func() { BeforeEach(func() { metricsClusterRoleBindingName = fmt.Sprintf("%s-metrics-reader", tc.ProjectName) - - By("checking samples") - memcachedSampleFile = filepath.Join(tc.Dir, "config", "samples", + samplesDir := filepath.Join(tc.Dir, "config", "samples") + fooSampleFile = filepath.Join(samplesDir, fmt.Sprintf("%s_%s_foo.yaml", tc.Group, tc.Version)) + memfinSampleFile = filepath.Join(samplesDir, fmt.Sprintf("%s_%s_memfin.yaml", tc.Group, tc.Version)) + memcachedSampleFile = filepath.Join(samplesDir, fmt.Sprintf("%s_%s_%s.yaml", tc.Group, tc.Version, strings.ToLower(tc.Kind))) - fooSampleFile = filepath.Join(tc.Dir, "config", "samples", - fmt.Sprintf("%s_%s_foo.yaml", tc.Group, tc.Version)) - memfinSampleFile = filepath.Join(tc.Dir, "config", "samples", - fmt.Sprintf("%s_%s_memfin.yaml", tc.Group, tc.Version)) By("deploying project on the cluster") - err := tc.Make("deploy", "IMG="+tc.ImageName) - Expect(err).NotTo(HaveOccurred()) + Expect(tc.Make("deploy", "IMG="+tc.ImageName)).To(Succeed()) }) + AfterEach(func() { - By("deleting Curl Pod created") - _, _ = tc.Kubectl.Delete(false, "pod", "curl") + By("deleting curl pod") + testutils.WrapWarnOutput(tc.Kubectl.Delete(false, "pod", "curl")) - By("deleting CR instances created") - _, _ = tc.Kubectl.Delete(false, "-f", memcachedSampleFile) - _, _ = tc.Kubectl.Delete(false, "-f", fooSampleFile) - _, _ = tc.Kubectl.Delete(false, "-f", memfinSampleFile) + By("deleting test CR instances") + for _, sample := range []string{memcachedSampleFile, fooSampleFile, memfinSampleFile} { + testutils.WrapWarnOutput(tc.Kubectl.Delete(false, "-f", sample)) + } By("cleaning up permissions") - _, _ = tc.Kubectl.Command("delete", "clusterrolebinding", - metricsClusterRoleBindingName) + testutils.WrapWarnOutput(tc.Kubectl.Command("delete", "clusterrolebinding", metricsClusterRoleBindingName)) By("undeploy project") - _ = tc.Make("undeploy") + testutils.WrapWarn(tc.Make("undeploy")) By("ensuring that the namespace was deleted") - verifyNamespaceDeleted := func() error { - _, err := tc.Kubectl.Command("get", "namespace", tc.Kubectl.Namespace) - if strings.Contains(err.Error(), "(NotFound): namespaces") { - return err - } - return nil - } - Eventually(verifyNamespaceDeleted, 2*time.Minute, time.Second).ShouldNot(Succeed()) + testutils.WrapWarnOutput(tc.Kubectl.Wait(false, "namespace", "foo", "--for", "delete", "--timeout", "2m")) }) It("should run correctly in a cluster", func() { @@ -165,19 +153,19 @@ var _ = Describe("Running ansible projects", func() { Eventually(verifyControllerProbe, time.Minute, time.Second).ShouldNot(ContainSubstring("Killing")) By("getting memcached deploy by labels") - getMencachedDeploument := func() string { - memcachedDeployment, err = tc.Kubectl.Get( + getMemcachedDeploymentName := func() string { + memcachedDeploymentName, err = tc.Kubectl.Get( false, "deployment", "-l", "app=memcached", "-o", "jsonpath={..metadata.name}") Expect(err).NotTo(HaveOccurred()) - return memcachedDeployment + return memcachedDeploymentName } - Eventually(getMencachedDeploument, 2*time.Minute, time.Second).ShouldNot(BeEmpty()) + Eventually(getMemcachedDeploymentName, 2*time.Minute, time.Second).ShouldNot(BeEmpty()) By("checking the Memcached CR deployment status") verifyCRUp := func() string { output, err := tc.Kubectl.Command( - "rollout", "status", "deployment", memcachedDeployment) + "rollout", "status", "deployment", memcachedDeploymentName) Expect(err).NotTo(HaveOccurred()) return output } @@ -211,14 +199,14 @@ var _ = Describe("Running ansible projects", func() { By("scaling deployment replicas to 2") _, err = tc.Kubectl.Command( - "scale", "deployment", memcachedDeployment, "--replicas", "2") + "scale", "deployment", memcachedDeploymentName, "--replicas", "2") Expect(err).NotTo(HaveOccurred()) By("verifying the deployment automatically scales back down to 1") verifyMemcachedScalesBack := func() error { replicas, err := tc.Kubectl.Get( false, - "deployment", memcachedDeployment, "-o", "jsonpath={..spec.replicas}") + "deployment", memcachedDeploymentName, "-o", "jsonpath={..spec.replicas}") Expect(err).NotTo(HaveOccurred()) if replicas != "1" { return fmt.Errorf("memcached(CR) deployment with %s replicas", replicas) @@ -249,7 +237,7 @@ var _ = Describe("Running ansible projects", func() { verifyMemcachedPatch := func() error { replicas, err := tc.Kubectl.Get( false, - "deployment", memcachedDeployment, "-o", "jsonpath={..spec.replicas}") + "deployment", memcachedDeploymentName, "-o", "jsonpath={..spec.replicas}") Expect(err).NotTo(HaveOccurred()) if replicas != "2" { return fmt.Errorf("memcached(CR) deployment with %s replicas", replicas) @@ -381,7 +369,7 @@ var _ = Describe("Running ansible projects", func() { getMemcachedDeployment := func() error { _, err := tc.Kubectl.Get( false, "deployment", - memcachedDeployment) + memcachedDeploymentName) return err } Eventually(getMemcachedDeployment, time.Minute*2, time.Second).ShouldNot(Succeed()) diff --git a/test/e2e-go/e2e_go_cluster_test.go b/test/e2e-go/e2e_go_cluster_test.go index 39ec38775c2..153a01fae4f 100644 --- a/test/e2e-go/e2e_go_cluster_test.go +++ b/test/e2e-go/e2e_go_cluster_test.go @@ -27,40 +27,34 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" kbtestutils "sigs.k8s.io/kubebuilder/v2/test/e2e/utils" + + "github.com/operator-framework/operator-sdk/internal/testutils" ) var _ = Describe("operator-sdk", func() { - var controllerPodName string - var metricsClusterRoleBindingName string + var controllerPodName, metricsClusterRoleBindingName string Context("built with operator-sdk", func() { + BeforeEach(func() { metricsClusterRoleBindingName = fmt.Sprintf("%s-metrics-reader", tc.ProjectName) - By("deploying project on the cluster") - err := tc.Make("deploy", "IMG="+tc.ImageName) - Expect(err).NotTo(HaveOccurred()) + By("deploying project on the cluster") + Expect(tc.Make("deploy", "IMG="+tc.ImageName)).To(Succeed()) }) + AfterEach(func() { - By("deleting Curl Pod created") - _, _ = tc.Kubectl.Delete(false, "pod", "curl") + By("deleting curl pod") + testutils.WrapWarnOutput(tc.Kubectl.Delete(false, "pod", "curl")) By("cleaning up permissions") - _, _ = tc.Kubectl.Command("delete", "clusterrolebinding", - metricsClusterRoleBindingName) + testutils.WrapWarnOutput(tc.Kubectl.Command("delete", "clusterrolebinding", metricsClusterRoleBindingName)) By("cleaning up created API objects during test process") tc.CleanupManifests(filepath.Join("config", "default")) By("ensuring that the namespace was deleted") - verifyNamespaceDeleted := func() error { - _, err := tc.Kubectl.Command("get", "namespace", tc.Kubectl.Namespace) - if strings.Contains(err.Error(), "(NotFound): namespaces") { - return err - } - return nil - } - Eventually(verifyNamespaceDeleted, 2*time.Minute, time.Second).ShouldNot(Succeed()) + testutils.WrapWarnOutput(tc.Kubectl.Wait(false, "namespace", "foo", "--for", "delete", "--timeout", "2m")) }) It("should run correctly in a cluster", func() { diff --git a/test/e2e-helm/e2e_helm_cluster_test.go b/test/e2e-helm/e2e_helm_cluster_test.go index 1e89f1457ab..05f600875d6 100644 --- a/test/e2e-helm/e2e_helm_cluster_test.go +++ b/test/e2e-helm/e2e_helm_cluster_test.go @@ -29,42 +29,36 @@ import ( ) var _ = Describe("Running Helm projects", func() { - var controllerPodName string - var metricsClusterRoleBindingName string + var ( + controllerPodName, metricsClusterRoleBindingName string + memcachedSampleFile string + ) Context("built with operator-sdk", func() { BeforeEach(func() { metricsClusterRoleBindingName = fmt.Sprintf("%s-metrics-reader", tc.ProjectName) + memcachedSampleFile = filepath.Join(tc.Dir, "config", "samples", + fmt.Sprintf("%s_%s_%s.yaml", tc.Group, tc.Version, strings.ToLower(tc.Kind))) By("deploying project on the cluster") - err := tc.Make("deploy", "IMG="+tc.ImageName) - Expect(err).NotTo(HaveOccurred()) + Expect(tc.Make("deploy", "IMG="+tc.ImageName)).To(Succeed()) }) + AfterEach(func() { - By("deleting Curl Pod created") - _, _ = tc.Kubectl.Delete(true, "pod", "curl") + By("deleting curl pod") + testutils.WrapWarnOutput(tc.Kubectl.Delete(false, "pod", "curl")) - By("deleting CR instances created") - sampleFile := filepath.Join("config", "samples", - fmt.Sprintf("%s_%s_%s.yaml", tc.Group, tc.Version, strings.ToLower(tc.Kind))) - _, _ = tc.Kubectl.Delete(false, "-f", sampleFile) + By("deleting test CR instances") + testutils.WrapWarnOutput(tc.Kubectl.Delete(false, "-f", memcachedSampleFile)) By("cleaning up permissions") - _, _ = tc.Kubectl.Command("delete", "clusterrolebinding", - metricsClusterRoleBindingName) + testutils.WrapWarnOutput(tc.Kubectl.Command("delete", "clusterrolebinding", metricsClusterRoleBindingName)) By("undeploy project") - _ = tc.Make("undeploy") + testutils.WrapWarn(tc.Make("undeploy")) By("ensuring that the namespace was deleted") - verifyNamespaceDeleted := func() error { - _, err := tc.Kubectl.Command("get", "namespace", tc.Kubectl.Namespace) - if strings.Contains(err.Error(), "(NotFound): namespaces") { - return err - } - return nil - } - Eventually(verifyNamespaceDeleted, 2*time.Minute, time.Second).ShouldNot(Succeed()) + testutils.WrapWarnOutput(tc.Kubectl.Wait(false, "namespace", "foo", "--for", "delete", "--timeout", "2m")) }) It("should run correctly in a cluster", func() { From 8a163da716a91fd909e294cbd509a4007a4b2770 Mon Sep 17 00:00:00 2001 From: Amarnath Valluri Date: Tue, 15 Dec 2020 11:22:51 +0200 Subject: [PATCH 245/376] olm/operator: fix issue in wrapping error (#4309) Randomly `run packagemanifests` fails with below error: ``` Failed to run packagemanifests: error approving install plan: Operation cannot be fulfilled on installplans.operators.coreos.com \"install-jp28s\": the object has been modified; please apply your changes to the latest version and try again ``` The reason is the way error wrapping while calling the `retry.RetryOnConflict()`. Using '%w' for formatting the error keeps the original error type unlike '%v'. FIXES #4308 Signed-off-by: reinvantveer --- internal/olm/operator/registry/operator_installer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/olm/operator/registry/operator_installer.go b/internal/olm/operator/registry/operator_installer.go index acb8ae5ea57..14c5c32fce8 100644 --- a/internal/olm/operator/registry/operator_installer.go +++ b/internal/olm/operator/registry/operator_installer.go @@ -335,7 +335,7 @@ func (o OperatorInstaller) approveInstallPlan(ctx context.Context, sub *v1alpha1 // approve the install plan by setting Approved to true ip.Spec.Approved = true if err := o.cfg.Client.Update(ctx, &ip); err != nil { - return fmt.Errorf("error approving install plan: %v", err) + return fmt.Errorf("error approving install plan: %w", err) } return nil }); err != nil { From 31ed5efe08f3d5819b7982b99bdc40af9a653be1 Mon Sep 17 00:00:00 2001 From: Camila Macedo Date: Tue, 15 Dec 2020 19:18:17 +0000 Subject: [PATCH 246/376] e2e-tests: fix advanced molecule ansible tests (#4273) **Description of the change:** - update advanced mock static scenario with 1.0+ layout (https://github.com/operator-framework/operator-sdk/pull/3433) - (note that we need to ensure that the test works with the new layout) - Fix CI issue (blocker master): `The error was: urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='172.30.99.1', port=24443): Max retries exceeded with url: /version (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 110] Connection timed out',))` in GA. NOTE: The follow up here is to replace the test/ansible static mock with samples to ensure that we are testing it with the latest changes always. See the issue https://github.com/operator-framework/operator-sdk/issues/4025 and its PR : https://github.com/operator-framework/operator-sdk/pull/4312 Signed-off-by: reinvantveer --- .github/workflows/test-ansible.yml | 1 - hack/tests/e2e-ansible-molecule.sh | 22 ++- test/ansible/.gitignore | 14 ++ test/ansible/{build => }/Dockerfile | 13 +- test/ansible/Makefile | 92 +++++++++ test/ansible/OWNERS | 6 - test/ansible/PROJECT | 24 +++ .../crd/bases/test.example.com_argstests.yaml | 44 +++++ .../crd/bases/test.example.com_casetests.yaml | 44 +++++ .../test.example.com_collectiontests.yaml | 44 +++++ .../test.example.com_inventorytests.yaml | 44 +++++ .../test.example.com_reconciliationtests.yaml | 44 +++++ .../bases/test.example.com_selectortests.yaml | 44 +++++ .../test.example.com_subresourcestests.yaml | 44 +++++ test/ansible/config/crd/kustomization.yaml | 12 ++ .../ansible/config/default/kustomization.yaml | 26 +++ .../default/manager_auth_proxy_patch.yaml | 27 +++ .../ansible/config/manager/kustomization.yaml | 2 + test/ansible/config/manager/manager.yaml | 40 ++++ .../config/prometheus/kustomization.yaml | 2 + test/ansible/config/prometheus/monitor.yaml | 16 ++ .../config/rbac/argstest_editor_role.yaml | 24 +++ .../config/rbac/argstest_viewer_role.yaml | 20 ++ .../rbac/auth_proxy_client_clusterrole.yaml | 7 + test/ansible/config/rbac/auth_proxy_role.yaml | 13 ++ .../config/rbac/auth_proxy_role_binding.yaml | 12 ++ .../config/rbac/auth_proxy_service.yaml | 14 ++ test/ansible/config/rbac/kustomization.yaml | 12 ++ .../config/rbac/leader_election_role.yaml | 25 +++ .../rbac/leader_election_role_binding.yaml} | 15 +- test/ansible/config/rbac/role.yaml | 186 ++++++++++++++++++ test/ansible/config/rbac/role_binding.yaml | 13 ++ .../ansible/config/samples/kustomization.yaml | 3 + .../samples/test_v1alpha1_inventorytest.yaml} | 3 +- .../config/testing/debug_logs_patch.yaml | 14 ++ .../ansible/config/testing/kustomization.yaml | 24 +++ .../ansible/config/testing/manager_image.yaml | 12 ++ .../config/testing/pull_policy/Always.yaml | 12 ++ .../testing/pull_policy/IfNotPresent.yaml | 12 ++ .../config/testing/pull_policy/Never.yaml | 12 ++ .../crds/test.example.com_argstest_crd.yaml | 22 --- .../crds/test.example.com_casetest_crd.yaml | 22 --- .../test.example.com_collectiontests_crd.yaml | 22 --- .../test.example.com_inventorytests_crd.yaml | 22 --- ...st.example.com_reconciliationtest_crd.yaml | 22 --- .../test.example.com_selectortest_crd.yaml | 22 --- ...est.example.com_subresourcestests_crd.yaml | 22 --- .../test.example.com_v1_inventorytest_cr.yaml | 9 - test/ansible/deploy/operator.yaml | 49 ----- test/ansible/deploy/role.yaml | 83 -------- test/ansible/deploy/service_account.yaml | 4 - test/ansible/molecule/cluster/converge.yml | 24 --- test/ansible/molecule/cluster/destroy.yml | 33 ---- test/ansible/molecule/cluster/prepare.yml | 34 ---- .../molecule/cluster/tasks/liveness_test.yml | 16 -- test/ansible/molecule/default/converge.yml | 18 ++ .../molecule/{cluster => default}/create.yml | 0 test/ansible/molecule/default/destroy.yml | 24 +++ test/ansible/molecule/default/kustomize.yml | 15 ++ .../{cluster => default}/molecule.yml | 11 +- test/ansible/molecule/default/prepare.yml | 45 ++--- .../tasks/argstest_test.yml} | 0 .../tasks/casetest_test.yml} | 0 .../tasks/collectiontest_test.yml} | 7 +- .../tasks/inventorytest_test.yml} | 5 +- .../tasks/reconciliationtest_test.yml} | 0 .../tasks/secretstest_test.yml} | 2 +- .../tasks/selectortest_test.yml} | 2 - .../tasks/subresourcestest_test.yml} | 0 .../molecule/{cluster => default}/verify.yml | 17 +- test/ansible/molecule/kind/converge.yml | 31 +++ test/ansible/molecule/kind/create.yml | 8 + test/ansible/molecule/kind/destroy.yml | 12 ++ test/ansible/molecule/kind/molecule.yml | 42 ++++ .../molecule/templates/operator.yaml.j2 | 54 ----- test/ansible/molecule/test-local/converge.yml | 55 ------ test/ansible/molecule/test-local/molecule.yml | 49 ----- test/ansible/molecule/test-local/prepare.yml | 34 ---- test/ansible/molecule/test-local/verify.yml | 2 - .../playbooks/{args.yml => argstest.yml} | 0 .../playbooks/{case.yml => casetest.yml} | 2 +- .../{inventory.yml => inventorytest.yml} | 5 +- ...onciliation.yml => reconciliationtest.yml} | 0 .../{selector.yml => selectortest.yml} | 0 ...{subresources.yml => subresourcestest.yml} | 0 test/ansible/requirements.yml | 3 +- .../tasks/main.yml | 0 test/ansible/watches.yaml | 14 +- 88 files changed, 1225 insertions(+), 676 deletions(-) create mode 100644 test/ansible/.gitignore rename test/ansible/{build => }/Dockerfile (84%) create mode 100644 test/ansible/Makefile delete mode 100644 test/ansible/OWNERS create mode 100644 test/ansible/PROJECT create mode 100644 test/ansible/config/crd/bases/test.example.com_argstests.yaml create mode 100644 test/ansible/config/crd/bases/test.example.com_casetests.yaml create mode 100644 test/ansible/config/crd/bases/test.example.com_collectiontests.yaml create mode 100644 test/ansible/config/crd/bases/test.example.com_inventorytests.yaml create mode 100644 test/ansible/config/crd/bases/test.example.com_reconciliationtests.yaml create mode 100644 test/ansible/config/crd/bases/test.example.com_selectortests.yaml create mode 100644 test/ansible/config/crd/bases/test.example.com_subresourcestests.yaml create mode 100644 test/ansible/config/crd/kustomization.yaml create mode 100644 test/ansible/config/default/kustomization.yaml create mode 100644 test/ansible/config/default/manager_auth_proxy_patch.yaml create mode 100644 test/ansible/config/manager/kustomization.yaml create mode 100644 test/ansible/config/manager/manager.yaml create mode 100644 test/ansible/config/prometheus/kustomization.yaml create mode 100644 test/ansible/config/prometheus/monitor.yaml create mode 100644 test/ansible/config/rbac/argstest_editor_role.yaml create mode 100644 test/ansible/config/rbac/argstest_viewer_role.yaml create mode 100644 test/ansible/config/rbac/auth_proxy_client_clusterrole.yaml create mode 100644 test/ansible/config/rbac/auth_proxy_role.yaml create mode 100644 test/ansible/config/rbac/auth_proxy_role_binding.yaml create mode 100644 test/ansible/config/rbac/auth_proxy_service.yaml create mode 100644 test/ansible/config/rbac/kustomization.yaml create mode 100644 test/ansible/config/rbac/leader_election_role.yaml rename test/ansible/{deploy/role_binding.yaml => config/rbac/leader_election_role_binding.yaml} (61%) create mode 100644 test/ansible/config/rbac/role.yaml create mode 100644 test/ansible/config/rbac/role_binding.yaml create mode 100644 test/ansible/config/samples/kustomization.yaml rename test/ansible/{deploy/crds/test.example.com_v1alpha1_inventorytest_cr.yaml => config/samples/test_v1alpha1_inventorytest.yaml} (76%) create mode 100644 test/ansible/config/testing/debug_logs_patch.yaml create mode 100644 test/ansible/config/testing/kustomization.yaml create mode 100644 test/ansible/config/testing/manager_image.yaml create mode 100644 test/ansible/config/testing/pull_policy/Always.yaml create mode 100644 test/ansible/config/testing/pull_policy/IfNotPresent.yaml create mode 100644 test/ansible/config/testing/pull_policy/Never.yaml delete mode 100644 test/ansible/deploy/crds/test.example.com_argstest_crd.yaml delete mode 100644 test/ansible/deploy/crds/test.example.com_casetest_crd.yaml delete mode 100644 test/ansible/deploy/crds/test.example.com_collectiontests_crd.yaml delete mode 100644 test/ansible/deploy/crds/test.example.com_inventorytests_crd.yaml delete mode 100644 test/ansible/deploy/crds/test.example.com_reconciliationtest_crd.yaml delete mode 100644 test/ansible/deploy/crds/test.example.com_selectortest_crd.yaml delete mode 100644 test/ansible/deploy/crds/test.example.com_subresourcestests_crd.yaml delete mode 100644 test/ansible/deploy/crds/test.example.com_v1_inventorytest_cr.yaml delete mode 100644 test/ansible/deploy/operator.yaml delete mode 100644 test/ansible/deploy/role.yaml delete mode 100644 test/ansible/deploy/service_account.yaml delete mode 100644 test/ansible/molecule/cluster/converge.yml delete mode 100644 test/ansible/molecule/cluster/destroy.yml delete mode 100644 test/ansible/molecule/cluster/prepare.yml delete mode 100644 test/ansible/molecule/cluster/tasks/liveness_test.yml create mode 100644 test/ansible/molecule/default/converge.yml rename test/ansible/molecule/{cluster => default}/create.yml (100%) create mode 100644 test/ansible/molecule/default/destroy.yml create mode 100644 test/ansible/molecule/default/kustomize.yml rename test/ansible/molecule/{cluster => default}/molecule.yml (75%) rename test/ansible/molecule/{cluster/tasks/args_test.yml => default/tasks/argstest_test.yml} (100%) rename test/ansible/molecule/{cluster/tasks/case_test.yml => default/tasks/casetest_test.yml} (100%) rename test/ansible/molecule/{cluster/tasks/collections_test.yml => default/tasks/collectiontest_test.yml} (76%) rename test/ansible/molecule/{cluster/tasks/inventory_test.yml => default/tasks/inventorytest_test.yml} (78%) rename test/ansible/molecule/{cluster/tasks/reconciliation_test.yml => default/tasks/reconciliationtest_test.yml} (100%) rename test/ansible/molecule/{cluster/tasks/secrets_test.yml => default/tasks/secretstest_test.yml} (98%) rename test/ansible/molecule/{cluster/tasks/selector_test.yml => default/tasks/selectortest_test.yml} (99%) rename test/ansible/molecule/{cluster/tasks/subresources_test.yml => default/tasks/subresourcestest_test.yml} (100%) rename test/ansible/molecule/{cluster => default}/verify.yml (75%) create mode 100644 test/ansible/molecule/kind/converge.yml create mode 100644 test/ansible/molecule/kind/create.yml create mode 100644 test/ansible/molecule/kind/destroy.yml create mode 100644 test/ansible/molecule/kind/molecule.yml delete mode 100644 test/ansible/molecule/templates/operator.yaml.j2 delete mode 100644 test/ansible/molecule/test-local/converge.yml delete mode 100644 test/ansible/molecule/test-local/molecule.yml delete mode 100644 test/ansible/molecule/test-local/prepare.yml delete mode 100644 test/ansible/molecule/test-local/verify.yml rename test/ansible/playbooks/{args.yml => argstest.yml} (100%) rename test/ansible/playbooks/{case.yml => casetest.yml} (100%) rename test/ansible/playbooks/{inventory.yml => inventorytest.yml} (76%) rename test/ansible/playbooks/{reconciliation.yml => reconciliationtest.yml} (100%) rename test/ansible/playbooks/{selector.yml => selectortest.yml} (100%) rename test/ansible/playbooks/{subresources.yml => subresourcestest.yml} (100%) rename test/ansible/roles/{inventory => inventorytest}/tasks/main.yml (100%) diff --git a/.github/workflows/test-ansible.yml b/.github/workflows/test-ansible.yml index c681898addf..561685c041e 100644 --- a/.github/workflows/test-ansible.yml +++ b/.github/workflows/test-ansible.yml @@ -49,7 +49,6 @@ jobs: env export PATH=/opt/python/3.6.7/bin:${PATH} sudo apt-get install python3 python3-pip - sudo pip3 install wheel sudo pip3 install --upgrade setuptools pip sudo pip3 install ansible~=2.9.13 make test-e2e-ansible-molecule diff --git a/hack/tests/e2e-ansible-molecule.sh b/hack/tests/e2e-ansible-molecule.sh index a4dbbda3e2c..a68976860ac 100755 --- a/hack/tests/e2e-ansible-molecule.sh +++ b/hack/tests/e2e-ansible-molecule.sh @@ -33,12 +33,22 @@ else fi KUSTOMIZE_PATH=${KUSTOMIZE} TEST_OPERATOR_NAMESPACE=default molecule test -s kind -cd $TMPDIR -KUSTOMIZE_PATH=${KUSTOMIZE} +rm -rf $KUSTOMIZE +cd $TMPDIR/ +rm -rf memcached-molecule-operator + header_text "Test Ansible Molecule scenarios" pushd "${ROOTDIR}/test/ansible" -DEST_IMAGE="quay.io/example/ansible-test-operator:v0.0.1" -sed -i".bak" -E -e 's/(FROM quay.io\/operator-framework\/ansible-operator)(:.*)?/\1:dev/g' build/Dockerfile; rm -f build/Dockerfile.bak -docker build -f build/Dockerfile -t "$DEST_IMAGE" --no-cache . + +make kustomize +if [ -f ./bin/kustomize ] ; then + KUSTOMIZE="$(realpath ./bin/kustomize)" +else + KUSTOMIZE="$(which kustomize)" +fi + +DEST_IMAGE="quay.io/example/advanced-molecule-operator:v0.0.1" +sed -i".bak" -E -e 's/(FROM quay.io\/operator-framework\/ansible-operator)(:.*)?/\1:dev/g' Dockerfile; rm -f Dockerfile.bak +docker build -t "$DEST_IMAGE" --no-cache . load_image_if_kind "$DEST_IMAGE" -OPERATOR_PULL_POLICY=Never OPERATOR_IMAGE=${DEST_IMAGE} TEST_CLUSTER_PORT=24443 TEST_OPERATOR_NAMESPACE=osdk-test molecule test --all +KUSTOMIZE_PATH=$KUSTOMIZE OPERATOR_PULL_POLICY=Never OPERATOR_IMAGE=${DEST_IMAGE} TEST_OPERATOR_NAMESPACE=osdk-test molecule test diff --git a/test/ansible/.gitignore b/test/ansible/.gitignore new file mode 100644 index 00000000000..62fd3e3995f --- /dev/null +++ b/test/ansible/.gitignore @@ -0,0 +1,14 @@ + +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib +bin + +# editor and IDE paraphernalia +.idea +*.swp +*.swo +*~ diff --git a/test/ansible/build/Dockerfile b/test/ansible/Dockerfile similarity index 84% rename from test/ansible/build/Dockerfile rename to test/ansible/Dockerfile index 8b899012548..b29926583a8 100644 --- a/test/ansible/build/Dockerfile +++ b/test/ansible/Dockerfile @@ -1,20 +1,23 @@ -FROM quay.io/operator-framework/ansible-operator:dev +FROM quay.io/operator-framework/ansible-operator:v1.2.0 COPY requirements.yml ${HOME}/requirements.yml RUN ansible-galaxy collection install -r ${HOME}/requirements.yml \ && chmod -R ug+rwx ${HOME}/.ansible -COPY ansible.cfg /etc/ansible/ansible.cfg -COPY watches.yaml ${HOME}/watches.yaml +COPY watches.yaml ${HOME}/watches.yaml COPY roles/ ${HOME}/roles/ COPY playbooks/ ${HOME}/playbooks/ + +# Customizations done to check advanced scenarios COPY inventory/ ${HOME}/inventory/ COPY plugins/ ${HOME}/plugins/ +COPY ansible.cfg /etc/ansible/ansible.cfg COPY fixture_collection/ /tmp/fixture_collection/ USER root RUN chmod -R ug+rwx /tmp/fixture_collection USER 1001 RUN ansible-galaxy collection build /tmp/fixture_collection/ --output-path /tmp/fixture_collection/ \ - && ansible-galaxy collection install /tmp/fixture_collection/operator_sdk-test_fixtures-0.0.0.tar.gz + && ansible-galaxy collection install /tmp/fixture_collection/operator_sdk-test_fixtures-0.0.0.tar.gz RUN echo abc123 > /opt/ansible/pwd.yml \ - && ansible-vault encrypt_string --vault-password-file /opt/ansible/pwd.yml 'thisisatest' --name 'the_secret' > /opt/ansible/vars.yml \ No newline at end of file + && ansible-vault encrypt_string --vault-password-file /opt/ansible/pwd.yml 'thisisatest' --name 'the_secret' > /opt/ansible/vars.yml + diff --git a/test/ansible/Makefile b/test/ansible/Makefile new file mode 100644 index 00000000000..1fdb9883652 --- /dev/null +++ b/test/ansible/Makefile @@ -0,0 +1,92 @@ +# Current Operator version +VERSION ?= 0.0.1 +# Default bundle image tag +BUNDLE_IMG ?= controller-bundle:$(VERSION) +# Options for 'bundle-build' +ifneq ($(origin CHANNELS), undefined) +BUNDLE_CHANNELS := --channels=$(CHANNELS) +endif +ifneq ($(origin DEFAULT_CHANNEL), undefined) +BUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL) +endif +BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL) + +# Image URL to use all building/pushing image targets +IMG ?= controller:latest + +all: docker-build + +# Run against the configured Kubernetes cluster in ~/.kube/config +run: ansible-operator + $(ANSIBLE_OPERATOR) run + +# Install CRDs into a cluster +install: kustomize + $(KUSTOMIZE) build config/crd | kubectl apply -f - + +# Uninstall CRDs from a cluster +uninstall: kustomize + $(KUSTOMIZE) build config/crd | kubectl delete -f - + +# Deploy controller in the configured Kubernetes cluster in ~/.kube/config +deploy: kustomize + cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG} + $(KUSTOMIZE) build config/default | kubectl apply -f - + +# Undeploy controller in the configured Kubernetes cluster in ~/.kube/config +undeploy: kustomize + $(KUSTOMIZE) build config/default | kubectl delete -f - + +# Build the docker image +docker-build: + docker build . -t ${IMG} + +# Push the docker image +docker-push: + docker push ${IMG} + +PATH := $(PATH):$(PWD)/bin +SHELL := env PATH=$(PATH) /bin/sh +OS = $(shell uname -s | tr '[:upper:]' '[:lower:]') +ARCH = $(shell uname -m | sed 's/x86_64/amd64/') +OSOPER = $(shell uname -s | tr '[:upper:]' '[:lower:]' | sed 's/darwin/apple-darwin/' | sed 's/linux/linux-gnu/') +ARCHOPER = $(shell uname -m ) + +kustomize: +ifeq (, $(shell which kustomize 2>/dev/null)) + @{ \ + set -e ;\ + mkdir -p bin ;\ + curl -sSLo - https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/v3.5.4/kustomize_v3.5.4_$(OS)_$(ARCH).tar.gz | tar xzf - -C bin/ ;\ + } +KUSTOMIZE=$(realpath ./bin/kustomize) +else +KUSTOMIZE=$(shell which kustomize) +endif + +ansible-operator: +ifeq (, $(shell which ansible-operator 2>/dev/null)) + @{ \ + set -e ;\ + mkdir -p bin ;\ + curl -LO https://github.com/operator-framework/operator-sdk/releases/download/v1.2.0/ansible-operator-v1.2.0-$(ARCHOPER)-$(OSOPER) ;\ + mv ansible-operator-v1.2.0-$(ARCHOPER)-$(OSOPER) ./bin/ansible-operator ;\ + chmod +x ./bin/ansible-operator ;\ + } +ANSIBLE_OPERATOR=$(realpath ./bin/ansible-operator) +else +ANSIBLE_OPERATOR=$(shell which ansible-operator) +endif + +# Generate bundle manifests and metadata, then validate generated files. +.PHONY: bundle +bundle: kustomize + operator-sdk generate kustomize manifests -q + cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG) + $(KUSTOMIZE) build config/manifests | operator-sdk generate bundle -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS) + operator-sdk bundle validate ./bundle + +# Build the bundle image. +.PHONY: bundle-build +bundle-build: + docker build -f bundle.Dockerfile -t $(BUNDLE_IMG) . diff --git a/test/ansible/OWNERS b/test/ansible/OWNERS deleted file mode 100644 index 9702fa34032..00000000000 --- a/test/ansible/OWNERS +++ /dev/null @@ -1,6 +0,0 @@ -approvers: - - fabianvf - - jmrodri -reviewers: - - fabianvf - - jmrodri diff --git a/test/ansible/PROJECT b/test/ansible/PROJECT new file mode 100644 index 00000000000..fb5e744071e --- /dev/null +++ b/test/ansible/PROJECT @@ -0,0 +1,24 @@ +domain: example.com +layout: ansible.sdk.operatorframework.io/v1 +multigroup: true +projectName: advanced-molecule-operator +resources: +- group: test + kind: InventoryTest + version: v1alpha1 +- group: test + kind: ArgsTest + version: v1alpha1 +- group: test + kind: CaseTest + version: v1alpha1 +- group: test + kind: CollectionTest + version: v1alpha1 +- group: test + kind: SelectorTest + version: v1alpha1 +- group: test + kind: SubresourcesTest + version: v1alpha1 +version: 3-alpha diff --git a/test/ansible/config/crd/bases/test.example.com_argstests.yaml b/test/ansible/config/crd/bases/test.example.com_argstests.yaml new file mode 100644 index 00000000000..4370af5f84d --- /dev/null +++ b/test/ansible/config/crd/bases/test.example.com_argstests.yaml @@ -0,0 +1,44 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: argstests.test.example.com +spec: + group: test.example.com + names: + kind: ArgsTest + listKind: ArgsTestList + plural: argstests + singular: argstest + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: ArgsTest is the Schema for the argstests API + 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 defines the desired state of ArgsTest + type: object + x-kubernetes-preserve-unknown-fields: true + status: + description: Status defines the observed state of ArgsTest + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + served: true + storage: true + subresources: + status: {} diff --git a/test/ansible/config/crd/bases/test.example.com_casetests.yaml b/test/ansible/config/crd/bases/test.example.com_casetests.yaml new file mode 100644 index 00000000000..639d2a77bca --- /dev/null +++ b/test/ansible/config/crd/bases/test.example.com_casetests.yaml @@ -0,0 +1,44 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: casetests.test.example.com +spec: + group: test.example.com + names: + kind: CaseTest + listKind: CaseTestList + plural: casetests + singular: casetest + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: CaseTest is the Schema for the casetests API + 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 defines the desired state of CaseTest + type: object + x-kubernetes-preserve-unknown-fields: true + status: + description: Status defines the observed state of CaseTest + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + served: true + storage: true + subresources: + status: {} diff --git a/test/ansible/config/crd/bases/test.example.com_collectiontests.yaml b/test/ansible/config/crd/bases/test.example.com_collectiontests.yaml new file mode 100644 index 00000000000..af8a6c499f6 --- /dev/null +++ b/test/ansible/config/crd/bases/test.example.com_collectiontests.yaml @@ -0,0 +1,44 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: collectiontests.test.example.com +spec: + group: test.example.com + names: + kind: CollectionTest + listKind: CollectionTestList + plural: collectiontests + singular: collectiontest + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: CollectionTest is the Schema for the collectiontests API + 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 defines the desired state of CollectionTest + type: object + x-kubernetes-preserve-unknown-fields: true + status: + description: Status defines the observed state of CollectionTest + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + served: true + storage: true + subresources: + status: {} diff --git a/test/ansible/config/crd/bases/test.example.com_inventorytests.yaml b/test/ansible/config/crd/bases/test.example.com_inventorytests.yaml new file mode 100644 index 00000000000..d10ff7c04a5 --- /dev/null +++ b/test/ansible/config/crd/bases/test.example.com_inventorytests.yaml @@ -0,0 +1,44 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: inventorytests.test.example.com +spec: + group: test.example.com + names: + kind: InventoryTest + listKind: InventoryTestList + plural: inventorytests + singular: inventorytest + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: InventoryTest is the Schema for the inventorytests API + 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 defines the desired state of InventoryTest + type: object + x-kubernetes-preserve-unknown-fields: true + status: + description: Status defines the observed state of InventoryTest + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + served: true + storage: true + subresources: + status: {} diff --git a/test/ansible/config/crd/bases/test.example.com_reconciliationtests.yaml b/test/ansible/config/crd/bases/test.example.com_reconciliationtests.yaml new file mode 100644 index 00000000000..d8343116ff0 --- /dev/null +++ b/test/ansible/config/crd/bases/test.example.com_reconciliationtests.yaml @@ -0,0 +1,44 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: reconciliationtests.test.example.com +spec: + group: test.example.com + names: + kind: ReconciliationTest + listKind: ReconciliationTestList + plural: reconciliationtests + singular: reconciliationtest + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: ReconciliationTest is the Schema for the reconciliationtests API + 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 defines the desired state of ReconciliationTest + type: object + x-kubernetes-preserve-unknown-fields: true + status: + description: Status defines the observed state of ReconciliationTest + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + served: true + storage: true + subresources: + status: {} diff --git a/test/ansible/config/crd/bases/test.example.com_selectortests.yaml b/test/ansible/config/crd/bases/test.example.com_selectortests.yaml new file mode 100644 index 00000000000..2068942e73f --- /dev/null +++ b/test/ansible/config/crd/bases/test.example.com_selectortests.yaml @@ -0,0 +1,44 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: selectortests.test.example.com +spec: + group: test.example.com + names: + kind: SelectorTest + listKind: SelectorTestList + plural: selectortests + singular: selectortest + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: SelectorTest is the Schema for the selectortests API + 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 defines the desired state of SelectorTest + type: object + x-kubernetes-preserve-unknown-fields: true + status: + description: Status defines the observed state of SelectorTest + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + served: true + storage: true + subresources: + status: {} diff --git a/test/ansible/config/crd/bases/test.example.com_subresourcestests.yaml b/test/ansible/config/crd/bases/test.example.com_subresourcestests.yaml new file mode 100644 index 00000000000..38c1d3a690c --- /dev/null +++ b/test/ansible/config/crd/bases/test.example.com_subresourcestests.yaml @@ -0,0 +1,44 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: subresourcestests.test.example.com +spec: + group: test.example.com + names: + kind: SubresourcesTest + listKind: SubresourcesTestList + plural: subresourcestests + singular: subresourcestest + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: SubresourcesTest is the Schema for the subresourcestests API + 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 defines the desired state of SubresourcesTest + type: object + x-kubernetes-preserve-unknown-fields: true + status: + description: Status defines the observed state of SubresourcesTest + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + served: true + storage: true + subresources: + status: {} diff --git a/test/ansible/config/crd/kustomization.yaml b/test/ansible/config/crd/kustomization.yaml new file mode 100644 index 00000000000..4742ee14fa0 --- /dev/null +++ b/test/ansible/config/crd/kustomization.yaml @@ -0,0 +1,12 @@ +# 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/test.example.com_inventorytests.yaml +- bases/test.example.com_argstests.yaml +- bases/test.example.com_casetests.yaml +- bases/test.example.com_collectiontests.yaml +- bases/test.example.com_selectortests.yaml +- bases/test.example.com_subresourcestests.yaml +- bases/test.example.com_reconciliationtests.yaml +# +kubebuilder:scaffold:crdkustomizeresource diff --git a/test/ansible/config/default/kustomization.yaml b/test/ansible/config/default/kustomization.yaml new file mode 100644 index 00000000000..13072005482 --- /dev/null +++ b/test/ansible/config/default/kustomization.yaml @@ -0,0 +1,26 @@ +# Adds namespace to all resources. +namespace: advanced-molecule-operator-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: advanced-molecule-operator- + +# Labels to add to all resources and selectors. +#commonLabels: +# someName: someValue + +bases: +- ../crd +- ../rbac +- ../manager +# [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'. +#- ../prometheus + +patchesStrategicMerge: + # Protect the /metrics endpoint by putting it behind auth. + # If you want your controller-manager to expose the /metrics + # endpoint w/o any authn/z, please comment the following line. +- manager_auth_proxy_patch.yaml diff --git a/test/ansible/config/default/manager_auth_proxy_patch.yaml b/test/ansible/config/default/manager_auth_proxy_patch.yaml new file mode 100644 index 00000000000..4fe5572c44b --- /dev/null +++ b/test/ansible/config/default/manager_auth_proxy_patch.yaml @@ -0,0 +1,27 @@ +# This patch inject a sidecar container which is a HTTP proxy for the +# controller manager, it performs RBAC authorization against the Kubernetes API using SubjectAccessReviews. +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system +spec: + template: + spec: + containers: + - name: kube-rbac-proxy + image: gcr.io/kubebuilder/kube-rbac-proxy:v0.5.0 + args: + - "--secure-listen-address=0.0.0.0:8443" + - "--upstream=http://127.0.0.1:8080/" + - "--logtostderr=true" + - "--v=10" + ports: + - containerPort: 8443 + name: https + - name: manager + args: + - "--metrics-addr=127.0.0.1:8080" + - "--enable-leader-election" + - "--leader-election-id=advanced-molecule-operator" + - "--ansible-args='--vault-password-file /opt/ansible/pwd.yml'" diff --git a/test/ansible/config/manager/kustomization.yaml b/test/ansible/config/manager/kustomization.yaml new file mode 100644 index 00000000000..5c5f0b84cba --- /dev/null +++ b/test/ansible/config/manager/kustomization.yaml @@ -0,0 +1,2 @@ +resources: +- manager.yaml diff --git a/test/ansible/config/manager/manager.yaml b/test/ansible/config/manager/manager.yaml new file mode 100644 index 00000000000..cfee93297e1 --- /dev/null +++ b/test/ansible/config/manager/manager.yaml @@ -0,0 +1,40 @@ +apiVersion: v1 +kind: Namespace +metadata: + labels: + control-plane: controller-manager + name: system +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system + labels: + control-plane: controller-manager +spec: + selector: + matchLabels: + control-plane: controller-manager + replicas: 1 + template: + metadata: + labels: + control-plane: controller-manager + spec: + containers: + - name: manager + args: + - "--metrics-addr=127.0.0.1:8080" + - "--enable-leader-election" + - "--leader-election-id=advanced-molecule-operator" + - "--ansible-args='--vault-password-file /opt/ansible/pwd.yml'" + env: + - name: ANSIBLE_DEBUG_LOGS + value: "TRUE" + - name: ANSIBLE_GATHERING + value: explicit + - name: ANSIBLE_INVENTORY + value: /opt/ansible/inventory + image: controller:latest + terminationGracePeriodSeconds: 10 diff --git a/test/ansible/config/prometheus/kustomization.yaml b/test/ansible/config/prometheus/kustomization.yaml new file mode 100644 index 00000000000..ed137168a1d --- /dev/null +++ b/test/ansible/config/prometheus/kustomization.yaml @@ -0,0 +1,2 @@ +resources: +- monitor.yaml diff --git a/test/ansible/config/prometheus/monitor.yaml b/test/ansible/config/prometheus/monitor.yaml new file mode 100644 index 00000000000..1b44d4f617f --- /dev/null +++ b/test/ansible/config/prometheus/monitor.yaml @@ -0,0 +1,16 @@ +--- +# Prometheus Monitor Service (Metrics) +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + labels: + control-plane: controller-manager + name: controller-manager-metrics-monitor + namespace: system +spec: + endpoints: + - path: /metrics + port: https + selector: + matchLabels: + control-plane: controller-manager diff --git a/test/ansible/config/rbac/argstest_editor_role.yaml b/test/ansible/config/rbac/argstest_editor_role.yaml new file mode 100644 index 00000000000..b436fa95618 --- /dev/null +++ b/test/ansible/config/rbac/argstest_editor_role.yaml @@ -0,0 +1,24 @@ +# permissions for end users to edit argstests. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: argstest-editor-role +rules: +- apiGroups: + - test.example.com + resources: + - argstests + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - test.example.com + resources: + - argstests/status + verbs: + - get diff --git a/test/ansible/config/rbac/argstest_viewer_role.yaml b/test/ansible/config/rbac/argstest_viewer_role.yaml new file mode 100644 index 00000000000..bba2d4f9c89 --- /dev/null +++ b/test/ansible/config/rbac/argstest_viewer_role.yaml @@ -0,0 +1,20 @@ +# permissions for end users to view argstests. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: argstest-viewer-role +rules: +- apiGroups: + - test.example.com + resources: + - argstests + verbs: + - get + - list + - watch +- apiGroups: + - test.example.com + resources: + - argstests/status + verbs: + - get diff --git a/test/ansible/config/rbac/auth_proxy_client_clusterrole.yaml b/test/ansible/config/rbac/auth_proxy_client_clusterrole.yaml new file mode 100644 index 00000000000..bd4af137a9f --- /dev/null +++ b/test/ansible/config/rbac/auth_proxy_client_clusterrole.yaml @@ -0,0 +1,7 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: metrics-reader +rules: +- nonResourceURLs: ["/metrics"] + verbs: ["get"] diff --git a/test/ansible/config/rbac/auth_proxy_role.yaml b/test/ansible/config/rbac/auth_proxy_role.yaml new file mode 100644 index 00000000000..618f5e4177c --- /dev/null +++ b/test/ansible/config/rbac/auth_proxy_role.yaml @@ -0,0 +1,13 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: proxy-role +rules: +- apiGroups: ["authentication.k8s.io"] + resources: + - tokenreviews + verbs: ["create"] +- apiGroups: ["authorization.k8s.io"] + resources: + - subjectaccessreviews + verbs: ["create"] diff --git a/test/ansible/config/rbac/auth_proxy_role_binding.yaml b/test/ansible/config/rbac/auth_proxy_role_binding.yaml new file mode 100644 index 00000000000..48ed1e4b85c --- /dev/null +++ b/test/ansible/config/rbac/auth_proxy_role_binding.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: proxy-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: proxy-role +subjects: +- kind: ServiceAccount + name: default + namespace: system diff --git a/test/ansible/config/rbac/auth_proxy_service.yaml b/test/ansible/config/rbac/auth_proxy_service.yaml new file mode 100644 index 00000000000..6cf656be149 --- /dev/null +++ b/test/ansible/config/rbac/auth_proxy_service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + control-plane: controller-manager + name: controller-manager-metrics-service + namespace: system +spec: + ports: + - name: https + port: 8443 + targetPort: https + selector: + control-plane: controller-manager diff --git a/test/ansible/config/rbac/kustomization.yaml b/test/ansible/config/rbac/kustomization.yaml new file mode 100644 index 00000000000..66c28338fe0 --- /dev/null +++ b/test/ansible/config/rbac/kustomization.yaml @@ -0,0 +1,12 @@ +resources: +- role.yaml +- role_binding.yaml +- leader_election_role.yaml +- leader_election_role_binding.yaml +# Comment the following 4 lines if you want to disable +# the auth proxy (https://github.com/brancz/kube-rbac-proxy) +# which protects your /metrics endpoint. +- auth_proxy_service.yaml +- auth_proxy_role.yaml +- auth_proxy_role_binding.yaml +- auth_proxy_client_clusterrole.yaml diff --git a/test/ansible/config/rbac/leader_election_role.yaml b/test/ansible/config/rbac/leader_election_role.yaml new file mode 100644 index 00000000000..53e974910be --- /dev/null +++ b/test/ansible/config/rbac/leader_election_role.yaml @@ -0,0 +1,25 @@ +# permissions to do leader election. +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: leader-election-role +rules: +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch diff --git a/test/ansible/deploy/role_binding.yaml b/test/ansible/config/rbac/leader_election_role_binding.yaml similarity index 61% rename from test/ansible/deploy/role_binding.yaml rename to test/ansible/config/rbac/leader_election_role_binding.yaml index 34a09cc757a..eed16906f4d 100644 --- a/test/ansible/deploy/role_binding.yaml +++ b/test/ansible/config/rbac/leader_election_role_binding.yaml @@ -1,11 +1,12 @@ -kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding metadata: - name: ansible -subjects: -- kind: ServiceAccount - name: ansible + name: leader-election-rolebinding roleRef: - kind: Role - name: ansible apiGroup: rbac.authorization.k8s.io + kind: Role + name: leader-election-role +subjects: +- kind: ServiceAccount + name: default + namespace: system diff --git a/test/ansible/config/rbac/role.yaml b/test/ansible/config/rbac/role.yaml new file mode 100644 index 00000000000..a023a52179e --- /dev/null +++ b/test/ansible/config/rbac/role.yaml @@ -0,0 +1,186 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: manager-role +rules: + ## + ## Base operator rules + ## + - apiGroups: + - "" + resources: + - secrets + - pods + - pods/exec + - pods/log + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - apps + resources: + - deployments + - daemonsets + - replicasets + - statefulsets + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + ## + ## Rules for test.example.com/v1alpha1, Kind: InventoryTest + ## + - apiGroups: + - test.example.com + resources: + - inventorytests + - inventorytests/status + - inventorytests/finalizers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + ## + ## Rules for test.example.com/v1alpha1, Kind: InventoryTest + ## + - apiGroups: + - test.example.com + resources: + - subresourcestests + - subresourcestests/status + - subresourcestests/finalizers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + ## + ## Rules for test.example.com/v1alpha1, Kind: InventoryTest + ## + - apiGroups: + - test.example.com + resources: + - collectiontests + - collectiontests/status + - collectiontests/finalizers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + ## + ## Rules for test.example.com/v1alpha1, Kind: InventoryTest + ## + - apiGroups: + - test.example.com + resources: + - selectortests + - selectortests/status + - selectortests/finalizers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + ## + ## Rules for test.example.com/v1alpha1, Kind: InventoryTest + ## + - apiGroups: + - test.example.com + resources: + - casetests + - casetests/status + - casetests/finalizers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + ## + ## Rules for test.example.com/v1alpha1, Kind: InventoryTest + ## + - apiGroups: + - test.example.com + resources: + - argstests + - argstests/status + - argstests/finalizers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + ## + ## Rules for test.example.com/v1alpha1, Kind: InventoryTest + ## + - apiGroups: + - test.example.com + resources: + - reconciliationtests + - reconciliationtests/status + - reconciliationtests/finalizers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + ## + ## Base operator rules + ## + - apiGroups: + - "" + resources: + - configmaps + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - apps + resources: + - configmaps + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +# +kubebuilder:scaffold:rules diff --git a/test/ansible/config/rbac/role_binding.yaml b/test/ansible/config/rbac/role_binding.yaml new file mode 100644 index 00000000000..98f87829e96 --- /dev/null +++ b/test/ansible/config/rbac/role_binding.yaml @@ -0,0 +1,13 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: manager-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: manager-role +subjects: +- kind: ServiceAccount + name: default + namespace: system diff --git a/test/ansible/config/samples/kustomization.yaml b/test/ansible/config/samples/kustomization.yaml new file mode 100644 index 00000000000..e353c59b277 --- /dev/null +++ b/test/ansible/config/samples/kustomization.yaml @@ -0,0 +1,3 @@ +## Append samples you want in your CSV to this file as resources ## +resources: +- test_v1alpha1_inventorytest.yaml diff --git a/test/ansible/deploy/crds/test.example.com_v1alpha1_inventorytest_cr.yaml b/test/ansible/config/samples/test_v1alpha1_inventorytest.yaml similarity index 76% rename from test/ansible/deploy/crds/test.example.com_v1alpha1_inventorytest_cr.yaml rename to test/ansible/config/samples/test_v1alpha1_inventorytest.yaml index d6f990b42be..27920633490 100644 --- a/test/ansible/deploy/crds/test.example.com_v1alpha1_inventorytest_cr.yaml +++ b/test/ansible/config/samples/test_v1alpha1_inventorytest.yaml @@ -1,9 +1,8 @@ apiVersion: test.example.com/v1alpha1 kind: InventoryTest metadata: - name: example-inventory + name: inventorytest-sample annotations: "ansible.sdk.operatorframework.io/verbosity": "0" spec: - # Add fields here size: 3 diff --git a/test/ansible/config/testing/debug_logs_patch.yaml b/test/ansible/config/testing/debug_logs_patch.yaml new file mode 100644 index 00000000000..3e31e2fba19 --- /dev/null +++ b/test/ansible/config/testing/debug_logs_patch.yaml @@ -0,0 +1,14 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system +spec: + template: + spec: + containers: + - name: manager + env: + - name: ANSIBLE_DEBUG_LOGS + value: "TRUE" diff --git a/test/ansible/config/testing/kustomization.yaml b/test/ansible/config/testing/kustomization.yaml new file mode 100644 index 00000000000..9757d27f748 --- /dev/null +++ b/test/ansible/config/testing/kustomization.yaml @@ -0,0 +1,24 @@ +# Adds namespace to all resources. +namespace: osdk-test + +namePrefix: osdk- + +# Labels to add to all resources and selectors. +#commonLabels: +# someName: someValue + +patchesStrategicMerge: +- manager_image.yaml +- pull_policy/Never.yaml +- debug_logs_patch.yaml +- ../default/manager_auth_proxy_patch.yaml + +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: +- ../crd +- ../rbac +- ../manager +images: +- name: testing + newName: testing-operator diff --git a/test/ansible/config/testing/manager_image.yaml b/test/ansible/config/testing/manager_image.yaml new file mode 100644 index 00000000000..e44f542d9bc --- /dev/null +++ b/test/ansible/config/testing/manager_image.yaml @@ -0,0 +1,12 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system +spec: + template: + spec: + containers: + - name: manager + image: testing diff --git a/test/ansible/config/testing/pull_policy/Always.yaml b/test/ansible/config/testing/pull_policy/Always.yaml new file mode 100644 index 00000000000..6b0a8e2a8ab --- /dev/null +++ b/test/ansible/config/testing/pull_policy/Always.yaml @@ -0,0 +1,12 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system +spec: + template: + spec: + containers: + - name: manager + imagePullPolicy: Always diff --git a/test/ansible/config/testing/pull_policy/IfNotPresent.yaml b/test/ansible/config/testing/pull_policy/IfNotPresent.yaml new file mode 100644 index 00000000000..2f52f496cd5 --- /dev/null +++ b/test/ansible/config/testing/pull_policy/IfNotPresent.yaml @@ -0,0 +1,12 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system +spec: + template: + spec: + containers: + - name: manager + imagePullPolicy: IfNotPresent diff --git a/test/ansible/config/testing/pull_policy/Never.yaml b/test/ansible/config/testing/pull_policy/Never.yaml new file mode 100644 index 00000000000..86f13d81645 --- /dev/null +++ b/test/ansible/config/testing/pull_policy/Never.yaml @@ -0,0 +1,12 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system +spec: + template: + spec: + containers: + - name: manager + imagePullPolicy: Never diff --git a/test/ansible/deploy/crds/test.example.com_argstest_crd.yaml b/test/ansible/deploy/crds/test.example.com_argstest_crd.yaml deleted file mode 100644 index 8b3ebe8b21e..00000000000 --- a/test/ansible/deploy/crds/test.example.com_argstest_crd.yaml +++ /dev/null @@ -1,22 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: argstests.test.example.com -spec: - group: test.example.com - names: - kind: ArgsTest - listKind: ArgsTestList - plural: argstests - singular: argstest - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - type: object - x-kubernetes-preserve-unknown-fields: true - served: true - storage: true - subresources: - status: {} diff --git a/test/ansible/deploy/crds/test.example.com_casetest_crd.yaml b/test/ansible/deploy/crds/test.example.com_casetest_crd.yaml deleted file mode 100644 index c336a0e1cb4..00000000000 --- a/test/ansible/deploy/crds/test.example.com_casetest_crd.yaml +++ /dev/null @@ -1,22 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: casetests.test.example.com -spec: - group: test.example.com - names: - kind: CaseTest - listKind: CaseTestList - plural: casetests - singular: casetest - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - type: object - x-kubernetes-preserve-unknown-fields: true - served: true - storage: true - subresources: - status: {} diff --git a/test/ansible/deploy/crds/test.example.com_collectiontests_crd.yaml b/test/ansible/deploy/crds/test.example.com_collectiontests_crd.yaml deleted file mode 100644 index 0ff88961533..00000000000 --- a/test/ansible/deploy/crds/test.example.com_collectiontests_crd.yaml +++ /dev/null @@ -1,22 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: collectiontests.test.example.com -spec: - group: test.example.com - names: - kind: CollectionTest - listKind: CollectionTestList - plural: collectiontests - singular: collectiontest - scope: Namespaced - subresources: - status: {} - validation: - openAPIV3Schema: - type: object - x-kubernetes-preserve-unknown-fields: true - versions: - - name: v1alpha1 - served: true - storage: true diff --git a/test/ansible/deploy/crds/test.example.com_inventorytests_crd.yaml b/test/ansible/deploy/crds/test.example.com_inventorytests_crd.yaml deleted file mode 100644 index d08bb9055b1..00000000000 --- a/test/ansible/deploy/crds/test.example.com_inventorytests_crd.yaml +++ /dev/null @@ -1,22 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: inventorytests.test.example.com -spec: - group: test.example.com - names: - kind: InventoryTest - listKind: InventoryTestList - plural: inventorytests - singular: inventorytest - scope: Namespaced - subresources: - status: {} - validation: - openAPIV3Schema: - type: object - x-kubernetes-preserve-unknown-fields: true - versions: - - name: v1alpha1 - served: true - storage: true diff --git a/test/ansible/deploy/crds/test.example.com_reconciliationtest_crd.yaml b/test/ansible/deploy/crds/test.example.com_reconciliationtest_crd.yaml deleted file mode 100644 index 6c964f0c56d..00000000000 --- a/test/ansible/deploy/crds/test.example.com_reconciliationtest_crd.yaml +++ /dev/null @@ -1,22 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: reconciliationtests.test.example.com -spec: - group: test.example.com - names: - kind: ReconciliationTest - listKind: ReconciliationTestList - plural: reconciliationtests - singular: reconciliationtest - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - type: object - x-kubernetes-preserve-unknown-fields: true - served: true - storage: true - subresources: - status: {} diff --git a/test/ansible/deploy/crds/test.example.com_selectortest_crd.yaml b/test/ansible/deploy/crds/test.example.com_selectortest_crd.yaml deleted file mode 100644 index fff1fe11d7e..00000000000 --- a/test/ansible/deploy/crds/test.example.com_selectortest_crd.yaml +++ /dev/null @@ -1,22 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: selectortests.test.example.com -spec: - group: test.example.com - names: - kind: SelectorTest - listKind: SelectorTestList - plural: selectortests - singular: selectortest - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - type: object - x-kubernetes-preserve-unknown-fields: true - served: true - storage: true - subresources: - status: {} diff --git a/test/ansible/deploy/crds/test.example.com_subresourcestests_crd.yaml b/test/ansible/deploy/crds/test.example.com_subresourcestests_crd.yaml deleted file mode 100644 index fb6687baa4b..00000000000 --- a/test/ansible/deploy/crds/test.example.com_subresourcestests_crd.yaml +++ /dev/null @@ -1,22 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: subresourcestests.test.example.com -spec: - group: test.example.com - names: - kind: SubresourcesTest - listKind: SubresourcesTestList - plural: subresourcestests - singular: subresourcestest - scope: Namespaced - subresources: - status: {} - validation: - openAPIV3Schema: - type: object - x-kubernetes-preserve-unknown-fields: true - versions: - - name: v1alpha1 - served: true - storage: true diff --git a/test/ansible/deploy/crds/test.example.com_v1_inventorytest_cr.yaml b/test/ansible/deploy/crds/test.example.com_v1_inventorytest_cr.yaml deleted file mode 100644 index 71f42e09b04..00000000000 --- a/test/ansible/deploy/crds/test.example.com_v1_inventorytest_cr.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: test.example.com/v1 -kind: InventoryTest -metadata: - name: example-inventorytest - annotations: - "ansible.sdk.operatorframework.io/verbosity": "3" -spec: - # Add fields here - size: 3 diff --git a/test/ansible/deploy/operator.yaml b/test/ansible/deploy/operator.yaml deleted file mode 100644 index df0545a8271..00000000000 --- a/test/ansible/deploy/operator.yaml +++ /dev/null @@ -1,49 +0,0 @@ ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: ansible -spec: - replicas: 1 - selector: - matchLabels: - name: ansible - template: - metadata: - labels: - name: ansible - spec: - serviceAccountName: ansible - containers: - - name: ansible - # Replace this with the built image name - image: "REPLACE_IMAGE" - imagePullPolicy: "Always" - volumeMounts: - - mountPath: /tmp/ansible-operator/runner - name: runner - env: - - name: WATCH_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: OPERATOR_NAME - value: "ansible" - - name: ANSIBLE_GATHERING - value: explicit - - name: ANSIBLE_INVENTORY - value: /opt/ansible/inventory - livenessProbe: - httpGet: - path: /healthz - port: 6789 - initialDelaySeconds: 5 - periodSeconds: 3 - - volumes: - - name: runner - emptyDir: {} diff --git a/test/ansible/deploy/role.yaml b/test/ansible/deploy/role.yaml deleted file mode 100644 index d30b87b2913..00000000000 --- a/test/ansible/deploy/role.yaml +++ /dev/null @@ -1,83 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - creationTimestamp: null - name: ansible -rules: -- apiGroups: - - "" - resources: - - pods - - pods/exec - - pods/log - - services - - services/finalizers - - endpoints - - persistentvolumeclaims - - events - - configmaps - - secrets - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - apps - resources: - - deployments - - daemonsets - - replicasets - - statefulsets - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - monitoring.coreos.com - resources: - - servicemonitors - verbs: - - get - - create -- apiGroups: - - apps - resourceNames: - - ansible - resources: - - deployments/finalizers - verbs: - - update -- apiGroups: - - "" - resources: - - pods - verbs: - - get -- apiGroups: - - apps - resources: - - replicasets - - deployments - verbs: - - get -- apiGroups: - - test.example.com - resources: - - '*' - - inventories - verbs: - - create - - delete - - get - - list - - patch - - update - - watch diff --git a/test/ansible/deploy/service_account.yaml b/test/ansible/deploy/service_account.yaml deleted file mode 100644 index 94be3a07558..00000000000 --- a/test/ansible/deploy/service_account.yaml +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: v1 -kind: ServiceAccount -metadata: - name: ansible diff --git a/test/ansible/molecule/cluster/converge.yml b/test/ansible/molecule/cluster/converge.yml deleted file mode 100644 index 8877f825889..00000000000 --- a/test/ansible/molecule/cluster/converge.yml +++ /dev/null @@ -1,24 +0,0 @@ ---- -- name: Converge - hosts: localhost - connection: local - gather_facts: no - collections: - - community.kubernetes - - tasks: - - name: Ensure operator image is set - fail: - msg: | - You must specify the OPERATOR_IMAGE environment variable in order to run the - 'cluster' scenario - when: not operator_image - - - name: Create the Operator Deployment - k8s: - namespace: '{{ namespace }}' - definition: "{{ lookup('template', '/'.join([template_dir, 'operator.yaml.j2'])) }}" - wait: yes - vars: - image: '{{ operator_image }}' - pull_policy: '{{ operator_pull_policy }}' diff --git a/test/ansible/molecule/cluster/destroy.yml b/test/ansible/molecule/cluster/destroy.yml deleted file mode 100644 index b55bb6f8d32..00000000000 --- a/test/ansible/molecule/cluster/destroy.yml +++ /dev/null @@ -1,33 +0,0 @@ ---- -- name: Destroy - hosts: localhost - connection: local - gather_facts: false - - tasks: - - name: Delete namespace - k8s: - api_version: v1 - kind: Namespace - name: '{{ namespace }}' - state: absent - wait: yes - - - name: Delete RBAC resources - k8s: - definition: "{{ lookup('template', '/'.join([deploy_dir, item])) }}" - namespace: '{{ namespace }}' - state: absent - wait: yes - with_items: - - role.yaml - - role_binding.yaml - - service_account.yaml - - - name: Delete Custom Resource Definitions - k8s: - definition: "{{ lookup('file', item) }}" - state: absent - wait: yes - with_fileglob: - - "{{ '/'.join([deploy_dir, 'crds']) }}/*_crd.yaml" diff --git a/test/ansible/molecule/cluster/prepare.yml b/test/ansible/molecule/cluster/prepare.yml deleted file mode 100644 index 942b1aa73f6..00000000000 --- a/test/ansible/molecule/cluster/prepare.yml +++ /dev/null @@ -1,34 +0,0 @@ ---- -- name: Prepare - hosts: localhost - connection: local - gather_facts: false - no_log: "{{ molecule_no_log }}" - vars: - deploy_dir: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/deploy" - - tasks: - - name: Create Custom Resource Definitions - k8s: - definition: "{{ lookup('file', item) }}" - with_fileglob: - - "{{ '/'.join([deploy_dir, 'crds']) }}/*_crd.yaml" - - - name: Create namespace - k8s: - api_version: v1 - kind: Namespace - name: '{{ namespace }}' - - - name: Create RBAC resources - k8s: - definition: "{{ lookup('template', '/'.join([deploy_dir, item])) }}" - namespace: '{{ namespace }}' - with_items: - - role.yaml - - role_binding.yaml - - service_account.yaml - - - name: Create ServiceMonitor Custom Resource Definiiton - k8s: - definition: "{{ lookup('url', 'https://raw.githubusercontent.com/coreos/prometheus-operator/release-0.35/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml', split_lines=False) | from_yaml_all | list }}" diff --git a/test/ansible/molecule/cluster/tasks/liveness_test.yml b/test/ansible/molecule/cluster/tasks/liveness_test.yml deleted file mode 100644 index 9f05a749815..00000000000 --- a/test/ansible/molecule/cluster/tasks/liveness_test.yml +++ /dev/null @@ -1,16 +0,0 @@ -- name: get the operator pod - set_fact: - op_pod: "{{ lookup('k8s', kind='Pod', label_selector='name=ansible') }}" - -- name: Check for liveness probe failure events - # We can't directly hit the endpoint, which is not publicly exposed. If k8s sees a failing endpoint, it will create a "Killing" event. - k8s_info: - kind: Event - field_selectors: - - "involvedObject.name={{ op_pod.metadata.name }}" - - "reason=Killing" - register: liveness_failures - -- name: Assert that the Pod has not been liveness probe Killed - assert: - that: liveness_failures.resources|length == 0 diff --git a/test/ansible/molecule/default/converge.yml b/test/ansible/molecule/default/converge.yml new file mode 100644 index 00000000000..0633db98492 --- /dev/null +++ b/test/ansible/molecule/default/converge.yml @@ -0,0 +1,18 @@ +--- +- name: Converge + hosts: localhost + connection: local + gather_facts: no + collections: + - community.kubernetes + + tasks: + - name: Create Namespace + k8s: + api_version: v1 + kind: Namespace + name: '{{ namespace }}' + + - import_tasks: kustomize.yml + vars: + state: present diff --git a/test/ansible/molecule/cluster/create.yml b/test/ansible/molecule/default/create.yml similarity index 100% rename from test/ansible/molecule/cluster/create.yml rename to test/ansible/molecule/default/create.yml diff --git a/test/ansible/molecule/default/destroy.yml b/test/ansible/molecule/default/destroy.yml new file mode 100644 index 00000000000..af55e4f1749 --- /dev/null +++ b/test/ansible/molecule/default/destroy.yml @@ -0,0 +1,24 @@ +--- +- name: Destroy + hosts: localhost + connection: local + gather_facts: false + collections: + - community.kubernetes + + tasks: + - import_tasks: kustomize.yml + vars: + state: absent + + - name: Destroy Namespace + k8s: + api_version: v1 + kind: Namespace + name: '{{ namespace }}' + state: absent + + - name: Unset pull policy + command: '{{ kustomize }} edit remove patch pull_policy/{{ operator_pull_policy }}.yaml' + args: + chdir: '{{ config_dir }}/testing' diff --git a/test/ansible/molecule/default/kustomize.yml b/test/ansible/molecule/default/kustomize.yml new file mode 100644 index 00000000000..f3d888c2f3b --- /dev/null +++ b/test/ansible/molecule/default/kustomize.yml @@ -0,0 +1,15 @@ +--- +- name: Build kustomize testing overlay + # load_restrictor must be set to none so we can load patch files from the default overlay + command: '{{ kustomize }} build --load_restrictor none .' + args: + chdir: '{{ config_dir }}/testing' + register: resources + changed_when: false + +- name: Set resources to {{ state }} + k8s: + definition: '{{ item }}' + state: '{{ state }}' + wait: yes + loop: '{{ resources.stdout | from_yaml_all | list }}' diff --git a/test/ansible/molecule/cluster/molecule.yml b/test/ansible/molecule/default/molecule.yml similarity index 75% rename from test/ansible/molecule/cluster/molecule.yml rename to test/ansible/molecule/default/molecule.yml index 06b307f7d11..ea58004dce7 100644 --- a/test/ansible/molecule/cluster/molecule.yml +++ b/test/ansible/molecule/default/molecule.yml @@ -7,9 +7,9 @@ lint: | set -e yamllint -d "{extends: relaxed, rules: {line-length: {max: 120}}}" . platforms: -- name: cluster - groups: - - k8s + - name: cluster + groups: + - k8s provisioner: name: ansible lint: | @@ -22,10 +22,11 @@ provisioner: host_vars: localhost: ansible_python_interpreter: '{{ ansible_playbook_python }}' - deploy_dir: ${MOLECULE_PROJECT_DIRECTORY}/deploy - template_dir: ${MOLECULE_PROJECT_DIRECTORY}/molecule/templates + config_dir: ${MOLECULE_PROJECT_DIRECTORY}/config + samples_dir: ${MOLECULE_PROJECT_DIRECTORY}/config/samples operator_image: ${OPERATOR_IMAGE:-""} operator_pull_policy: ${OPERATOR_PULL_POLICY:-"Always"} + kustomize: ${KUSTOMIZE_PATH:-kustomize} env: K8S_AUTH_KUBECONFIG: ${KUBECONFIG:-"~/.kube/config"} verifier: diff --git a/test/ansible/molecule/default/prepare.yml b/test/ansible/molecule/default/prepare.yml index 0ef09072db5..7d9f3f1b765 100644 --- a/test/ansible/molecule/default/prepare.yml +++ b/test/ansible/molecule/default/prepare.yml @@ -1,27 +1,28 @@ --- - name: Prepare - hosts: k8s - gather_facts: no + hosts: localhost + connection: local + gather_facts: false + tasks: - - name: Fetch the kubeconfig - fetch: - dest: '{{ kubeconfig_file }}' - flat: yes - src: /root/.kube/config + - name: Ensure operator image is set + fail: + msg: | + You must specify the OPERATOR_IMAGE environment variable in order to run the + 'default' scenario + when: not operator_image + + - name: Set testing image + command: '{{ kustomize }} edit set image testing={{ operator_image }}' + args: + chdir: '{{ config_dir }}/testing' - - name: Change the kubeconfig port to the proper value - replace: - regexp: '8443' - replace: "{{ lookup('env', 'KIND_PORT') }}" - path: '{{ kubeconfig_file }}' - delegate_to: localhost + - name: Set pull policy + command: '{{ kustomize }} edit add patch pull_policy/{{ operator_pull_policy }}.yaml' + args: + chdir: '{{ config_dir }}/testing' - - name: Wait for the Kubernetes API to become available (this could take a minute) - uri: - url: "http://localhost:10080/kubernetes-ready" - status_code: 200 - validate_certs: no - register: result - until: (result.status|default(-1)) == 200 - retries: 60 - delay: 5 + - name: Set testing namespace + command: '{{ kustomize }} edit set namespace {{ namespace }}' + args: + chdir: '{{ config_dir }}/testing' diff --git a/test/ansible/molecule/cluster/tasks/args_test.yml b/test/ansible/molecule/default/tasks/argstest_test.yml similarity index 100% rename from test/ansible/molecule/cluster/tasks/args_test.yml rename to test/ansible/molecule/default/tasks/argstest_test.yml diff --git a/test/ansible/molecule/cluster/tasks/case_test.yml b/test/ansible/molecule/default/tasks/casetest_test.yml similarity index 100% rename from test/ansible/molecule/cluster/tasks/case_test.yml rename to test/ansible/molecule/default/tasks/casetest_test.yml diff --git a/test/ansible/molecule/cluster/tasks/collections_test.yml b/test/ansible/molecule/default/tasks/collectiontest_test.yml similarity index 76% rename from test/ansible/molecule/cluster/tasks/collections_test.yml rename to test/ansible/molecule/default/tasks/collectiontest_test.yml index 61ba0c40b9b..f7053f24bd3 100644 --- a/test/ansible/molecule/cluster/tasks/collections_test.yml +++ b/test/ansible/molecule/default/tasks/collectiontest_test.yml @@ -19,4 +19,9 @@ assert: that: cm.data.did_it_work == 'indeed' vars: - cm: "{{ q('k8s', api_version='v1', kind='ConfigMap', namespace=namespace, resource_name='test-this-collection').0 }}" + cm: "{{ q('k8s', + api_version='v1', + kind='ConfigMap', + namespace=namespace, + resource_name='test-this-collection' + ).0 }}" diff --git a/test/ansible/molecule/cluster/tasks/inventory_test.yml b/test/ansible/molecule/default/tasks/inventorytest_test.yml similarity index 78% rename from test/ansible/molecule/cluster/tasks/inventory_test.yml rename to test/ansible/molecule/default/tasks/inventorytest_test.yml index 909f8960c5b..acb7e7e34d8 100644 --- a/test/ansible/molecule/cluster/tasks/inventory_test.yml +++ b/test/ansible/molecule/default/tasks/inventorytest_test.yml @@ -11,7 +11,10 @@ reason: Successful status: "True" vars: - custom_resource: "{{ lookup('template', '/'.join([deploy_dir, 'crds/test.example.com_v1alpha1_inventorytest_cr.yaml'])) | from_yaml }}" + custom_resource: "{{ lookup('template', '/'.join([ + config_dir, + 'samples/test_v1alpha1_inventorytest.yaml' + ])) | from_yaml }}" - name: Assert sentinel ConfigMap has been created for Molecule Test assert: diff --git a/test/ansible/molecule/cluster/tasks/reconciliation_test.yml b/test/ansible/molecule/default/tasks/reconciliationtest_test.yml similarity index 100% rename from test/ansible/molecule/cluster/tasks/reconciliation_test.yml rename to test/ansible/molecule/default/tasks/reconciliationtest_test.yml diff --git a/test/ansible/molecule/cluster/tasks/secrets_test.yml b/test/ansible/molecule/default/tasks/secretstest_test.yml similarity index 98% rename from test/ansible/molecule/cluster/tasks/secrets_test.yml rename to test/ansible/molecule/default/tasks/secretstest_test.yml index 1b6888c001c..ce8f454bb21 100644 --- a/test/ansible/molecule/cluster/tasks/secrets_test.yml +++ b/test/ansible/molecule/default/tasks/secretstest_test.yml @@ -42,7 +42,7 @@ new: '{{ "content" | b64encode }}' - name: Wait for the corresponding key to be created - k8s_facts: + k8s_info: api_version: v1 kind: ConfigMap name: test-secret diff --git a/test/ansible/molecule/cluster/tasks/selector_test.yml b/test/ansible/molecule/default/tasks/selectortest_test.yml similarity index 99% rename from test/ansible/molecule/cluster/tasks/selector_test.yml rename to test/ansible/molecule/default/tasks/selectortest_test.yml index 5084a1d6010..9254657cfe9 100644 --- a/test/ansible/molecule/cluster/tasks/selector_test.yml +++ b/test/ansible/molecule/default/tasks/selectortest_test.yml @@ -50,5 +50,3 @@ vars: cm: "{{ q('k8s', api_version='v1', kind='ConfigMap', namespace=namespace, resource_name='selector-test-fail')}}" - - diff --git a/test/ansible/molecule/cluster/tasks/subresources_test.yml b/test/ansible/molecule/default/tasks/subresourcestest_test.yml similarity index 100% rename from test/ansible/molecule/cluster/tasks/subresources_test.yml rename to test/ansible/molecule/default/tasks/subresourcestest_test.yml diff --git a/test/ansible/molecule/cluster/verify.yml b/test/ansible/molecule/default/verify.yml similarity index 75% rename from test/ansible/molecule/cluster/verify.yml rename to test/ansible/molecule/default/verify.yml index 386bfbb7219..8670d557a16 100644 --- a/test/ansible/molecule/cluster/verify.yml +++ b/test/ansible/molecule/default/verify.yml @@ -5,12 +5,16 @@ gather_facts: no collections: - community.kubernetes + + vars: + ctrl_label: control-plane=controller-manager + tasks: - block: - - name: Import all test files from tasks/ - include_tasks: '{{ item }}' - with_fileglob: - - tasks/*_test.yml + - name: Import all test files from tasks/ + include_tasks: '{{ item }}' + with_fileglob: + - tasks/*_test.yml rescue: - name: Retrieve relevant resources k8s_info: @@ -32,10 +36,11 @@ k8s_log: name: '{{ item.metadata.name }}' namespace: '{{ namespace }}' - loop: '{{ q("k8s", api_version="v1", kind="Pod", namespace=namespace) }}' + container: manager + loop: "{{ q('k8s', api_version='v1', kind='Pod', namespace=namespace, label_selector=ctrl_label) }}" register: debug_logs - - name: Ouput gathered resources + - name: Output gathered resources debug: var: debug_resources diff --git a/test/ansible/molecule/kind/converge.yml b/test/ansible/molecule/kind/converge.yml new file mode 100644 index 00000000000..dbd27374a5e --- /dev/null +++ b/test/ansible/molecule/kind/converge.yml @@ -0,0 +1,31 @@ +--- +- name: Converge + hosts: localhost + connection: local + gather_facts: no + + tasks: + - name: Build Ansible dev base image + make: + chdir: '{{ project_dir }}/../../' + target: image-build-ansible + # Not important, but maybe should fix someday + changed_when: false + + - name: Build operator image + docker_image: + build: + path: '{{ project_dir }}' + pull: no + name: '{{ operator_image }}' + tag: latest + push: no + source: build + force_source: yes + + - name: Load image into kind cluster + command: kind load docker-image --name osdk-test '{{ operator_image }}' + register: result + changed_when: '"not yet present" in result.stdout' + +- import_playbook: ../default/converge.yml diff --git a/test/ansible/molecule/kind/create.yml b/test/ansible/molecule/kind/create.yml new file mode 100644 index 00000000000..66a84a14f7b --- /dev/null +++ b/test/ansible/molecule/kind/create.yml @@ -0,0 +1,8 @@ +--- +- name: Create + hosts: localhost + connection: local + gather_facts: false + tasks: + - name: Create test kind cluster + command: kind create cluster --name osdk-test --kubeconfig {{ kubeconfig }} diff --git a/test/ansible/molecule/kind/destroy.yml b/test/ansible/molecule/kind/destroy.yml new file mode 100644 index 00000000000..77b75a1d578 --- /dev/null +++ b/test/ansible/molecule/kind/destroy.yml @@ -0,0 +1,12 @@ +--- +- name: Destroy + hosts: localhost + connection: local + gather_facts: false + collections: + - community.kubernetes + + tasks: + - name: Destroy test kind cluster + command: kind delete cluster --name osdk-test --kubeconfig {{ kubeconfig }} + diff --git a/test/ansible/molecule/kind/molecule.yml b/test/ansible/molecule/kind/molecule.yml new file mode 100644 index 00000000000..d4361f32fcb --- /dev/null +++ b/test/ansible/molecule/kind/molecule.yml @@ -0,0 +1,42 @@ +--- +dependency: + name: galaxy +driver: + name: delegated +lint: | + set -e + yamllint -d "{extends: relaxed, rules: {line-length: {max: 120}}}" . +platforms: + - name: cluster + groups: + - k8s +provisioner: + name: ansible + playbooks: + prepare: ../default/prepare.yml + verify: ../default/verify.yml + lint: | + set -e + ansible-lint + inventory: + group_vars: + all: + namespace: ${TEST_OPERATOR_NAMESPACE:-osdk-test} + host_vars: + localhost: + ansible_python_interpreter: '{{ ansible_playbook_python }}' + config_dir: ${MOLECULE_PROJECT_DIRECTORY}/config + samples_dir: ${MOLECULE_PROJECT_DIRECTORY}/config/samples + project_dir: ${MOLECULE_PROJECT_DIRECTORY} + operator_image: testing-operator + operator_pull_policy: "Never" + kubeconfig: "{{ lookup('env', 'KUBECONFIG') }}" + kustomize: ${KUSTOMIZE_PATH:-kustomize} + env: + K8S_AUTH_KUBECONFIG: ${MOLECULE_EPHEMERAL_DIRECTORY}/kubeconfig + KUBECONFIG: ${MOLECULE_EPHEMERAL_DIRECTORY}/kubeconfig +verifier: + name: ansible + lint: | + set -e + ansible-lint diff --git a/test/ansible/molecule/templates/operator.yaml.j2 b/test/ansible/molecule/templates/operator.yaml.j2 deleted file mode 100644 index ac940a6030a..00000000000 --- a/test/ansible/molecule/templates/operator.yaml.j2 +++ /dev/null @@ -1,54 +0,0 @@ ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: ansible -spec: - replicas: 1 - selector: - matchLabels: - name: ansible - template: - metadata: - labels: - name: ansible -{% if hash is defined %} - image_hash: "{{ hash }}" -{% endif %} - spec: - serviceAccountName: ansible - containers: - - name: operator - # Replace this with the built image name - image: "{{ image }}" - imagePullPolicy: "{{ pull_policy }}" - volumeMounts: - - mountPath: /tmp/ansible-operator/runner - name: runner - env: - - name: WATCH_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: OPERATOR_NAME - value: "ansible" - - name: ANSIBLE_GATHERING - value: explicit - - name: ANSIBLE_INVENTORY - value: /opt/ansible/inventory - - name: ANSIBLE_DEBUG_LOGS - value: "TRUE" - livenessProbe: - httpGet: - path: /healthz - port: 6789 - initialDelaySeconds: 5 - periodSeconds: 3 - args: ["--ansible-args='--vault-password-file /opt/ansible/pwd.yml'"] - volumes: - - name: runner - emptyDir: {} diff --git a/test/ansible/molecule/test-local/converge.yml b/test/ansible/molecule/test-local/converge.yml deleted file mode 100644 index bf3bd13d501..00000000000 --- a/test/ansible/molecule/test-local/converge.yml +++ /dev/null @@ -1,55 +0,0 @@ ---- -- name: Build Operator in Kubernetes docker container - hosts: k8s - gather_facts: no - collections: - - community.kubernetes - - vars: - image: test.example.com/ansible:testing - - tasks: - # using command so we don't need to install any dependencies - - name: Get existing image hash - command: docker images -q {{ image }} - register: prev_hash_raw - changed_when: false - - - - name: Build Operator Image - command: docker build -f /build/build/Dockerfile -t {{ image }} /build - register: build_cmd - changed_when: not hash or (hash and hash not in cmd_out) - vars: - hash: '{{ prev_hash_raw.stdout }}' - cmd_out: '{{ "".join(build_cmd.stdout_lines[-2:]) }}' - - - name: Get new image hash - command: docker images -q {{ image }} - register: hash_raw - changed_when: false - - - name: Set localhost hash fact - set_fact: - hash: '{{ hash_raw.stdout }}' - delegate_to: localhost - delegate_facts: true - -- name: Converge - hosts: localhost - connection: local - collections: - - community.kubernetes - - vars: - image: test.example.com/ansible:testing - operator_template: "{{ '/'.join([template_dir, 'operator.yaml.j2']) }}" - - tasks: - - name: Create the Operator Deployment - k8s: - namespace: '{{ namespace }}' - definition: "{{ lookup('template', operator_template) }}" - wait: yes - vars: - pull_policy: Never diff --git a/test/ansible/molecule/test-local/molecule.yml b/test/ansible/molecule/test-local/molecule.yml deleted file mode 100644 index 6fc64c04a9c..00000000000 --- a/test/ansible/molecule/test-local/molecule.yml +++ /dev/null @@ -1,49 +0,0 @@ ---- -dependency: - name: galaxy -driver: - name: docker -lint: | - set -e - yamllint -d "{extends: relaxed, rules: {line-length: {max: 120}}}" . -platforms: - - name: kind-test-local - groups: - - k8s - image: bsycorp/kind:latest-${KUBE_VERSION:-1.17} - privileged: true - override_command: false - exposed_ports: - - 8443/tcp - - 10080/tcp - published_ports: - - 0.0.0.0:${TEST_CLUSTER_PORT:-10443}:8443/tcp - pre_build_image: true - volumes: - - ${MOLECULE_PROJECT_DIRECTORY}:/build:Z -provisioner: - name: ansible - log: true - lint: | - set -e - ansible-lint - inventory: - group_vars: - all: - namespace: ${TEST_OPERATOR_NAMESPACE:-osdk-test} - kubeconfig_file: ${MOLECULE_EPHEMERAL_DIRECTORY}/kubeconfig - host_vars: - localhost: - ansible_python_interpreter: '{{ ansible_playbook_python }}' - template_dir: ${MOLECULE_PROJECT_DIRECTORY}/molecule/templates - deploy_dir: ${MOLECULE_PROJECT_DIRECTORY}/deploy - env: - K8S_AUTH_KUBECONFIG: ${MOLECULE_EPHEMERAL_DIRECTORY}/kubeconfig - KUBECONFIG: ${MOLECULE_EPHEMERAL_DIRECTORY}/kubeconfig - ANSIBLE_ROLES_PATH: ${MOLECULE_PROJECT_DIRECTORY}/roles - KIND_PORT: '${TEST_CLUSTER_PORT:-10443}' -verifier: - name: ansible - lint: | - set -e - ansible-lint diff --git a/test/ansible/molecule/test-local/prepare.yml b/test/ansible/molecule/test-local/prepare.yml deleted file mode 100644 index c070cca02bd..00000000000 --- a/test/ansible/molecule/test-local/prepare.yml +++ /dev/null @@ -1,34 +0,0 @@ ---- -- import_playbook: ../default/prepare.yml -- import_playbook: ../cluster/prepare.yml - -- name: Dump the dev image - hosts: localhost - connection: local - gather_facts: no - - tasks: - - name: Dump the dev image - command: docker save -o /tmp/dev-operator.tar quay.io/operator-framework/ansible-operator:dev - - - name: Copy the image to the kind container - command: docker cp /tmp/dev-operator.tar kind-test-local:/dev-operator.tar - -- name: Make dev operator image available for Molecule Test - hosts: k8s - gather_facts: no - - tasks: - - name: Make dev operator available - command: docker load -i /dev-operator.tar - -- name: Clean up for Molecule Test - hosts: localhost - connection: local - gather_facts: no - - tasks: - - name: remove dev-operator.tar - file: - path: /tmp/dev-operator.tar - state: absent diff --git a/test/ansible/molecule/test-local/verify.yml b/test/ansible/molecule/test-local/verify.yml deleted file mode 100644 index 4c003088462..00000000000 --- a/test/ansible/molecule/test-local/verify.yml +++ /dev/null @@ -1,2 +0,0 @@ ---- -- import_playbook: ../cluster/verify.yml diff --git a/test/ansible/playbooks/args.yml b/test/ansible/playbooks/argstest.yml similarity index 100% rename from test/ansible/playbooks/args.yml rename to test/ansible/playbooks/argstest.yml diff --git a/test/ansible/playbooks/case.yml b/test/ansible/playbooks/casetest.yml similarity index 100% rename from test/ansible/playbooks/case.yml rename to test/ansible/playbooks/casetest.yml index 06ba12109f0..083416793a1 100644 --- a/test/ansible/playbooks/case.yml +++ b/test/ansible/playbooks/casetest.yml @@ -3,7 +3,6 @@ gather_facts: no collections: - community.kubernetes - tasks: - name: Create configmap k8s: @@ -15,3 +14,4 @@ namespace: '{{ meta.namespace }}' data: shouldBeCamel: '{{ camelCaseVar | default("false") }}' + diff --git a/test/ansible/playbooks/inventory.yml b/test/ansible/playbooks/inventorytest.yml similarity index 76% rename from test/ansible/playbooks/inventory.yml rename to test/ansible/playbooks/inventorytest.yml index d77d0e73638..3f57edac2d8 100644 --- a/test/ansible/playbooks/inventory.yml +++ b/test/ansible/playbooks/inventorytest.yml @@ -1,10 +1,9 @@ --- - - hosts: test gather_facts: no tasks: - - import_role: - name: inventory + - import_role: + name: "inventorytest" - hosts: localhost gather_facts: no diff --git a/test/ansible/playbooks/reconciliation.yml b/test/ansible/playbooks/reconciliationtest.yml similarity index 100% rename from test/ansible/playbooks/reconciliation.yml rename to test/ansible/playbooks/reconciliationtest.yml diff --git a/test/ansible/playbooks/selector.yml b/test/ansible/playbooks/selectortest.yml similarity index 100% rename from test/ansible/playbooks/selector.yml rename to test/ansible/playbooks/selectortest.yml diff --git a/test/ansible/playbooks/subresources.yml b/test/ansible/playbooks/subresourcestest.yml similarity index 100% rename from test/ansible/playbooks/subresources.yml rename to test/ansible/playbooks/subresourcestest.yml diff --git a/test/ansible/requirements.yml b/test/ansible/requirements.yml index e7849b923e8..8a661f8b95e 100644 --- a/test/ansible/requirements.yml +++ b/test/ansible/requirements.yml @@ -1,4 +1,5 @@ +--- collections: - name: community.kubernetes - version: <1.0.0 + version: "<1.0.0" - operator_sdk.util diff --git a/test/ansible/roles/inventory/tasks/main.yml b/test/ansible/roles/inventorytest/tasks/main.yml similarity index 100% rename from test/ansible/roles/inventory/tasks/main.yml rename to test/ansible/roles/inventorytest/tasks/main.yml diff --git a/test/ansible/watches.yaml b/test/ansible/watches.yaml index b17940e6bd7..2f9392daaf1 100644 --- a/test/ansible/watches.yaml +++ b/test/ansible/watches.yaml @@ -1,8 +1,9 @@ --- +# Use the 'create api' subcommand to add watches to this file. - version: v1alpha1 group: test.example.com kind: InventoryTest - playbook: playbooks/inventory.yml + playbook: playbooks/inventorytest.yml vars: meta: '{{ ansible_operator_meta }}' @@ -16,7 +17,7 @@ - version: v1alpha1 group: test.example.com kind: SubresourcesTest - playbook: playbooks/subresources.yml + playbook: playbooks/subresourcestest.yml vars: meta: '{{ ansible_operator_meta }}' @@ -31,7 +32,7 @@ - version: v1alpha1 group: test.example.com kind: SelectorTest - playbook: playbooks/selector.yml + playbook: playbooks/selectortest.yml selector: matchExpressions: - {key: testLabel, operator: Exists, values: []} @@ -41,7 +42,7 @@ - version: v1alpha1 group: test.example.com kind: CaseTest - playbook: playbooks/case.yml + playbook: playbooks/casetest.yml snakeCaseParameters: false vars: meta: '{{ ansible_operator_meta }}' @@ -49,13 +50,14 @@ - version: v1alpha1 group: test.example.com kind: ArgsTest - playbook: playbooks/args.yml + playbook: playbooks/argstest.yml vars: meta: '{{ ansible_operator_meta }}' - version: v1alpha1 group: test.example.com kind: ReconciliationTest - playbook: playbooks/reconciliation.yml + playbook: playbooks/reconciliationtest.yml vars: meta: '{{ ansible_operator_meta }}' +# +kubebuilder:scaffold:watch From 8367ffb0445fcbcf6391157cc550b1d18cd8d66c Mon Sep 17 00:00:00 2001 From: Austin Macdonald Date: Tue, 15 Dec 2020 14:37:24 -0500 Subject: [PATCH 247/376] Pin top level Python dependencies (#4321) This rolls back the version of Ansible installed in the Ansible base image, fixing a syntax error in the Dockerfile. Signed-off-by: reinvantveer --- changelog/fragments/pin-ansible-2.9.yaml | 9 +++++++++ images/ansible-operator/Dockerfile | 9 +++++---- 2 files changed, 14 insertions(+), 4 deletions(-) create mode 100644 changelog/fragments/pin-ansible-2.9.yaml diff --git a/changelog/fragments/pin-ansible-2.9.yaml b/changelog/fragments/pin-ansible-2.9.yaml new file mode 100644 index 00000000000..7c51087137d --- /dev/null +++ b/changelog/fragments/pin-ansible-2.9.yaml @@ -0,0 +1,9 @@ +# entries is a list of entries to include in +# release notes and/or the migration guide +entries: + - description: > + (ansible/v1) Pin all top level Python requirements. This fixes a bug that + erroneously installed Ansible 2.10.z instead of Ansible 2.9.z. + + kind: "bugfix" + breaking: false diff --git a/images/ansible-operator/Dockerfile b/images/ansible-operator/Dockerfile index 65e30e2e87d..0b813e706f7 100644 --- a/images/ansible-operator/Dockerfile +++ b/images/ansible-operator/Dockerfile @@ -17,12 +17,13 @@ RUN yum clean all && rm -rf /var/cache/yum/* \ && yum -y update \ && yum install -y libffi-devel openssl-devel python36-devel gcc python3-pip python3-setuptools \ && pip3 install --no-cache-dir \ - ipaddress \ ansible-runner==1.3.4 \ ansible-runner-http==1.0.0 \ - openshift~=0.10.0 \ - ansible~=2.9 \ - jmespath \ + ipaddress==1.0.23 \ + kubernetes==10.1.0 \ + openshift==0.10.3 \ + ansible==2.9.15 \ + jmespath==0.10.0 \ && yum remove -y gcc libffi-devel openssl-devel python36-devel \ && yum clean all \ && rm -rf /var/cache/yum From 59bb637ba09c79b6aa5818be401591afa7f90c95 Mon Sep 17 00:00:00 2001 From: Camila Macedo Date: Wed, 16 Dec 2020 18:33:36 +0000 Subject: [PATCH 248/376] test-e2e/samples/cleanup: centralize code to integrate the project with OLM (#4144) **Description of the change:** - Move the olm helpers in the `hack/generate/samples/internal/pkg/utils.go` to `internal/testutils/olm.go`. Reason: allow samples and tests to use the same helper and keep it in a more appropriate place. - Remove the duplicates calls made in the e2e tests which are already done in the samples in the e2e tests - Use the e2e test the helper instead of duplicate the code. **Motivation for the change:** - Maintainability - Reduce CI effort by not calling make bundle twice. - Centralize the steps to integrate the projects with OLM and keep samples and e2e tests using the same func - Reduce the duplication of code as of the calls made Signed-off-by: reinvantveer --- .../generate/samples/internal/ansible/memcached.go | 8 +++++++- .../internal/go/v2/memcached_with_webhooks.go | 8 +++++++- .../internal/go/v3/memcached_with_webhooks.go | 8 +++++++- hack/generate/samples/internal/helm/memcached.go | 8 +++++++- hack/generate/samples/internal/pkg/utils.go | 13 ------------- internal/testutils/olm.go | 13 +++++++++++++ test/e2e-ansible/e2e_ansible_olm_test.go | 12 +----------- test/e2e-ansible/e2e_ansible_suite_test.go | 4 ++-- test/e2e-go/e2e_go_suite_test.go | 14 ++------------ test/e2e-helm/e2e_helm_olm_test.go | 6 ------ test/e2e-helm/e2e_helm_suite_test.go | 4 ++-- 11 files changed, 48 insertions(+), 50 deletions(-) diff --git a/hack/generate/samples/internal/ansible/memcached.go b/hack/generate/samples/internal/ansible/memcached.go index 2a4252c0ba7..c191d6c1dde 100644 --- a/hack/generate/samples/internal/ansible/memcached.go +++ b/hack/generate/samples/internal/ansible/memcached.go @@ -76,7 +76,13 @@ func (ma *MemcachedAnsible) Run() { ma.addingAnsibleTask() ma.addingMoleculeMockData() - ma.ctx.CreateBundle() + log.Infof("creating the bundle") + err = ma.ctx.GenerateBundle() + pkg.CheckError("creating the bundle", err) + + log.Infof("striping bundle annotations") + err = ma.ctx.StripBundleAnnotations() + pkg.CheckError("striping bundle annotations", err) } // addingMoleculeMockData will customize the molecule data diff --git a/hack/generate/samples/internal/go/v2/memcached_with_webhooks.go b/hack/generate/samples/internal/go/v2/memcached_with_webhooks.go index 9c1afcb68e1..f920219c92d 100644 --- a/hack/generate/samples/internal/go/v2/memcached_with_webhooks.go +++ b/hack/generate/samples/internal/go/v2/memcached_with_webhooks.go @@ -93,7 +93,13 @@ func (mh *MemcachedGoWithWebhooks) Run() { mh.implementingWebhooks() mh.uncommentKustomizationFile() - mh.ctx.CreateBundle() + log.Infof("creating the bundle") + err = mh.ctx.GenerateBundle() + pkg.CheckError("creating the bundle", err) + + log.Infof("striping bundle annotations") + err = mh.ctx.StripBundleAnnotations() + pkg.CheckError("striping bundle annotations", err) pkg.CheckError("formatting project", mh.ctx.Make("fmt")) diff --git a/hack/generate/samples/internal/go/v3/memcached_with_webhooks.go b/hack/generate/samples/internal/go/v3/memcached_with_webhooks.go index 57c7ac51ab6..30172df6bb0 100644 --- a/hack/generate/samples/internal/go/v3/memcached_with_webhooks.go +++ b/hack/generate/samples/internal/go/v3/memcached_with_webhooks.go @@ -94,7 +94,13 @@ func (mh *MemcachedGoWithWebhooks) Run() { mh.implementingWebhooks() mh.uncommentKustomizationFile() - mh.ctx.CreateBundle() + log.Infof("creating the bundle") + err = mh.ctx.GenerateBundle() + pkg.CheckError("creating the bundle", err) + + log.Infof("striping bundle annotations") + err = mh.ctx.StripBundleAnnotations() + pkg.CheckError("striping bundle annotations", err) pkg.CheckError("formatting project", mh.ctx.Make("fmt")) diff --git a/hack/generate/samples/internal/helm/memcached.go b/hack/generate/samples/internal/helm/memcached.go index 9abf434e5a7..92839e35c22 100644 --- a/hack/generate/samples/internal/helm/memcached.go +++ b/hack/generate/samples/internal/helm/memcached.go @@ -93,7 +93,13 @@ func (mh *MemcachedHelm) Run() { "# +kubebuilder:scaffold:rules", policyRolesFragment) pkg.CheckError("adding customized roles", err) - mh.ctx.CreateBundle() + log.Infof("creating the bundle") + err = mh.ctx.GenerateBundle() + pkg.CheckError("creating the bundle", err) + + log.Infof("striping bundle annotations") + err = mh.ctx.StripBundleAnnotations() + pkg.CheckError("striping bundle annotations", err) } // GenerateMemcachedHelmSample will call all actions to create the directory and generate the sample diff --git a/hack/generate/samples/internal/pkg/utils.go b/hack/generate/samples/internal/pkg/utils.go index d1dbefeb5c8..92ea7078d20 100644 --- a/hack/generate/samples/internal/pkg/utils.go +++ b/hack/generate/samples/internal/pkg/utils.go @@ -34,19 +34,6 @@ func CheckError(msg string, err error) { } } -// CreateBundle runs all commands to create an operator bundle. -func (ctx *SampleContext) CreateBundle() { - log.Infof("integrating project with OLM") - err := ctx.DisableManifestsInteractiveMode() - CheckError("disabling `generate kustomize manifests` interactive mode", err) - - err = ctx.Make("bundle", "IMG="+ctx.ImageName) - CheckError("running make bundle", err) - - err = ctx.StripBundleAnnotations() - CheckError("stripping bundle annotations", err) -} - // StripBundleAnnotations removes all annotations applied to bundle manifests and metadata // by operator-sdk/internal/annotations/metrics annotators. Doing so decouples samples // from which operator-sdk version they were build with, as this information is already diff --git a/internal/testutils/olm.go b/internal/testutils/olm.go index 59ebed81627..151994eb0a0 100644 --- a/internal/testutils/olm.go +++ b/internal/testutils/olm.go @@ -89,3 +89,16 @@ func (tc TestContext) DisableManifestsInteractiveMode() error { replace := content + " --interactive=false" return ReplaceInFile(filepath.Join(tc.Dir, "Makefile"), content, replace) } + +// GenerateBundle runs all commands to create an operator bundle. +func (tc TestContext) GenerateBundle() error { + if err := tc.DisableManifestsInteractiveMode(); err != nil { + return err + } + + if err := tc.Make("bundle", "IMG="+tc.ImageName); err != nil { + return err + } + + return nil +} diff --git a/test/e2e-ansible/e2e_ansible_olm_test.go b/test/e2e-ansible/e2e_ansible_olm_test.go index a78d261b25b..00726fb807e 100644 --- a/test/e2e-ansible/e2e_ansible_olm_test.go +++ b/test/e2e-ansible/e2e_ansible_olm_test.go @@ -26,20 +26,10 @@ var _ = Describe("Integrating ansible Projects with OLM", func() { const operatorVersion = "0.0.1" It("should generate and run a valid OLM bundle and packagemanifests", func() { - By("building the bundle") - err := tc.Make("bundle", "IMG="+tc.ImageName) - Expect(err).NotTo(HaveOccurred()) - By("building the operator bundle image") - err = tc.Make("bundle-build", "BUNDLE_IMG="+tc.BundleImageName) + err := tc.Make("bundle-build", "BUNDLE_IMG="+tc.BundleImageName) Expect(err).NotTo(HaveOccurred()) - if tc.IsRunningOnKind() { - By("loading the bundle image into Kind cluster") - err = tc.LoadImageToKindClusterWithName(tc.BundleImageName) - Expect(err).NotTo(HaveOccurred()) - } - By("adding the 'packagemanifests' rule to the Makefile") err = tc.AddPackagemanifestsTarget() Expect(err).NotTo(HaveOccurred()) diff --git a/test/e2e-ansible/e2e_ansible_suite_test.go b/test/e2e-ansible/e2e_ansible_suite_test.go index c2256ccacc7..6f008e158d9 100644 --- a/test/e2e-ansible/e2e_ansible_suite_test.go +++ b/test/e2e-ansible/e2e_ansible_suite_test.go @@ -121,8 +121,8 @@ var _ = BeforeSuite(func() { Expect(tc.LoadImageToKindClusterWithName("quay.io/operator-framework/scorecard-test:dev")).To(Succeed()) } - By("building the bundle") - err = tc.Make("bundle", "IMG="+tc.ImageName) + By("creating bundle image") + err = tc.GenerateBundle() Expect(err).NotTo(HaveOccurred()) }) diff --git a/test/e2e-go/e2e_go_suite_test.go b/test/e2e-go/e2e_go_suite_test.go index b3b2831250f..9fb9ca0c4c3 100644 --- a/test/e2e-go/e2e_go_suite_test.go +++ b/test/e2e-go/e2e_go_suite_test.go @@ -83,20 +83,10 @@ var _ = BeforeSuite(func() { Expect(tc.LoadImageToKindClusterWithName("quay.io/operator-framework/custom-scorecard-tests:dev")).To(Succeed()) } - By("generating the operator bundle") - err = tc.Make("bundle", "IMG="+tc.ImageName) + By("creating bundle image") + err = tc.GenerateBundle() Expect(err).NotTo(HaveOccurred()) - By("building the operator bundle image") - err = tc.Make("bundle-build", "BUNDLE_IMG="+tc.BundleImageName) - Expect(err).NotTo(HaveOccurred()) - - if tc.IsRunningOnKind() { - By("loading the bundle image into Kind cluster") - err = tc.LoadImageToKindClusterWithName(tc.BundleImageName) - Expect(err).NotTo(HaveOccurred()) - } - By("installing cert manager bundle") Expect(tc.InstallCertManager(true)).To(Succeed()) }) diff --git a/test/e2e-helm/e2e_helm_olm_test.go b/test/e2e-helm/e2e_helm_olm_test.go index 143e1b11661..ec7d8f349cd 100644 --- a/test/e2e-helm/e2e_helm_olm_test.go +++ b/test/e2e-helm/e2e_helm_olm_test.go @@ -30,12 +30,6 @@ var _ = Describe("Integrating Helm Projects with OLM", func() { err := tc.Make("bundle-build", "BUNDLE_IMG="+tc.BundleImageName) Expect(err).NotTo(HaveOccurred()) - if tc.IsRunningOnKind() { - By("loading the bundle image into Kind cluster") - err = tc.LoadImageToKindClusterWithName(tc.BundleImageName) - Expect(err).NotTo(HaveOccurred()) - } - By("adding the 'packagemanifests' rule to the Makefile") err = tc.AddPackagemanifestsTarget() Expect(err).NotTo(HaveOccurred()) diff --git a/test/e2e-helm/e2e_helm_suite_test.go b/test/e2e-helm/e2e_helm_suite_test.go index 12e96f845dd..14bb9b17d90 100644 --- a/test/e2e-helm/e2e_helm_suite_test.go +++ b/test/e2e-helm/e2e_helm_suite_test.go @@ -87,8 +87,8 @@ var _ = BeforeSuite(func() { Expect(tc.LoadImageToKindClusterWithName("quay.io/operator-framework/scorecard-test:dev")).To(Succeed()) } - By("generating the operator bundle") - err = tc.Make("bundle", "IMG="+tc.ImageName) + By("creating bundle image") + err = tc.GenerateBundle() Expect(err).NotTo(HaveOccurred()) }) From 8a16d2fcd256f007284d70dfe4ae06b106a33114 Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Wed, 16 Dec 2020 13:30:28 -0800 Subject: [PATCH 249/376] *: make go/v3 the default plugin (#4307) Signed-off-by: reinvantveer --- .gitignore | 12 +++----- changelog/fragments/go-v3-default.yaml | 28 +++++++++++++++++++ go.mod | 2 +- go.sum | 4 +-- .../internal/go/v3/memcached_with_webhooks.go | 3 +- internal/cmd/operator-sdk/cli/cli.go | 3 +- internal/generate/testdata/go/PROJECT | 3 -- test/e2e-go/e2e_go_cluster_test.go | 15 ++++++++-- test/e2e-go/e2e_go_suite_test.go | 6 ++-- testdata/go/v3/memcached-operator/PROJECT | 2 +- ...cached-operator.clusterserviceversion.yaml | 4 +-- .../config/manager/manager.yaml | 4 +-- .../building-operators/golang/tutorial.md | 2 +- .../content/en/docs/cli/operator-sdk_init.md | 3 +- 14 files changed, 60 insertions(+), 31 deletions(-) create mode 100644 changelog/fragments/go-v3-default.yaml diff --git a/.gitignore b/.gitignore index 8a8884325af..a73e7b67226 100644 --- a/.gitignore +++ b/.gitignore @@ -4,8 +4,10 @@ # Build artifacts /build /dist -/tools/bin -/images/*/bin +**/bin/ + +# Test artifacts +**/testbin/ # CI GPG keyring /.ci/gpg/keyring @@ -16,12 +18,6 @@ website/resources/ website/node_modules/ website/tech-doc-hugo -# Ensure that will not commit the bin gen in the go sample -testdata/go/v2/memcached-operator/bin/* -testdata/go/v3/memcached-operator/bin/* -testdata/ansible/memcached-operator/bin/* -testdata/helm/memcached-operator/bin/* - # Ignore molecule samples testdata if it be generated in the testdata/ diretory testdata/ansible/memcached-molecule-operator diff --git a/changelog/fragments/go-v3-default.yaml b/changelog/fragments/go-v3-default.yaml new file mode 100644 index 00000000000..bebca94ab19 --- /dev/null +++ b/changelog/fragments/go-v3-default.yaml @@ -0,0 +1,28 @@ +entries: + - description: > + Go CLI plugin go/v3 is now the default. + kind: change + breaking: false + migration: + header: Upgrade your Go project from "go.kubebuilder.io/v2" to "go.kubebuilder.io/v3" + body: > + The newly released go/v3 plugin has many new features and (breaking) changes + incompatible with projects created by go/v2. You are not required to upgrade + and your go/v2 project will continue to work with new operator-sdk versions. + If you wish to upgrade, check out the upstream + [migration guide](https://master.book.kubebuilder.io/migration/plugin/plugins.html). + + Additionally, if using project version "3-alpha", you must update your "plugins" config field: + + Old: + ```yaml + plugins: + go.sdk.operatorframework.io/v2-alpha: {} + ``` + + New: + ```yaml + plugins: + manifests.sdk.operatorframework.io/v2: {} + scorecard.sdk.operatorframework.io/v2: {} + ``` diff --git a/go.mod b/go.mod index b0a0f336604..90c8b5fe6dd 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( rsc.io/letsencrypt v0.0.3 // indirect sigs.k8s.io/controller-runtime v0.7.0 sigs.k8s.io/controller-tools v0.4.1 - sigs.k8s.io/kubebuilder/v2 v2.3.2-0.20201211222127-503ba3b7e4ad + sigs.k8s.io/kubebuilder/v2 v2.3.2-0.20201214213149-0a807f4e9428 sigs.k8s.io/yaml v1.2.0 ) diff --git a/go.sum b/go.sum index c80021a92c1..8a11841724d 100644 --- a/go.sum +++ b/go.sum @@ -1354,8 +1354,8 @@ sigs.k8s.io/controller-tools v0.3.0 h1:y3YD99XOyWaXkiF1kd41uRvfp/64teWcrEZFuHxPh sigs.k8s.io/controller-tools v0.3.0/go.mod h1:enhtKGfxZD1GFEoMgP8Fdbu+uKQ/cq1/WGJhdVChfvI= sigs.k8s.io/controller-tools v0.4.1 h1:VkuV0MxlRPmRu5iTgBZU4UxUX2LiR99n3sdQGRxZF4w= sigs.k8s.io/controller-tools v0.4.1/go.mod h1:G9rHdZMVlBDocIxGkK3jHLWqcTMNvveypYJwrvYKjWU= -sigs.k8s.io/kubebuilder/v2 v2.3.2-0.20201211222127-503ba3b7e4ad h1:QCCQLxLLZsNKgp49jG0rErcSz9oa/4J5WU7lnaEA99A= -sigs.k8s.io/kubebuilder/v2 v2.3.2-0.20201211222127-503ba3b7e4ad/go.mod h1:J/D/179LBZhQOhRvmMRNbje/Bk+PjbN0/fzUupmO7+U= +sigs.k8s.io/kubebuilder/v2 v2.3.2-0.20201214213149-0a807f4e9428 h1:VUvP/g8pDUdqBHgKPoSX6WA/ZH1Y1+FBOk7khgyTLJw= +sigs.k8s.io/kubebuilder/v2 v2.3.2-0.20201214213149-0a807f4e9428/go.mod h1:J/D/179LBZhQOhRvmMRNbje/Bk+PjbN0/fzUupmO7+U= sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0= sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU= sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= diff --git a/hack/generate/samples/internal/go/v3/memcached_with_webhooks.go b/hack/generate/samples/internal/go/v3/memcached_with_webhooks.go index 30172df6bb0..7fa47552baf 100644 --- a/hack/generate/samples/internal/go/v3/memcached_with_webhooks.go +++ b/hack/generate/samples/internal/go/v3/memcached_with_webhooks.go @@ -61,8 +61,7 @@ func (mh *MemcachedGoWithWebhooks) Run() { err := mh.ctx.Init( // TODO(estroz): change this to 3 when stabilized. "--project-version", "3-alpha", - // TODO(estroz): change this to go/v3 when stabilized. - "--plugins", "go/v3-alpha", + "--plugins", "go/v3", "--repo", "github.com/example/memcached-operator", "--domain", mh.ctx.Domain) diff --git a/internal/cmd/operator-sdk/cli/cli.go b/internal/cmd/operator-sdk/cli/cli.go index 8b8641858da..4d58761120a 100644 --- a/internal/cmd/operator-sdk/cli/cli.go +++ b/internal/cmd/operator-sdk/cli/cli.go @@ -66,8 +66,7 @@ func GetPluginsCLIAndRoot() (cli.CLI, *cobra.Command) { &ansiblev1.Plugin{}, ), cli.WithDefaultPlugins(config.Version2, &golangv2.Plugin{}), - // TODO(estroz): make go/v3-alpha plugin the default once stabilized. - cli.WithDefaultPlugins(config.Version3Alpha, &golangv2.Plugin{}), + cli.WithDefaultPlugins(config.Version3Alpha, &golangv3.Plugin{}), cli.WithExtraCommands(commands...), ) if err != nil { diff --git a/internal/generate/testdata/go/PROJECT b/internal/generate/testdata/go/PROJECT index 29a8478d6fd..645b55f2cd7 100644 --- a/internal/generate/testdata/go/PROJECT +++ b/internal/generate/testdata/go/PROJECT @@ -1,5 +1,4 @@ domain: example.com -layout: go.kubebuilder.io/v2 projectName: memcached-operator repo: github.com/example/memcached-operator resources: @@ -7,5 +6,3 @@ resources: kind: Memcached version: v1alpha1 version: 3-alpha -plugins: - go.sdk.operatorframework.io/v2-alpha: {} diff --git a/test/e2e-go/e2e_go_cluster_test.go b/test/e2e-go/e2e_go_cluster_test.go index 153a01fae4f..01aafbdd753 100644 --- a/test/e2e-go/e2e_go_cluster_test.go +++ b/test/e2e-go/e2e_go_cluster_test.go @@ -19,6 +19,7 @@ package e2e_go_test import ( "encoding/base64" "encoding/json" + "errors" "fmt" "path/filepath" "strings" @@ -51,7 +52,8 @@ var _ = Describe("operator-sdk", func() { testutils.WrapWarnOutput(tc.Kubectl.Command("delete", "clusterrolebinding", metricsClusterRoleBindingName)) By("cleaning up created API objects during test process") - tc.CleanupManifests(filepath.Join("config", "default")) + // TODO(estroz): go/v2 does not have this target, so generalize once tests are refactored. + testutils.WrapWarn(tc.Make("undeploy")) By("ensuring that the namespace was deleted") testutils.WrapWarnOutput(tc.Kubectl.Wait(false, "namespace", "foo", "--for", "delete", "--timeout", "2m")) @@ -174,8 +176,15 @@ var _ = Describe("operator-sdk", func() { // The controller updates memcacheds' status.nodes with a list of pods it is replicated across // on a successful reconcile. By("validating that the created resource object gets reconciled in the controller") - status, err := tc.Kubectl.Get(true, "memcacheds", "memcached-sample", "-o", "jsonpath={.status.nodes}") - Expect(err).NotTo(HaveOccurred()) + var status string + getStatus := func() error { + status, err = tc.Kubectl.Get(true, "memcacheds", "memcached-sample", "-o", "jsonpath={.status.nodes}") + if err == nil && strings.TrimSpace(status) == "" { + err = errors.New("empty status, continue") + } + return err + } + Eventually(getStatus, 1*time.Minute, time.Second).Should(Succeed()) var nodes []string Expect(json.Unmarshal([]byte(status), &nodes)).To(Succeed()) Expect(len(nodes)).To(BeNumerically(">", 0)) diff --git a/test/e2e-go/e2e_go_suite_test.go b/test/e2e-go/e2e_go_suite_test.go index 9fb9ca0c4c3..b56119dbd19 100644 --- a/test/e2e-go/e2e_go_suite_test.go +++ b/test/e2e-go/e2e_go_suite_test.go @@ -55,7 +55,7 @@ var _ = BeforeSuite(func() { tc.Kubectl.Namespace = fmt.Sprintf("%s-system", tc.ProjectName) By("copying sample to a temporary e2e directory") - Expect(exec.Command("cp", "-r", "../../testdata/go/v2/memcached-operator", tc.Dir).Run()).To(Succeed()) + Expect(exec.Command("cp", "-r", "../../testdata/go/v3/memcached-operator", tc.Dir).Run()).To(Succeed()) By("fetching the current-context") tc.Kubectx, err = tc.Kubectl.Command("config", "current-context") @@ -88,14 +88,14 @@ var _ = BeforeSuite(func() { Expect(err).NotTo(HaveOccurred()) By("installing cert manager bundle") - Expect(tc.InstallCertManager(true)).To(Succeed()) + Expect(tc.InstallCertManager(false)).To(Succeed()) }) // AfterSuite run after all the specs have run, regardless of whether any tests have failed to ensures that // all be cleaned up var _ = AfterSuite(func() { By("uninstall cert manager bundle") - tc.UninstallCertManager(true) + tc.UninstallCertManager(false) By("uninstalling prerequisites") tc.UninstallPrerequisites() diff --git a/testdata/go/v3/memcached-operator/PROJECT b/testdata/go/v3/memcached-operator/PROJECT index f968692d2db..aa02ce8b005 100644 --- a/testdata/go/v3/memcached-operator/PROJECT +++ b/testdata/go/v3/memcached-operator/PROJECT @@ -1,5 +1,5 @@ domain: example.com -layout: go.kubebuilder.io/v3-alpha +layout: go.kubebuilder.io/v3 projectName: memcached-operator repo: github.com/example/memcached-operator resources: diff --git a/testdata/go/v3/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml b/testdata/go/v3/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml index 44ab0a69513..227fc73d1f3 100644 --- a/testdata/go/v3/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml +++ b/testdata/go/v3/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml @@ -128,7 +128,7 @@ spec: image: quay.io/example/memcached-operator:v0.0.1 livenessProbe: httpGet: - path: /readyz + path: /healthz port: 8081 initialDelaySeconds: 15 periodSeconds: 20 @@ -139,7 +139,7 @@ spec: protocol: TCP readinessProbe: httpGet: - path: /healthz + path: /readyz port: 8081 initialDelaySeconds: 5 periodSeconds: 10 diff --git a/testdata/go/v3/memcached-operator/config/manager/manager.yaml b/testdata/go/v3/memcached-operator/config/manager/manager.yaml index 11cf9f6af38..70e3f6acf1a 100644 --- a/testdata/go/v3/memcached-operator/config/manager/manager.yaml +++ b/testdata/go/v3/memcached-operator/config/manager/manager.yaml @@ -35,13 +35,13 @@ spec: allowPrivilegeEscalation: false livenessProbe: httpGet: - path: /readyz + path: /healthz port: 8081 initialDelaySeconds: 15 periodSeconds: 20 readinessProbe: httpGet: - path: /healthz + path: /readyz port: 8081 initialDelaySeconds: 5 periodSeconds: 10 diff --git a/website/content/en/docs/building-operators/golang/tutorial.md b/website/content/en/docs/building-operators/golang/tutorial.md index 0a88e0533f7..00dd447e8db 100644 --- a/website/content/en/docs/building-operators/golang/tutorial.md +++ b/website/content/en/docs/building-operators/golang/tutorial.md @@ -65,7 +65,7 @@ Before creating an API and controller, consider if your operator requires multip ```YAML domain: example.com -layout: go.kubebuilder.io/v2 +layout: go.kubebuilder.io/v3 multigroup: true ... ``` diff --git a/website/content/en/docs/cli/operator-sdk_init.md b/website/content/en/docs/cli/operator-sdk_init.md index b018748f815..7e1d0d257e6 100644 --- a/website/content/en/docs/cli/operator-sdk_init.md +++ b/website/content/en/docs/cli/operator-sdk_init.md @@ -37,12 +37,13 @@ operator-sdk init [flags] ### Options ``` + --component-config create a versioned ComponentConfig file, may be 'true' or 'false' --domain string domain for groups (default "my.domain") --fetch-deps ensure dependencies are downloaded (default true) -h, --help help for init --license string license to use to boilerplate, may be one of 'apache2', 'none' (default "apache2") --owner string owner to add to the copyright - --plugins strings Name and optionally version of the plugin to initialize the project with. Available plugins: ("ansible.sdk.operatorframework.io/v1", "go.kubebuilder.io/v2", "go.kubebuilder.io/v3-alpha", "helm.sdk.operatorframework.io/v1") + --plugins strings Name and optionally version of the plugin to initialize the project with. Available plugins: ("ansible.sdk.operatorframework.io/v1", "go.kubebuilder.io/v2", "go.kubebuilder.io/v3", "helm.sdk.operatorframework.io/v1") --project-name string name of this project --project-version string project version, possible values: ("2", "3-alpha") (default "3-alpha") --repo string name to use for go module (e.g., github.com/user/repo), defaults to the go package of the current working directory. From e9351c75bb119f61dc69c905f1a6ba66ba03e361 Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Thu, 17 Dec 2020 14:23:35 -0800 Subject: [PATCH 250/376] docs: update old links, FAQ, and Reconcile() code references (#4333) Signed-off-by: reinvantveer --- .../golang/advanced-topics.md | 3 +- .../building-operators/golang/migration.md | 4 +- .../golang/references/client.md | 22 +++--- .../golang/references/logging.md | 5 +- .../building-operators/golang/tutorial.md | 8 +- website/content/en/docs/faqs/_index.md | 77 +++++++++---------- 6 files changed, 56 insertions(+), 63 deletions(-) diff --git a/website/content/en/docs/building-operators/golang/advanced-topics.md b/website/content/en/docs/building-operators/golang/advanced-topics.md index 05b5d5eb7f0..ef319d96d8f 100644 --- a/website/content/en/docs/building-operators/golang/advanced-topics.md +++ b/website/content/en/docs/building-operators/golang/advanced-topics.md @@ -142,8 +142,7 @@ import ( const memcachedFinalizer = "finalizer.cache.example.com" -func (r *MemcachedReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { - ctx := context.Background() +func (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { reqLogger := r.log.WithValues("memcached", req.NamespacedName) reqLogger.Info("Reconciling Memcached") diff --git a/website/content/en/docs/building-operators/golang/migration.md b/website/content/en/docs/building-operators/golang/migration.md index ff3a47b44b9..d0d3eaa5a0f 100644 --- a/website/content/en/docs/building-operators/golang/migration.md +++ b/website/content/en/docs/building-operators/golang/migration.md @@ -331,7 +331,7 @@ E.g `kubectl logs deployment.apps/memcached-operator-controller-manager -n memca [integration-doc]: https://github.com/kubernetes-sigs/kubebuilder/blob/master/designs/integrating-kubebuilder-and-osdk.md [quickstart]: /docs/building-operators/golang/quickstart/ [metrics]: https://book.kubebuilder.io/reference/metrics.html?highlight=metr#metrics -[memcached_controller]: https://github.com/operator-framework/operator-sdk/blob/master/testdata/go/memcached-operator/controllers/memcached_controller.go +[memcached_controller]: https://github.com/operator-framework/operator-sdk/blob/v1.2.0/testdata/go/memcached-operator/controllers/memcached_controller.go [rbac_markers]: https://book.kubebuilder.io/reference/markers/rbac.html [kube-auth-proxy]: https://github.com/brancz/kube-rbac-proxy [markers]: https://book.kubebuilder.io/reference/markers.html?highlight=markers#marker-syntax @@ -350,4 +350,4 @@ E.g `kubectl logs deployment.apps/memcached-operator-controller-manager -n memca [ctrl-options]: https://godoc.org/sigs.k8s.io/controller-runtime/pkg/manager#Options [envtest]: https://godoc.org/sigs.k8s.io/controller-runtime/pkg/envtest [gomega]: https://onsi.github.io/gomega/ -[multigroup-kubebuilder-doc]: https://book.kubebuilder.io/migration/multi-group.html \ No newline at end of file +[multigroup-kubebuilder-doc]: https://book.kubebuilder.io/migration/multi-group.html diff --git a/website/content/en/docs/building-operators/golang/references/client.md b/website/content/en/docs/building-operators/golang/references/client.md index cd447a30c63..b1a3cadb086 100644 --- a/website/content/en/docs/building-operators/golang/references/client.md +++ b/website/content/en/docs/building-operators/golang/references/client.md @@ -82,7 +82,7 @@ Creating a new Client is not usually necessary nor advised, as the default Clien ### Reconcile and the Client API -A Reconciler implements the [`reconcile.Reconciler`][doc-reconcile-reconciler] interface, which exposes the Reconcile method. Reconcilers are added to a corresponding Controller for a Kind; Reconcile is called in response to cluster or external Events, with a `reconcile.Request` object argument, to read and write cluster state by the Controller, and returns a `reconcile.Result`. SDK Reconcilers have access to a Client in order to make Kubernetes API calls. +A Reconciler implements the [`reconcile.Reconciler`][doc-reconcile-reconciler] interface, which exposes the Reconcile method. Reconcilers are added to a corresponding Controller for a Kind; Reconcile is called in response to cluster or external Events, with a `reconcile.Request` object argument, to read and write cluster state by the Controller, and returns a `ctrl.Result`. SDK Reconcilers have access to a Client in order to make Kubernetes API calls. ```Go // KindReconciler reconciles a Kind object @@ -106,7 +106,7 @@ type KindReconciler struct { // The Controller will requeue the Request to be processed again if an error // is non-nil or Result.Requeue is true, otherwise upon completion it will // remove the work from the queue. -func (r *KindReconciler) Reconcile(req ctrl.Request) (ctrl.Request, error) +func (r *KindReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Result, error) ``` Reconcile is where Controller business logic lives, i.e. where Client API calls are made via `KindReconciler.client`. A `client.Client` implementer performs the following operations: @@ -128,7 +128,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" ) -func (r *AppReconciler) Reconcile(req ctrl.Request) (ctrl.Request, error) { +func (r *AppReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Result, error) { ... app := &v1alpha1.App{} @@ -160,7 +160,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" ) -func (r *AppReconciler) Reconcile(req ctrl.Request) (ctrl.Request, error) { +func (r *AppReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Result, error) { ... // Return all pods in the request namespace with a label of `app=` @@ -202,7 +202,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" ) -func (r *AppReconciler) Reconcile(req ctrl.Request) (ctrl.Request, error) { +func (r *AppReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Result, error) { ... app := &v1.Deployment{ // Any cluster object you want to create. @@ -238,7 +238,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" ) -func (r *AppReconciler) Reconcile(req ctrl.Request) (ctrl.Request, error) { +func (r *AppReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Result, error) { ... dep := &v1.Deployment{} @@ -276,7 +276,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" ) -func (r *AppReconciler) Reconcile(req ctrl.Request) (ctrl.Request, error) { +func (r *AppReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Result, error) { ... dep := &v1.Deployment{} @@ -320,7 +320,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" ) -func (r *AppReconciler) Reconcile(req ctrl.Request) (ctrl.Request, error) { +func (r *AppReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Result, error) { ... ctx := context.TODO() @@ -365,7 +365,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" ) -func (r *AppReconciler) Reconcile(req ctrl.Request) (ctrl.Request, error) { +func (r *AppReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Result, error) { ... pod := &v1.Pod{} @@ -409,7 +409,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" ) -func (r *AppReconciler) Reconcile(req ctrl.Request) (ctrl.Request, error) { +func (r *AppReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Result, error) { ... // Delete all pods in the request namespace with a label of `app=` @@ -457,7 +457,7 @@ type AppReconciler struct { Scheme *runtime.Scheme } -func (r *AppReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { +func (r *AppReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Result, error) { // Fetch the App instance. app := &appv1alpha1.App{} diff --git a/website/content/en/docs/building-operators/golang/references/logging.md b/website/content/en/docs/building-operators/golang/references/logging.md index 8f7bd4b1e96..2daab30c9ac 100644 --- a/website/content/en/docs/building-operators/golang/references/logging.md +++ b/website/content/en/docs/building-operators/golang/references/logging.md @@ -202,8 +202,7 @@ type MemcachedReconciler struct { Scheme *runtime.Scheme } -func (r *MemcachedReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { - ctx := context.Background() +func (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { log := r.Log.WithValues("memcached", req.NamespacedName) // Fetch the Memcached instance @@ -260,7 +259,7 @@ If you do not want to use `logr` as your logging tool, you can remove `logr`-spe [repo_zapr]:https://godoc.org/github.com/go-logr/zapr [godoc_logr_logger]:https://godoc.org/github.com/go-logr/logr#Logger [site_struct_logging]:https://www.client9.com/structured-logging-in-golang/ -[code_memcached_controller]: https://github.com/operator-framework/operator-sdk/blob/master/testdata/go/memcached-operator/controllers/memcached_controller.go +[code_memcached_controller]: https://github.com/operator-framework/operator-sdk/blob/v1.2.0/testdata/go/memcached-operator/controllers/memcached_controller.go [logfmt_repo]:https://github.com/jsternberg/zap-logfmt [controller_runtime_zap]:https://github.com/kubernetes-sigs/controller-runtime/tree/master/pkg/log/zap [logging_godocs]: https://godoc.org/github.com/kubernetes-sigs/controller-runtime/pkg/log/zap#Options.BindFlags diff --git a/website/content/en/docs/building-operators/golang/tutorial.md b/website/content/en/docs/building-operators/golang/tutorial.md index 00dd447e8db..838c909d13a 100644 --- a/website/content/en/docs/building-operators/golang/tutorial.md +++ b/website/content/en/docs/building-operators/golang/tutorial.md @@ -225,7 +225,7 @@ import ( ... ) -func (r *MemcachedReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { +func (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { // Lookup the Memcached instance for this reconcile request memcached := &cachev1alpha1.Memcached{} err := r.Get(ctx, req.NamespacedName, memcached) @@ -267,7 +267,9 @@ The controller needs certain RBAC permissions to interact with the resources it // +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=core,resources=pods,verbs=get;list; -func (r *MemcachedReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { +func (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + ... +} ``` The `ClusterRole` manifest at `config/rbac/role.yaml` is generated from the above markers via controller-gen with the following command: @@ -493,7 +495,7 @@ Also see the [advanced topics][advanced_topics] doc for more use cases and under [markers]: https://book.kubebuilder.io/reference/markers.html [crd-markers]: https://book.kubebuilder.io/reference/markers/crd-validation.html [rbac-markers]: https://book.kubebuilder.io/reference/markers/rbac.html -[memcached_controller]: https://github.com/operator-framework/operator-sdk/blob/master/testdata/go/memcached-operator/controllers/memcached_controller.go +[memcached_controller]: https://github.com/operator-framework/operator-sdk/blob/v1.2.0/testdata/go/memcached-operator/controllers/memcached_controller.go [builder_godocs]: https://godoc.org/github.com/kubernetes-sigs/controller-runtime/pkg/builder#example-Builder [legacy_quickstart_doc]:https://v0-19-x.sdk.operatorframework.io/docs/golang/legacy/quickstart/ [activate_modules]: https://github.com/golang/go/wiki/Modules#how-to-install-and-activate-module-support diff --git a/website/content/en/docs/faqs/_index.md b/website/content/en/docs/faqs/_index.md index e65211f1ffe..cef4e89f9c6 100644 --- a/website/content/en/docs/faqs/_index.md +++ b/website/content/en/docs/faqs/_index.md @@ -33,88 +33,81 @@ For more information on `kube-apiserver` request timeout options, see the [Kuber Unfortunately, adding the entire dependency tree for all Ansible modules would be excessive. Fortunately, you can add it easily. Simply edit your build/Dockerfile. You'll want to change to root for the install command, just be sure to swap back using a series of commands like the following right after the `FROM` line. -``` +```docker USER 0 RUN yum -y install my-dependency RUN pip3 install my-python-dependency USER 1001 ``` -If you aren't sure what dependencies are required, start up a container using the image in the `FROM` line as root. That will look something like this. -`docker run -u 0 -it --rm --entrypoint /bin/bash quay.io/operator-framework/ansible-operator:` +If you aren't sure what dependencies are required, start up a container using the image in the `FROM` line as root. That will look something like this: +```sh +docker run -u 0 -it --rm --entrypoint /bin/bash quay.io/operator-framework/ansible-operator: +``` ## I keep seeing errors like "Failed to watch", how do I fix this? -If you run into the following error message, it means that your operator is unable to watch the resoruce: +If you run into the following error message, it means that your operator is unable to watch the resource: ``` E0320 15:42:17.676888 1 reflector.go:280] pkg/mod/k8s.io/client-go@v0.0.0-20191016111102-bec269661e48/tools/cache/reflector.go:96: Failed to watch *v1.ImageStreamTag: unknown (get imagestreamtags.image.openshift.io) {"level":"info","ts":1584718937.766342,"logger":"controller_memcached","msg":"ImageStreamTag resource not found. ``` -Using controller-runtime's split client means that read operations (gets and lists) are read from a cache, and write operations are written directly to the API server. To populate the cache for reads, controller-runtime initiates a `list` and then a `watch` even when your operator is only attempting to `get` a single resource. The above scenario occurs when the operator does not have an (RBAC)[rbac] permission to `watch` the resource. The solution is to grant permission in the `config/rbac/role.yaml` file. +Using controller-runtime's split client means that read operations (gets and lists) are read from a cache, and write operations are written directly to the API server. To populate the cache for reads, controller-runtime initiates a `list` and then a `watch` even when your operator is only attempting to `get` a single resource. The above scenario occurs when the operator does not have an [RBAC][rbac] permission to `watch` the resource. The solution is to add an RBAC directive to generate a `config/rbac/role.yaml` with `watch` privileges: -In rare cases, it also could be that the particular resource does not implement the `watch` verb. In this case, it is necessary to use the [client.Reader][client.Reader] instead of the default split client. The manager's `GetAPIReader()` function can be used to get this reader. - -**Example** +```go +// +kubebuilder:rbac:groups=some.group.com,resources=myresources,verbs=watch +``` -Here is an example that demonstrates how to use a `client.Reader` when a resource does not implement the `watch` verb: +Alternatively, if the resource you're attempting to cannot be watched (like `v1.ImageStreamTag` above), you can specify that objects of this type should not be cached by adding the following to `main.go`: ```go - import ( ... imagev1 "github.com/openshift/api/image/v1" ) -... - -// newReconciler returns a new reconcile.Reconciler -func newReconciler(mgr manager.Manager) reconcile.Reconciler { - return &ReconcileMemcached{client: mgr.GetClient(), scheme: mgr.GetScheme(), APIReader: mgr.GetAPIReader() } +var ( + scheme = runtime.NewScheme() +) +func init() { + utilruntime.Must(clientgoscheme.AddToScheme(scheme)) + // Add imagev1's scheme. + utilruntime.Must(imagev1.AddToScheme(scheme)) } -... - -// ReconcileMemcached reconciles a Memcached object -type ReconcileMemcached struct { - // TODO: Clarify the split client - // This client, initialized using mgr.Client() above, is a split client - // that reads objects from the cache and writes to the apiserver - client client.Client - scheme *runtime.Scheme - APIReader client.Reader // the APIReader will not use the cache +func main() { + mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ + Scheme: scheme, + // Specify that ImageStreamTag's should not be cached. + ClientBuilder: manager.NewClientBuilder().WithUncached(&imagev1.ImageStreamTag{}), + }) } +``` -... -func (r *ReconcileMemcached) Reconcile(request reconcile.Request) (reconcile.Result, error) { - - // Get the ImageStreamTag from OCP API which has not the WATCH verb. - img := &imagev1.ImageStreamTag{} - err = r.APIReader.Get(context.TODO(), types.NamespacedName{Name: fmt.Sprintf("%s:%s", "example-name", "example-tag"), img) - if err != nil { - if errors.IsNotFound(err) { - reqLogger.Info("resource not found") - } else { - reqLogger.Error(err, "unexpected error") - } - } +Then in your controller file, add an RBAC directive to generate a `config/rbac/role.yaml` with `get` privileges: + +```go +// +kubebuilder:rbac:groups=image.openshift.io,resources=imagestreamtags,verbs=get ``` +Now run `make manifests` to update your `role.yaml`. + + ## I keep hitting errors like "is forbidden: cannot set blockOwnerDeletion if an ownerReference refers to a resource you can't set finalizers on:", how do I fix this? If you are facing this issue, it means that the operator is missing the required RBAC permissions to update finalizers on the APIs it manages. This permission is necessary if the [OwnerReferencesPermissionEnforcement][owner-references-permission-enforcement] plugin is enabled in your cluster. -For Helm and Ansible operators, this permission is configured by default. However for Go operators, it may be necessary to add this permission yourself. - -In Go operators, RBAC permissions are configured via [RBAC markers][rbac-markers], which are used to generate and update the manifest files present in `config/rbac/`. Add the following marker line on your controller's `Reconcile()` method: +For Helm and Ansible operators, this permission is configured by default. However for Go operators, it may be necessary to add this permission yourself +by adding an RBAC directive to generate a `config/rbac/role.yaml` with `update` privileges on your CR's finalizers: ```go // +kubebuilder:rbac:groups=cache.example.com,resources=memcacheds/finalizers,verbs=update ``` -To update `config/rbac/role.yaml` after changing the markers, run `make manifests`. +Now run `make manifests` to update your `role.yaml`. [kube-apiserver_options]: https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/#options From 58a8855ac81c6ac220fd5d36fe1a51cbb84f34b7 Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Thu, 17 Dec 2020 14:23:57 -0800 Subject: [PATCH 251/376] Makefile: bump IMAGE_VERSION to v1.3.0 (#4332) docs: fix releasing.md formatting Signed-off-by: reinvantveer --- Makefile | 2 +- testdata/ansible/memcached-operator/Dockerfile | 2 +- testdata/ansible/memcached-operator/Makefile | 4 ++-- .../bundle/tests/scorecard/config.yaml | 12 ++++++------ .../config/scorecard/patches/basic.config.yaml | 2 +- .../config/scorecard/patches/olm.config.yaml | 10 +++++----- .../bundle/tests/scorecard/config.yaml | 12 ++++++------ .../config/scorecard/patches/basic.config.yaml | 2 +- .../config/scorecard/patches/olm.config.yaml | 10 +++++----- .../bundle/tests/scorecard/config.yaml | 12 ++++++------ .../config/scorecard/patches/basic.config.yaml | 2 +- .../config/scorecard/patches/olm.config.yaml | 10 +++++----- testdata/helm/memcached-operator/Dockerfile | 2 +- testdata/helm/memcached-operator/Makefile | 4 ++-- .../bundle/tests/scorecard/config.yaml | 12 ++++++------ .../config/scorecard/patches/basic.config.yaml | 2 +- .../config/scorecard/patches/olm.config.yaml | 10 +++++----- .../en/docs/contribution-guidelines/releasing.md | 6 ------ 18 files changed, 55 insertions(+), 61 deletions(-) diff --git a/Makefile b/Makefile index e3563d70ec6..085b41b6996 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ SHELL = /bin/bash # This value must be updated to the release tag of the most recent release, a change that must # occur in the release commit. IMAGE_VERSION will be removed once each subproject that uses this # version is moved to a separate repo and release process. -export IMAGE_VERSION = v1.2.0 +export IMAGE_VERSION = v1.3.0 # Build-time variables to inject into binaries export SIMPLE_VERSION = $(shell (test "$(shell git describe)" = "$(shell git describe --abbrev=0)" && echo $(shell git describe)) || echo $(shell git describe --abbrev=0)+git) export GIT_VERSION = $(shell git describe --dirty --tags --always) diff --git a/testdata/ansible/memcached-operator/Dockerfile b/testdata/ansible/memcached-operator/Dockerfile index 04e5216dcbe..96a41837c53 100644 --- a/testdata/ansible/memcached-operator/Dockerfile +++ b/testdata/ansible/memcached-operator/Dockerfile @@ -1,4 +1,4 @@ -FROM quay.io/operator-framework/ansible-operator:v1.2.0 +FROM quay.io/operator-framework/ansible-operator:v1.3.0 COPY requirements.yml ${HOME}/requirements.yml RUN ansible-galaxy collection install -r ${HOME}/requirements.yml \ diff --git a/testdata/ansible/memcached-operator/Makefile b/testdata/ansible/memcached-operator/Makefile index eed3911bc98..3aeddf1d189 100644 --- a/testdata/ansible/memcached-operator/Makefile +++ b/testdata/ansible/memcached-operator/Makefile @@ -69,8 +69,8 @@ ifeq (, $(shell which ansible-operator 2>/dev/null)) @{ \ set -e ;\ mkdir -p bin ;\ - curl -LO https://github.com/operator-framework/operator-sdk/releases/download/v1.2.0/ansible-operator-v1.2.0-$(ARCHOPER)-$(OSOPER) ;\ - mv ansible-operator-v1.2.0-$(ARCHOPER)-$(OSOPER) ./bin/ansible-operator ;\ + curl -LO https://github.com/operator-framework/operator-sdk/releases/download/v1.3.0/ansible-operator-v1.3.0-$(ARCHOPER)-$(OSOPER) ;\ + mv ansible-operator-v1.3.0-$(ARCHOPER)-$(OSOPER) ./bin/ansible-operator ;\ chmod +x ./bin/ansible-operator ;\ } ANSIBLE_OPERATOR=$(realpath ./bin/ansible-operator) diff --git a/testdata/ansible/memcached-operator/bundle/tests/scorecard/config.yaml b/testdata/ansible/memcached-operator/bundle/tests/scorecard/config.yaml index e39a5d88b57..11a06ffe7fe 100644 --- a/testdata/ansible/memcached-operator/bundle/tests/scorecard/config.yaml +++ b/testdata/ansible/memcached-operator/bundle/tests/scorecard/config.yaml @@ -8,42 +8,42 @@ stages: - entrypoint: - scorecard-test - basic-check-spec - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: basic test: basic-check-spec-test - entrypoint: - scorecard-test - olm-bundle-validation - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-bundle-validation-test - entrypoint: - scorecard-test - olm-crds-have-validation - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-crds-have-validation-test - entrypoint: - scorecard-test - olm-crds-have-resources - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-crds-have-resources-test - entrypoint: - scorecard-test - olm-spec-descriptors - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-spec-descriptors-test - entrypoint: - scorecard-test - olm-status-descriptors - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-status-descriptors-test diff --git a/testdata/ansible/memcached-operator/config/scorecard/patches/basic.config.yaml b/testdata/ansible/memcached-operator/config/scorecard/patches/basic.config.yaml index f80c746f9e7..d4347861781 100644 --- a/testdata/ansible/memcached-operator/config/scorecard/patches/basic.config.yaml +++ b/testdata/ansible/memcached-operator/config/scorecard/patches/basic.config.yaml @@ -4,7 +4,7 @@ entrypoint: - scorecard-test - basic-check-spec - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: basic test: basic-check-spec-test diff --git a/testdata/ansible/memcached-operator/config/scorecard/patches/olm.config.yaml b/testdata/ansible/memcached-operator/config/scorecard/patches/olm.config.yaml index ef6834b1e3d..890bf0572a3 100644 --- a/testdata/ansible/memcached-operator/config/scorecard/patches/olm.config.yaml +++ b/testdata/ansible/memcached-operator/config/scorecard/patches/olm.config.yaml @@ -4,7 +4,7 @@ entrypoint: - scorecard-test - olm-bundle-validation - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-bundle-validation-test @@ -14,7 +14,7 @@ entrypoint: - scorecard-test - olm-crds-have-validation - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-crds-have-validation-test @@ -24,7 +24,7 @@ entrypoint: - scorecard-test - olm-crds-have-resources - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-crds-have-resources-test @@ -34,7 +34,7 @@ entrypoint: - scorecard-test - olm-spec-descriptors - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-spec-descriptors-test @@ -44,7 +44,7 @@ entrypoint: - scorecard-test - olm-status-descriptors - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-status-descriptors-test diff --git a/testdata/go/v2/memcached-operator/bundle/tests/scorecard/config.yaml b/testdata/go/v2/memcached-operator/bundle/tests/scorecard/config.yaml index e39a5d88b57..11a06ffe7fe 100644 --- a/testdata/go/v2/memcached-operator/bundle/tests/scorecard/config.yaml +++ b/testdata/go/v2/memcached-operator/bundle/tests/scorecard/config.yaml @@ -8,42 +8,42 @@ stages: - entrypoint: - scorecard-test - basic-check-spec - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: basic test: basic-check-spec-test - entrypoint: - scorecard-test - olm-bundle-validation - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-bundle-validation-test - entrypoint: - scorecard-test - olm-crds-have-validation - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-crds-have-validation-test - entrypoint: - scorecard-test - olm-crds-have-resources - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-crds-have-resources-test - entrypoint: - scorecard-test - olm-spec-descriptors - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-spec-descriptors-test - entrypoint: - scorecard-test - olm-status-descriptors - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-status-descriptors-test diff --git a/testdata/go/v2/memcached-operator/config/scorecard/patches/basic.config.yaml b/testdata/go/v2/memcached-operator/config/scorecard/patches/basic.config.yaml index f80c746f9e7..d4347861781 100644 --- a/testdata/go/v2/memcached-operator/config/scorecard/patches/basic.config.yaml +++ b/testdata/go/v2/memcached-operator/config/scorecard/patches/basic.config.yaml @@ -4,7 +4,7 @@ entrypoint: - scorecard-test - basic-check-spec - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: basic test: basic-check-spec-test diff --git a/testdata/go/v2/memcached-operator/config/scorecard/patches/olm.config.yaml b/testdata/go/v2/memcached-operator/config/scorecard/patches/olm.config.yaml index ef6834b1e3d..890bf0572a3 100644 --- a/testdata/go/v2/memcached-operator/config/scorecard/patches/olm.config.yaml +++ b/testdata/go/v2/memcached-operator/config/scorecard/patches/olm.config.yaml @@ -4,7 +4,7 @@ entrypoint: - scorecard-test - olm-bundle-validation - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-bundle-validation-test @@ -14,7 +14,7 @@ entrypoint: - scorecard-test - olm-crds-have-validation - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-crds-have-validation-test @@ -24,7 +24,7 @@ entrypoint: - scorecard-test - olm-crds-have-resources - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-crds-have-resources-test @@ -34,7 +34,7 @@ entrypoint: - scorecard-test - olm-spec-descriptors - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-spec-descriptors-test @@ -44,7 +44,7 @@ entrypoint: - scorecard-test - olm-status-descriptors - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-status-descriptors-test diff --git a/testdata/go/v3/memcached-operator/bundle/tests/scorecard/config.yaml b/testdata/go/v3/memcached-operator/bundle/tests/scorecard/config.yaml index e39a5d88b57..11a06ffe7fe 100644 --- a/testdata/go/v3/memcached-operator/bundle/tests/scorecard/config.yaml +++ b/testdata/go/v3/memcached-operator/bundle/tests/scorecard/config.yaml @@ -8,42 +8,42 @@ stages: - entrypoint: - scorecard-test - basic-check-spec - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: basic test: basic-check-spec-test - entrypoint: - scorecard-test - olm-bundle-validation - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-bundle-validation-test - entrypoint: - scorecard-test - olm-crds-have-validation - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-crds-have-validation-test - entrypoint: - scorecard-test - olm-crds-have-resources - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-crds-have-resources-test - entrypoint: - scorecard-test - olm-spec-descriptors - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-spec-descriptors-test - entrypoint: - scorecard-test - olm-status-descriptors - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-status-descriptors-test diff --git a/testdata/go/v3/memcached-operator/config/scorecard/patches/basic.config.yaml b/testdata/go/v3/memcached-operator/config/scorecard/patches/basic.config.yaml index f80c746f9e7..d4347861781 100644 --- a/testdata/go/v3/memcached-operator/config/scorecard/patches/basic.config.yaml +++ b/testdata/go/v3/memcached-operator/config/scorecard/patches/basic.config.yaml @@ -4,7 +4,7 @@ entrypoint: - scorecard-test - basic-check-spec - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: basic test: basic-check-spec-test diff --git a/testdata/go/v3/memcached-operator/config/scorecard/patches/olm.config.yaml b/testdata/go/v3/memcached-operator/config/scorecard/patches/olm.config.yaml index ef6834b1e3d..890bf0572a3 100644 --- a/testdata/go/v3/memcached-operator/config/scorecard/patches/olm.config.yaml +++ b/testdata/go/v3/memcached-operator/config/scorecard/patches/olm.config.yaml @@ -4,7 +4,7 @@ entrypoint: - scorecard-test - olm-bundle-validation - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-bundle-validation-test @@ -14,7 +14,7 @@ entrypoint: - scorecard-test - olm-crds-have-validation - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-crds-have-validation-test @@ -24,7 +24,7 @@ entrypoint: - scorecard-test - olm-crds-have-resources - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-crds-have-resources-test @@ -34,7 +34,7 @@ entrypoint: - scorecard-test - olm-spec-descriptors - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-spec-descriptors-test @@ -44,7 +44,7 @@ entrypoint: - scorecard-test - olm-status-descriptors - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-status-descriptors-test diff --git a/testdata/helm/memcached-operator/Dockerfile b/testdata/helm/memcached-operator/Dockerfile index 594ad0c9f84..2bc9187976d 100644 --- a/testdata/helm/memcached-operator/Dockerfile +++ b/testdata/helm/memcached-operator/Dockerfile @@ -1,5 +1,5 @@ # Build the manager binary -FROM quay.io/operator-framework/helm-operator:v1.2.0 +FROM quay.io/operator-framework/helm-operator:v1.3.0 ENV HOME=/opt/helm COPY watches.yaml ${HOME}/watches.yaml diff --git a/testdata/helm/memcached-operator/Makefile b/testdata/helm/memcached-operator/Makefile index 6e63eef6a39..4fdc5c786eb 100644 --- a/testdata/helm/memcached-operator/Makefile +++ b/testdata/helm/memcached-operator/Makefile @@ -69,8 +69,8 @@ ifeq (, $(shell which helm-operator 2>/dev/null)) @{ \ set -e ;\ mkdir -p bin ;\ - curl -LO https://github.com/operator-framework/operator-sdk/releases/download/v1.2.0/helm-operator-v1.2.0-$(ARCHOPER)-$(OSOPER) ;\ - mv helm-operator-v1.2.0-$(ARCHOPER)-$(OSOPER) ./bin/helm-operator ;\ + curl -LO https://github.com/operator-framework/operator-sdk/releases/download/v1.3.0/helm-operator-v1.3.0-$(ARCHOPER)-$(OSOPER) ;\ + mv helm-operator-v1.3.0-$(ARCHOPER)-$(OSOPER) ./bin/helm-operator ;\ chmod +x ./bin/helm-operator ;\ } HELM_OPERATOR=$(realpath ./bin/helm-operator) diff --git a/testdata/helm/memcached-operator/bundle/tests/scorecard/config.yaml b/testdata/helm/memcached-operator/bundle/tests/scorecard/config.yaml index e39a5d88b57..11a06ffe7fe 100644 --- a/testdata/helm/memcached-operator/bundle/tests/scorecard/config.yaml +++ b/testdata/helm/memcached-operator/bundle/tests/scorecard/config.yaml @@ -8,42 +8,42 @@ stages: - entrypoint: - scorecard-test - basic-check-spec - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: basic test: basic-check-spec-test - entrypoint: - scorecard-test - olm-bundle-validation - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-bundle-validation-test - entrypoint: - scorecard-test - olm-crds-have-validation - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-crds-have-validation-test - entrypoint: - scorecard-test - olm-crds-have-resources - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-crds-have-resources-test - entrypoint: - scorecard-test - olm-spec-descriptors - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-spec-descriptors-test - entrypoint: - scorecard-test - olm-status-descriptors - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-status-descriptors-test diff --git a/testdata/helm/memcached-operator/config/scorecard/patches/basic.config.yaml b/testdata/helm/memcached-operator/config/scorecard/patches/basic.config.yaml index f80c746f9e7..d4347861781 100644 --- a/testdata/helm/memcached-operator/config/scorecard/patches/basic.config.yaml +++ b/testdata/helm/memcached-operator/config/scorecard/patches/basic.config.yaml @@ -4,7 +4,7 @@ entrypoint: - scorecard-test - basic-check-spec - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: basic test: basic-check-spec-test diff --git a/testdata/helm/memcached-operator/config/scorecard/patches/olm.config.yaml b/testdata/helm/memcached-operator/config/scorecard/patches/olm.config.yaml index ef6834b1e3d..890bf0572a3 100644 --- a/testdata/helm/memcached-operator/config/scorecard/patches/olm.config.yaml +++ b/testdata/helm/memcached-operator/config/scorecard/patches/olm.config.yaml @@ -4,7 +4,7 @@ entrypoint: - scorecard-test - olm-bundle-validation - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-bundle-validation-test @@ -14,7 +14,7 @@ entrypoint: - scorecard-test - olm-crds-have-validation - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-crds-have-validation-test @@ -24,7 +24,7 @@ entrypoint: - scorecard-test - olm-crds-have-resources - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-crds-have-resources-test @@ -34,7 +34,7 @@ entrypoint: - scorecard-test - olm-spec-descriptors - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-spec-descriptors-test @@ -44,7 +44,7 @@ entrypoint: - scorecard-test - olm-status-descriptors - image: quay.io/operator-framework/scorecard-test:v1.2.0 + image: quay.io/operator-framework/scorecard-test:v1.3.0 labels: suite: olm test: olm-status-descriptors-test diff --git a/website/content/en/docs/contribution-guidelines/releasing.md b/website/content/en/docs/contribution-guidelines/releasing.md index 62d3553efb3..d590fdd03af 100644 --- a/website/content/en/docs/contribution-guidelines/releasing.md +++ b/website/content/en/docs/contribution-guidelines/releasing.md @@ -32,22 +32,18 @@ to appease the Netlify website configuration demons. You can ping SDK [approvers [release branch](#release-branches) is created prior to the release and that this mapping is created. If you have the proper permissions, you can do this by running the following, assuming the upstream SDK is the `upstream` remote repo: - ```sh git checkout master git pull git checkout -b v1.3.x git push -u upstream v1.3.x ``` - 1. Create and merge a commit that updates the top-level [Makefile] variable `IMAGE_VERSION` to the upcoming release tag `v1.3.0`. This variable ensures sample projects have been tagged correctly prior to the release commit. - ```sh sed -i -E 's/(IMAGE_VERSION = ).+/\1v1\.3\.0/g' Makefile ``` - 1. Lock down the `master` branch to prevent further commits before the release completes: 1. Go to `Settings -> Branches` in the SDK repo. 1. Under `Branch protection rules`, click `Edit` on the `master` branch rule. @@ -135,11 +131,9 @@ We will use the `v1.3.1` release version in this example. 1. Create and merge a commit that updates the top-level [Makefile] variable `IMAGE_VERSION` to the upcoming release tag `v1.3.1`. This variable ensures sample projects have been tagged correctly prior to the release commit. - ```sh sed -i -E 's/(IMAGE_VERSION = ).+/\1v1\.3\.1/g' Makefile ``` - 1. Lock down the `v1.3.x` branch to prevent further commits before the release completes: 1. Go to `Settings -> Branches` in the SDK repo. 1. Under `Branch protection rules`, click `Edit` on the `v.*` branch rule. From 594f2da3e7d903dc0f86b35ba68a363eba5c0618 Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Thu, 17 Dec 2020 18:59:45 -0800 Subject: [PATCH 252/376] Release v1.3.0 (#4334) Signed-off-by: reinvantveer --- .../fragments/add-0.17.0-olm-bindata.yaml | 16 -------- .../fragments/cleanup-all-resources.yaml | 13 ------ changelog/fragments/csv-base-name-bugfix.yaml | 6 --- changelog/fragments/csv-order.yaml | 5 --- changelog/fragments/go-v3-alpha.yaml | 8 ---- changelog/fragments/go-v3-default.yaml | 28 ------------- .../helm-ansible-version-metric.yaml | 9 ---- .../fragments/operator-sdk-binary-v1.19.yaml | 4 -- changelog/fragments/pin-ansible-2.9.yaml | 9 ---- .../refactor-generate-subcommands.yaml | 9 ---- changelog/fragments/run-bundle-upgrade.yaml | 4 -- ...update-k8s-controller-runtime-version.yaml | 7 ---- ...-kb-from-36124ae2e027-to-9c02d557f01b.yaml | 16 -------- ...-kb-from-9c02d557f01b-to-c158f4fa4207.yaml | 8 ---- changelog/generated/v1.3.0.md | 29 +++++++++++++ website/config.toml | 4 ++ .../en/docs/upgrading-sdk-version/v1.3.0.md | 41 +++++++++++++++++++ 17 files changed, 74 insertions(+), 142 deletions(-) delete mode 100644 changelog/fragments/add-0.17.0-olm-bindata.yaml delete mode 100644 changelog/fragments/cleanup-all-resources.yaml delete mode 100644 changelog/fragments/csv-base-name-bugfix.yaml delete mode 100644 changelog/fragments/csv-order.yaml delete mode 100644 changelog/fragments/go-v3-alpha.yaml delete mode 100644 changelog/fragments/go-v3-default.yaml delete mode 100644 changelog/fragments/helm-ansible-version-metric.yaml delete mode 100644 changelog/fragments/operator-sdk-binary-v1.19.yaml delete mode 100644 changelog/fragments/pin-ansible-2.9.yaml delete mode 100644 changelog/fragments/refactor-generate-subcommands.yaml delete mode 100644 changelog/fragments/run-bundle-upgrade.yaml delete mode 100644 changelog/fragments/update-k8s-controller-runtime-version.yaml delete mode 100644 changelog/fragments/update-kb-from-36124ae2e027-to-9c02d557f01b.yaml delete mode 100644 changelog/fragments/update-kb-from-9c02d557f01b-to-c158f4fa4207.yaml create mode 100644 changelog/generated/v1.3.0.md create mode 100644 website/content/en/docs/upgrading-sdk-version/v1.3.0.md diff --git a/changelog/fragments/add-0.17.0-olm-bindata.yaml b/changelog/fragments/add-0.17.0-olm-bindata.yaml deleted file mode 100644 index fa1d6ea0295..00000000000 --- a/changelog/fragments/add-0.17.0-olm-bindata.yaml +++ /dev/null @@ -1,16 +0,0 @@ -# entries is a list of entries to include in -# release notes and/or the migration guide -entries: - - description: > - Add OLM bindata for the 0.17.0 release version. - - # kind is one of: - # - addition - # - change - # - deprecation - # - removal - # - bugfix - kind: "addition" - - # Is this a breaking change? - breaking: false diff --git a/changelog/fragments/cleanup-all-resources.yaml b/changelog/fragments/cleanup-all-resources.yaml deleted file mode 100644 index ff50fb13bcf..00000000000 --- a/changelog/fragments/cleanup-all-resources.yaml +++ /dev/null @@ -1,13 +0,0 @@ -entries: - - description: > - Made the `cleanup` command's error handling more robust on deletion and "not found" events. - kind: bugfix - - description: > - Fixed the documented `packagemanifests` make recipe. - kind: bugfix - migration: - header: Update `packagemanifests` make recipe variable `PKG_MAN_OPTS` - body: > - If your project uses the `packagemanifests` make recipe, update your `PKG_MAN_OPTS` - variable to include `PKG_FROM_VERSION` instead of `FROM_VERSION`, ex. - `PKG_MAN_OPTS ?= $(PKG_FROM_VERSION) $(PKG_CHANNELS) $(PKG_IS_DEFAULT_CHANNEL)`. diff --git a/changelog/fragments/csv-base-name-bugfix.yaml b/changelog/fragments/csv-base-name-bugfix.yaml deleted file mode 100644 index e2edb1eb6e9..00000000000 --- a/changelog/fragments/csv-base-name-bugfix.yaml +++ /dev/null @@ -1,6 +0,0 @@ -# entries is a list of entries to include in -# release notes and/or the migration guide -entries: - - description: > - `generate kustomize manifests` will (re)generate a base `ClusterServiceVersion` manifest with a valid name. - kind: bugfix diff --git a/changelog/fragments/csv-order.yaml b/changelog/fragments/csv-order.yaml deleted file mode 100644 index 3d122e9fd99..00000000000 --- a/changelog/fragments/csv-order.yaml +++ /dev/null @@ -1,5 +0,0 @@ -entries: - - description: > - Added [`order=`](https://sdk.operatorframework.io/docs/building-operators/golang/references/markers/#usage) marker fields to CSV markers. - - kind: addition diff --git a/changelog/fragments/go-v3-alpha.yaml b/changelog/fragments/go-v3-alpha.yaml deleted file mode 100644 index 96542f03461..00000000000 --- a/changelog/fragments/go-v3-alpha.yaml +++ /dev/null @@ -1,8 +0,0 @@ -entries: - - description: > - (go/v2) bumped controller-runtime from v0.6.3 to v0.6.4 - kind: change - migration: - header: Go projects should update their controller-runtime version to v0.6.4 - body: > - In your go.mod file, update the sigs.k8s.io/controller-runtime version to v0.6.4 diff --git a/changelog/fragments/go-v3-default.yaml b/changelog/fragments/go-v3-default.yaml deleted file mode 100644 index bebca94ab19..00000000000 --- a/changelog/fragments/go-v3-default.yaml +++ /dev/null @@ -1,28 +0,0 @@ -entries: - - description: > - Go CLI plugin go/v3 is now the default. - kind: change - breaking: false - migration: - header: Upgrade your Go project from "go.kubebuilder.io/v2" to "go.kubebuilder.io/v3" - body: > - The newly released go/v3 plugin has many new features and (breaking) changes - incompatible with projects created by go/v2. You are not required to upgrade - and your go/v2 project will continue to work with new operator-sdk versions. - If you wish to upgrade, check out the upstream - [migration guide](https://master.book.kubebuilder.io/migration/plugin/plugins.html). - - Additionally, if using project version "3-alpha", you must update your "plugins" config field: - - Old: - ```yaml - plugins: - go.sdk.operatorframework.io/v2-alpha: {} - ``` - - New: - ```yaml - plugins: - manifests.sdk.operatorframework.io/v2: {} - scorecard.sdk.operatorframework.io/v2: {} - ``` diff --git a/changelog/fragments/helm-ansible-version-metric.yaml b/changelog/fragments/helm-ansible-version-metric.yaml deleted file mode 100644 index 67a740de210..00000000000 --- a/changelog/fragments/helm-ansible-version-metric.yaml +++ /dev/null @@ -1,9 +0,0 @@ -entries: - - description: > - In Ansible-based operators, added the `ansible_operator_build_info` - metric to instrument commit and version information. - kind: "addition" - - description: > - In Helm-based operators, added the `helm_operator_build_info` - metric to instrument commit and version information. - kind: "addition" diff --git a/changelog/fragments/operator-sdk-binary-v1.19.yaml b/changelog/fragments/operator-sdk-binary-v1.19.yaml deleted file mode 100644 index fc2abf0ef19..00000000000 --- a/changelog/fragments/operator-sdk-binary-v1.19.yaml +++ /dev/null @@ -1,4 +0,0 @@ -entries: - - description: > - Bumped `operator-sdk` binary dependencies to their k8s v1.19 equivalents. - kind: change diff --git a/changelog/fragments/pin-ansible-2.9.yaml b/changelog/fragments/pin-ansible-2.9.yaml deleted file mode 100644 index 7c51087137d..00000000000 --- a/changelog/fragments/pin-ansible-2.9.yaml +++ /dev/null @@ -1,9 +0,0 @@ -# entries is a list of entries to include in -# release notes and/or the migration guide -entries: - - description: > - (ansible/v1) Pin all top level Python requirements. This fixes a bug that - erroneously installed Ansible 2.10.z instead of Ansible 2.9.z. - - kind: "bugfix" - breaking: false diff --git a/changelog/fragments/refactor-generate-subcommands.yaml b/changelog/fragments/refactor-generate-subcommands.yaml deleted file mode 100644 index 54f70d00526..00000000000 --- a/changelog/fragments/refactor-generate-subcommands.yaml +++ /dev/null @@ -1,9 +0,0 @@ -entries: - - description: > - Added the `--package ` flag to all `generate` subcommands. This flag is required by `generate bundle|packagemanifests` when not run in a project. - kind: "addition" - breaking: false - - description: > - Refactored the `generate bundle|packagemanifest` commands to generate bundles/package manifest data outside of projects. - kind: "bugfix" - breaking: false diff --git a/changelog/fragments/run-bundle-upgrade.yaml b/changelog/fragments/run-bundle-upgrade.yaml deleted file mode 100644 index 35e42a656d9..00000000000 --- a/changelog/fragments/run-bundle-upgrade.yaml +++ /dev/null @@ -1,4 +0,0 @@ -entries: - - description: > - Added the `run bundle-upgrade` subcommand to automate testing upgrades of an operator from one version to another using OLM. - kind: addition diff --git a/changelog/fragments/update-k8s-controller-runtime-version.yaml b/changelog/fragments/update-k8s-controller-runtime-version.yaml deleted file mode 100644 index 44b27aeea10..00000000000 --- a/changelog/fragments/update-k8s-controller-runtime-version.yaml +++ /dev/null @@ -1,7 +0,0 @@ -# entries is a list of entries to include in -# release notes and/or the migration guide - -entries: - - description: > - Updated helm-operator's Helm dependency to v3.4.1. - kind: "change" diff --git a/changelog/fragments/update-kb-from-36124ae2e027-to-9c02d557f01b.yaml b/changelog/fragments/update-kb-from-36124ae2e027-to-9c02d557f01b.yaml deleted file mode 100644 index 7e8c00506e6..00000000000 --- a/changelog/fragments/update-kb-from-36124ae2e027-to-9c02d557f01b.yaml +++ /dev/null @@ -1,16 +0,0 @@ -# entries is a list of entries to include in -# release notes and/or the migration guide -entries: - - description: > - (go/v2) Added the command `òperator-sdk edit` which allows users edit the project layout to support [multi-group](https://book.kubebuilder.io/migration/multi-group.html) - kind: "addition" - breaking: false - - description: > - (go/v2) Removed unused import for defaulting webhooks scaffolded by `create webhook` ([kubebuilder#1718](https://github.com/kubernetes-sigs/kubebuilder/pull/1718)). - kind: "bugfix" - breaking: false - - description: > - (go/v2) Allow owner to not be specified in generated licenses ([kubebuilder#1749](https://github.com/kubernetes-sigs/kubebuilder/pull/1749)). - kind: "bugfix" - # Is this a breaking change? - breaking: false diff --git a/changelog/fragments/update-kb-from-9c02d557f01b-to-c158f4fa4207.yaml b/changelog/fragments/update-kb-from-9c02d557f01b-to-c158f4fa4207.yaml deleted file mode 100644 index d96e11e3eeb..00000000000 --- a/changelog/fragments/update-kb-from-9c02d557f01b-to-c158f4fa4207.yaml +++ /dev/null @@ -1,8 +0,0 @@ -# entries is a list of entries to include in -# release notes and/or the migration guide -entries: - - description: > - (go/v2) Fixed controller imports scaffolded by `create api` when `--resource=false` - ([kubebuilder#1770](https://github.com/kubernetes-sigs/kubebuilder/pull/1770)) - kind: "bugfix" - breaking: false diff --git a/changelog/generated/v1.3.0.md b/changelog/generated/v1.3.0.md new file mode 100644 index 00000000000..e8980515d6e --- /dev/null +++ b/changelog/generated/v1.3.0.md @@ -0,0 +1,29 @@ +## v1.3.0 + +### Additions + +- Added OLM bindata for the 0.17.0 release version. ([#4242](https://github.com/operator-framework/operator-sdk/pull/4242)) +- Added [`order=`](https://sdk.operatorframework.io/docs/building-operators/golang/references/markers/#usage) marker fields to CSV markers. ([#4254](https://github.com/operator-framework/operator-sdk/pull/4254)) +- In Ansible-based operators, added the `ansible_operator_build_info` metric to instrument commit and version information. ([#4220](https://github.com/operator-framework/operator-sdk/pull/4220)) +- In Helm-based operators, added the `helm_operator_build_info` metric to instrument commit and version information. ([#4220](https://github.com/operator-framework/operator-sdk/pull/4220)) +- Added the `--package ` flag to all `generate` subcommands. This flag is required by `generate ` when run outside of a project. ([#4074](https://github.com/operator-framework/operator-sdk/pull/4074)) +- Added the `run bundle-upgrade` subcommand to automate testing upgrades of an operator from one version to another using OLM. ([#4271](https://github.com/operator-framework/operator-sdk/pull/4271)) +- (go/v2) Added the command `òperator-sdk edit` which allows users edit the project layout to support [multi-group](https://book.kubebuilder.io/migration/multi-group.html). ([#4156](https://github.com/operator-framework/operator-sdk/pull/4156)) + +### Changes + +- (go/v2) Bumped controller-runtime from v0.6.3 to v0.6.4. ([#4282](https://github.com/operator-framework/operator-sdk/pull/4282)) +- Go CLI plugin go/v3 is now the default. ([#4307](https://github.com/operator-framework/operator-sdk/pull/4307)) +- Bumped `operator-sdk` binary dependencies to their k8s v1.19 equivalents. ([#4294](https://github.com/operator-framework/operator-sdk/pull/4294)) +- Updated helm-operator's Helm dependency to v3.4.1. ([#4259](https://github.com/operator-framework/operator-sdk/pull/4259)) + +### Bug Fixes + +- Made the `cleanup` command's error handling more robust on deletion and "not found" events. ([#4303](https://github.com/operator-framework/operator-sdk/pull/4303)) +- Fixed the documented `packagemanifests` make recipe. ([#4303](https://github.com/operator-framework/operator-sdk/pull/4303)) +- `generate kustomize manifests` will now (re)generate a base `ClusterServiceVersion` manifest with a valid name. ([#4276](https://github.com/operator-framework/operator-sdk/pull/4276)) +- (ansible/v1) Pinned all top level Python requirements. This fixes a bug that erroneously installed Ansible 2.10.z instead of Ansible 2.9.z. ([#4321](https://github.com/operator-framework/operator-sdk/pull/4321)) +- Refactored the `generate bundle|packagemanifest` commands to generate bundles/package manifest data outside of projects. ([#4074](https://github.com/operator-framework/operator-sdk/pull/4074)) +- (go/v2) Removed unused import for defaulting webhooks scaffolded by `create webhook` ([kubebuilder#1718](https://github.com/kubernetes-sigs/kubebuilder/pull/1718)). ([#4156](https://github.com/operator-framework/operator-sdk/pull/4156)) +- (go/v2) Allow owner to not be specified in generated licenses ([kubebuilder#1749](https://github.com/kubernetes-sigs/kubebuilder/pull/1749)). ([#4156](https://github.com/operator-framework/operator-sdk/pull/4156)) +- (go/v2) Fixed controller imports scaffolded by `create api` when `--resource=false` ([kubebuilder#1770](https://github.com/kubernetes-sigs/kubebuilder/pull/1770)). ([#4215](https://github.com/operator-framework/operator-sdk/pull/4215)) diff --git a/website/config.toml b/website/config.toml index 4a5943b1ae6..751512ab200 100644 --- a/website/config.toml +++ b/website/config.toml @@ -96,6 +96,10 @@ algolia_docsearch = false ##RELEASE_ADDME## +[[params.versions]] + version = "v1.3" + url = "https://v1-3-x.sdk.operatorframework.io" + [[params.versions]] version = "v1.2" url = "https://v1-2-x.sdk.operatorframework.io" diff --git a/website/content/en/docs/upgrading-sdk-version/v1.3.0.md b/website/content/en/docs/upgrading-sdk-version/v1.3.0.md new file mode 100644 index 00000000000..e7d073c0b72 --- /dev/null +++ b/website/content/en/docs/upgrading-sdk-version/v1.3.0.md @@ -0,0 +1,41 @@ +--- +title: v1.3.0 +weight: 998997000 +--- + +## Update `packagemanifests` make recipe variable `PKG_MAN_OPTS` + +If your project uses the `packagemanifests` make recipe, update your `PKG_MAN_OPTS` variable to include `PKG_FROM_VERSION` instead of `FROM_VERSION`, ex: + +```make +PKG_MAN_OPTS ?= $(PKG_FROM_VERSION) $(PKG_CHANNELS) $(PKG_IS_DEFAULT_CHANNEL) +``` + +_See [#4303](https://github.com/operator-framework/operator-sdk/pull/4303) for more details._ + +## Update your Go project's controller-runtime version to v0.6.4 + +In your go.mod file, update the `sigs.k8s.io/controller-runtime` version to v0.6.4 + +_See [#4282](https://github.com/operator-framework/operator-sdk/pull/4282) for more details._ + +## Upgrade your Go project from "go.kubebuilder.io/v2" to "go.kubebuilder.io/v3" + +The newly released go/v3 plugin has many new features and (breaking) changes incompatible with projects created by go/v2. You are not required to upgrade and your go/v2 project will continue to work with new operator-sdk versions. If you wish to upgrade, check out the upstream [migration guide](https://master.book.kubebuilder.io/migration/plugin/plugins.html). + +Additionally, if using project version "3-alpha", you must update your `plugins` config field: + +Old: +```yaml +plugins: + go.sdk.operatorframework.io/v2-alpha: {} +``` + +New: +```yaml +plugins: + manifests.sdk.operatorframework.io/v2: {} + scorecard.sdk.operatorframework.io/v2: {} +``` + +_See [#4307](https://github.com/operator-framework/operator-sdk/pull/4307) for more details._ From 6b60957e66868882923078f7ead16079fce3631c Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Thu, 17 Dec 2020 20:03:03 -0800 Subject: [PATCH 253/376] docs/building-operators: clean up and align quickstarts (#4335) Signed-off-by: reinvantveer --- .../docs/building-operators/ansible/_index.md | 2 - .../ansible/installation.md | 21 ++- .../building-operators/ansible/migration.md | 54 ++++---- .../building-operators/ansible/quickstart.md | 128 +++++++++-------- .../building-operators/ansible/tutorial.md | 24 ++-- .../building-operators/golang/installation.md | 10 +- .../building-operators/golang/migration.md | 6 +- .../building-operators/golang/quickstart.md | 129 ++++++++++-------- .../building-operators/golang/tutorial.md | 13 +- .../building-operators/helm/installation.md | 20 +++ .../docs/building-operators/helm/migration.md | 42 +++--- .../building-operators/helm/quickstart.md | 128 +++++++++-------- .../docs/building-operators/helm/tutorial.md | 26 ++-- 13 files changed, 325 insertions(+), 278 deletions(-) create mode 100644 website/content/en/docs/building-operators/helm/installation.md diff --git a/website/content/en/docs/building-operators/ansible/_index.md b/website/content/en/docs/building-operators/ansible/_index.md index ac48585e0ed..97e572c25ef 100644 --- a/website/content/en/docs/building-operators/ansible/_index.md +++ b/website/content/en/docs/building-operators/ansible/_index.md @@ -3,5 +3,3 @@ title: Ansible weight: 1 description: Guide to building a Ansible Based Operator using Operator SDK --- - -Ansible based operators run playbooks and roles to react to changes in tracked Kubernetes resources (usually CRs). diff --git a/website/content/en/docs/building-operators/ansible/installation.md b/website/content/en/docs/building-operators/ansible/installation.md index 544cee7a77f..fdc5f5cdaed 100644 --- a/website/content/en/docs/building-operators/ansible/installation.md +++ b/website/content/en/docs/building-operators/ansible/installation.md @@ -1,26 +1,23 @@ --- -title: Ansible Operator SDK Installation +title: Installation Guide linkTitle: Installation weight: 1 --- -Follow the steps in the [installation guide][install-guide] to learn how to install the Operator SDK CLI tool. +## Install `operator-sdk` + +Follow the steps in the [installation guide][install-guide] to learn how to install the `operator-sdk` CLI tool. ## Additional Prerequisites -- [ansible][ansible-tool] version v2.9.0+ -- [ansible-runner][ansible-runner-tool] version v1.1.0+ +- [ansible][ansible] version v2.9.0+ +- [ansible-runner][ansible-runner] version v1.1.0+ - [ansible-runner-http][ansible-runner-http-plugin] version v1.0.0+ - [openshift][openshift-module] version v0.11.2+ -**Note**: This guide uses [minikube][minikube-tool] version v0.25.0+ as the -local Kubernetes cluster and [quay.io][quay-link] for the public registry. - -[ansible-tool]:https://docs.ansible.com/ansible/latest/index.html -[ansible-runner-tool]:https://ansible-runner.readthedocs.io/en/latest/install.html +[install-guide]:/docs/installation/ +[ansible]:https://docs.ansible.com/ansible/latest/index.html +[ansible-runner]:https://ansible-runner.readthedocs.io/en/latest/install.html [ansible-runner-http-plugin]:https://github.com/ansible/ansible-runner-http -[install-guide]: /docs/installation/ -[minikube-tool]:https://github.com/kubernetes/minikube#installation -[quay-link]:https://quay.io [openshift-module]:https://pypi.org/project/openshift/ diff --git a/website/content/en/docs/building-operators/ansible/migration.md b/website/content/en/docs/building-operators/ansible/migration.md index 825d6ffd8ad..a85d3be320e 100644 --- a/website/content/en/docs/building-operators/ansible/migration.md +++ b/website/content/en/docs/building-operators/ansible/migration.md @@ -1,23 +1,23 @@ --- -title: Migrating Legacy Projects -linkTitle: Migrating Projects to 1.0.0+ +link: Migrating pre-v1.0.0 Projects +linkTitle: Migrating pre-v1.0.0 Projects weight: 6 -description: Instructions for migrating a Ansible-based project built prior to 1.0.0 to use the new Kubebuilder-style layout. +description: Instructions for migrating a Ansible-based project built prior to v1.0.0 to use the new Kubebuilder-style layout. --- ## Overview -The motivations for the new layout are related to bringing more flexibility to users and +The motivations for the new layout are related to bringing more flexibility to users and part of the process to [Integrating Kubebuilder and Operator SDK][integration-doc]. ### What was changed - + - The `deploy` directory was replaced with the `config` directory including a new layout of Kubernetes manifests files: * CRD manifests in `deploy/crds/` are now in `config/crd/bases` * CR manifests in `deploy/crds/` are now in `config/samples` - * Controller manifest `deploy/operator.yaml` is now in `config/manager/manager.yaml` + * Controller manifest `deploy/operator.yaml` is now in `config/manager/manager.yaml` * RBAC manifests in `deploy` are now in `config/rbac/` - + - `build/Dockerfile` is moved to `Dockerfile` in the project root directory - The `molecule/` directory is now more aligned to Ansible and the new Layout @@ -32,7 +32,7 @@ Scaffolded projects now use: ## How to migrate The easy migration path is to a project from the scratch and let the tool scaffold the new layout. Then, add your customizations and implementations. See below for an example. - + ### Creating a new project In Kubebuilder-style projects, CRD groups are defined using two different flags @@ -56,7 +56,7 @@ cd memcached-operator operator-sdk init --plugins=ansible --domain=example.com ``` -Now that we have our new project initialized, we need to recreate each of our APIs. +Now that we have our new project initialized, we need to recreate each of our APIs. Using our API example from earlier (`cache.example.com`), we'll use `cache` for the `--group` flag. @@ -68,14 +68,14 @@ For each API in the existing project, run: operator-sdk create api \ --group=cache \ --version=v1 \ - --kind=Memcached + --kind=Memcached ``` Running the above command creates an empty `roles/`. We can copy over the content of our old `roles/` to the new one. - + ### Migrating your Custom Resource samples -Update the CR manifests in `config/samples` with the values of the CRs in your existing project which are in `deploy/crds/___cr.yaml` In our example +Update the CR manifests in `config/samples` with the values of the CRs in your existing project which are in `deploy/crds/___cr.yaml` In our example the `config/samples/cache_v1alpha1_memcached.yaml` will look like: ```yaml @@ -100,11 +100,11 @@ In our example, we will replace `# FIXME: Specify the role or playbook for this - version: v1alpha1 group: cache.example.com kind: Memcached - role: memcached + role: memcached # +kubebuilder:scaffold:watch ``` -**NOTE**: Do not remove the `+kubebuilder:scaffold:watch` [marker][marker]. It allows the tool to update the watches file when new APIs are created. +**NOTE**: Do not remove the `+kubebuilder:scaffold:watch` [marker][marker]. It allows the tool to update the watches file when new APIs are created. ### Migrating your Molecule tests @@ -135,7 +135,7 @@ See that default structure changed from: ``` -To: +To: ``` ├── default @@ -155,7 +155,7 @@ To: └── molecule.yml ``` -Ensure that the `provisioner.host_vars.localhost` has the following `host_vars`: +Ensure that the `provisioner.host_vars.localhost` has the following `host_vars`: ``` .... @@ -202,36 +202,36 @@ The following rules were used in earlier versions of anisible-operator to automa ### Configuring your Operator -If your existing project has customizations in `deploy/operator.yaml`, they need to be ported to +If your existing project has customizations in `deploy/operator.yaml`, they need to be ported to `config/manager/manager.yaml`. If you are passing custom arguments in your deployment, make sure to also update `config/default/auth_proxy_patch.yaml`. -Note that the following environment variables are no longer used. +Note that the following environment variables are no longer used. - `OPERATOR_NAME` is deprecated. It is used to define the name for a leader election config map. Operator authors should begin using `--leader-election-id` instead. - `POD_NAME` has been removed. It was used to enable a particular pod to hold the leader election lock when the Ansible operator used the leader for life mechanism. Ansible operator now uses controller-runtime's leader with lease mechanism. -## Exporting metrics +## Exporting metrics -If you are using metrics and would like to keep them exported you will need to configure -it in the `config/default/kustomization.yaml`. Please see the [metrics][metrics] doc to know how you can perform this setup. +If you are using metrics and would like to keep them exported you will need to configure +it in the `config/default/kustomization.yaml`. Please see the [metrics][metrics] doc to know how you can perform this setup. -The default port used by the metric endpoint binds to was changed from `:8383` to `:8080`. To continue using port `8383`, specify `--metrics-addr=:8383` when you start the operator. +The default port used by the metric endpoint binds to was changed from `:8383` to `:8080`. To continue using port `8383`, specify `--metrics-addr=:8383` when you start the operator. ## Checking the changes -Finally, follow the steps in the section [Build and run the Operator][build-and-run-the-operator] to verify your project is running. +Finally, follow the steps in the section [Build and run the Operator][build-and-run-the-operator] to verify your project is running. -Note that, you also can troubleshooting by checking the container logs. +Note that, you also can troubleshooting by checking the container logs. E.g `$ kubectl logs deployment.apps/memcached-operator-controller-manager -n memcached-operator-system -c manager` [quickstart-legacy]: https://v0-19-x.sdk.operatorframework.io/docs/ansible/quickstart/ [quickstart]: /docs/building-operators/ansible/quickstart [integration-doc]: https://github.com/kubernetes-sigs/kubebuilder/blob/master/designs/integrating-kubebuilder-and-osdk.md [build-and-run-the-operator]: /docs/building-operators/ansible/tutorial/#deploy-the-operator -[kustomize]: https://github.com/kubernetes-sigs/kustomize -[kube-auth-proxy]: https://github.com/brancz/kube-rbac-proxy +[kustomize]: https://github.com/kubernetes-sigs/kustomize +[kube-auth-proxy]: https://github.com/brancz/kube-rbac-proxy [metrics]: https://book.kubebuilder.io/reference/metrics.html?highlight=metr#metrics [marker]: https://book.kubebuilder.io/reference/markers.html?highlight=markers#marker-syntax [operator-scope]: /docs/building-operators/golang/operator-scope -[molecule]: https://molecule.readthedocs.io/en/latest/# +[molecule]: https://molecule.readthedocs.io/en/latest/# [testing-guide]: /docs/building-operators/ansible/testing-guide diff --git a/website/content/en/docs/building-operators/ansible/quickstart.md b/website/content/en/docs/building-operators/ansible/quickstart.md index ac64ab5f37c..e13406a4d94 100644 --- a/website/content/en/docs/building-operators/ansible/quickstart.md +++ b/website/content/en/docs/building-operators/ansible/quickstart.md @@ -2,91 +2,107 @@ title: Quickstart for Ansible-based Operators linkTitle: Quickstart weight: 2 -description: A simple set of instructions that demonstrates the basics of setting up and running a Ansible-based operator. +description: A simple set of instructions to set up and run an Ansible-based operator. --- This guide walks through an example of building a simple memcached-operator powered by [Ansible][ansible-link] using tools and libraries provided by the Operator SDK. ## Prerequisites -- [Install `operator-sdk`][operator_install] and the [Ansible prequisites][ansible-operator-install] -- Access to a Kubernetes v1.16.0+ cluster. +- Go through the [installation guide][install-guide]. - User authorized with `cluster-admin` permissions. -## Quickstart Steps +## Steps -### Create a project +1. Create a project directory for your project and initialize the project: -Create and change into a directory for your project. Then call `operator-sdk init` -with the Ansible plugin to initialize the [base project layout][layout-doc]: + ```sh + mkdir memcached-operator + cd memcached-operator + operator-sdk init --domain example.com --plugins ansible + ``` -```sh -mkdir memcached-operator -cd memcached-operator -operator-sdk init --plugins=ansible --domain=example.com -``` +1. Create a simple Memcached API: -### Create an API + ```sh + operator-sdk create api --group cache --version v1alpha1 --kind Memcached --generate-role + ``` -Let's create a new API with a role for it: +1. Use the built-in Makefile targets to build and push your operator. +Make sure to define `IMG` when you call `make`: -```sh -operator-sdk create api --group cache --version v1 --kind Memcached --generate-role -``` + ```sh + export OPERATOR_IMG="quay.io/example-inc/memcached-operator:v0.0.1" + make docker-build docker-push IMG=$OPERATOR_IMG + ``` -### Build and push the operator image -Use the built-in Makefile targets to build and push your operator. Make -sure to define `IMG` when you call `make`: +### OLM deployment -```sh -make docker-build docker-push IMG=/: -``` +1. Install [OLM][doc-olm]: -**NOTE**: To allow the cluster pull the image the repository needs to be - set as public or you must configure an image pull secret. + ```sh + operator-sdk olm install + ``` +1. Bundle your operator and push the bundle image: -### Run the operator + ```sh + make bundle IMG=$OPERATOR_IMG + # Note the "-bundle" component in the image name below. + export BUNDLE_IMG="quay.io/example-inc/memcached-operator-bundle:v0.0.1" + make bundle-build BUNDLE_IMG=$BUNDLE_IMG + make docker-push IMG=$BUNDLE_IMG + ``` -Install the CRD and deploy the project to the cluster. Set `IMG` with -`make deploy` to use the image you just pushed: +1. Run your bundle: -```sh -make install -make deploy IMG=/: -``` + ```sh + operator-sdk run bundle $BUNDLE_IMG + ``` -### Create a sample custom resource +1. Create a sample Memcached custom resource: -Create a sample CR: -```sh -kubectl apply -f config/samples/cache_v1_memcached.yaml -``` + ```console + $ kubectl apply -f config/samples/cache_v1alpha1_memcached.yaml + memcached.cache.example.com/memcached-sample created + ``` -Watch for the CR be reconciled by the operator: -```sh -kubectl logs deployment.apps/memcached-operator-controller-manager -n memcached-operator-system -c manager -``` +1. Uninstall the operator: -### Clean up + ```sh + operator-sdk cleanup memcached-operator + ``` -Delete the CR to uninstall memcached: -```sh -kubectl delete -f config/samples/cache_v1_memcached.yaml -``` -Use `make undeploy` to uninstall the operator and its CRDs: -```sh -make undeploy -``` +### Direct deployment + +1. Deploy your operator: + + ```sh + make deploy IMG=$OPERATOR_IMG + ``` + +1. Create a sample Memcached custom resource: + + ```console + $ kubectl apply -f config/samples/cache_v1alpha1_memcached.yaml + memcached.cache.example.com/memcached-sample created + ``` + +1. Uninstall the operator: + + ```sh + make undeploy + ``` + ## Next Steps -Read the [tutorial][tutorial] for an in-depth walkthough of building a Ansible operator. +Read the [full tutorial][tutorial] for an in-depth walkthough of building a Ansible operator. + -[operator_install]: /docs/installation/ -[ansible-operator-install]: /docs/building-operators/ansible/installation -[layout-doc]:../reference/scaffolding -[tutorial]: /docs/building-operators/ansible/tutorial/ -[ansible-link]: https://www.ansible.com/ +[ansible-link]:https://www.ansible.com/ +[install-guide]:/docs/building-operators/ansible/installation +[doc-olm]:/docs/olm-integration/quickstart-bundle/#enabling-olm +[tutorial]:/docs/building-operators/ansible/tutorial/ diff --git a/website/content/en/docs/building-operators/ansible/tutorial.md b/website/content/en/docs/building-operators/ansible/tutorial.md index e3b55838f45..97a026e5262 100644 --- a/website/content/en/docs/building-operators/ansible/tutorial.md +++ b/website/content/en/docs/building-operators/ansible/tutorial.md @@ -9,8 +9,7 @@ This guide walks through an example of building a simple memcached-operator powe ## Prerequisites -- [Install `operator-sdk`][operator_install] and the [Ansible prequisites][ansible-operator-install] -- Access to a Kubernetes v1.16.0+ cluster. +- Go through the [installation guide][install-guide]. - User authorized with `cluster-admin` permissions. ## Creating an Operator @@ -24,7 +23,7 @@ In this section we will: Begin by generating a new project from a new directory. ```sh -$ mkdir memcached-operator +$ mkdir memcached-operator $ cd memcached-operator $ operator-sdk init --plugins=ansible --domain example.com ``` @@ -163,7 +162,7 @@ $ make deploy ``` We are using the `memcached-operator-system` Namespace, so let's set -that context. +that context. ```sh $ kubectl config set-context --current --namespace=memcached-operator-system @@ -172,7 +171,7 @@ $ kubectl config set-context --current --namespace=memcached-operator-system Verify that the memcached-operator is up and running: ```sh -$ kubectl get deployment +$ kubectl get deployment NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE memcached-operator 1 1 1 1 1m @@ -223,13 +222,10 @@ can also be used with cluster-wide scope. See the [operator scope][operator-scop OLM will manage creation of most if not all resources required to run your operator, using a bit of setup from other operator-sdk commands. Check out the [OLM integration guide][quickstart-bundle]. -[ansible-operator-install]: /docs/building-operators/ansible/installation -[ansible-developer-tips]: /docs/building-operators/ansible/development-tips/ -[ansible-watches]: /docs/building-operators/ansible/reference/watches -[custom-resources]: https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/ +[install-guide]:/docs/building-operators/ansible/installation +[ansible-developer-tips]:/docs/building-operators/ansible/development-tips/ +[ansible-watches]:/docs/building-operators/ansible/reference/watches +[custom-resources]:https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/ [operator-scope]:https://v0-19-x.sdk.operatorframework.io/docs/legacy-common/operator-scope/ -[layout-doc]:../reference/scaffolding -[docker-tool]:https://docs.docker.com/install/ -[kubectl-tool]:https://kubernetes.io/docs/tasks/tools/install-kubectl/ -[quickstart-bundle]: /docs/olm-integration/quickstart-bundle/ -[operator_install]: /docs/installation/ +[layout-doc]:/docs/building-operators/ansible/reference/scaffolding +[quickstart-bundle]:/docs/olm-integration/quickstart-bundle/ diff --git a/website/content/en/docs/building-operators/golang/installation.md b/website/content/en/docs/building-operators/golang/installation.md index 323164ff4dd..166224f29a4 100644 --- a/website/content/en/docs/building-operators/golang/installation.md +++ b/website/content/en/docs/building-operators/golang/installation.md @@ -1,10 +1,12 @@ --- -title: Golang Based Operator SDK Installation +title: Installation Guide linkTitle: Installation weight: 1 --- -Follow the steps in the [installation guide][install-guide] to learn how to install the Operator SDK CLI tool. +## Install `operator-sdk` + +Follow the steps in the [installation guide][install-guide] to learn how to install the `operator-sdk` CLI tool. ## Additional Prerequisites @@ -15,10 +17,10 @@ Follow the steps in the [installation guide][install-guide] to learn how to inst - [kubectl][kubectl_tool] version v1.11.3+. - Access to a Kubernetes v1.11.3+ cluster (v1.16.0+ if using `apiextensions.k8s.io/v1` CRDs). + +[install-guide]:/docs/installation/ [git_tool]:https://git-scm.com/downloads [go_tool]:https://golang.org/dl/ [docker_tool]:https://docs.docker.com/install/ [mercurial_tool]:https://www.mercurial-scm.org/downloads [kubectl_tool]:https://kubernetes.io/docs/tasks/tools/install-kubectl/ -[install-guide]: /docs/installation/ -[quay-link]:https://quay.io diff --git a/website/content/en/docs/building-operators/golang/migration.md b/website/content/en/docs/building-operators/golang/migration.md index d0d3eaa5a0f..64dfbf43a33 100644 --- a/website/content/en/docs/building-operators/golang/migration.md +++ b/website/content/en/docs/building-operators/golang/migration.md @@ -1,8 +1,8 @@ --- -title: Migrating Legacy Projects -linkTitle: Migrating Projects to 1.0.0+ +link: Migrating pre-v1.0.0 Projects +linkTitle: Migrating pre-v1.0.0 Projects weight: 200 -description: Instructions for migrating a legacy Go-based project to use the new Kubebuilder-style layout. +description: Instructions for migrating a Go-based project built prior to v1.0.0 to use the new Kubebuilder-style layout. --- ## Overview diff --git a/website/content/en/docs/building-operators/golang/quickstart.md b/website/content/en/docs/building-operators/golang/quickstart.md index dd2e5d4a84c..17808add393 100644 --- a/website/content/en/docs/building-operators/golang/quickstart.md +++ b/website/content/en/docs/building-operators/golang/quickstart.md @@ -2,91 +2,106 @@ title: Quickstart for Go-based Operators linkTitle: Quickstart weight: 20 -description: A simple set of instructions that demonstrates the basics of setting up and running Go-based operator. +description: A simple set of instructions to set up and run a Go-based operator. --- This guide walks through an example of building a simple memcached-operator using tools and libraries provided by the Operator SDK. ## Prerequisites -- [Install operator-sdk][operator_install] and its prequisites. -- Access to a Kubernetes v1.11.3+ cluster (v1.16.0+ if using `apiextensions.k8s.io/v1` CRDs). +- Go through the [installation guide][install-guide]. - User authorized with `cluster-admin` permissions -## Quickstart Steps +## Steps -### Create a project +1. Create a project directory for your project and initialize the project: -Create and change into a directory for your project. Then call `operator-sdk init` -with the Go plugin to initialize the project. - -```sh -mkdir memcached-operator -cd memcached-operator -operator-sdk init --domain=example.com --repo=github.com/example-inc/memcached-operator -``` + ```sh + mkdir memcached-operator + cd memcached-operator + operator-sdk init --domain example.com --repo github.com/example-inc/memcached-operator + ``` -### Create an API +1. Create a simple Memcached API: -Create a simple Memcached API: + ```sh + operator-sdk create api --group cache --version v1alpha1 --kind Memcached --resource --controller + ``` -```sh -operator-sdk create api --group cache --version v1 --kind Memcached --resource=true --controller=true -``` +1. Use the built-in Makefile targets to build and push your operator. +Make sure to define `IMG` when you call `make`: -### Build and push the operator image + ```sh + export OPERATOR_IMG="quay.io/example-inc/memcached-operator:v0.0.1" + make docker-build docker-push IMG=$OPERATOR_IMG + ``` -Use the built-in Makefile targets to build and push your operator. Make -sure to define `IMG` when you call `make`: -```sh -make docker-build docker-push IMG=/: -``` +### OLM deployment -**NOTE**: To allow the cluster pull the image the repository needs to be - set as public or you must configure an image pull secret. +1. Install [OLM][doc-olm]: + ```sh + operator-sdk olm install + ``` -### Run the operator +1. Bundle your operator and push the bundle image: -Install the CRD and deploy the project to the cluster. Set `IMG` with -`make deploy` to use the image you just pushed: + ```sh + make bundle IMG=$OPERATOR_IMG + # Note the "-bundle" component in the image name below. + export BUNDLE_IMG="quay.io/example-inc/memcached-operator-bundle:v0.0.1" + make bundle-build BUNDLE_IMG=$BUNDLE_IMG + make docker-push IMG=$BUNDLE_IMG + ``` -```sh -make install -make deploy IMG=/: -``` +1. Run your bundle: -### Create a sample custom resource + ```sh + operator-sdk run bundle $BUNDLE_IMG + ``` -Create a sample CR: -```sh -kubectl apply -f config/samples/cache_v1_memcached.yaml -``` +1. Create a sample Memcached custom resource: -Watch for the CR be reconciled by the operator: -``` -kubectl logs deployment.apps/memcached-operator-controller-manager -n memcached-operator-system -c manager -``` + ```console + $ kubectl apply -f config/samples/cache_v1alpha1_memcached.yaml + memcached.cache.example.com/memcached-sample created + ``` -## Clean up +1. Uninstall the operator: -Delete the CR to uninstall memcached: -```sh -kubectl delete -f config/samples/cache_v1_memcached.yaml -``` + ```sh + operator-sdk cleanup memcached-operator + ``` + + +### Direct deployment + +1. Deploy your operator: + + ```sh + make deploy IMG=$OPERATOR_IMG + ``` + +1. Create a sample Memcached custom resource: + + ```console + $ kubectl apply -f config/samples/cache_v1alpha1_memcached.yaml + memcached.cache.example.com/memcached-sample created + ``` + +1. Uninstall the operator: + + ```sh + make undeploy + ``` -Uninstall the operator and its CRDs: -```sh -kustomize build config/default | kubectl delete -f - -``` ## Next Steps -Read the [tutorial][tutorial] for an in-depth walkthough of building a Go operator. -[go_tool]:https://golang.org/dl/ -[docker_tool]:https://docs.docker.com/install/ -[kubectl_tool]:https://kubernetes.io/docs/tasks/tools/install-kubectl/ -[operator_install]: /docs/installation/ -[tutorial]: /docs/building-operators/golang/tutorial/ +Read the [full tutorial][tutorial] for an in-depth walkthough of building a Go operator. + +[install-guide]:/docs/building-operators/golang/installation +[doc-olm]:/docs/olm-integration/quickstart-bundle/#enabling-olm +[tutorial]:/docs/building-operators/golang/tutorial/ diff --git a/website/content/en/docs/building-operators/golang/tutorial.md b/website/content/en/docs/building-operators/golang/tutorial.md index 838c909d13a..7df97192805 100644 --- a/website/content/en/docs/building-operators/golang/tutorial.md +++ b/website/content/en/docs/building-operators/golang/tutorial.md @@ -461,12 +461,7 @@ The following guides build off the operator created in this example, adding adva Also see the [advanced topics][advanced_topics] doc for more use cases and under the hood details. -[operator_install]: https://sdk.operatorframework.io/docs/installation/install-operator-sdk/ -[go_tool]:https://golang.org/dl/ -[docker_tool]:https://docs.docker.com/install/ -[kubectl_tool]:https://kubernetes.io/docs/tasks/tools/install-kubectl/ -[kustomize_tool]: https://sigs.k8s.io/kustomize/docs/INSTALL.md - +[install-guide]:/docs/building-operators/golang/installation [enqueue_requests_from_map_func]: https://godoc.org/sigs.k8s.io/controller-runtime/pkg/handler#EnqueueRequestsFromMapFunc [event_handler_godocs]: https://godoc.org/sigs.k8s.io/controller-runtime/pkg/handler#hdr-EventHandlers [event_filtering]:/docs/building-operators/golang/references/event-filtering/ @@ -474,18 +469,14 @@ Also see the [advanced topics][advanced_topics] doc for more use cases and under [controller_godocs]: https://godoc.org/github.com/kubernetes-sigs/controller-runtime/pkg/controller [operator_scope]:/docs/building-operators/golang/operator-scope/ [kubebuilder_layout_doc]:https://book.kubebuilder.io/cronjob-tutorial/basic-project.html -[homebrew_tool]:https://brew.sh/ [go_mod_wiki]: https://github.com/golang/go/wiki/Modules -[go_vendoring]: https://blog.gopheracademy.com/advent-2015/vendor-folder/ [doc_client_api]:/docs/building-operators/golang/references/client/ [manager_go_doc]: https://godoc.org/github.com/kubernetes-sigs/controller-runtime/pkg/manager#Manager -[controller-go-doc]: https://godoc.org/github.com/kubernetes-sigs/controller-runtime/pkg#hdr-Controller [request-go-doc]: https://godoc.org/github.com/kubernetes-sigs/controller-runtime/pkg/reconcile#Request [result_go_doc]: https://godoc.org/github.com/kubernetes-sigs/controller-runtime/pkg/reconcile#Result [multi-namespaced-cache-builder]: https://godoc.org/github.com/kubernetes-sigs/controller-runtime/pkg/cache#MultiNamespacedCacheBuilder [cli-run-olm]: /docs/olm-integration/cli-overview [kubebuilder_entrypoint_doc]: https://book.kubebuilder.io/cronjob-tutorial/empty-main.html - [api_terms_doc]: https://book.kubebuilder.io/cronjob-tutorial/gvks.html [kb_controller_doc]: https://book.kubebuilder.io/cronjob-tutorial/controller-overview.html [kb_api_doc]: https://book.kubebuilder.io/cronjob-tutorial/new-api.html @@ -494,7 +485,6 @@ Also see the [advanced topics][advanced_topics] doc for more use cases and under [generating-crd]: https://book.kubebuilder.io/reference/generating-crd.html [markers]: https://book.kubebuilder.io/reference/markers.html [crd-markers]: https://book.kubebuilder.io/reference/markers/crd-validation.html -[rbac-markers]: https://book.kubebuilder.io/reference/markers/rbac.html [memcached_controller]: https://github.com/operator-framework/operator-sdk/blob/v1.2.0/testdata/go/memcached-operator/controllers/memcached_controller.go [builder_godocs]: https://godoc.org/github.com/kubernetes-sigs/controller-runtime/pkg/builder#example-Builder [legacy_quickstart_doc]:https://v0-19-x.sdk.operatorframework.io/docs/golang/legacy/quickstart/ @@ -503,7 +493,6 @@ Also see the [advanced topics][advanced_topics] doc for more use cases and under [create_a_webhook]: https://book.kubebuilder.io/cronjob-tutorial/webhook-implementation.html [status_marker]: https://book.kubebuilder.io/reference/generating-crd.html#status [status_subresource]: https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#status-subresource -[API-groups]:https://kubernetes.io/docs/concepts/overview/kubernetes-api/#api-groups [legacy_CLI]:https://v0-19-x.sdk.operatorframework.io/docs/cli/ [env-test-setup]: /docs/building-operators/golang/references/envtest-setup [role-based-access-control]: https://cloud.google.com/kubernetes-engine/docs/how-to/role-based-access-control#iam-rolebinding-bootstrap diff --git a/website/content/en/docs/building-operators/helm/installation.md b/website/content/en/docs/building-operators/helm/installation.md new file mode 100644 index 00000000000..b58c942f3d9 --- /dev/null +++ b/website/content/en/docs/building-operators/helm/installation.md @@ -0,0 +1,20 @@ +--- +title: Installation Guide +linkTitle: Installation +weight: 1 +--- + +## Install `operator-sdk` + +Follow the steps in the [installation guide][install-guide] to learn how to install the `operator-sdk` CLI tool. + +### Additional Prerequisites + +- [docker][docker_tool] version 17.03+. +- [kubectl][kubectl_tool] version v1.11.3+. +- Access to a Kubernetes v1.11.3+ cluster (v1.16.0+ if using `apiextensions.k8s.io/v1` CRDs). + + +[install-guide]:/docs/installation/ +[docker_tool]:https://docs.docker.com/install/ +[kubectl_tool]:https://kubernetes.io/docs/tasks/tools/install-kubectl/ diff --git a/website/content/en/docs/building-operators/helm/migration.md b/website/content/en/docs/building-operators/helm/migration.md index 6ee04feb36b..de27a3ddc2f 100644 --- a/website/content/en/docs/building-operators/helm/migration.md +++ b/website/content/en/docs/building-operators/helm/migration.md @@ -1,23 +1,23 @@ --- -title: Migrating Helm-based Legacy Projects -linkTitle: Migrating Legacy Projects +link: Migrating pre-v1.0.0 Projects +linkTitle: Migrating pre-v1.0.0 Projects weight: 300 -description: Instructions for migrating a legacy Helm-based project to use the new Kubebuilder-style layout. +description: Instructions for migrating a Helm-based project built prior to v1.0.0 to use the new Kubebuilder-style layout. --- ## Overview -The motivations for the new layout are related to bringing more flexibility to users and +The motivations for the new layout are related to bringing more flexibility to users and part of the process to [Integrating Kubebuilder and Operator SDK][integration-doc]. ### What was changed - + - The `deploy` directory was replaced with the `config` directory including a new layout of Kubernetes manifests files: * CRD manifests in `deploy/crds/` are now in `config/crd/bases` * CR manifests in `deploy/crds/` are now in `config/samples` - * Controller manifest `deploy/operator.yaml` is now in `config/manager/manager.yaml` + * Controller manifest `deploy/operator.yaml` is now in `config/manager/manager.yaml` * RBAC manifests in `deploy` are now in `config/rbac/` - + - `build/Dockerfile` is moved to `Dockerfile` in the project root directory ### What is new @@ -30,9 +30,9 @@ Projects are now scaffold using: ## How to migrate -The easy migration path is to create a new project from the scratch and let the tool scaffold the files properly and then, -just replace with your customizations and implementations. Following an example. - +The easy migration path is to create a new project from the scratch and let the tool scaffold the files properly and then, +just replace with your customizations and implementations. Following an example. + ### Creating a new project In Kubebuilder-style projects, CRD groups are defined using two different flags @@ -88,7 +88,7 @@ Check if you have custom options in the `watches.yaml` file of your existing pro # +kubebuilder:scaffold:watch ``` -**NOTE**: Do not remove the `+kubebuilder:scaffold:watch` [marker][marker]. It allows the tool to update the watches file when new APIs are created. +**NOTE**: Do not remove the `+kubebuilder:scaffold:watch` [marker][marker]. It allows the tool to update the watches file when new APIs are created. ### Checking the Permissions (RBAC) @@ -120,29 +120,29 @@ The following rules were used in earlier versions of helm-operator to automatica ### Configuring your Operator -If your existing project has customizations in `deploy/operator.yaml`, they need to be ported to +If your existing project has customizations in `deploy/operator.yaml`, they need to be ported to `config/manager/manager.yaml`. If you are passing custom arguments in your deployment, make sure to also update `config/default/auth_proxy_patch.yaml`. -Note that the following environment variables are no longer used. +Note that the following environment variables are no longer used. - `OPERATOR_NAME` is deprecated. It is used to define the name for a leader election config map. Operator authors should begin using `--leader-election-id` instead. - `POD_NAME` was used to enable a particular pod to hold the leader election lock when the Helm operator used the leader for life mechanism. Helm operator now uses controller-runtime's leader with lease mechanism, and `POD_NAME` is no longer necessary. -## Exporting metrics +## Exporting metrics -If you are using metrics and would like to keep them exported you will need to configure -it in the `config/default/kustomization.yaml`. Please see the [metrics][metrics] doc to know how you can perform this setup. +If you are using metrics and would like to keep them exported you will need to configure +it in the `config/default/kustomization.yaml`. Please see the [metrics][metrics] doc to know how you can perform this setup. -The default port used by the metric endpoint binds to was changed from `:8383` to `:8080`. To continue using port `8383`, specify `--metrics-addr=:8383` when you start the operator. +The default port used by the metric endpoint binds to was changed from `:8383` to `:8080`. To continue using port `8383`, specify `--metrics-addr=:8383` when you start the operator. ## Checking the changes -Finally, follow the steps in the section [Build and run the operator][build-and-run-the-operator] to verify your project is running. +Finally, follow the steps in the section [Build and run the operator][build-and-run-the-operator] to verify your project is running. [quickstart]: /docs/building-operators/helm/quickstart [integration-doc]: https://github.com/kubernetes-sigs/kubebuilder/blob/master/designs/integrating-kubebuilder-and-osdk.md [build-and-run-the-operator]: /docs/building-operators/helm/tutorial#build-and-run-the-operator -[kustomize]: https://github.com/kubernetes-sigs/kustomize -[kube-auth-proxy]: https://github.com/brancz/kube-rbac-proxy +[kustomize]: https://github.com/kubernetes-sigs/kustomize +[kube-auth-proxy]: https://github.com/brancz/kube-rbac-proxy [metrics]: https://book.kubebuilder.io/reference/metrics.html?highlight=metr#metrics -[marker]: https://book.kubebuilder.io/reference/markers.html?highlight=markers#marker-syntax \ No newline at end of file +[marker]: https://book.kubebuilder.io/reference/markers.html?highlight=markers#marker-syntax diff --git a/website/content/en/docs/building-operators/helm/quickstart.md b/website/content/en/docs/building-operators/helm/quickstart.md index a8b1dff5bb5..ebc8b37ae99 100644 --- a/website/content/en/docs/building-operators/helm/quickstart.md +++ b/website/content/en/docs/building-operators/helm/quickstart.md @@ -2,92 +2,106 @@ title: Quickstart for Helm-based Operators linkTitle: Quickstart weight: 100 -description: A simple set of instructions that demonstrates the basics of setting up and running a Helm-based operator. +description: A simple set of instructions to set up and run a Helm-based operator. --- This guide walks through an example of building a simple nginx-operator powered by [Helm][helm-official] using tools and libraries provided by the Operator SDK. ## Prerequisites -- [Install `operator-sdk`][operator_install] and its prequisites. -- Access to a Kubernetes v1.16.0+ cluster. +- Go through the [installation guide][install-guide]. - User authorized with `cluster-admin` permissions. -## Quickstart Steps +## Steps -### Create a project +1. Create a project directory for your project and initialize the project: -Create and change into a directory for your project. Then call `operator-sdk init` -with the Helm plugin to initialize the [base project layout][project_layout]: + ```sh + mkdir nginx-operator + cd nginx-operator + operator-sdk init --domain example.com --plugins helm + ``` -```sh -mkdir nginx-operator -cd nginx-operator -operator-sdk init --plugins=helm -``` +1. Create a simple nginx API using Helm's built-in chart boilerplate (from `helm create`): -### Create an API + ```sh + operator-sdk create api --group demo --version v1alpha1 --kind Nginx + ``` -Create a simple nginx API using Helm's built-in chart boilerplate (from -`helm create`): +1. Use the built-in Makefile targets to build and push your operator. +Make sure to define `IMG` when you call `make`: -```sh -operator-sdk create api --group demo --version v1 --kind Nginx -``` + ```sh + export OPERATOR_IMG="quay.io/example-inc/nginx-operator:v0.0.1" + make docker-build docker-push IMG=$OPERATOR_IMG + ``` -### Build and push the operator image -Use the built-in Makefile targets to build and push your operator. Make -sure to define `IMG` when you call `make`: +### OLM deployment -```sh -make docker-build docker-push IMG=/: -``` +1. Install [OLM][doc-olm]: -**NOTE**: To allow the cluster pull the image the repository needs to be - set as public or you must configure an image pull secret. + ```sh + operator-sdk olm install + ``` +1. Bundle your operator and push the bundle image: -### Run the operator + ```sh + make bundle IMG=$OPERATOR_IMG + # Note the "-bundle" component in the image name below. + export BUNDLE_IMG="quay.io/example-inc/nginx-operator-bundle:v0.0.1" + make bundle-build BUNDLE_IMG=$BUNDLE_IMG + make docker-push IMG=$BUNDLE_IMG + ``` -Install the CRD and deploy the project to the cluster. Set `IMG` with -`make deploy` to use the image you just pushed: +1. Run your bundle: -```sh -make install -make deploy IMG=/: -``` + ```sh + operator-sdk run bundle $BUNDLE_IMG + ``` -### Create a sample custom resource +1. Create a sample Nginx custom resource: -Create a sample CR: -```sh -kubectl apply -f config/samples/demo_v1_nginx.yaml -``` + ```console + $ kubectl apply -f config/samples/demo_v1alpha1_nginx.yaml + nginx.demo.example.com/nginx-sample created + ``` -Watch for the CR to trigger the operator to deploy the nginx deployment -and service: -```sh -kubectl get all -l "app.kubernetes.io/instance=nginx-sample" -``` +1. Uninstall the operator: -### Clean up + ```sh + operator-sdk cleanup nginx-operator + ``` -Delete the CR to uninstall the release: -```sh -kubectl delete -f config/samples/demo_v1_nginx.yaml -``` -Use `make undeploy` to uninstall the operator and its CRDs: -```sh -make undeploy -``` +### Direct deployment + +1. Deploy your operator: + + ```sh + make deploy IMG=$OPERATOR_IMG + ``` + +1. Create a sample Nginx custom resource: + + ```console + $ kubectl apply -f config/samples/demo_v1alpha1_nginx.yaml + nginx.demo.example.com/nginx-sample created + ``` + +1. Uninstall the operator: + + ```sh + make undeploy + ``` ## Next Steps -Read the [tutorial][tutorial] for an in-depth walkthough of building a Helm operator. +Read the [full tutorial][tutorial] for an in-depth walkthough of building a Helm operator. + -[operator_install]: /docs/installation/ -[project_layout]: /docs/building-operators/helm/reference/project_layout/ -[tutorial]: /docs/building-operators/helm/tutorial/ -[helm-official]: https://helm.sh/docs/ +[helm-official]:https://helm.sh/docs/ +[install-guide]:/docs/building-operators/helm/installation +[doc-olm]:/docs/olm-integration/quickstart-bundle/#enabling-olm +[tutorial]:/docs/building-operators/helm/tutorial/ diff --git a/website/content/en/docs/building-operators/helm/tutorial.md b/website/content/en/docs/building-operators/helm/tutorial.md index be6a4c250a7..52d523cd122 100644 --- a/website/content/en/docs/building-operators/helm/tutorial.md +++ b/website/content/en/docs/building-operators/helm/tutorial.md @@ -11,8 +11,7 @@ This guide walks through an example of building a simple nginx-operator powered ## Prerequisites -- [Install `operator-sdk`][operator_install] and its prequisites. -- Access to a Kubernetes v1.16.0+ cluster. +- Go through the [installation guide][install-guide]. - User authorized with `cluster-admin` permissions. ## Create a new project @@ -50,7 +49,7 @@ If `--helm-chart` is specified, the `--group`, `--version`, and `--kind` flags b | kind | deduce from the specified chart | | version | v1alpha1 | -If `--helm-chart` is a local chart archive (e.g `example-chart-1.2.0.tgz`) or directory, +If `--helm-chart` is a local chart archive (e.g `example-chart-1.2.0.tgz`) or directory, it will be validated and unpacked or copied into the project. Otherwise, the SDK will attempt to fetch the specified helm chart from a remote repository. @@ -195,7 +194,7 @@ make deploy IMG=$IMG Verify that the nginx-operator is up and running: -```sh +```console $ kubectl get deployment -n nginx-operator-system NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE nginx-operator-controller-manager 1/1 1 1 1 77s @@ -224,7 +223,7 @@ kubectl apply -f config/samples/example_v1alpha1_nginx.yaml Ensure that the nginx-operator creates the deployment for the CR: -```sh +```console $ kubectl get deployment NAME READY UP-TO-DATE AVAILABLE AGE nginx-sample 2/2 2 2 2m13s @@ -232,15 +231,16 @@ nginx-sample 2/2 2 2 2m13s Check the pods to confirm 2 replicas were created: -```sh +```console $ kubectl get pods NAME READY STATUS RESTARTS AGE nginx-sample-c786bfdcf-4g6md 1/1 Running 0 81s nginx-sample-c786bfdcf-6bhmx 1/1 Running 0 81s +``` Check that the service port is set to `8080`: -```sh +```console $ kubectl get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx-sample ClusterIP 10.96.26.3 8080/TCP 1m @@ -251,7 +251,7 @@ nginx-sample ClusterIP 10.96.26.3 Change the `spec.replicaCount` field from 2 to 3, remove the `spec.service` field: -```sh +```console $ cat config/samples/example_v1alpha1_nginx.yaml apiVersion: example.com/v1alpha1 kind: Nginx @@ -269,7 +269,7 @@ kubectl apply -f config/samples/example_v1alpha1_nginx.yaml Confirm that the operator changes the deployment size: -```sh +```console $ kubectl get deployment NAME DESIRED CURRENT UP-TO-DATE AGE nginx-sample 3/3 3 3 7m29s @@ -277,7 +277,7 @@ nginx-sample 3/3 3 3 Check that the service port is set to the default (`80`): -```sh +```console $ kubectl get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx-sample ClusterIP 10.96.152.76 80/TCP 7m54s @@ -294,7 +294,7 @@ kubectl logs deployment.apps/nginx-operator-controller-manager -n nginx-operato Use the following command to check the CR status and events. ```sh -kubectl describe nginxes.example.com +kubectl describe nginxes.example.com ``` ### Cleanup @@ -308,11 +308,11 @@ make undeploy **NOTE** Additional CR/CRD's can be added to the project by running, for example, the command :`operator-sdk create api --group=example --version=v1alpha1 --kind=AppService` +[install-guide]:/docs/building-operators/helm/installation [operator-scope]: /docs/building-operators/golang/operator-scope [layout-doc]: /docs/building-operators/helm/reference/project_layout/ [helm-charts]:https://helm.sh/docs/topics/charts/ [helm-values]:https://helm.sh/docs/intro/using_helm/#customizing-the-chart-before-installing [helm-official]:https://helm.sh/docs/ -[operator_install]: /docs/installation/ From 935c709908c312fc9f4d4746767ec6b62721dde2 Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Thu, 17 Dec 2020 21:38:17 -0800 Subject: [PATCH 254/376] docs/building-operators: update and align tutorials (#4336) Signed-off-by: reinvantveer --- .../operator-sdk/generate/bundle/bundle.go | 2 +- .../building-operators/ansible/migration.md | 12 +- .../building-operators/ansible/tutorial.md | 184 ++++++++++++++---- .../building-operators/golang/quickstart.md | 5 +- .../building-operators/golang/tutorial.md | 138 +++++++------ .../docs/building-operators/helm/migration.md | 11 +- .../docs/building-operators/helm/tutorial.md | 129 ++++++------ .../docs/cli/operator-sdk_generate_bundle.md | 2 +- 8 files changed, 303 insertions(+), 180 deletions(-) diff --git a/internal/cmd/operator-sdk/generate/bundle/bundle.go b/internal/cmd/operator-sdk/generate/bundle/bundle.go index 20351c9d308..051adf33c61 100644 --- a/internal/cmd/operator-sdk/generate/bundle/bundle.go +++ b/internal/cmd/operator-sdk/generate/bundle/bundle.go @@ -57,7 +57,7 @@ https://github.com/operator-framework/operator-registry/#manifest-format examples = ` # Generate bundle files and build your bundle image with these 'make' recipes: $ make bundle - $ export USERNAME= + $ export USERNAME= $ export BUNDLE_IMG=quay.io/$USERNAME/memcached-operator-bundle:v0.0.1 $ make bundle-build BUNDLE_IMG=$BUNDLE_IMG diff --git a/website/content/en/docs/building-operators/ansible/migration.md b/website/content/en/docs/building-operators/ansible/migration.md index a85d3be320e..a06099b2437 100644 --- a/website/content/en/docs/building-operators/ansible/migration.md +++ b/website/content/en/docs/building-operators/ansible/migration.md @@ -178,7 +178,12 @@ In your new project, roles are automatically generated in `config/rbac/role.yaml If you modified these permissions manually in `deploy/role.yaml` in your existing project, you need to re-apply them in `config/rbac/role.yaml`. -New projects are configured to watch all namespaces by default, so they need a `ClusterRole` to have the necessary permissions. Ensure that `config/rbac/role.yaml` remains a `ClusterRole` if you want to retain the default behavior of the new project conventions. For further information refer to the [operator scope][operator-scope] documentation. + + +New projects are configured to watch all namespaces by default, so they need a `ClusterRole` to have the necessary permissions. Ensure that `config/rbac/role.yaml` remains a `ClusterRole` if you want to retain the default behavior of the new project conventions. The following rules were used in earlier versions of anisible-operator to automatically create and manage services and `servicemonitors` for metrics collection. If your operator's don't require these rules, they can safely be left out of the new `config/rbac/role.yaml` file: @@ -219,7 +224,7 @@ The default port used by the metric endpoint binds to was changed from `:8383` t ## Checking the changes -Finally, follow the steps in the section [Build and run the Operator][build-and-run-the-operator] to verify your project is running. +Finally, follow the steps in the ["run the Operator"][run-the-operator] section to verify your project is running. Note that, you also can troubleshooting by checking the container logs. E.g `$ kubectl logs deployment.apps/memcached-operator-controller-manager -n memcached-operator-system -c manager` @@ -227,11 +232,10 @@ E.g `$ kubectl logs deployment.apps/memcached-operator-controller-manager -n mem [quickstart-legacy]: https://v0-19-x.sdk.operatorframework.io/docs/ansible/quickstart/ [quickstart]: /docs/building-operators/ansible/quickstart [integration-doc]: https://github.com/kubernetes-sigs/kubebuilder/blob/master/designs/integrating-kubebuilder-and-osdk.md -[build-and-run-the-operator]: /docs/building-operators/ansible/tutorial/#deploy-the-operator +[run-the-operator]: /docs/building-operators/ansible/tutorial/#run-the-operator [kustomize]: https://github.com/kubernetes-sigs/kustomize [kube-auth-proxy]: https://github.com/brancz/kube-rbac-proxy [metrics]: https://book.kubebuilder.io/reference/metrics.html?highlight=metr#metrics [marker]: https://book.kubebuilder.io/reference/markers.html?highlight=markers#marker-syntax -[operator-scope]: /docs/building-operators/golang/operator-scope [molecule]: https://molecule.readthedocs.io/en/latest/# [testing-guide]: /docs/building-operators/ansible/testing-guide diff --git a/website/content/en/docs/building-operators/ansible/tutorial.md b/website/content/en/docs/building-operators/ansible/tutorial.md index 97a026e5262..b95d1b62ac1 100644 --- a/website/content/en/docs/building-operators/ansible/tutorial.md +++ b/website/content/en/docs/building-operators/ansible/tutorial.md @@ -2,25 +2,20 @@ title: Ansible Operator Tutorial linkTitle: Tutorial weight: 3 -description: An in-depth walkthough that demonstrates how to build and run a Ansible-based operator. +description: An in-depth walkthough of building and running an Ansible-based operator. --- -This guide walks through an example of building a simple memcached-operator powered by Ansible using tools and libraries provided by the Operator SDK. +**NOTE:** If your project was created with an `operator-sdk` version prior to `v1.0.0` +please [migrate][migration-guide], or consult the [legacy docs][legacy-quickstart-doc]. ## Prerequisites - Go through the [installation guide][install-guide]. - User authorized with `cluster-admin` permissions. -## Creating an Operator +## Create a new project -In this section we will: - - extend the Kubernetes API with a [Custom Resource Definition][custom-resources] that allows users to create `Memcached` resources. - - create a manager that updates the state of the cluster to the desired state defined by `Memcached` resources. - -#### Scaffold a New Project - -Begin by generating a new project from a new directory. +Use the CLI to create a new memcached-operator project: ```sh $ mkdir memcached-operator @@ -122,7 +117,7 @@ spec: The key-value pairs in the Custom Resource spec are passed to Ansible as extra variables. -__Note:__ The names of all variables in the spec field are converted to +**Note:** The names of all variables in the spec field are converted to snake_case by the operator before running ansible. For example, serviceAccount in the spec becomes service_account in ansible. You can disable this case conversion by setting the `snakeCaseParameters` option @@ -141,68 +136,164 @@ $ make docker-build docker-push IMG=/:tag NOTE: To allow the cluster pull the image the repository needs to be set as public or you must configure an image pull secret -## Using the Operator +## Run the Operator -This section walks through the steps that operator users will perform -to deploy the operator and managed resources. +There are three ways to run the operator: -#### Install the CRD +- As Go program outside a cluster +- As a Deployment inside a Kubernetes cluster +- Managed by the [Operator Lifecycle Manager (OLM)][doc-olm] in [bundle][quickstart-bundle] format -To apply the `Memcached` Kind (CRD): +### 1. Run locally outside the cluster + +Execute the following command, which install your CRDs and run the manager locally: ```sh -$ make install +make install run ``` -#### Deploy the Operator: + +### 2. Run as a Deployment inside the cluster + +#### Build and push the image + +Build and push the image: ```sh -# IMG environment variable must be set -$ export IMG= -$ make deploy +export USERNAME= +make docker-build docker-push IMG=quay.io/$USERNAME/memcached-operator:v0.0.1 ``` -We are using the `memcached-operator-system` Namespace, so let's set -that context. +**Note**: The name and tag of the image (`IMG=/:tag`) in both the commands can also be set in the Makefile. +Modify the line which has `IMG ?= controller:latest` to set your desired default image name. + +#### Deploy the operator + +By default, a new namespace is created with name `-system`, i.e. memcached-operator-system and will be used for the deployment. + +Run the following to deploy the operator. This will also install the RBAC manifests from `config/rbac`. ```sh -$ kubectl config set-context --current --namespace=memcached-operator-system +make deploy IMG=quay.io/$USERNAME/memcached-operator:v0.0.1 ``` Verify that the memcached-operator is up and running: -```sh -$ kubectl get deployment +```console +$ kubectl get deployment -n memcached-operator-system +NAME READY UP-TO-DATE AVAILABLE AGE +memcached-operator-controller-manager 1/1 1 1 8m +``` + +### 3. Deploy your Operator with OLM + +First, install [OLM][doc-olm]: -NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE -memcached-operator 1 1 1 1 1m +```sh +operator-sdk olm install ``` -#### Create Memcached Resource +Then bundle your operator and push the bundle image: + +```sh +make bundle IMG=$OPERATOR_IMG +# Note the "-bundle" component in the image name below. +export BUNDLE_IMG="quay.io/$USERNAME/memcached-operator-bundle:v0.0.1" +make bundle-build BUNDLE_IMG=$BUNDLE_IMG +make docker-push IMG=$BUNDLE_IMG +``` -Create the resource, the operator will do the rest. +Finally, run your bundle: ```sh -$ kubectl apply -f config/samples/cache_v1alpha1_memcached.yaml +operator-sdk run bundle $BUNDLE_IMG +``` + +Check out the [docs][quickstart-bundle] for a deep dive into `operator-sdk`'s OLM integration. + + +## Create a Memcached CR + +Update the sample Memcached CR manifest at `config/samples/cache_v1alpha1_memcached.yaml` and define the `spec` as the following: + +```YAML +apiVersion: cache.example.com/v1alpha1 +kind: Memcached +metadata: + name: memcached-sample +spec: + size: 3 ``` -Verify that Memcached pods are created +Create the CR: ```sh +kubectl apply -f config/samples/cache_v1alpha1_memcached.yaml +``` + +Ensure that the memcached operator creates the deployment for the sample CR with the correct size: + +```console +$ kubectl get deployment +NAME READY UP-TO-DATE AVAILABLE AGE +memcached-operator-controller-manager 1/1 1 1 8m +memcached-sample 3/3 3 3 1m +``` + +Check the pods and CR status to confirm the status is updated with the memcached pod names: + +```console $ kubectl get pods +NAME READY STATUS RESTARTS AGE +memcached-sample-6fd7c98d8-7dqdr 1/1 Running 0 1m +memcached-sample-6fd7c98d8-g5k7v 1/1 Running 0 1m +memcached-sample-6fd7c98d8-m7vn7 1/1 Running 0 1m +``` -NAME READY STATUS RESTARTS AGE -memcached-operator-controller-manager-7b667d9979-4jkfb 2/2 Running 0 14s -memcached-sample-memcached-6456bdd5fc-8zgjf 1/1 Running 0 5s -memcached-sample-memcached-6456bdd5fc-hjkrp 1/1 Running 0 5s -memcached-sample-memcached-6456bdd5fc-mcqc5 1/1 Running 0 5s +```console +$ kubectl get memcached/memcached-sample -o yaml +apiVersion: cache.example.com/v1alpha1 +kind: Memcached +metadata: + clusterName: "" + creationTimestamp: 2018-03-31T22:51:08Z + generation: 0 + name: memcached-sample + namespace: default + resourceVersion: "245453" + selfLink: /apis/cache.example.com/v1alpha1/namespaces/default/memcacheds/memcached-sample + uid: 0026cc97-3536-11e8-bd83-0800274106a1 +spec: + size: 3 +status: + nodes: + - memcached-sample-6fd7c98d8-7dqdr + - memcached-sample-6fd7c98d8-g5k7v + - memcached-sample-6fd7c98d8-m7vn7 ``` -#### Cleanup +### Update the size -Clean up the resources: +Update `config/samples/cache_v1alpha1_memcached.yaml` to change the `spec.size` field in the Memcached CR from 3 to 5: ```sh -$ make undeploy +kubectl patch memcached memcached-sample -p '{"spec":{"size": 5}}' --type=merge +``` + +Confirm that the operator changes the deployment size: + +```console +$ kubectl get deployment +NAME READY UP-TO-DATE AVAILABLE AGE +memcached-operator-controller-manager 1/1 1 1 10m +memcached-sample 5/5 5 5 3m +``` + +### Cleanup + +Call the following to delete all deployed resources: + +```sh +make undeploy ``` ## Next Steps @@ -218,14 +309,21 @@ For brevity, some of the scaffolded files were left out of this guide. See [Scaffolding Reference][layout-doc] This example built a namespaced scope operator, but Ansible operators -can also be used with cluster-wide scope. See the [operator scope][operator-scope] documentation. +can also be used with cluster-wide scope. + + OLM will manage creation of most if not all resources required to run your operator, using a bit of setup from other operator-sdk commands. Check out the [OLM integration guide][quickstart-bundle]. +[legacy-quickstart-doc]:https://v0-19-x.sdk.operatorframework.io/docs/ansible/quickstart/ +[migration-guide]:/docs/building-operators/ansible/migration [install-guide]:/docs/building-operators/ansible/installation [ansible-developer-tips]:/docs/building-operators/ansible/development-tips/ [ansible-watches]:/docs/building-operators/ansible/reference/watches [custom-resources]:https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/ -[operator-scope]:https://v0-19-x.sdk.operatorframework.io/docs/legacy-common/operator-scope/ [layout-doc]:/docs/building-operators/ansible/reference/scaffolding -[quickstart-bundle]:/docs/olm-integration/quickstart-bundle/ +[quickstart-bundle]:/docs/olm-integration/quickstart-bundle +[doc-olm]:/docs/olm-integration/quickstart-bundle/#enabling-olm diff --git a/website/content/en/docs/building-operators/golang/quickstart.md b/website/content/en/docs/building-operators/golang/quickstart.md index 17808add393..271b2673e24 100644 --- a/website/content/en/docs/building-operators/golang/quickstart.md +++ b/website/content/en/docs/building-operators/golang/quickstart.md @@ -32,7 +32,8 @@ This guide walks through an example of building a simple memcached-operator usin Make sure to define `IMG` when you call `make`: ```sh - export OPERATOR_IMG="quay.io/example-inc/memcached-operator:v0.0.1" + export USERNAME= + export OPERATOR_IMG="quay.io/$USERNAME/memcached-operator:v0.0.1" make docker-build docker-push IMG=$OPERATOR_IMG ``` @@ -50,7 +51,7 @@ Make sure to define `IMG` when you call `make`: ```sh make bundle IMG=$OPERATOR_IMG # Note the "-bundle" component in the image name below. - export BUNDLE_IMG="quay.io/example-inc/memcached-operator-bundle:v0.0.1" + export BUNDLE_IMG="quay.io/$USERNAME/memcached-operator-bundle:v0.0.1" make bundle-build BUNDLE_IMG=$BUNDLE_IMG make docker-push IMG=$BUNDLE_IMG ``` diff --git a/website/content/en/docs/building-operators/golang/tutorial.md b/website/content/en/docs/building-operators/golang/tutorial.md index 7df97192805..d8799fb6828 100644 --- a/website/content/en/docs/building-operators/golang/tutorial.md +++ b/website/content/en/docs/building-operators/golang/tutorial.md @@ -1,11 +1,12 @@ --- -title: Golang Based Operator Tutorial +title: Golang Operator Tutorial linkTitle: Tutorial weight: 30 -description: This guide walks through an example of building a simple memcached-operator using the operator-sdk CLI tool and controller-runtime library API. +description: An in-depth walkthough of building and running a Go-based operator. --- -**NOTE:** For the SDK versions prior to `v0.19.0` please consult the [legacy docs][legacy_quickstart_doc] for the [legacy CLI][legacy_CLI] and project. +**NOTE:** If your project was created with an `operator-sdk` version prior to `v1.0.0` +please [migrate][migration-guide], or consult the [legacy docs][legacy-quickstart-doc]. ## Prerequisites @@ -18,11 +19,11 @@ description: This guide walks through an example of building a simple memcached- Use the CLI to create a new memcached-operator project: ```sh -$ mkdir -p $HOME/projects/memcached-operator -$ cd $HOME/projects/memcached-operator +mkdir -p $HOME/projects/memcached-operator +cd $HOME/projects/memcached-operator # we'll use a domain of example.com # so all API groups will be .example.com -$ operator-sdk init --domain=example.com --repo=github.com/example-inc/memcached-operator +operator-sdk init --domain example.com --repo github.com/example-inc/memcached-operator ``` To learn about the project directory structure, see [Kubebuilder project layout][kubebuilder_layout_doc] doc. @@ -32,6 +33,7 @@ To learn about the project directory structure, see [Kubebuilder project layout] `operator-sdk init` generates a `go.mod` file to be used with [Go modules][go_mod_wiki]. The `--repo=` flag is required when creating a project outside of `$GOPATH/src`, as scaffolded files require a valid module path. Ensure you [activate module support][activate_modules] by running `export GO111MODULE=on` before using the SDK. ### Manager + The main program for the operator `main.go` initializes and runs the [Manager][manager_go_doc]. See the [Kubebuilder entrypoint doc][kubebuilder_entrypoint_doc] for more details on how the manager registers the Scheme for the custom resource API defintions, and sets up and runs controllers and webhooks. @@ -61,7 +63,7 @@ Read the [operator scope][operator_scope] documentation on how to run your opera ### Multi-Group APIs -Before creating an API and controller, consider if your operator requires multiple API [groups][api-groups]. Then to change the layout of your project to support multi-group run the command `operator-sdk edit --multigroup=true`. It will update the `PROJECT` file which should look like the following: +Before creating an API and controller, consider if your operator requires multiple API [groups][api-groups]. Then to change the layout of your project to support multi-group run the command `operator-sdk edit --multigroup`. It will update the `PROJECT` file which should look like the following: ```YAML domain: example.com @@ -79,11 +81,7 @@ Create a new Custom Resource Definition(CRD) API with group `cache` version `v1a When prompted, enter yes `y` for creating both the resource and controller. ```console -$ operator-sdk create api --group=cache --version=v1alpha1 --kind=Memcached -Create Resource [y/n] -y -Create Controller [y/n] -y +$ operator-sdk create api --group cache --version v1alpha1 --kind Memcached --resource --controller Writing scaffold for you to edit... api/v1alpha1/memcached_types.go controllers/memcached_controller.go @@ -132,7 +130,7 @@ type Memcached struct { After modifying the `*_types.go` file always run the following command to update the generated code for that resource type: ```sh -$ make generate +make generate ``` The above makefile target will invoke the [controller-gen][controller_tools] utility to update the `api/v1alpha1/zz_generated.deepcopy.go` file to ensure our API's Go type definitons implement the `runtime.Object` interface that all Kind types must implement. @@ -141,8 +139,8 @@ The above makefile target will invoke the [controller-gen][controller_tools] uti Once the API is defined with spec/status fields and CRD validation markers, the CRD manifests can be generated and updated with the following command: -```console -$ make manifests +```sh +make manifests ``` This makefile target will invoke controller-gen to generate the CRD manifests at `config/crd/bases/cache.example.com_memcacheds.yaml`. @@ -166,7 +164,7 @@ The example controller executes the following reconciliation logic for each Memc - Ensure that the Deployment size is the same as specified by the Memcached CR spec - Update the Memcached CR status using the status writer with the names of the memcached pods -The next two subsections explain how the controller watches resources and how the reconcile loop is triggered. Skip to the [Build](#build-and-run-the-operator) section to see how to build and run the operator. +The next two subsections explain how the controller watches resources and how the reconcile loop is triggered. Skip to the ["run the Operator"](#run-the-operator) section to see how to build and run the operator. #### Resources watched by the Controller @@ -199,15 +197,13 @@ There are a number of other useful configurations that can be made when initialz - Set the max number of concurrent Reconciles for the controller via the [`MaxConcurrentReconciles`][controller_options] option. Defaults to 1. ```Go - func (r *MemcachedReconciler) SetupWithManager(mgr ctrl.Manager) error { - return ctrl.NewControllerManagedBy(mgr). - For(&cachev1alpha1.Memcached{}). - Owns(&appsv1.Deployment{}). - WithOptions(controller.Options{ - MaxConcurrentReconciles: 2, - }). - Complete(r) - } + func (r *MemcachedReconciler) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr). + For(&cachev1alpha1.Memcached{}). + Owns(&appsv1.Deployment{}). + WithOptions(controller.Options{MaxConcurrentReconciles: 2}). + Complete(r) + } ``` - Filter watch events using [predicates][event_filtering] - Choose the type of [EventHandler][event_handler_godocs] to change how a watch event will translate to reconcile requests for the reconcile loop. For operator relationships that are more complex than primary and secondary resources, the [`EnqueueRequestsFromMapFunc`][enqueue_requests_from_map_func] handler can be used to transform a watch event into an arbitrary set of reconcile requests. @@ -275,34 +271,23 @@ func (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) ( The `ClusterRole` manifest at `config/rbac/role.yaml` is generated from the above markers via controller-gen with the following command: ```sh -$ make manifests +make manifests ``` -## Build and run the operator - -Before running the operator, the CRD must be registered with the Kubernetes apiserver: +## Run the Operator -```sh -$ make install -``` - -Once this is done, there are two ways to run the operator: +There are three ways to run the operator: - As Go program outside a cluster - As a Deployment inside a Kubernetes cluster - -## Configuring your test environment - -Projects are scaffolded with unit tests that utilize the [envtest](https://godoc.org/sigs.k8s.io/controller-runtime/pkg/envtest) -library, which requires certain Kubernetes server binaries be present locally. -Installation instructions can be found [here][env-test-setup]. +- Managed by the [Operator Lifecycle Manager (OLM)][doc-olm] in [bundle][quickstart-bundle] format ### 1. Run locally outside the cluster -To run the operator locally execute the following command: +Execute the following command, which install your CRDs and run the manager locally: ```sh -$ make run ENABLE_WEBHOOKS=false +make install run ENABLE_WEBHOOKS=false ``` ### 2. Run as a Deployment inside the cluster @@ -319,21 +304,15 @@ Make sure to modify the `IMG` arg in the example below to reference a container you have access to. You can obtain an account for storing containers at repository sites such quay.io or hub.docker.com. This example uses quay. -Build the image: -```sh -$ export USERNAME= - -$ make docker-build IMG=quay.io/$USERNAME/memcached-operator:v0.0.1 -``` - -Push the image to a repository: +Build and push the image: ```sh -$ make docker-push IMG=quay.io/$USERNAME/memcached-operator:v0.0.1 +export USERNAME= +make docker-build docker-push IMG=quay.io/$USERNAME/memcached-operator:v0.0.1 ``` -**Note**: -The name and tag of the image (`IMG=/:tag`) in both the commands can also be set in the Makefile. Modify the line which has `IMG ?= controller:latest` to set your desired default image name. +**Note**: The name and tag of the image (`IMG=/:tag`) in both the commands can also be set in the Makefile. +Modify the line which has `IMG ?= controller:latest` to set your desired default image name. #### Deploy the operator @@ -342,7 +321,7 @@ By default, a new namespace is created with name `-system`, i.e. m Run the following to deploy the operator. This will also install the RBAC manifests from `config/rbac`. ```sh -$ make deploy IMG=quay.io/$USERNAME/memcached-operator:v0.0.1 +make deploy IMG=quay.io/$USERNAME/memcached-operator:v0.0.1 ``` *NOTE* If you have enabled webhooks in your deployments, you will need to have cert-manager already installed @@ -356,9 +335,32 @@ NAME READY UP-TO-DATE AVAILABLE AGE memcached-operator-controller-manager 1/1 1 1 8m ``` -### 3. Deploy your Operator with the Operator Lifecycle Manager (OLM) +### 3. Deploy your Operator with OLM + +First, install [OLM][doc-olm]: + +```sh +operator-sdk olm install +``` + +Then bundle your operator and push the bundle image: + +```sh +make bundle IMG=$OPERATOR_IMG +# Note the "-bundle" component in the image name below. +export BUNDLE_IMG="quay.io/$USERNAME/memcached-operator-bundle:v0.0.1" +make bundle-build BUNDLE_IMG=$BUNDLE_IMG +make docker-push IMG=$BUNDLE_IMG +``` + +Finally, run your bundle: + +```sh +operator-sdk run bundle $BUNDLE_IMG +``` + +Check out the [docs][quickstart-bundle] for a deep dive into `operator-sdk`'s OLM integration. -OLM will manage creation of most if not all resources required to run your operator, using a bit of setup from other `operator-sdk` commands. Check out the [docs][cli-run-olm] for more information. ## Create a Memcached CR @@ -376,7 +378,7 @@ spec: Create the CR: ```sh -$ kubectl apply -f config/samples/cache_v1alpha1_memcached.yaml +kubectl apply -f config/samples/cache_v1alpha1_memcached.yaml ``` Ensure that the memcached operator creates the deployment for the sample CR with the correct size: @@ -425,7 +427,7 @@ status: Update `config/samples/cache_v1alpha1_memcached.yaml` to change the `spec.size` field in the Memcached CR from 3 to 5: ```sh -$ kubectl patch memcached memcached-sample -p '{"spec":{"size": 5}}' --type=merge +kubectl patch memcached memcached-sample -p '{"spec":{"size": 5}}' --type=merge ``` Confirm that the operator changes the deployment size: @@ -439,18 +441,10 @@ memcached-sample 5/5 5 5 3m ### Cleanup -A new target can be added into the Makefile for cleaning up the resources that have been created along this tutorial: - -```make -# Undeploy controller from the configured Kubernetes cluster -undeploy: - $(KUSTOMIZE) build config/default | kubectl delete -f - -``` - -Once that's done the simple command below will delete all the resources: +Call the following to delete all deployed resources: ```sh -$ make undeploy +make undeploy ``` ## Further steps @@ -461,6 +455,9 @@ The following guides build off the operator created in this example, adding adva Also see the [advanced topics][advanced_topics] doc for more use cases and under the hood details. + +[legacy-quickstart-doc]:https://v0-19-x.sdk.operatorframework.io/docs/golang/legacy/quickstart/ +[migration-guide]:/docs/building-operators/golang/migration [install-guide]:/docs/building-operators/golang/installation [enqueue_requests_from_map_func]: https://godoc.org/sigs.k8s.io/controller-runtime/pkg/handler#EnqueueRequestsFromMapFunc [event_handler_godocs]: https://godoc.org/sigs.k8s.io/controller-runtime/pkg/handler#hdr-EventHandlers @@ -475,7 +472,6 @@ Also see the [advanced topics][advanced_topics] doc for more use cases and under [request-go-doc]: https://godoc.org/github.com/kubernetes-sigs/controller-runtime/pkg/reconcile#Request [result_go_doc]: https://godoc.org/github.com/kubernetes-sigs/controller-runtime/pkg/reconcile#Result [multi-namespaced-cache-builder]: https://godoc.org/github.com/kubernetes-sigs/controller-runtime/pkg/cache#MultiNamespacedCacheBuilder -[cli-run-olm]: /docs/olm-integration/cli-overview [kubebuilder_entrypoint_doc]: https://book.kubebuilder.io/cronjob-tutorial/empty-main.html [api_terms_doc]: https://book.kubebuilder.io/cronjob-tutorial/gvks.html [kb_controller_doc]: https://book.kubebuilder.io/cronjob-tutorial/controller-overview.html @@ -487,13 +483,13 @@ Also see the [advanced topics][advanced_topics] doc for more use cases and under [crd-markers]: https://book.kubebuilder.io/reference/markers/crd-validation.html [memcached_controller]: https://github.com/operator-framework/operator-sdk/blob/v1.2.0/testdata/go/memcached-operator/controllers/memcached_controller.go [builder_godocs]: https://godoc.org/github.com/kubernetes-sigs/controller-runtime/pkg/builder#example-Builder -[legacy_quickstart_doc]:https://v0-19-x.sdk.operatorframework.io/docs/golang/legacy/quickstart/ [activate_modules]: https://github.com/golang/go/wiki/Modules#how-to-install-and-activate-module-support [advanced_topics]: /docs/building-operators/golang/advanced-topics/ [create_a_webhook]: https://book.kubebuilder.io/cronjob-tutorial/webhook-implementation.html [status_marker]: https://book.kubebuilder.io/reference/generating-crd.html#status [status_subresource]: https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#status-subresource -[legacy_CLI]:https://v0-19-x.sdk.operatorframework.io/docs/cli/ [env-test-setup]: /docs/building-operators/golang/references/envtest-setup [role-based-access-control]: https://cloud.google.com/kubernetes-engine/docs/how-to/role-based-access-control#iam-rolebinding-bootstrap [multigroup-kubebuilder-doc]: https://book.kubebuilder.io/migration/multi-group.html +[quickstart-bundle]:/docs/olm-integration/quickstart-bundle +[doc-olm]:/docs/olm-integration/quickstart-bundle/#enabling-olm diff --git a/website/content/en/docs/building-operators/helm/migration.md b/website/content/en/docs/building-operators/helm/migration.md index de27a3ddc2f..fdefacfa2cf 100644 --- a/website/content/en/docs/building-operators/helm/migration.md +++ b/website/content/en/docs/building-operators/helm/migration.md @@ -96,7 +96,12 @@ In your new project, roles are automatically generated in `config/rbac/role.yaml If you modified these permissions manually in `deploy/role.yaml` in your existing project, you need to re-apply them in `config/rbac/role.yaml`. -New projects are configured to watch all namespaces by default, so they need a `ClusterRole` to have the necessary permissions. Ensure that `config/rbac/role.yaml` remains a `ClusterRole` if you want to retain the default behavior of the new project conventions. For further information refer to the [operator scope][operator-scope] documentation. +New projects are configured to watch all namespaces by default, so they need a `ClusterRole` to have the necessary permissions. Ensure that `config/rbac/role.yaml` remains a `ClusterRole` if you want to retain the default behavior of the new project conventions. + + The following rules were used in earlier versions of helm-operator to automatically create and manage services and servicemonitors for metrics collection. If your operator's charts don't require these rules, they can safely be left out of the new `config/rbac/role.yaml` file: @@ -137,11 +142,11 @@ The default port used by the metric endpoint binds to was changed from `:8383` t ## Checking the changes -Finally, follow the steps in the section [Build and run the operator][build-and-run-the-operator] to verify your project is running. +Finally, follow the steps in the ["run the Operator"][run-the-operator] section to verify your project is running. [quickstart]: /docs/building-operators/helm/quickstart [integration-doc]: https://github.com/kubernetes-sigs/kubebuilder/blob/master/designs/integrating-kubebuilder-and-osdk.md -[build-and-run-the-operator]: /docs/building-operators/helm/tutorial#build-and-run-the-operator +[run-the-operator]: /docs/building-operators/helm/tutorial#run-the-operator [kustomize]: https://github.com/kubernetes-sigs/kustomize [kube-auth-proxy]: https://github.com/brancz/kube-rbac-proxy [metrics]: https://book.kubebuilder.io/reference/metrics.html?highlight=metr#metrics diff --git a/website/content/en/docs/building-operators/helm/tutorial.md b/website/content/en/docs/building-operators/helm/tutorial.md index 52d523cd122..472953f80e2 100644 --- a/website/content/en/docs/building-operators/helm/tutorial.md +++ b/website/content/en/docs/building-operators/helm/tutorial.md @@ -1,13 +1,12 @@ --- -title: Tutorial for Helm-based Operators +title: Helm Operator Tutorial linkTitle: Tutorial weight: 200 -description: An in-depth walkthough that demonstrates how to build and run a Helm-based operator. +description: An in-depth walkthough of building and running a Helm-based operator. --- -## Overview - -This guide walks through an example of building a simple nginx-operator powered by [Helm][helm-official] using tools and libraries provided by the Operator SDK. +**NOTE:** If your project was created with an `operator-sdk` version prior to `v1.0.0` +please [migrate][migration-guide], or consult the [legacy docs][legacy-quickstart-doc]. ## Prerequisites @@ -21,11 +20,11 @@ Use the CLI to create a new Helm-based nginx-operator project: ```sh mkdir nginx-operator cd nginx-operator -operator-sdk init --plugins=helm --domain=com --group=example --version=v1alpha1 --kind=Nginx +operator-sdk init --plugins helm --domain example.com --group demo --version v1alpha1 --kind Nginx ``` This creates the nginx-operator project specifically for watching the -Nginx resource with APIVersion `example.com/v1alpha1` and Kind +Nginx resource with APIVersion `demo.example.com/v1alpha1` and Kind `Nginx`. For Helm-based projects, `operator-sdk init` also generates the RBAC rules @@ -70,11 +69,12 @@ If a custom repository URL is specified by `--helm-chart-repo`, the only support If `--helm-chart-version` is not set, the SDK will fetch the latest available version of the helm chart. Otherwise, it will fetch the specified version. The option `--helm-chart-version` is not used when `--helm-chart` itself refers to a specific version, for example when it is a local path or a URL. -**Note:** For more details and examples run `operator-sdk init --plugins=helm --help`. - -### Operator scope +**Note:** For more details and examples run `operator-sdk init --plugins helm --help`. -Read the [operator scope][operator-scope] documentation on how to run your operator as namespace-scoped vs cluster-scoped. + ## Customize the operator logic @@ -94,7 +94,7 @@ in `watches.yaml` and executes Helm releases using the specified chart: ```yaml # Use the 'create api' subcommand to add watches to this file. -- group: example.com +- group: demo version: v1alpha1 kind: Nginx chart: helm-charts/nginx @@ -127,10 +127,10 @@ value called `replicaCount` and it is set to `1` by default. If we want to have 2 nginx instances in our deployment, we would need to make sure our CR spec contained `replicaCount: 2`. -Update `config/samples/example_v1alpha1_nginx.yaml` to look like the following: +Update `config/samples/demo_v1alpha1_nginx.yaml` to look like the following: ```yaml -apiVersion: example.com/v1alpha1 +apiVersion: demo.example.com/v1alpha1 kind: Nginx metadata: name: nginx-sample @@ -139,11 +139,11 @@ spec: ``` Similarly, we see that the default service port is set to `80`, but we would -like to use `8080`, so we'll again update `config/samples/example_v1alpha1_nginx.yaml` +like to use `8080`, so we'll again update `config/samples/demo_v1alpha1_nginx.yaml` by adding the service port override: ```yaml -apiVersion: example.com/v1alpha1 +apiVersion: demo.example.com/v1alpha1 kind: Nginx metadata: name: nginx-sample @@ -157,68 +157,87 @@ As you may have noticed, the Helm operator simply applies the entire spec as if it was the contents of a values file, just like `helm install -f ./overrides.yaml` works. -## Build and run the operator +## Run the operator -Before running the operator, Kubernetes needs to know about the new custom -resource definition the operator will be watching. +There are three ways to run the operator: -Deploy the CRD: +- As Go program outside a cluster +- As a Deployment inside a Kubernetes cluster +- Managed by the [Operator Lifecycle Manager (OLM)][doc-olm] in [bundle][quickstart-bundle] format -```sh -make install -``` +### 1. Run locally outside the cluster -Once this is done, there are two ways to run the operator: +Execute the following command, which install your CRDs and run the manager locally: -- As a pod inside a Kubernetes cluster -- As a go program outside the cluster using `operator-sdk` +```sh +make install run +``` -### 1. Run as a pod inside a Kubernetes cluster +### 2. Run as a Deployment inside the cluster -Running as a pod inside a Kubernetes cluster is preferred for production use. +#### Build and push the image -Build the nginx-operator image and push it to a registry: +Build and push the image: ```sh -export IMG=quay.io/example/nginx-operator:v0.0.1 -make docker-build docker-push IMG=$IMG +export USERNAME= +make docker-build docker-push IMG=quay.io/$USERNAME/nginx-operator:v0.0.1 ``` -**Note:** Kubernetes deployment manifests are generated in `config/manager/manager.yaml`. +**Note**: The name and tag of the image (`IMG=/:tag`) in both the commands can also be set in the Makefile. +Modify the line which has `IMG ?= controller:latest` to set your desired default image name. + +#### Deploy the operator -Deploy the nginx-operator: +By default, a new namespace is created with name `-system`, i.e. nginx-operator-system and will be used for the deployment. + +Run the following to deploy the operator. This will also install the RBAC manifests from `config/rbac`. ```sh -make deploy IMG=$IMG +make deploy IMG=quay.io/$USERNAME/nginx-operator:v0.0.1 ``` Verify that the nginx-operator is up and running: ```console $ kubectl get deployment -n nginx-operator-system -NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE -nginx-operator-controller-manager 1/1 1 1 1 77s +NAME READY UP-TO-DATE AVAILABLE AGE +nginx-operator-controller-manager 1/1 1 1 8m ``` -### 2. Run outside the cluster +### 3. Deploy your Operator with OLM -This method is preferred during the development cycle to speed up deployment and testing. +First, install [OLM][doc-olm]: -Run the operator locally with the default Kubernetes config file present at -`$HOME/.kube/config` via the Makefile target `make run`. +```sh +operator-sdk olm install +``` -### 3. Deploy your Operator with the Operator Lifecycle Manager (OLM) +Then bundle your operator and push the bundle image: + +```sh +make bundle IMG=$OPERATOR_IMG +# Note the "-bundle" component in the image name below. +export BUNDLE_IMG="quay.io/$USERNAME/nginx-operator-bundle:v0.0.1" +make bundle-build BUNDLE_IMG=$BUNDLE_IMG +make docker-push IMG=$BUNDLE_IMG +``` + +Finally, run your bundle: + +```sh +operator-sdk run bundle $BUNDLE_IMG +``` + +Check out the [docs][quickstart-bundle] for a deep dive into `operator-sdk`'s OLM integration. -OLM will manage creation of most if not all resources required to run your operator, -using a bit of setup from other `operator-sdk` commands. Check out the OLM integration -[user guide][quickstart-bundle] for more information. ## Deploy the Nginx custom resource Apply the nginx CR that we modified earlier: ```sh -kubectl apply -f config/samples/example_v1alpha1_nginx.yaml +kubectl apply -f config/samples/demo_v1alpha1_nginx.yaml ``` Ensure that the nginx-operator creates the deployment for the CR: @@ -252,8 +271,8 @@ Change the `spec.replicaCount` field from 2 to 3, remove the `spec.service` field: ```console -$ cat config/samples/example_v1alpha1_nginx.yaml -apiVersion: example.com/v1alpha1 +$ cat config/samples/demo_v1alpha1_nginx.yaml +apiVersion: demo.example.com/v1alpha1 kind: Nginx metadata: name: nginx-sample @@ -264,7 +283,7 @@ spec: And apply the change: ```sh -kubectl apply -f config/samples/example_v1alpha1_nginx.yaml +kubectl apply -f config/samples/demo_v1alpha1_nginx.yaml ``` Confirm that the operator changes the deployment size: @@ -294,7 +313,7 @@ kubectl logs deployment.apps/nginx-operator-controller-manager -n nginx-operato Use the following command to check the CR status and events. ```sh -kubectl describe nginxes.example.com +kubectl describe nginxes.demo.example.com ``` ### Cleanup @@ -302,17 +321,17 @@ kubectl describe nginxes.example.com Clean up the resources: ```sh -kubectl delete -f config/samples/example_v1alpha1_nginx.yaml +kubectl delete -f config/samples/demo_v1alpha1_nginx.yaml make undeploy ``` -**NOTE** Additional CR/CRD's can be added to the project by running, for example, the command :`operator-sdk create api --group=example --version=v1alpha1 --kind=AppService` - + +[legacy-quickstart-doc]:https://v0-19-x.sdk.operatorframework.io/docs/helm/quickstart/ +[migration-guide]:/docs/building-operators/helm/migration [install-guide]:/docs/building-operators/helm/installation -[operator-scope]: /docs/building-operators/golang/operator-scope [layout-doc]: /docs/building-operators/helm/reference/project_layout/ [helm-charts]:https://helm.sh/docs/topics/charts/ [helm-values]:https://helm.sh/docs/intro/using_helm/#customizing-the-chart-before-installing [helm-official]:https://helm.sh/docs/ +[quickstart-bundle]:/docs/olm-integration/quickstart-bundle +[doc-olm]:/docs/olm-integration/quickstart-bundle/#enabling-olm diff --git a/website/content/en/docs/cli/operator-sdk_generate_bundle.md b/website/content/en/docs/cli/operator-sdk_generate_bundle.md index 2d0b3bc6795..8a0fe806744 100644 --- a/website/content/en/docs/cli/operator-sdk_generate_bundle.md +++ b/website/content/en/docs/cli/operator-sdk_generate_bundle.md @@ -32,7 +32,7 @@ operator-sdk generate bundle [flags] # Generate bundle files and build your bundle image with these 'make' recipes: $ make bundle - $ export USERNAME= + $ export USERNAME= $ export BUNDLE_IMG=quay.io/$USERNAME/memcached-operator-bundle:v0.0.1 $ make bundle-build BUNDLE_IMG=$BUNDLE_IMG From e29d24757ce52400349b5b912498e0f13d1e104e Mon Sep 17 00:00:00 2001 From: Camila Macedo Date: Fri, 18 Dec 2020 16:34:43 +0000 Subject: [PATCH 255/376] For Ansible/Helm-based operators, add Liveness and Readiness probe (#4326) **Description of the change:** - Add the probes for Helm/Ansible by default as it was done for Golang go/v3 in upstream. - For Ansible/Helm-based operators, added new flag `--health-probe-bind-address` to allow customize the probe port used. - For Ansible-based operators, deprecated the ping endpoint **Motivation for the change:** - https://github.com/operator-framework/operator-sdk/issues/1234 Signed-off-by: reinvantveer --- ...liveness_readiness_probe_for_operator.yaml | 91 +++++++++++++++++++ internal/ansible/flags/flag.go | 9 ++ internal/cmd/ansible-operator/run/cmd.go | 18 ++-- internal/cmd/helm-operator/run/cmd.go | 11 +++ internal/helm/flags/flag.go | 6 ++ .../templates/config/manager/manager.go | 12 +++ .../templates/config/manager/manager.go | 12 +++ ...cached-operator.clusterserviceversion.yaml | 12 +++ .../config/manager/manager.yaml | 12 +++ ...cached-operator.clusterserviceversion.yaml | 12 +++ .../config/manager/manager.yaml | 12 +++ 11 files changed, 201 insertions(+), 6 deletions(-) create mode 100644 changelog/fragments/liveness_readiness_probe_for_operator.yaml diff --git a/changelog/fragments/liveness_readiness_probe_for_operator.yaml b/changelog/fragments/liveness_readiness_probe_for_operator.yaml new file mode 100644 index 00000000000..dfe7df56210 --- /dev/null +++ b/changelog/fragments/liveness_readiness_probe_for_operator.yaml @@ -0,0 +1,91 @@ +# entries is a list of entries to include in +# release notes and/or the migration guide +entries: + - description: > + For Helm-based operators, added Liveness and Readiness probe by default using [`healthz.Ping`](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/healthz#CheckHandler). + + # kind is one of: + # - addition + # - change + # - deprecation + # - removal + # - bugfix + kind: "addition" + + # Is this a breaking change? + breaking: false + + # Migration can be defined to automatically add a section to + # the migration guide. This is required for breaking changes. + migration: + header: (Optional) For Helm-based operators, add Liveness and Readiness probe + body: > + New projects built with the tool will have the probes configured by default. The endpoints `/healthz` and + `/readyz` are available now in the image based provided. + + You can update your pre-existing project to use them. For that update the Dockerfile to use the latest + release base image, then add the following to the `manager` container in + `config/default/manager/manager.yaml`: + + ```yaml + livenessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 15 + periodSeconds: 20 + readinessProbe: + httpGet: + path: /readyz + port: 8081 + initialDelaySeconds: 5 + periodSeconds: 10 + ``` + - description: > + For Ansible-based operators, added Liveness and Readiness probe by default using [`healthz.Ping`](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/healthz#CheckHandler). + + # kind is one of: + # - addition + # - change + # - deprecation + # - removal + # - bugfix + kind: "addition" + + # Is this a breaking change? + breaking: false + + # Migration can be defined to automatically add a section to + # the migration guide. This is required for breaking changes. + migration: + header: (Optional) For Ansible-based operators, add Liveness and Readiness probe + body: > + New projects built with the tool will have the probes configured by default. The endpoints `/healthz` and + `/readyz` are available now in the image based provided. + + You can update your pre-existing project to use them. For that update the Dockerfile to use the latest + release base image, then add the following to the `manager` container in + `config/default/manager/manager.yaml`: + + ```yaml + livenessProbe: + httpGet: + path: /healthz + port: 6789 + initialDelaySeconds: 15 + periodSeconds: 20 + readinessProbe: + httpGet: + path: /readyz + port: 6789 + initialDelaySeconds: 5 + periodSeconds: 10 + ``` + - description: > + For Ansible-based operators, the `/ping` endpoint is deprecated. Use `/healthz` instead. + kind: "deprecation" + breaking: false + + - description: > + For Ansible/Helm-based operators, added new flag `--health-probe-bind-address` to set the health probe address. + kind: "addition" diff --git a/internal/ansible/flags/flag.go b/internal/ansible/flags/flag.go index 8e8168d78a6..3fb6cd644e2 100644 --- a/internal/ansible/flags/flag.go +++ b/internal/ansible/flags/flag.go @@ -32,6 +32,7 @@ type Flags struct { AnsibleRolesPath string AnsibleCollectionsPath string MetricsAddress string + ProbeAddr string LeaderElectionID string LeaderElectionNamespace string AnsibleArgs string @@ -82,6 +83,14 @@ func (f *Flags) AddTo(flagSet *pflag.FlagSet) { ":8080", "The address the metric endpoint binds to", ) + // todo: for Go/Helm the port used is: 8081 + // update it to keep the project aligned to the other + // types for 2.0 + flagSet.StringVar(&f.ProbeAddr, + "health-probe-bind-address", + ":6789", + "The address the probe endpoint binds to.", + ) flagSet.BoolVar(&f.EnableLeaderElection, "enable-leader-election", false, diff --git a/internal/cmd/ansible-operator/run/cmd.go b/internal/cmd/ansible-operator/run/cmd.go index fe3764c5a3e..d09fa3ba065 100644 --- a/internal/cmd/ansible-operator/run/cmd.go +++ b/internal/cmd/ansible-operator/run/cmd.go @@ -45,11 +45,7 @@ import ( sdkVersion "github.com/operator-framework/operator-sdk/internal/version" ) -var ( - metricsHost = "0.0.0.0" - log = logf.Log.WithName("cmd") - healthProbePort int32 = 6789 -) +var log = logf.Log.WithName("cmd") func printVersion() { log.Info("Version", @@ -105,8 +101,8 @@ func run(cmd *cobra.Command, f *flags.Flags) { // Set default manager options // TODO: probably should expose the host & port as an environment variables options := manager.Options{ - HealthProbeBindAddress: fmt.Sprintf("%s:%d", metricsHost, healthProbePort), MetricsBindAddress: f.MetricsAddress, + HealthProbeBindAddress: f.ProbeAddr, LeaderElection: f.EnableLeaderElection, LeaderElectionID: f.LeaderElectionID, LeaderElectionResourceLock: resourcelock.ConfigMapsResourceLock, @@ -148,6 +144,15 @@ func run(cmd *cobra.Command, f *flags.Flags) { os.Exit(1) } + if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { + log.Error(err, "Unable to set up health check") + os.Exit(1) + } + if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil { + log.Error(err, "Unable to set up ready check") + os.Exit(1) + } + cMap := controllermap.NewControllerMap() watches, err := watches.Load(f.WatchesFile, f.MaxConcurrentReconciles, f.AnsibleVerbosity) if err != nil { @@ -183,6 +188,7 @@ func run(cmd *cobra.Command, f *flags.Flags) { }, w.Blacklist) } + // todo: remove when a upper version be bumped err = mgr.AddHealthzCheck("ping", healthz.Ping) if err != nil { log.Error(err, "Failed to add Healthz check.") diff --git a/internal/cmd/helm-operator/run/cmd.go b/internal/cmd/helm-operator/run/cmd.go index 195d4a9f9c1..b10bf950c0e 100644 --- a/internal/cmd/helm-operator/run/cmd.go +++ b/internal/cmd/helm-operator/run/cmd.go @@ -26,6 +26,7 @@ import ( "k8s.io/client-go/tools/leaderelection/resourcelock" "sigs.k8s.io/controller-runtime/pkg/cache" "sigs.k8s.io/controller-runtime/pkg/client/config" + "sigs.k8s.io/controller-runtime/pkg/healthz" logf "sigs.k8s.io/controller-runtime/pkg/log" zapf "sigs.k8s.io/controller-runtime/pkg/log/zap" "sigs.k8s.io/controller-runtime/pkg/manager" @@ -96,6 +97,7 @@ func run(cmd *cobra.Command, f *flags.Flags) { // Set default manager options options := manager.Options{ MetricsBindAddress: f.MetricsAddress, + HealthProbeBindAddress: f.ProbeAddr, LeaderElection: f.EnableLeaderElection, LeaderElectionID: f.LeaderElectionID, LeaderElectionResourceLock: resourcelock.ConfigMapsResourceLock, @@ -130,6 +132,15 @@ func run(cmd *cobra.Command, f *flags.Flags) { os.Exit(1) } + if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { + log.Error(err, "Unable to set up health check") + os.Exit(1) + } + if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil { + log.Error(err, "Unable to set up ready check") + os.Exit(1) + } + ws, err := watches.Load(f.WatchesFile) if err != nil { log.Error(err, "Failed to create new manager factories.") diff --git a/internal/helm/flags/flag.go b/internal/helm/flags/flag.go index e272a8b4bff..2b2750c7357 100644 --- a/internal/helm/flags/flag.go +++ b/internal/helm/flags/flag.go @@ -30,6 +30,7 @@ type Flags struct { LeaderElectionID string LeaderElectionNamespace string MaxConcurrentReconciles int + ProbeAddr string } // AddTo - Add the helm operator flags to the the flagset @@ -49,6 +50,11 @@ func (f *Flags) AddTo(flagSet *pflag.FlagSet) { ":8080", "The address the metric endpoint binds to", ) + flagSet.StringVar(&f.ProbeAddr, + "health-probe-bind-address", + ":8081", + "The address the probe endpoint binds to.", + ) flagSet.BoolVar(&f.EnableLeaderElection, "enable-leader-election", false, diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/manager/manager.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/manager/manager.go index 9a076261186..463ded8493a 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/manager/manager.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/manager/manager.go @@ -78,5 +78,17 @@ spec: - name: ANSIBLE_GATHERING value: explicit image: {{ .Image }} + livenessProbe: + httpGet: + path: /readyz + port: 6789 + initialDelaySeconds: 15 + periodSeconds: 20 + readinessProbe: + httpGet: + path: /healthz + port: 6789 + initialDelaySeconds: 5 + periodSeconds: 10 terminationGracePeriodSeconds: 10 ` diff --git a/internal/plugins/helm/v1/scaffolds/internal/templates/config/manager/manager.go b/internal/plugins/helm/v1/scaffolds/internal/templates/config/manager/manager.go index 6568b0467fc..beb54f70ee0 100644 --- a/internal/plugins/helm/v1/scaffolds/internal/templates/config/manager/manager.go +++ b/internal/plugins/helm/v1/scaffolds/internal/templates/config/manager/manager.go @@ -75,6 +75,18 @@ spec: - "--enable-leader-election" - "--leader-election-id={{ .ProjectName }}" name: manager + livenessProbe: + httpGet: + path: /readyz + port: 8081 + initialDelaySeconds: 15 + periodSeconds: 20 + readinessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 5 + periodSeconds: 10 resources: limits: cpu: 100m diff --git a/testdata/ansible/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml b/testdata/ansible/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml index 43f07252740..8fefea49050 100644 --- a/testdata/ansible/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml +++ b/testdata/ansible/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml @@ -124,7 +124,19 @@ spec: - name: ANSIBLE_GATHERING value: explicit image: quay.io/example/memcached-operator:v0.0.1 + livenessProbe: + httpGet: + path: /readyz + port: 6789 + initialDelaySeconds: 15 + periodSeconds: 20 name: manager + readinessProbe: + httpGet: + path: /healthz + port: 6789 + initialDelaySeconds: 5 + periodSeconds: 10 resources: {} terminationGracePeriodSeconds: 10 permissions: diff --git a/testdata/ansible/memcached-operator/config/manager/manager.yaml b/testdata/ansible/memcached-operator/config/manager/manager.yaml index 0141d1e514e..d39460e3688 100644 --- a/testdata/ansible/memcached-operator/config/manager/manager.yaml +++ b/testdata/ansible/memcached-operator/config/manager/manager.yaml @@ -31,4 +31,16 @@ spec: - name: ANSIBLE_GATHERING value: explicit image: controller:latest + livenessProbe: + httpGet: + path: /readyz + port: 6789 + initialDelaySeconds: 15 + periodSeconds: 20 + readinessProbe: + httpGet: + path: /healthz + port: 6789 + initialDelaySeconds: 5 + periodSeconds: 10 terminationGracePeriodSeconds: 10 diff --git a/testdata/helm/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml b/testdata/helm/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml index eba15872125..3cd62bf7e7f 100644 --- a/testdata/helm/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml +++ b/testdata/helm/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml @@ -209,7 +209,19 @@ spec: - --enable-leader-election - --leader-election-id=memcached-operator image: quay.io/example/memcached-operator:v0.0.1 + livenessProbe: + httpGet: + path: /readyz + port: 8081 + initialDelaySeconds: 15 + periodSeconds: 20 name: manager + readinessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 5 + periodSeconds: 10 resources: limits: cpu: 100m diff --git a/testdata/helm/memcached-operator/config/manager/manager.yaml b/testdata/helm/memcached-operator/config/manager/manager.yaml index 26a86eadc53..72d3a0cefaf 100644 --- a/testdata/helm/memcached-operator/config/manager/manager.yaml +++ b/testdata/helm/memcached-operator/config/manager/manager.yaml @@ -28,6 +28,18 @@ spec: - "--enable-leader-election" - "--leader-election-id=memcached-operator" name: manager + livenessProbe: + httpGet: + path: /readyz + port: 8081 + initialDelaySeconds: 15 + periodSeconds: 20 + readinessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 5 + periodSeconds: 10 resources: limits: cpu: 100m From 77c38f87f0e0e449eab5f023f9c4ba6808d2bff5 Mon Sep 17 00:00:00 2001 From: Camila Macedo Date: Fri, 18 Dec 2020 16:35:17 +0000 Subject: [PATCH 256/376] helm/samples: customize config/sample to allow it runs in OCP with default config (#4340) **Description** Disable `securityContext` config for Helm sample **Motivation** Allow sample runs in OCP without: ``` Warning FailedCreate 2m (x18 over 10m) statefulset-controller create Pod memcached-sample-0 in StatefulSet memcached-sample failed error: pods "memcached-sample-0" is forbidden: unable to validate against any security context constraint: [provider restricted: .spec.securityContext.fsGroup: Invalid value: []int64{1001}: 1001 is not an allowed group spec.containers[0].securityContext.runAsUser: Invalid value: 1001: must be in the ranges: [1000630000, 1000639999]] ``` - Make easier the downstream process by addressing the same fix done in https://github.com/openshift/ocp-release-operator-sdk/pull/84/files#diff-62df55fca2d17f047db431766e3962fa139afff08331dedf0863ec9d86dd7011R9 Signed-off-by: reinvantveer --- hack/generate/samples/internal/helm/memcached.go | 5 +++++ .../manifests/memcached-operator.clusterserviceversion.yaml | 2 +- .../config/samples/cache_v1alpha1_memcached.yaml | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/hack/generate/samples/internal/helm/memcached.go b/hack/generate/samples/internal/helm/memcached.go index 92839e35c22..c677c166d31 100644 --- a/hack/generate/samples/internal/helm/memcached.go +++ b/hack/generate/samples/internal/helm/memcached.go @@ -82,6 +82,11 @@ func (mh *MemcachedHelm) Run() { pkg.CheckError("scaffolding apis", err) log.Infof("customizing the sample") + err = testutils.ReplaceInFile( + filepath.Join(mh.ctx.Dir, "config", "samples", "cache_v1alpha1_memcached.yaml"), + "securityContext:\n enabled: true", "securityContext:\n enabled: false") + pkg.CheckError("customizing the sample", err) + log.Infof("enabling prometheus metrics") err = testutils.UncommentCode( filepath.Join(mh.ctx.Dir, "config", "default", "kustomization.yaml"), diff --git a/testdata/helm/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml b/testdata/helm/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml index 3cd62bf7e7f..d458af73a95 100644 --- a/testdata/helm/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml +++ b/testdata/helm/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml @@ -43,7 +43,7 @@ metadata: } }, "securityContext": { - "enabled": true, + "enabled": false, "fsGroup": 1001, "runAsUser": 1001 }, diff --git a/testdata/helm/memcached-operator/config/samples/cache_v1alpha1_memcached.yaml b/testdata/helm/memcached-operator/config/samples/cache_v1alpha1_memcached.yaml index 00f28f96bcb..fa396b02451 100644 --- a/testdata/helm/memcached-operator/config/samples/cache_v1alpha1_memcached.yaml +++ b/testdata/helm/memcached-operator/config/samples/cache_v1alpha1_memcached.yaml @@ -31,7 +31,7 @@ spec: cpu: 50m memory: 64Mi securityContext: - enabled: true + enabled: false fsGroup: 1001 runAsUser: 1001 serviceAnnotations: {} From e31c8e48df014dde2e3ca7cbdf5c497fa05c3598 Mon Sep 17 00:00:00 2001 From: Camila Macedo Date: Fri, 18 Dec 2020 18:59:46 +0000 Subject: [PATCH 257/376] =?UTF-8?q?e2e-tests:=20auto=20generate=20advanced?= =?UTF-8?q?=20molecule=20ansible=20tests=20with=20samples=E2=80=A6=20(#431?= =?UTF-8?q?2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Description** Replace static mock test/ansible by auto-generated mock via samples stack **Motivation for the change:** Ensure that e2e molecule tests are done with the PR changes by automating its generation. Otherwise, we cannot check if a change in the scaffold files could break it. Closes: https://github.com/operator-framework/operator-sdk/issues/4025 **Note**: To check the scenario locally run ` go run ./hack/generate/samples/molecule/generate.go` the advanced-molecule-operator will be generate in the testdata. Then, it can be checked for development purposes. Signed-off-by: reinvantveer --- .gitignore | 1 + Makefile | 1 + .../internal/ansible/advanced_molecule.go | 533 ++++++++++++++++++ .../{molecule.go => memcached_molecule.go} | 0 .../internal/ansible/testdata}/ansible.cfg | 0 .../testdata}/fixture_collection/galaxy.yml | 0 .../roles/dummy/tasks/main.yml | 0 .../testdata}/inventory/group_vars/test.yml | 0 .../ansible/testdata}/inventory/hosts | 0 .../ansible/testdata}/plugins/filter/test.py | 0 .../internal/ansible/testdata}/secret.yml | 0 .../ansible/testdata}/tasks/argstest_test.yml | 0 .../ansible/testdata}/tasks/casetest_test.yml | 0 .../testdata}/tasks/collectiontest_test.yml | 0 .../testdata}/tasks/inventorytest_test.yml | 0 .../tasks/reconciliationtest_test.yml | 0 .../testdata}/tasks/secretstest_test.yml | 0 .../testdata}/tasks/selectortest_test.yml | 0 .../testdata}/tasks/subresourcestest_test.yml | 0 .../internal/ansible/testdata}/watches.yaml | 0 hack/generate/samples/molecule/generate.go | 13 +- hack/tests/e2e-ansible-molecule.sh | 15 +- internal/ansible/OWNERS | 6 - test/ansible/.gitignore | 14 - test/ansible/Dockerfile | 23 - test/ansible/Makefile | 92 --- test/ansible/PROJECT | 24 - .../crd/bases/test.example.com_argstests.yaml | 44 -- .../crd/bases/test.example.com_casetests.yaml | 44 -- .../test.example.com_collectiontests.yaml | 44 -- .../test.example.com_inventorytests.yaml | 44 -- .../test.example.com_reconciliationtests.yaml | 44 -- .../bases/test.example.com_selectortests.yaml | 44 -- .../test.example.com_subresourcestests.yaml | 44 -- test/ansible/config/crd/kustomization.yaml | 12 - .../ansible/config/default/kustomization.yaml | 26 - .../default/manager_auth_proxy_patch.yaml | 27 - .../ansible/config/manager/kustomization.yaml | 2 - test/ansible/config/manager/manager.yaml | 40 -- .../config/prometheus/kustomization.yaml | 2 - test/ansible/config/prometheus/monitor.yaml | 16 - .../config/rbac/argstest_editor_role.yaml | 24 - .../config/rbac/argstest_viewer_role.yaml | 20 - .../rbac/auth_proxy_client_clusterrole.yaml | 7 - test/ansible/config/rbac/auth_proxy_role.yaml | 13 - .../config/rbac/auth_proxy_role_binding.yaml | 12 - .../config/rbac/auth_proxy_service.yaml | 14 - test/ansible/config/rbac/kustomization.yaml | 12 - .../config/rbac/leader_election_role.yaml | 25 - .../rbac/leader_election_role_binding.yaml | 12 - test/ansible/config/rbac/role.yaml | 186 ------ test/ansible/config/rbac/role_binding.yaml | 13 - .../ansible/config/samples/kustomization.yaml | 3 - .../samples/test_v1alpha1_inventorytest.yaml | 8 - .../config/testing/debug_logs_patch.yaml | 14 - .../ansible/config/testing/kustomization.yaml | 24 - .../ansible/config/testing/manager_image.yaml | 12 - .../config/testing/pull_policy/Always.yaml | 12 - .../testing/pull_policy/IfNotPresent.yaml | 12 - .../config/testing/pull_policy/Never.yaml | 12 - test/ansible/molecule/default/converge.yml | 18 - test/ansible/molecule/default/create.yml | 6 - test/ansible/molecule/default/destroy.yml | 24 - test/ansible/molecule/default/kustomize.yml | 15 - test/ansible/molecule/default/molecule.yml | 36 -- test/ansible/molecule/default/prepare.yml | 28 - test/ansible/molecule/default/verify.yml | 58 -- test/ansible/molecule/kind/converge.yml | 31 - test/ansible/molecule/kind/create.yml | 8 - test/ansible/molecule/kind/destroy.yml | 12 - test/ansible/molecule/kind/molecule.yml | 42 -- test/ansible/playbooks/argstest.yml | 20 - test/ansible/playbooks/casetest.yml | 17 - test/ansible/playbooks/inventorytest.yml | 12 - test/ansible/playbooks/reconciliationtest.yml | 50 -- test/ansible/playbooks/selectortest.yml | 16 - test/ansible/playbooks/subresourcestest.yml | 51 -- test/ansible/requirements.yml | 5 - .../roles/inventorytest/tasks/main.yml | 13 - 79 files changed, 553 insertions(+), 1499 deletions(-) create mode 100644 hack/generate/samples/internal/ansible/advanced_molecule.go rename hack/generate/samples/internal/ansible/{molecule.go => memcached_molecule.go} (100%) rename {test/ansible => hack/generate/samples/internal/ansible/testdata}/ansible.cfg (100%) rename {test/ansible => hack/generate/samples/internal/ansible/testdata}/fixture_collection/galaxy.yml (100%) rename {test/ansible => hack/generate/samples/internal/ansible/testdata}/fixture_collection/roles/dummy/tasks/main.yml (100%) rename {test/ansible => hack/generate/samples/internal/ansible/testdata}/inventory/group_vars/test.yml (100%) rename {test/ansible => hack/generate/samples/internal/ansible/testdata}/inventory/hosts (100%) rename {test/ansible => hack/generate/samples/internal/ansible/testdata}/plugins/filter/test.py (100%) rename {test/ansible/playbooks => hack/generate/samples/internal/ansible/testdata}/secret.yml (100%) rename {test/ansible/molecule/default => hack/generate/samples/internal/ansible/testdata}/tasks/argstest_test.yml (100%) rename {test/ansible/molecule/default => hack/generate/samples/internal/ansible/testdata}/tasks/casetest_test.yml (100%) rename {test/ansible/molecule/default => hack/generate/samples/internal/ansible/testdata}/tasks/collectiontest_test.yml (100%) rename {test/ansible/molecule/default => hack/generate/samples/internal/ansible/testdata}/tasks/inventorytest_test.yml (100%) rename {test/ansible/molecule/default => hack/generate/samples/internal/ansible/testdata}/tasks/reconciliationtest_test.yml (100%) rename {test/ansible/molecule/default => hack/generate/samples/internal/ansible/testdata}/tasks/secretstest_test.yml (100%) rename {test/ansible/molecule/default => hack/generate/samples/internal/ansible/testdata}/tasks/selectortest_test.yml (100%) rename {test/ansible/molecule/default => hack/generate/samples/internal/ansible/testdata}/tasks/subresourcestest_test.yml (100%) rename {test/ansible => hack/generate/samples/internal/ansible/testdata}/watches.yaml (100%) delete mode 100644 internal/ansible/OWNERS delete mode 100644 test/ansible/.gitignore delete mode 100644 test/ansible/Dockerfile delete mode 100644 test/ansible/Makefile delete mode 100644 test/ansible/PROJECT delete mode 100644 test/ansible/config/crd/bases/test.example.com_argstests.yaml delete mode 100644 test/ansible/config/crd/bases/test.example.com_casetests.yaml delete mode 100644 test/ansible/config/crd/bases/test.example.com_collectiontests.yaml delete mode 100644 test/ansible/config/crd/bases/test.example.com_inventorytests.yaml delete mode 100644 test/ansible/config/crd/bases/test.example.com_reconciliationtests.yaml delete mode 100644 test/ansible/config/crd/bases/test.example.com_selectortests.yaml delete mode 100644 test/ansible/config/crd/bases/test.example.com_subresourcestests.yaml delete mode 100644 test/ansible/config/crd/kustomization.yaml delete mode 100644 test/ansible/config/default/kustomization.yaml delete mode 100644 test/ansible/config/default/manager_auth_proxy_patch.yaml delete mode 100644 test/ansible/config/manager/kustomization.yaml delete mode 100644 test/ansible/config/manager/manager.yaml delete mode 100644 test/ansible/config/prometheus/kustomization.yaml delete mode 100644 test/ansible/config/prometheus/monitor.yaml delete mode 100644 test/ansible/config/rbac/argstest_editor_role.yaml delete mode 100644 test/ansible/config/rbac/argstest_viewer_role.yaml delete mode 100644 test/ansible/config/rbac/auth_proxy_client_clusterrole.yaml delete mode 100644 test/ansible/config/rbac/auth_proxy_role.yaml delete mode 100644 test/ansible/config/rbac/auth_proxy_role_binding.yaml delete mode 100644 test/ansible/config/rbac/auth_proxy_service.yaml delete mode 100644 test/ansible/config/rbac/kustomization.yaml delete mode 100644 test/ansible/config/rbac/leader_election_role.yaml delete mode 100644 test/ansible/config/rbac/leader_election_role_binding.yaml delete mode 100644 test/ansible/config/rbac/role.yaml delete mode 100644 test/ansible/config/rbac/role_binding.yaml delete mode 100644 test/ansible/config/samples/kustomization.yaml delete mode 100644 test/ansible/config/samples/test_v1alpha1_inventorytest.yaml delete mode 100644 test/ansible/config/testing/debug_logs_patch.yaml delete mode 100644 test/ansible/config/testing/kustomization.yaml delete mode 100644 test/ansible/config/testing/manager_image.yaml delete mode 100644 test/ansible/config/testing/pull_policy/Always.yaml delete mode 100644 test/ansible/config/testing/pull_policy/IfNotPresent.yaml delete mode 100644 test/ansible/config/testing/pull_policy/Never.yaml delete mode 100644 test/ansible/molecule/default/converge.yml delete mode 100644 test/ansible/molecule/default/create.yml delete mode 100644 test/ansible/molecule/default/destroy.yml delete mode 100644 test/ansible/molecule/default/kustomize.yml delete mode 100644 test/ansible/molecule/default/molecule.yml delete mode 100644 test/ansible/molecule/default/prepare.yml delete mode 100644 test/ansible/molecule/default/verify.yml delete mode 100644 test/ansible/molecule/kind/converge.yml delete mode 100644 test/ansible/molecule/kind/create.yml delete mode 100644 test/ansible/molecule/kind/destroy.yml delete mode 100644 test/ansible/molecule/kind/molecule.yml delete mode 100644 test/ansible/playbooks/argstest.yml delete mode 100644 test/ansible/playbooks/casetest.yml delete mode 100644 test/ansible/playbooks/inventorytest.yml delete mode 100644 test/ansible/playbooks/reconciliationtest.yml delete mode 100644 test/ansible/playbooks/selectortest.yml delete mode 100644 test/ansible/playbooks/subresourcestest.yml delete mode 100644 test/ansible/requirements.yml delete mode 100644 test/ansible/roles/inventorytest/tasks/main.yml diff --git a/.gitignore b/.gitignore index a73e7b67226..dab1d92fac9 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ website/tech-doc-hugo # Ignore molecule samples testdata if it be generated in the testdata/ diretory testdata/ansible/memcached-molecule-operator +testdata/ansible/advanced-molecule-operator # Trash files *\.DS_Store diff --git a/Makefile b/Makefile index 085b41b6996..7d51a607c05 100644 --- a/Makefile +++ b/Makefile @@ -165,6 +165,7 @@ test-e2e-ansible:: image/ansible-operator ## Run Ansible e2e tests go test -count=1 ./internal/ansible/proxy/... go test ./test/e2e-ansible -v -ginkgo.v test-e2e-ansible-molecule:: image/ansible-operator ## Run molecule-based Ansible e2e tests + go run ./hack/generate/samples/molecule/generate.go ./hack/tests/e2e-ansible-molecule.sh test-e2e-helm:: image/helm-operator ## Run Helm e2e tests go test ./test/e2e-helm -v -ginkgo.v diff --git a/hack/generate/samples/internal/ansible/advanced_molecule.go b/hack/generate/samples/internal/ansible/advanced_molecule.go new file mode 100644 index 00000000000..e066339fa48 --- /dev/null +++ b/hack/generate/samples/internal/ansible/advanced_molecule.go @@ -0,0 +1,533 @@ +// Copyright 2020 The Operator-SDK 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. + +package ansible + +import ( + "fmt" + "os/exec" + "path/filepath" + "strings" + + log "github.com/sirupsen/logrus" + kbtestutils "sigs.k8s.io/kubebuilder/v2/test/e2e/utils" + + "github.com/operator-framework/operator-sdk/hack/generate/samples/internal/pkg" + "github.com/operator-framework/operator-sdk/internal/testutils" +) + +// AdvancedMolecule defines the context for the sample +type AdvancedMolecule struct { + ctx *pkg.SampleContext +} + +// NewMoleculeAnsible return a MoleculeAnsible +func NewAdvancedMolecule(ctx *pkg.SampleContext) AdvancedMolecule { + return AdvancedMolecule{ctx} +} + +// Prepare the Context for the Memcached Ansible Sample +// Note that sample directory will be re-created and the context data for the sample +// will be set such as the domain and GVK. +func (ma *AdvancedMolecule) Prepare() { + log.Infof("destroying directory for memcached Ansible samples") + ma.ctx.Destroy() + + log.Infof("creating directory") + err := ma.ctx.Prepare() + pkg.CheckError("creating directory for Advanced Molecule Sample", err) + + log.Infof("setting domain and GVK") + // nolint:goconst + ma.ctx.Domain = "example.com" + // nolint:goconst + ma.ctx.Version = "v1alpha1" + ma.ctx.Group = "test" + ma.ctx.Kind = "InventoryTest" +} + +// Run the steps to create the Memcached Ansible Sample +func (ma *AdvancedMolecule) Run() { + log.Infof("creating the project") + err := ma.ctx.Init( + "--plugins", "ansible", + "--group", ma.ctx.Group, + "--version", ma.ctx.Version, + "--kind", ma.ctx.Kind, + "--domain", ma.ctx.Domain, + "--generate-role", + "--generate-playbook") + pkg.CheckError("creating the project", err) + + log.Infof("enabling multigroup support") + err = ma.ctx.AllowProjectBeMultiGroup() + pkg.CheckError("updating PROJECT file", err) + + inventoryRoleTask := filepath.Join(ma.ctx.Dir, "roles", "inventorytest", "tasks", "main.yml") + log.Infof("inserting code to inventory role task") + const inventoryRoleTaskFragment = ` +- when: sentinel | test + block: + - community.kubernetes.k8s: + definition: + apiVersion: v1 + kind: ConfigMap + metadata: + name: inventory-cm + namespace: '{{ meta.namespace }}' + data: + sentinel: '{{ sentinel }}' + groups: '{{ groups | to_nice_yaml }}'` + err = testutils.ReplaceInFile( + inventoryRoleTask, + "# tasks file for InventoryTest", + inventoryRoleTaskFragment) + pkg.CheckError("replacing inventory task", err) + + log.Infof("updating inventorytest sample") + err = testutils.ReplaceInFile( + filepath.Join(ma.ctx.Dir, "config", "samples", "test_v1alpha1_inventorytest.yaml"), + "name: inventorytest-sample", + inventorysampleFragment) + pkg.CheckError("updating inventorytest sample", err) + + log.Infof("updating spec of inventorytest sample") + err = testutils.ReplaceInFile( + filepath.Join(ma.ctx.Dir, "config", "samples", "test_v1alpha1_inventorytest.yaml"), + "foo: bar", + "size: 3") + pkg.CheckError("updating spec of inventorytest sample", err) + + ma.addPlaybooks() + ma.updatePlaybooks() + ma.addMocksFromTestdata() + ma.updateDockerfile() + ma.updateConfig() +} + +func (ma *AdvancedMolecule) updateConfig() { + log.Infof("adding customized roles") + const cmRolesFragment = ` ## + ## Base operator rules + ## + - apiGroups: + - "" + resources: + - configmaps + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - apps + resources: + - configmaps + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +# +kubebuilder:scaffold:rules` + err := testutils.ReplaceInFile( + filepath.Join(ma.ctx.Dir, "config", "rbac", "role.yaml"), + "# +kubebuilder:scaffold:rules", + cmRolesFragment) + pkg.CheckError("adding customized roles", err) + + log.Infof("adding manager arg") + const ansibleVaultArg = ` + - "--ansible-args='--vault-password-file /opt/ansible/pwd.yml'"` + err = kbtestutils.InsertCode( + filepath.Join(ma.ctx.Dir, "config", "manager", "manager.yaml"), + "- \"--leader-election-id=advanced-molecule-operator\"", + ansibleVaultArg) + pkg.CheckError("adding manager arg", err) + + log.Infof("adding manager env") + const managerEnv = ` + - name: ANSIBLE_DEBUG_LOGS + value: "TRUE" + - name: ANSIBLE_INVENTORY + value: /opt/ansible/inventory` + err = kbtestutils.InsertCode( + filepath.Join(ma.ctx.Dir, "config", "manager", "manager.yaml"), + "value: explicit", + managerEnv) + pkg.CheckError("adding manager env", err) + + log.Infof("adding vaulting args to the proxy auth") + const managerAuthArgs = ` + - "--ansible-args='--vault-password-file /opt/ansible/pwd.yml'"` + err = kbtestutils.InsertCode( + filepath.Join(ma.ctx.Dir, "config", "default", "manager_auth_proxy_patch.yaml"), + "- \"--enable-leader-election\"", + managerAuthArgs) + pkg.CheckError("adding vaulting args to the proxy auth", err) + + log.Infof("adding task to not pull image to the config/testing") + err = testutils.ReplaceInFile( + filepath.Join(ma.ctx.Dir, "config", "testing", "kustomization.yaml"), + "- manager_image.yaml", + "- manager_image.yaml\n- pull_policy/Never.yaml") + pkg.CheckError("adding task to not pull image to the config/testing", err) +} + +func (ma *AdvancedMolecule) addMocksFromTestdata() { + log.Infof("adding ansible.cfg") + cmd := exec.Command("cp", "../../../hack/generate/samples/internal/ansible/testdata/ansible.cfg", ma.ctx.Dir) + _, err := ma.ctx.Run(cmd) + pkg.CheckError("adding ansible.cfg", err) + + log.Infof("adding plugins/") + cmd = exec.Command("cp", "-r", "../../../hack/generate/samples/internal/ansible/testdata/plugins/", filepath.Join(ma.ctx.Dir, "plugins/")) + _, err = ma.ctx.Run(cmd) + pkg.CheckError("adding plugins/", err) + + log.Infof("adding fixture_collection/") + cmd = exec.Command("cp", "-r", "../../../hack/generate/samples/internal/ansible/testdata/fixture_collection/", filepath.Join(ma.ctx.Dir, "fixture_collection/")) + _, err = ma.ctx.Run(cmd) + pkg.CheckError("adding fixture_collection/", err) + + log.Infof("replacing watches.yaml") + cmd = exec.Command("cp", "-r", "../../../hack/generate/samples/internal/ansible/testdata/watches.yaml", ma.ctx.Dir) + _, err = ma.ctx.Run(cmd) + pkg.CheckError("replacing watches.yaml", err) + + log.Infof("adding tasks/") + cmd = exec.Command("cp", "-r", "../../../hack/generate/samples/internal/ansible/testdata/tasks/", filepath.Join(ma.ctx.Dir, "molecule/default/")) + _, err = ma.ctx.Run(cmd) + pkg.CheckError("adding tasks/", err) + + log.Infof("adding secret playbook") + cmd = exec.Command("cp", "-r", "../../../hack/generate/samples/internal/ansible/testdata/secret.yml", filepath.Join(ma.ctx.Dir, "playbooks/secret.yml")) + _, err = ma.ctx.Run(cmd) + pkg.CheckError("adding secret playbook", err) + + log.Infof("adding inventory/") + cmd = exec.Command("cp", "-r", "../../../hack/generate/samples/internal/ansible/testdata/inventory/", filepath.Join(ma.ctx.Dir, "inventory/")) + _, err = ma.ctx.Run(cmd) + pkg.CheckError("adding inventory/", err) +} + +func (ma *AdvancedMolecule) updateDockerfile() { + log.Infof("replacing project Dockerfile to use ansible base image with the dev tag") + err := testutils.ReplaceRegexInFile( + filepath.Join(ma.ctx.Dir, "Dockerfile"), + "quay.io/operator-framework/ansible-operator:.*", + "quay.io/operator-framework/ansible-operator:dev") + pkg.CheckError("replacing Dockerfile", err) + + log.Infof("inserting code to Dockerfile") + const dockerfileFragment = ` + +# Customizations done to check advanced scenarios +COPY inventory/ ${HOME}/inventory/ +COPY plugins/ ${HOME}/plugins/ +COPY ansible.cfg /etc/ansible/ansible.cfg +COPY fixture_collection/ /tmp/fixture_collection/ +USER root +RUN chmod -R ug+rwx /tmp/fixture_collection +USER 1001 +RUN ansible-galaxy collection build /tmp/fixture_collection/ --output-path /tmp/fixture_collection/ \ + && ansible-galaxy collection install /tmp/fixture_collection/operator_sdk-test_fixtures-0.0.0.tar.gz +RUN echo abc123 > /opt/ansible/pwd.yml \ + && ansible-vault encrypt_string --vault-password-file /opt/ansible/pwd.yml 'thisisatest' --name 'the_secret' > /opt/ansible/vars.yml +` + err = kbtestutils.InsertCode( + filepath.Join(ma.ctx.Dir, "Dockerfile"), + "COPY playbooks/ ${HOME}/playbooks/", + dockerfileFragment) + pkg.CheckError("replacing Dockerfile", err) +} + +func (ma *AdvancedMolecule) updatePlaybooks() { + log.Infof("adding playbook for argstest") + const argsPlaybook = `--- +- hosts: localhost + gather_facts: no + collections: + - community.kubernetes + tasks: + - name: Get the decrypted message variable + include_vars: + file: /opt/ansible/vars.yml + name: the_secret + - name: Create configmap + k8s: + definition: + apiVersion: v1 + kind: ConfigMap + metadata: + name: '{{ meta.name }}' + namespace: '{{ meta.namespace }}' + data: + msg: The decrypted value is {{the_secret.the_secret}} +` + err := testutils.ReplaceInFile( + filepath.Join(ma.ctx.Dir, "playbooks", "argstest.yml"), + originalPlaybookFragment, + argsPlaybook) + pkg.CheckError("adding playbook for argstest", err) + + log.Infof("adding playbook for casetest") + const casePlaybook = `--- +- hosts: localhost + gather_facts: no + collections: + - community.kubernetes + tasks: + - name: Create configmap + k8s: + definition: + apiVersion: v1 + kind: ConfigMap + metadata: + name: '{{ meta.name }}' + namespace: '{{ meta.namespace }}' + data: + shouldBeCamel: '{{ camelCaseVar | default("false") }}' +` + err = testutils.ReplaceInFile( + filepath.Join(ma.ctx.Dir, "playbooks", "casetest.yml"), + originalPlaybookFragment, + casePlaybook) + pkg.CheckError("adding playbook for casetest", err) + + log.Infof("adding playbook for inventorytest") + const inventoryPlaybook = `--- +- hosts: test + gather_facts: no + tasks: + - import_role: + name: "inventorytest" + +- hosts: localhost + gather_facts: no + tasks: + - command: echo hello + - debug: msg='{{ "hello" | test }}'` + err = testutils.ReplaceInFile( + filepath.Join(ma.ctx.Dir, "playbooks", "inventorytest.yml"), + "---\n- hosts: localhost\n gather_facts: no\n collections:\n - community.kubernetes\n - operator_sdk.util\n tasks:\n - import_role:\n name: \"inventorytest\"", + inventoryPlaybook) + pkg.CheckError("adding playbook for inventorytest", err) + + log.Infof("adding playbook for reconciliationtest") + const reconciliationPlaybook = `--- +- hosts: localhost + gather_facts: no + collections: + - community.kubernetes + tasks: + - name: retrieve configmap + k8s_info: + api_version: v1 + kind: ConfigMap + namespace: '{{ meta.namespace }}' + name: '{{ meta.name }}' + register: configmap + + - name: create configmap + k8s: + definition: + apiVersion: v1 + kind: ConfigMap + metadata: + name: '{{ meta.name }}' + namespace: '{{ meta.namespace }}' + data: + iterations: '1' + when: configmap.resources|length == 0 + + - name: Update ConfigMap + k8s: + definition: + apiVersion: v1 + kind: ConfigMap + metadata: + name: '{{ meta.name }}' + namespace: '{{ meta.namespace }}' + data: + iterations: '{{ (configmap.resources.0.data.iterations|int) + 1 }}' + when: configmap.resources|length > 0 and (configmap.resources.0.data.iterations|int) < 5 + + - name: retrieve configmap + k8s_info: + api_version: v1 + kind: ConfigMap + namespace: '{{ meta.namespace }}' + name: '{{ meta.name }}' + register: configmap + + - name: Using the requeue_after module + operator_sdk.util.requeue_after: + time: 1s + when: configmap.resources|length > 0 and (configmap.resources.0.data.iterations|int) < 5 +` + err = testutils.ReplaceInFile( + filepath.Join(ma.ctx.Dir, "playbooks", "reconciliationtest.yml"), + originalPlaybookFragment, + reconciliationPlaybook) + pkg.CheckError("adding playbook for reconciliationtest", err) + + log.Infof("adding playbook for selectortest") + const selectorPlaybook = `--- +- hosts: localhost + gather_facts: no + collections: + - community.kubernetes + tasks: + - name: Create configmap + k8s: + definition: + apiVersion: v1 + kind: ConfigMap + metadata: + name: '{{ meta.name }}' + namespace: '{{ meta.namespace }}' + data: + hello: "world" +` + err = testutils.ReplaceInFile( + filepath.Join(ma.ctx.Dir, "playbooks", "selectortest.yml"), + originalPlaybookFragment, + selectorPlaybook) + pkg.CheckError("adding playbook for selectortest", err) + + log.Infof("adding playbook for subresourcestest") + const subresourcesPlaybook = `--- +- hosts: localhost + gather_facts: no + collections: + - community.kubernetes + - operator_sdk.util + + tasks: + - name: Deploy busybox pod + k8s: + definition: + apiVersion: v1 + kind: Pod + metadata: + name: '{{ meta.name }}-busybox' + namespace: '{{ meta.namespace }}' + spec: + containers: + - image: busybox + name: sleep + args: + - "/bin/sh" + - "-c" + - "while true ; do echo '{{ log_message }}' ; sleep 5 ; done" + wait: yes + + - name: Execute command in busybox pod + k8s_exec: + namespace: '{{ meta.namespace }}' + pod: '{{ meta.name }}-busybox' + command: '{{ exec_command }}' + register: exec_result + + - debug: var=exec_result + + - name: Get logs from busybox pod + k8s_log: + name: '{{ meta.name }}-busybox' + namespace: '{{ meta.namespace }}' + register: log_result + + - name: Write results to resource status + k8s_status: + api_version: test.example.com/v1alpha1 + kind: SubresourcesTest + name: '{{ meta.name }}' + namespace: '{{ meta.namespace }}' + status: + execCommandStdout: '{{ exec_result.stdout.strip() }}' + execCommandStderr: '{{ exec_result.stderr.strip() }}' + logs: '{{ log_result.log }}' +` + err = testutils.ReplaceInFile( + filepath.Join(ma.ctx.Dir, "playbooks", "subresourcestest.yml"), + originalPlaybookFragment, + subresourcesPlaybook) + pkg.CheckError("adding playbook for subresourcestest", err) +} + +func (ma *AdvancedMolecule) addPlaybooks() { + allPlaybookKinds := []string{ + "ArgsTest", + "CaseTest", + "CollectionTest", + "ReconciliationTest", + "SelectorTest", + "SubresourcesTest", + } + + // Crate API + for _, k := range allPlaybookKinds { + logMsgForKind := fmt.Sprintf("creating an API %s", k) + log.Infof(logMsgForKind) + err := ma.ctx.CreateAPI( + "--group", ma.ctx.Group, + "--version", ma.ctx.Version, + "--kind", k, + "--generate-playbook") + pkg.CheckError(logMsgForKind, err) + + k = strings.ToLower(k) + task := fmt.Sprintf("%s_test.yml", k) + logMsgForKind = fmt.Sprintf("removing FIXME assert from %s", task) + log.Infof(logMsgForKind) + err = testutils.ReplaceInFile( + filepath.Join(ma.ctx.Dir, "molecule", "default", "tasks", task), + fixmeAssert, + "") + pkg.CheckError(logMsgForKind, err) + } +} + +const originalPlaybookFragment = `--- +- hosts: localhost + gather_facts: no + collections: + - community.kubernetes + - operator_sdk.util + tasks: [] +` + +const inventorysampleFragment = `name: inventorytest-sample + annotations: + "ansible.sdk.operatorframework.io/verbosity": "0"` + +// GenerateMoleculeAnsibleSample will call all actions to create the directory and generate the sample +// The Context to run the samples are not the same in the e2e test. In this way, note that it should NOT +// be called in the e2e tests since it will call the Prepare() to set the sample context and generate the files +// in the testdata directory. The e2e tests only ought to use the Run() method with the TestContext. +func GenerateMoleculeAdvancedAnsibleSample(path string) { + ctx, err := pkg.NewSampleContext(testutils.BinaryName, filepath.Join(path, "advanced-molecule-operator"), + "GO111MODULE=on") + pkg.CheckError("generating Ansible Molecule Advanced Operator context", err) + + molecule := NewAdvancedMolecule(&ctx) + molecule.Prepare() + molecule.Run() +} diff --git a/hack/generate/samples/internal/ansible/molecule.go b/hack/generate/samples/internal/ansible/memcached_molecule.go similarity index 100% rename from hack/generate/samples/internal/ansible/molecule.go rename to hack/generate/samples/internal/ansible/memcached_molecule.go diff --git a/test/ansible/ansible.cfg b/hack/generate/samples/internal/ansible/testdata/ansible.cfg similarity index 100% rename from test/ansible/ansible.cfg rename to hack/generate/samples/internal/ansible/testdata/ansible.cfg diff --git a/test/ansible/fixture_collection/galaxy.yml b/hack/generate/samples/internal/ansible/testdata/fixture_collection/galaxy.yml similarity index 100% rename from test/ansible/fixture_collection/galaxy.yml rename to hack/generate/samples/internal/ansible/testdata/fixture_collection/galaxy.yml diff --git a/test/ansible/fixture_collection/roles/dummy/tasks/main.yml b/hack/generate/samples/internal/ansible/testdata/fixture_collection/roles/dummy/tasks/main.yml similarity index 100% rename from test/ansible/fixture_collection/roles/dummy/tasks/main.yml rename to hack/generate/samples/internal/ansible/testdata/fixture_collection/roles/dummy/tasks/main.yml diff --git a/test/ansible/inventory/group_vars/test.yml b/hack/generate/samples/internal/ansible/testdata/inventory/group_vars/test.yml similarity index 100% rename from test/ansible/inventory/group_vars/test.yml rename to hack/generate/samples/internal/ansible/testdata/inventory/group_vars/test.yml diff --git a/test/ansible/inventory/hosts b/hack/generate/samples/internal/ansible/testdata/inventory/hosts similarity index 100% rename from test/ansible/inventory/hosts rename to hack/generate/samples/internal/ansible/testdata/inventory/hosts diff --git a/test/ansible/plugins/filter/test.py b/hack/generate/samples/internal/ansible/testdata/plugins/filter/test.py similarity index 100% rename from test/ansible/plugins/filter/test.py rename to hack/generate/samples/internal/ansible/testdata/plugins/filter/test.py diff --git a/test/ansible/playbooks/secret.yml b/hack/generate/samples/internal/ansible/testdata/secret.yml similarity index 100% rename from test/ansible/playbooks/secret.yml rename to hack/generate/samples/internal/ansible/testdata/secret.yml diff --git a/test/ansible/molecule/default/tasks/argstest_test.yml b/hack/generate/samples/internal/ansible/testdata/tasks/argstest_test.yml similarity index 100% rename from test/ansible/molecule/default/tasks/argstest_test.yml rename to hack/generate/samples/internal/ansible/testdata/tasks/argstest_test.yml diff --git a/test/ansible/molecule/default/tasks/casetest_test.yml b/hack/generate/samples/internal/ansible/testdata/tasks/casetest_test.yml similarity index 100% rename from test/ansible/molecule/default/tasks/casetest_test.yml rename to hack/generate/samples/internal/ansible/testdata/tasks/casetest_test.yml diff --git a/test/ansible/molecule/default/tasks/collectiontest_test.yml b/hack/generate/samples/internal/ansible/testdata/tasks/collectiontest_test.yml similarity index 100% rename from test/ansible/molecule/default/tasks/collectiontest_test.yml rename to hack/generate/samples/internal/ansible/testdata/tasks/collectiontest_test.yml diff --git a/test/ansible/molecule/default/tasks/inventorytest_test.yml b/hack/generate/samples/internal/ansible/testdata/tasks/inventorytest_test.yml similarity index 100% rename from test/ansible/molecule/default/tasks/inventorytest_test.yml rename to hack/generate/samples/internal/ansible/testdata/tasks/inventorytest_test.yml diff --git a/test/ansible/molecule/default/tasks/reconciliationtest_test.yml b/hack/generate/samples/internal/ansible/testdata/tasks/reconciliationtest_test.yml similarity index 100% rename from test/ansible/molecule/default/tasks/reconciliationtest_test.yml rename to hack/generate/samples/internal/ansible/testdata/tasks/reconciliationtest_test.yml diff --git a/test/ansible/molecule/default/tasks/secretstest_test.yml b/hack/generate/samples/internal/ansible/testdata/tasks/secretstest_test.yml similarity index 100% rename from test/ansible/molecule/default/tasks/secretstest_test.yml rename to hack/generate/samples/internal/ansible/testdata/tasks/secretstest_test.yml diff --git a/test/ansible/molecule/default/tasks/selectortest_test.yml b/hack/generate/samples/internal/ansible/testdata/tasks/selectortest_test.yml similarity index 100% rename from test/ansible/molecule/default/tasks/selectortest_test.yml rename to hack/generate/samples/internal/ansible/testdata/tasks/selectortest_test.yml diff --git a/test/ansible/molecule/default/tasks/subresourcestest_test.yml b/hack/generate/samples/internal/ansible/testdata/tasks/subresourcestest_test.yml similarity index 100% rename from test/ansible/molecule/default/tasks/subresourcestest_test.yml rename to hack/generate/samples/internal/ansible/testdata/tasks/subresourcestest_test.yml diff --git a/test/ansible/watches.yaml b/hack/generate/samples/internal/ansible/testdata/watches.yaml similarity index 100% rename from test/ansible/watches.yaml rename to hack/generate/samples/internal/ansible/testdata/watches.yaml diff --git a/hack/generate/samples/molecule/generate.go b/hack/generate/samples/molecule/generate.go index 5345a2af9bc..69f330269f8 100644 --- a/hack/generate/samples/molecule/generate.go +++ b/hack/generate/samples/molecule/generate.go @@ -35,6 +35,9 @@ func main() { // path is the path provided to generate the molecule sample path string + + // sample is the name of the mock was selected to be generated + sample string ) // testdata is the path where all samples are generate @@ -42,6 +45,7 @@ func main() { flag.StringVar(&binaryName, "bin", testutils.BinaryName, "Binary path that should be used") flag.StringVar(&path, "path", "", "Path where the molecule should be called") + flag.StringVar(&sample, "sample", "", "To generate only the selected option. Options: [advanced,memcached]") flag.Parse() @@ -59,5 +63,12 @@ func main() { log.Infof("creating Ansible Molecule Mock Sample") log.Infof("using the path: (%v)", path) - ansible.GenerateMoleculeAnsibleSample(path) + + if sample == "" || sample == "memcached" { + ansible.GenerateMoleculeAnsibleSample(path) + } + + if sample == "" || sample == "advanced" { + ansible.GenerateMoleculeAdvancedAnsibleSample(path) + } } diff --git a/hack/tests/e2e-ansible-molecule.sh b/hack/tests/e2e-ansible-molecule.sh index a68976860ac..087db61fc7c 100755 --- a/hack/tests/e2e-ansible-molecule.sh +++ b/hack/tests/e2e-ansible-molecule.sh @@ -17,14 +17,15 @@ pip3 install --user ansible-lint yamllint pip3 install --user docker==4.2.2 openshift jmespath ansible-galaxy collection install 'community.kubernetes:<1.0.0' -header_text "Creating molecule sample" -go run ./hack/generate/samples/molecule/generate.go --path=$TMPDIR +header_text "Copying molecule testdata scenarios" +cp -r $ROOTDIR/testdata/ansible/memcached-molecule-operator/ $TMPDIR/memcached-molecule-operator +cp -r $ROOTDIR/testdata/ansible/advanced-molecule-operator/ $TMPDIR/advanced-molecule-operator pushd "$TMPDIR" popd cd $TMPDIR/memcached-molecule-operator -header_text "Test Kind" +header_text "Running Kind test with memcached-molecule-operator/" make kustomize if [ -f ./bin/kustomize ] ; then KUSTOMIZE="$(realpath ./bin/kustomize)" @@ -33,12 +34,9 @@ else fi KUSTOMIZE_PATH=${KUSTOMIZE} TEST_OPERATOR_NAMESPACE=default molecule test -s kind -rm -rf $KUSTOMIZE -cd $TMPDIR/ -rm -rf memcached-molecule-operator -header_text "Test Ansible Molecule scenarios" -pushd "${ROOTDIR}/test/ansible" +header_text "Running Default test with advanced-molecule-operator/" +cd $TMPDIR/advanced-molecule-operator make kustomize if [ -f ./bin/kustomize ] ; then @@ -48,7 +46,6 @@ else fi DEST_IMAGE="quay.io/example/advanced-molecule-operator:v0.0.1" -sed -i".bak" -E -e 's/(FROM quay.io\/operator-framework\/ansible-operator)(:.*)?/\1:dev/g' Dockerfile; rm -f Dockerfile.bak docker build -t "$DEST_IMAGE" --no-cache . load_image_if_kind "$DEST_IMAGE" KUSTOMIZE_PATH=$KUSTOMIZE OPERATOR_PULL_POLICY=Never OPERATOR_IMAGE=${DEST_IMAGE} TEST_OPERATOR_NAMESPACE=osdk-test molecule test diff --git a/internal/ansible/OWNERS b/internal/ansible/OWNERS deleted file mode 100644 index 9702fa34032..00000000000 --- a/internal/ansible/OWNERS +++ /dev/null @@ -1,6 +0,0 @@ -approvers: - - fabianvf - - jmrodri -reviewers: - - fabianvf - - jmrodri diff --git a/test/ansible/.gitignore b/test/ansible/.gitignore deleted file mode 100644 index 62fd3e3995f..00000000000 --- a/test/ansible/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ - -# Binaries for programs and plugins -*.exe -*.exe~ -*.dll -*.so -*.dylib -bin - -# editor and IDE paraphernalia -.idea -*.swp -*.swo -*~ diff --git a/test/ansible/Dockerfile b/test/ansible/Dockerfile deleted file mode 100644 index b29926583a8..00000000000 --- a/test/ansible/Dockerfile +++ /dev/null @@ -1,23 +0,0 @@ -FROM quay.io/operator-framework/ansible-operator:v1.2.0 - -COPY requirements.yml ${HOME}/requirements.yml -RUN ansible-galaxy collection install -r ${HOME}/requirements.yml \ - && chmod -R ug+rwx ${HOME}/.ansible - -COPY watches.yaml ${HOME}/watches.yaml -COPY roles/ ${HOME}/roles/ -COPY playbooks/ ${HOME}/playbooks/ - -# Customizations done to check advanced scenarios -COPY inventory/ ${HOME}/inventory/ -COPY plugins/ ${HOME}/plugins/ -COPY ansible.cfg /etc/ansible/ansible.cfg -COPY fixture_collection/ /tmp/fixture_collection/ -USER root -RUN chmod -R ug+rwx /tmp/fixture_collection -USER 1001 -RUN ansible-galaxy collection build /tmp/fixture_collection/ --output-path /tmp/fixture_collection/ \ - && ansible-galaxy collection install /tmp/fixture_collection/operator_sdk-test_fixtures-0.0.0.tar.gz -RUN echo abc123 > /opt/ansible/pwd.yml \ - && ansible-vault encrypt_string --vault-password-file /opt/ansible/pwd.yml 'thisisatest' --name 'the_secret' > /opt/ansible/vars.yml - diff --git a/test/ansible/Makefile b/test/ansible/Makefile deleted file mode 100644 index 1fdb9883652..00000000000 --- a/test/ansible/Makefile +++ /dev/null @@ -1,92 +0,0 @@ -# Current Operator version -VERSION ?= 0.0.1 -# Default bundle image tag -BUNDLE_IMG ?= controller-bundle:$(VERSION) -# Options for 'bundle-build' -ifneq ($(origin CHANNELS), undefined) -BUNDLE_CHANNELS := --channels=$(CHANNELS) -endif -ifneq ($(origin DEFAULT_CHANNEL), undefined) -BUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL) -endif -BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL) - -# Image URL to use all building/pushing image targets -IMG ?= controller:latest - -all: docker-build - -# Run against the configured Kubernetes cluster in ~/.kube/config -run: ansible-operator - $(ANSIBLE_OPERATOR) run - -# Install CRDs into a cluster -install: kustomize - $(KUSTOMIZE) build config/crd | kubectl apply -f - - -# Uninstall CRDs from a cluster -uninstall: kustomize - $(KUSTOMIZE) build config/crd | kubectl delete -f - - -# Deploy controller in the configured Kubernetes cluster in ~/.kube/config -deploy: kustomize - cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG} - $(KUSTOMIZE) build config/default | kubectl apply -f - - -# Undeploy controller in the configured Kubernetes cluster in ~/.kube/config -undeploy: kustomize - $(KUSTOMIZE) build config/default | kubectl delete -f - - -# Build the docker image -docker-build: - docker build . -t ${IMG} - -# Push the docker image -docker-push: - docker push ${IMG} - -PATH := $(PATH):$(PWD)/bin -SHELL := env PATH=$(PATH) /bin/sh -OS = $(shell uname -s | tr '[:upper:]' '[:lower:]') -ARCH = $(shell uname -m | sed 's/x86_64/amd64/') -OSOPER = $(shell uname -s | tr '[:upper:]' '[:lower:]' | sed 's/darwin/apple-darwin/' | sed 's/linux/linux-gnu/') -ARCHOPER = $(shell uname -m ) - -kustomize: -ifeq (, $(shell which kustomize 2>/dev/null)) - @{ \ - set -e ;\ - mkdir -p bin ;\ - curl -sSLo - https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/v3.5.4/kustomize_v3.5.4_$(OS)_$(ARCH).tar.gz | tar xzf - -C bin/ ;\ - } -KUSTOMIZE=$(realpath ./bin/kustomize) -else -KUSTOMIZE=$(shell which kustomize) -endif - -ansible-operator: -ifeq (, $(shell which ansible-operator 2>/dev/null)) - @{ \ - set -e ;\ - mkdir -p bin ;\ - curl -LO https://github.com/operator-framework/operator-sdk/releases/download/v1.2.0/ansible-operator-v1.2.0-$(ARCHOPER)-$(OSOPER) ;\ - mv ansible-operator-v1.2.0-$(ARCHOPER)-$(OSOPER) ./bin/ansible-operator ;\ - chmod +x ./bin/ansible-operator ;\ - } -ANSIBLE_OPERATOR=$(realpath ./bin/ansible-operator) -else -ANSIBLE_OPERATOR=$(shell which ansible-operator) -endif - -# Generate bundle manifests and metadata, then validate generated files. -.PHONY: bundle -bundle: kustomize - operator-sdk generate kustomize manifests -q - cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG) - $(KUSTOMIZE) build config/manifests | operator-sdk generate bundle -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS) - operator-sdk bundle validate ./bundle - -# Build the bundle image. -.PHONY: bundle-build -bundle-build: - docker build -f bundle.Dockerfile -t $(BUNDLE_IMG) . diff --git a/test/ansible/PROJECT b/test/ansible/PROJECT deleted file mode 100644 index fb5e744071e..00000000000 --- a/test/ansible/PROJECT +++ /dev/null @@ -1,24 +0,0 @@ -domain: example.com -layout: ansible.sdk.operatorframework.io/v1 -multigroup: true -projectName: advanced-molecule-operator -resources: -- group: test - kind: InventoryTest - version: v1alpha1 -- group: test - kind: ArgsTest - version: v1alpha1 -- group: test - kind: CaseTest - version: v1alpha1 -- group: test - kind: CollectionTest - version: v1alpha1 -- group: test - kind: SelectorTest - version: v1alpha1 -- group: test - kind: SubresourcesTest - version: v1alpha1 -version: 3-alpha diff --git a/test/ansible/config/crd/bases/test.example.com_argstests.yaml b/test/ansible/config/crd/bases/test.example.com_argstests.yaml deleted file mode 100644 index 4370af5f84d..00000000000 --- a/test/ansible/config/crd/bases/test.example.com_argstests.yaml +++ /dev/null @@ -1,44 +0,0 @@ ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: argstests.test.example.com -spec: - group: test.example.com - names: - kind: ArgsTest - listKind: ArgsTestList - plural: argstests - singular: argstest - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: ArgsTest is the Schema for the argstests API - 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 defines the desired state of ArgsTest - type: object - x-kubernetes-preserve-unknown-fields: true - status: - description: Status defines the observed state of ArgsTest - type: object - x-kubernetes-preserve-unknown-fields: true - type: object - served: true - storage: true - subresources: - status: {} diff --git a/test/ansible/config/crd/bases/test.example.com_casetests.yaml b/test/ansible/config/crd/bases/test.example.com_casetests.yaml deleted file mode 100644 index 639d2a77bca..00000000000 --- a/test/ansible/config/crd/bases/test.example.com_casetests.yaml +++ /dev/null @@ -1,44 +0,0 @@ ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: casetests.test.example.com -spec: - group: test.example.com - names: - kind: CaseTest - listKind: CaseTestList - plural: casetests - singular: casetest - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: CaseTest is the Schema for the casetests API - 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 defines the desired state of CaseTest - type: object - x-kubernetes-preserve-unknown-fields: true - status: - description: Status defines the observed state of CaseTest - type: object - x-kubernetes-preserve-unknown-fields: true - type: object - served: true - storage: true - subresources: - status: {} diff --git a/test/ansible/config/crd/bases/test.example.com_collectiontests.yaml b/test/ansible/config/crd/bases/test.example.com_collectiontests.yaml deleted file mode 100644 index af8a6c499f6..00000000000 --- a/test/ansible/config/crd/bases/test.example.com_collectiontests.yaml +++ /dev/null @@ -1,44 +0,0 @@ ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: collectiontests.test.example.com -spec: - group: test.example.com - names: - kind: CollectionTest - listKind: CollectionTestList - plural: collectiontests - singular: collectiontest - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: CollectionTest is the Schema for the collectiontests API - 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 defines the desired state of CollectionTest - type: object - x-kubernetes-preserve-unknown-fields: true - status: - description: Status defines the observed state of CollectionTest - type: object - x-kubernetes-preserve-unknown-fields: true - type: object - served: true - storage: true - subresources: - status: {} diff --git a/test/ansible/config/crd/bases/test.example.com_inventorytests.yaml b/test/ansible/config/crd/bases/test.example.com_inventorytests.yaml deleted file mode 100644 index d10ff7c04a5..00000000000 --- a/test/ansible/config/crd/bases/test.example.com_inventorytests.yaml +++ /dev/null @@ -1,44 +0,0 @@ ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: inventorytests.test.example.com -spec: - group: test.example.com - names: - kind: InventoryTest - listKind: InventoryTestList - plural: inventorytests - singular: inventorytest - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: InventoryTest is the Schema for the inventorytests API - 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 defines the desired state of InventoryTest - type: object - x-kubernetes-preserve-unknown-fields: true - status: - description: Status defines the observed state of InventoryTest - type: object - x-kubernetes-preserve-unknown-fields: true - type: object - served: true - storage: true - subresources: - status: {} diff --git a/test/ansible/config/crd/bases/test.example.com_reconciliationtests.yaml b/test/ansible/config/crd/bases/test.example.com_reconciliationtests.yaml deleted file mode 100644 index d8343116ff0..00000000000 --- a/test/ansible/config/crd/bases/test.example.com_reconciliationtests.yaml +++ /dev/null @@ -1,44 +0,0 @@ ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: reconciliationtests.test.example.com -spec: - group: test.example.com - names: - kind: ReconciliationTest - listKind: ReconciliationTestList - plural: reconciliationtests - singular: reconciliationtest - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: ReconciliationTest is the Schema for the reconciliationtests API - 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 defines the desired state of ReconciliationTest - type: object - x-kubernetes-preserve-unknown-fields: true - status: - description: Status defines the observed state of ReconciliationTest - type: object - x-kubernetes-preserve-unknown-fields: true - type: object - served: true - storage: true - subresources: - status: {} diff --git a/test/ansible/config/crd/bases/test.example.com_selectortests.yaml b/test/ansible/config/crd/bases/test.example.com_selectortests.yaml deleted file mode 100644 index 2068942e73f..00000000000 --- a/test/ansible/config/crd/bases/test.example.com_selectortests.yaml +++ /dev/null @@ -1,44 +0,0 @@ ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: selectortests.test.example.com -spec: - group: test.example.com - names: - kind: SelectorTest - listKind: SelectorTestList - plural: selectortests - singular: selectortest - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: SelectorTest is the Schema for the selectortests API - 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 defines the desired state of SelectorTest - type: object - x-kubernetes-preserve-unknown-fields: true - status: - description: Status defines the observed state of SelectorTest - type: object - x-kubernetes-preserve-unknown-fields: true - type: object - served: true - storage: true - subresources: - status: {} diff --git a/test/ansible/config/crd/bases/test.example.com_subresourcestests.yaml b/test/ansible/config/crd/bases/test.example.com_subresourcestests.yaml deleted file mode 100644 index 38c1d3a690c..00000000000 --- a/test/ansible/config/crd/bases/test.example.com_subresourcestests.yaml +++ /dev/null @@ -1,44 +0,0 @@ ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: subresourcestests.test.example.com -spec: - group: test.example.com - names: - kind: SubresourcesTest - listKind: SubresourcesTestList - plural: subresourcestests - singular: subresourcestest - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: SubresourcesTest is the Schema for the subresourcestests API - 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 defines the desired state of SubresourcesTest - type: object - x-kubernetes-preserve-unknown-fields: true - status: - description: Status defines the observed state of SubresourcesTest - type: object - x-kubernetes-preserve-unknown-fields: true - type: object - served: true - storage: true - subresources: - status: {} diff --git a/test/ansible/config/crd/kustomization.yaml b/test/ansible/config/crd/kustomization.yaml deleted file mode 100644 index 4742ee14fa0..00000000000 --- a/test/ansible/config/crd/kustomization.yaml +++ /dev/null @@ -1,12 +0,0 @@ -# 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/test.example.com_inventorytests.yaml -- bases/test.example.com_argstests.yaml -- bases/test.example.com_casetests.yaml -- bases/test.example.com_collectiontests.yaml -- bases/test.example.com_selectortests.yaml -- bases/test.example.com_subresourcestests.yaml -- bases/test.example.com_reconciliationtests.yaml -# +kubebuilder:scaffold:crdkustomizeresource diff --git a/test/ansible/config/default/kustomization.yaml b/test/ansible/config/default/kustomization.yaml deleted file mode 100644 index 13072005482..00000000000 --- a/test/ansible/config/default/kustomization.yaml +++ /dev/null @@ -1,26 +0,0 @@ -# Adds namespace to all resources. -namespace: advanced-molecule-operator-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: advanced-molecule-operator- - -# Labels to add to all resources and selectors. -#commonLabels: -# someName: someValue - -bases: -- ../crd -- ../rbac -- ../manager -# [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'. -#- ../prometheus - -patchesStrategicMerge: - # Protect the /metrics endpoint by putting it behind auth. - # If you want your controller-manager to expose the /metrics - # endpoint w/o any authn/z, please comment the following line. -- manager_auth_proxy_patch.yaml diff --git a/test/ansible/config/default/manager_auth_proxy_patch.yaml b/test/ansible/config/default/manager_auth_proxy_patch.yaml deleted file mode 100644 index 4fe5572c44b..00000000000 --- a/test/ansible/config/default/manager_auth_proxy_patch.yaml +++ /dev/null @@ -1,27 +0,0 @@ -# This patch inject a sidecar container which is a HTTP proxy for the -# controller manager, it performs RBAC authorization against the Kubernetes API using SubjectAccessReviews. -apiVersion: apps/v1 -kind: Deployment -metadata: - name: controller-manager - namespace: system -spec: - template: - spec: - containers: - - name: kube-rbac-proxy - image: gcr.io/kubebuilder/kube-rbac-proxy:v0.5.0 - args: - - "--secure-listen-address=0.0.0.0:8443" - - "--upstream=http://127.0.0.1:8080/" - - "--logtostderr=true" - - "--v=10" - ports: - - containerPort: 8443 - name: https - - name: manager - args: - - "--metrics-addr=127.0.0.1:8080" - - "--enable-leader-election" - - "--leader-election-id=advanced-molecule-operator" - - "--ansible-args='--vault-password-file /opt/ansible/pwd.yml'" diff --git a/test/ansible/config/manager/kustomization.yaml b/test/ansible/config/manager/kustomization.yaml deleted file mode 100644 index 5c5f0b84cba..00000000000 --- a/test/ansible/config/manager/kustomization.yaml +++ /dev/null @@ -1,2 +0,0 @@ -resources: -- manager.yaml diff --git a/test/ansible/config/manager/manager.yaml b/test/ansible/config/manager/manager.yaml deleted file mode 100644 index cfee93297e1..00000000000 --- a/test/ansible/config/manager/manager.yaml +++ /dev/null @@ -1,40 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - labels: - control-plane: controller-manager - name: system ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: controller-manager - namespace: system - labels: - control-plane: controller-manager -spec: - selector: - matchLabels: - control-plane: controller-manager - replicas: 1 - template: - metadata: - labels: - control-plane: controller-manager - spec: - containers: - - name: manager - args: - - "--metrics-addr=127.0.0.1:8080" - - "--enable-leader-election" - - "--leader-election-id=advanced-molecule-operator" - - "--ansible-args='--vault-password-file /opt/ansible/pwd.yml'" - env: - - name: ANSIBLE_DEBUG_LOGS - value: "TRUE" - - name: ANSIBLE_GATHERING - value: explicit - - name: ANSIBLE_INVENTORY - value: /opt/ansible/inventory - image: controller:latest - terminationGracePeriodSeconds: 10 diff --git a/test/ansible/config/prometheus/kustomization.yaml b/test/ansible/config/prometheus/kustomization.yaml deleted file mode 100644 index ed137168a1d..00000000000 --- a/test/ansible/config/prometheus/kustomization.yaml +++ /dev/null @@ -1,2 +0,0 @@ -resources: -- monitor.yaml diff --git a/test/ansible/config/prometheus/monitor.yaml b/test/ansible/config/prometheus/monitor.yaml deleted file mode 100644 index 1b44d4f617f..00000000000 --- a/test/ansible/config/prometheus/monitor.yaml +++ /dev/null @@ -1,16 +0,0 @@ ---- -# Prometheus Monitor Service (Metrics) -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - labels: - control-plane: controller-manager - name: controller-manager-metrics-monitor - namespace: system -spec: - endpoints: - - path: /metrics - port: https - selector: - matchLabels: - control-plane: controller-manager diff --git a/test/ansible/config/rbac/argstest_editor_role.yaml b/test/ansible/config/rbac/argstest_editor_role.yaml deleted file mode 100644 index b436fa95618..00000000000 --- a/test/ansible/config/rbac/argstest_editor_role.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# permissions for end users to edit argstests. -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: argstest-editor-role -rules: -- apiGroups: - - test.example.com - resources: - - argstests - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - test.example.com - resources: - - argstests/status - verbs: - - get diff --git a/test/ansible/config/rbac/argstest_viewer_role.yaml b/test/ansible/config/rbac/argstest_viewer_role.yaml deleted file mode 100644 index bba2d4f9c89..00000000000 --- a/test/ansible/config/rbac/argstest_viewer_role.yaml +++ /dev/null @@ -1,20 +0,0 @@ -# permissions for end users to view argstests. -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: argstest-viewer-role -rules: -- apiGroups: - - test.example.com - resources: - - argstests - verbs: - - get - - list - - watch -- apiGroups: - - test.example.com - resources: - - argstests/status - verbs: - - get diff --git a/test/ansible/config/rbac/auth_proxy_client_clusterrole.yaml b/test/ansible/config/rbac/auth_proxy_client_clusterrole.yaml deleted file mode 100644 index bd4af137a9f..00000000000 --- a/test/ansible/config/rbac/auth_proxy_client_clusterrole.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: metrics-reader -rules: -- nonResourceURLs: ["/metrics"] - verbs: ["get"] diff --git a/test/ansible/config/rbac/auth_proxy_role.yaml b/test/ansible/config/rbac/auth_proxy_role.yaml deleted file mode 100644 index 618f5e4177c..00000000000 --- a/test/ansible/config/rbac/auth_proxy_role.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: proxy-role -rules: -- apiGroups: ["authentication.k8s.io"] - resources: - - tokenreviews - verbs: ["create"] -- apiGroups: ["authorization.k8s.io"] - resources: - - subjectaccessreviews - verbs: ["create"] diff --git a/test/ansible/config/rbac/auth_proxy_role_binding.yaml b/test/ansible/config/rbac/auth_proxy_role_binding.yaml deleted file mode 100644 index 48ed1e4b85c..00000000000 --- a/test/ansible/config/rbac/auth_proxy_role_binding.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: proxy-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: proxy-role -subjects: -- kind: ServiceAccount - name: default - namespace: system diff --git a/test/ansible/config/rbac/auth_proxy_service.yaml b/test/ansible/config/rbac/auth_proxy_service.yaml deleted file mode 100644 index 6cf656be149..00000000000 --- a/test/ansible/config/rbac/auth_proxy_service.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - labels: - control-plane: controller-manager - name: controller-manager-metrics-service - namespace: system -spec: - ports: - - name: https - port: 8443 - targetPort: https - selector: - control-plane: controller-manager diff --git a/test/ansible/config/rbac/kustomization.yaml b/test/ansible/config/rbac/kustomization.yaml deleted file mode 100644 index 66c28338fe0..00000000000 --- a/test/ansible/config/rbac/kustomization.yaml +++ /dev/null @@ -1,12 +0,0 @@ -resources: -- role.yaml -- role_binding.yaml -- leader_election_role.yaml -- leader_election_role_binding.yaml -# Comment the following 4 lines if you want to disable -# the auth proxy (https://github.com/brancz/kube-rbac-proxy) -# which protects your /metrics endpoint. -- auth_proxy_service.yaml -- auth_proxy_role.yaml -- auth_proxy_role_binding.yaml -- auth_proxy_client_clusterrole.yaml diff --git a/test/ansible/config/rbac/leader_election_role.yaml b/test/ansible/config/rbac/leader_election_role.yaml deleted file mode 100644 index 53e974910be..00000000000 --- a/test/ansible/config/rbac/leader_election_role.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# permissions to do leader election. -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: leader-election-role -rules: -- apiGroups: - - "" - resources: - - configmaps - verbs: - - get - - list - - watch - - create - - update - - patch - - delete -- apiGroups: - - "" - resources: - - events - verbs: - - create - - patch diff --git a/test/ansible/config/rbac/leader_election_role_binding.yaml b/test/ansible/config/rbac/leader_election_role_binding.yaml deleted file mode 100644 index eed16906f4d..00000000000 --- a/test/ansible/config/rbac/leader_election_role_binding.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: leader-election-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: leader-election-role -subjects: -- kind: ServiceAccount - name: default - namespace: system diff --git a/test/ansible/config/rbac/role.yaml b/test/ansible/config/rbac/role.yaml deleted file mode 100644 index a023a52179e..00000000000 --- a/test/ansible/config/rbac/role.yaml +++ /dev/null @@ -1,186 +0,0 @@ ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: manager-role -rules: - ## - ## Base operator rules - ## - - apiGroups: - - "" - resources: - - secrets - - pods - - pods/exec - - pods/log - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - apiGroups: - - apps - resources: - - deployments - - daemonsets - - replicasets - - statefulsets - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - ## - ## Rules for test.example.com/v1alpha1, Kind: InventoryTest - ## - - apiGroups: - - test.example.com - resources: - - inventorytests - - inventorytests/status - - inventorytests/finalizers - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - ## - ## Rules for test.example.com/v1alpha1, Kind: InventoryTest - ## - - apiGroups: - - test.example.com - resources: - - subresourcestests - - subresourcestests/status - - subresourcestests/finalizers - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - ## - ## Rules for test.example.com/v1alpha1, Kind: InventoryTest - ## - - apiGroups: - - test.example.com - resources: - - collectiontests - - collectiontests/status - - collectiontests/finalizers - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - ## - ## Rules for test.example.com/v1alpha1, Kind: InventoryTest - ## - - apiGroups: - - test.example.com - resources: - - selectortests - - selectortests/status - - selectortests/finalizers - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - ## - ## Rules for test.example.com/v1alpha1, Kind: InventoryTest - ## - - apiGroups: - - test.example.com - resources: - - casetests - - casetests/status - - casetests/finalizers - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - ## - ## Rules for test.example.com/v1alpha1, Kind: InventoryTest - ## - - apiGroups: - - test.example.com - resources: - - argstests - - argstests/status - - argstests/finalizers - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - ## - ## Rules for test.example.com/v1alpha1, Kind: InventoryTest - ## - - apiGroups: - - test.example.com - resources: - - reconciliationtests - - reconciliationtests/status - - reconciliationtests/finalizers - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - ## - ## Base operator rules - ## - - apiGroups: - - "" - resources: - - configmaps - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - apiGroups: - - apps - resources: - - configmaps - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -# +kubebuilder:scaffold:rules diff --git a/test/ansible/config/rbac/role_binding.yaml b/test/ansible/config/rbac/role_binding.yaml deleted file mode 100644 index 98f87829e96..00000000000 --- a/test/ansible/config/rbac/role_binding.yaml +++ /dev/null @@ -1,13 +0,0 @@ ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: manager-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: manager-role -subjects: -- kind: ServiceAccount - name: default - namespace: system diff --git a/test/ansible/config/samples/kustomization.yaml b/test/ansible/config/samples/kustomization.yaml deleted file mode 100644 index e353c59b277..00000000000 --- a/test/ansible/config/samples/kustomization.yaml +++ /dev/null @@ -1,3 +0,0 @@ -## Append samples you want in your CSV to this file as resources ## -resources: -- test_v1alpha1_inventorytest.yaml diff --git a/test/ansible/config/samples/test_v1alpha1_inventorytest.yaml b/test/ansible/config/samples/test_v1alpha1_inventorytest.yaml deleted file mode 100644 index 27920633490..00000000000 --- a/test/ansible/config/samples/test_v1alpha1_inventorytest.yaml +++ /dev/null @@ -1,8 +0,0 @@ -apiVersion: test.example.com/v1alpha1 -kind: InventoryTest -metadata: - name: inventorytest-sample - annotations: - "ansible.sdk.operatorframework.io/verbosity": "0" -spec: - size: 3 diff --git a/test/ansible/config/testing/debug_logs_patch.yaml b/test/ansible/config/testing/debug_logs_patch.yaml deleted file mode 100644 index 3e31e2fba19..00000000000 --- a/test/ansible/config/testing/debug_logs_patch.yaml +++ /dev/null @@ -1,14 +0,0 @@ ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: controller-manager - namespace: system -spec: - template: - spec: - containers: - - name: manager - env: - - name: ANSIBLE_DEBUG_LOGS - value: "TRUE" diff --git a/test/ansible/config/testing/kustomization.yaml b/test/ansible/config/testing/kustomization.yaml deleted file mode 100644 index 9757d27f748..00000000000 --- a/test/ansible/config/testing/kustomization.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# Adds namespace to all resources. -namespace: osdk-test - -namePrefix: osdk- - -# Labels to add to all resources and selectors. -#commonLabels: -# someName: someValue - -patchesStrategicMerge: -- manager_image.yaml -- pull_policy/Never.yaml -- debug_logs_patch.yaml -- ../default/manager_auth_proxy_patch.yaml - -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization -resources: -- ../crd -- ../rbac -- ../manager -images: -- name: testing - newName: testing-operator diff --git a/test/ansible/config/testing/manager_image.yaml b/test/ansible/config/testing/manager_image.yaml deleted file mode 100644 index e44f542d9bc..00000000000 --- a/test/ansible/config/testing/manager_image.yaml +++ /dev/null @@ -1,12 +0,0 @@ ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: controller-manager - namespace: system -spec: - template: - spec: - containers: - - name: manager - image: testing diff --git a/test/ansible/config/testing/pull_policy/Always.yaml b/test/ansible/config/testing/pull_policy/Always.yaml deleted file mode 100644 index 6b0a8e2a8ab..00000000000 --- a/test/ansible/config/testing/pull_policy/Always.yaml +++ /dev/null @@ -1,12 +0,0 @@ ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: controller-manager - namespace: system -spec: - template: - spec: - containers: - - name: manager - imagePullPolicy: Always diff --git a/test/ansible/config/testing/pull_policy/IfNotPresent.yaml b/test/ansible/config/testing/pull_policy/IfNotPresent.yaml deleted file mode 100644 index 2f52f496cd5..00000000000 --- a/test/ansible/config/testing/pull_policy/IfNotPresent.yaml +++ /dev/null @@ -1,12 +0,0 @@ ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: controller-manager - namespace: system -spec: - template: - spec: - containers: - - name: manager - imagePullPolicy: IfNotPresent diff --git a/test/ansible/config/testing/pull_policy/Never.yaml b/test/ansible/config/testing/pull_policy/Never.yaml deleted file mode 100644 index 86f13d81645..00000000000 --- a/test/ansible/config/testing/pull_policy/Never.yaml +++ /dev/null @@ -1,12 +0,0 @@ ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: controller-manager - namespace: system -spec: - template: - spec: - containers: - - name: manager - imagePullPolicy: Never diff --git a/test/ansible/molecule/default/converge.yml b/test/ansible/molecule/default/converge.yml deleted file mode 100644 index 0633db98492..00000000000 --- a/test/ansible/molecule/default/converge.yml +++ /dev/null @@ -1,18 +0,0 @@ ---- -- name: Converge - hosts: localhost - connection: local - gather_facts: no - collections: - - community.kubernetes - - tasks: - - name: Create Namespace - k8s: - api_version: v1 - kind: Namespace - name: '{{ namespace }}' - - - import_tasks: kustomize.yml - vars: - state: present diff --git a/test/ansible/molecule/default/create.yml b/test/ansible/molecule/default/create.yml deleted file mode 100644 index 1eeaf9226e0..00000000000 --- a/test/ansible/molecule/default/create.yml +++ /dev/null @@ -1,6 +0,0 @@ ---- -- name: Create - hosts: localhost - connection: local - gather_facts: false - tasks: [] diff --git a/test/ansible/molecule/default/destroy.yml b/test/ansible/molecule/default/destroy.yml deleted file mode 100644 index af55e4f1749..00000000000 --- a/test/ansible/molecule/default/destroy.yml +++ /dev/null @@ -1,24 +0,0 @@ ---- -- name: Destroy - hosts: localhost - connection: local - gather_facts: false - collections: - - community.kubernetes - - tasks: - - import_tasks: kustomize.yml - vars: - state: absent - - - name: Destroy Namespace - k8s: - api_version: v1 - kind: Namespace - name: '{{ namespace }}' - state: absent - - - name: Unset pull policy - command: '{{ kustomize }} edit remove patch pull_policy/{{ operator_pull_policy }}.yaml' - args: - chdir: '{{ config_dir }}/testing' diff --git a/test/ansible/molecule/default/kustomize.yml b/test/ansible/molecule/default/kustomize.yml deleted file mode 100644 index f3d888c2f3b..00000000000 --- a/test/ansible/molecule/default/kustomize.yml +++ /dev/null @@ -1,15 +0,0 @@ ---- -- name: Build kustomize testing overlay - # load_restrictor must be set to none so we can load patch files from the default overlay - command: '{{ kustomize }} build --load_restrictor none .' - args: - chdir: '{{ config_dir }}/testing' - register: resources - changed_when: false - -- name: Set resources to {{ state }} - k8s: - definition: '{{ item }}' - state: '{{ state }}' - wait: yes - loop: '{{ resources.stdout | from_yaml_all | list }}' diff --git a/test/ansible/molecule/default/molecule.yml b/test/ansible/molecule/default/molecule.yml deleted file mode 100644 index ea58004dce7..00000000000 --- a/test/ansible/molecule/default/molecule.yml +++ /dev/null @@ -1,36 +0,0 @@ ---- -dependency: - name: galaxy -driver: - name: delegated -lint: | - set -e - yamllint -d "{extends: relaxed, rules: {line-length: {max: 120}}}" . -platforms: - - name: cluster - groups: - - k8s -provisioner: - name: ansible - lint: | - set -e - ansible-lint - inventory: - group_vars: - all: - namespace: ${TEST_OPERATOR_NAMESPACE:-osdk-test} - host_vars: - localhost: - ansible_python_interpreter: '{{ ansible_playbook_python }}' - config_dir: ${MOLECULE_PROJECT_DIRECTORY}/config - samples_dir: ${MOLECULE_PROJECT_DIRECTORY}/config/samples - operator_image: ${OPERATOR_IMAGE:-""} - operator_pull_policy: ${OPERATOR_PULL_POLICY:-"Always"} - kustomize: ${KUSTOMIZE_PATH:-kustomize} - env: - K8S_AUTH_KUBECONFIG: ${KUBECONFIG:-"~/.kube/config"} -verifier: - name: ansible - lint: | - set -e - ansible-lint diff --git a/test/ansible/molecule/default/prepare.yml b/test/ansible/molecule/default/prepare.yml deleted file mode 100644 index 7d9f3f1b765..00000000000 --- a/test/ansible/molecule/default/prepare.yml +++ /dev/null @@ -1,28 +0,0 @@ ---- -- name: Prepare - hosts: localhost - connection: local - gather_facts: false - - tasks: - - name: Ensure operator image is set - fail: - msg: | - You must specify the OPERATOR_IMAGE environment variable in order to run the - 'default' scenario - when: not operator_image - - - name: Set testing image - command: '{{ kustomize }} edit set image testing={{ operator_image }}' - args: - chdir: '{{ config_dir }}/testing' - - - name: Set pull policy - command: '{{ kustomize }} edit add patch pull_policy/{{ operator_pull_policy }}.yaml' - args: - chdir: '{{ config_dir }}/testing' - - - name: Set testing namespace - command: '{{ kustomize }} edit set namespace {{ namespace }}' - args: - chdir: '{{ config_dir }}/testing' diff --git a/test/ansible/molecule/default/verify.yml b/test/ansible/molecule/default/verify.yml deleted file mode 100644 index 8670d557a16..00000000000 --- a/test/ansible/molecule/default/verify.yml +++ /dev/null @@ -1,58 +0,0 @@ ---- -- name: Verify - hosts: localhost - connection: local - gather_facts: no - collections: - - community.kubernetes - - vars: - ctrl_label: control-plane=controller-manager - - tasks: - - block: - - name: Import all test files from tasks/ - include_tasks: '{{ item }}' - with_fileglob: - - tasks/*_test.yml - rescue: - - name: Retrieve relevant resources - k8s_info: - api_version: '{{ item.api_version }}' - kind: '{{ item.kind }}' - namespace: '{{ namespace }}' - loop: - - api_version: v1 - kind: Pod - - api_version: apps/v1 - kind: Deployment - - api_version: v1 - kind: Secret - - api_version: v1 - kind: ConfigMap - register: debug_resources - - - name: Retrieve Pod logs - k8s_log: - name: '{{ item.metadata.name }}' - namespace: '{{ namespace }}' - container: manager - loop: "{{ q('k8s', api_version='v1', kind='Pod', namespace=namespace, label_selector=ctrl_label) }}" - register: debug_logs - - - name: Output gathered resources - debug: - var: debug_resources - - - name: Output gathered logs - debug: - var: item.log_lines - loop: '{{ debug_logs.results }}' - - - name: Re-emit failure - vars: - failed_task: - name: '{{ ansible_failed_task.name }}' - result: '{{ ansible_failed_result }}' - fail: - msg: '{{ failed_task }}' diff --git a/test/ansible/molecule/kind/converge.yml b/test/ansible/molecule/kind/converge.yml deleted file mode 100644 index dbd27374a5e..00000000000 --- a/test/ansible/molecule/kind/converge.yml +++ /dev/null @@ -1,31 +0,0 @@ ---- -- name: Converge - hosts: localhost - connection: local - gather_facts: no - - tasks: - - name: Build Ansible dev base image - make: - chdir: '{{ project_dir }}/../../' - target: image-build-ansible - # Not important, but maybe should fix someday - changed_when: false - - - name: Build operator image - docker_image: - build: - path: '{{ project_dir }}' - pull: no - name: '{{ operator_image }}' - tag: latest - push: no - source: build - force_source: yes - - - name: Load image into kind cluster - command: kind load docker-image --name osdk-test '{{ operator_image }}' - register: result - changed_when: '"not yet present" in result.stdout' - -- import_playbook: ../default/converge.yml diff --git a/test/ansible/molecule/kind/create.yml b/test/ansible/molecule/kind/create.yml deleted file mode 100644 index 66a84a14f7b..00000000000 --- a/test/ansible/molecule/kind/create.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -- name: Create - hosts: localhost - connection: local - gather_facts: false - tasks: - - name: Create test kind cluster - command: kind create cluster --name osdk-test --kubeconfig {{ kubeconfig }} diff --git a/test/ansible/molecule/kind/destroy.yml b/test/ansible/molecule/kind/destroy.yml deleted file mode 100644 index 77b75a1d578..00000000000 --- a/test/ansible/molecule/kind/destroy.yml +++ /dev/null @@ -1,12 +0,0 @@ ---- -- name: Destroy - hosts: localhost - connection: local - gather_facts: false - collections: - - community.kubernetes - - tasks: - - name: Destroy test kind cluster - command: kind delete cluster --name osdk-test --kubeconfig {{ kubeconfig }} - diff --git a/test/ansible/molecule/kind/molecule.yml b/test/ansible/molecule/kind/molecule.yml deleted file mode 100644 index d4361f32fcb..00000000000 --- a/test/ansible/molecule/kind/molecule.yml +++ /dev/null @@ -1,42 +0,0 @@ ---- -dependency: - name: galaxy -driver: - name: delegated -lint: | - set -e - yamllint -d "{extends: relaxed, rules: {line-length: {max: 120}}}" . -platforms: - - name: cluster - groups: - - k8s -provisioner: - name: ansible - playbooks: - prepare: ../default/prepare.yml - verify: ../default/verify.yml - lint: | - set -e - ansible-lint - inventory: - group_vars: - all: - namespace: ${TEST_OPERATOR_NAMESPACE:-osdk-test} - host_vars: - localhost: - ansible_python_interpreter: '{{ ansible_playbook_python }}' - config_dir: ${MOLECULE_PROJECT_DIRECTORY}/config - samples_dir: ${MOLECULE_PROJECT_DIRECTORY}/config/samples - project_dir: ${MOLECULE_PROJECT_DIRECTORY} - operator_image: testing-operator - operator_pull_policy: "Never" - kubeconfig: "{{ lookup('env', 'KUBECONFIG') }}" - kustomize: ${KUSTOMIZE_PATH:-kustomize} - env: - K8S_AUTH_KUBECONFIG: ${MOLECULE_EPHEMERAL_DIRECTORY}/kubeconfig - KUBECONFIG: ${MOLECULE_EPHEMERAL_DIRECTORY}/kubeconfig -verifier: - name: ansible - lint: | - set -e - ansible-lint diff --git a/test/ansible/playbooks/argstest.yml b/test/ansible/playbooks/argstest.yml deleted file mode 100644 index c7a6670d122..00000000000 --- a/test/ansible/playbooks/argstest.yml +++ /dev/null @@ -1,20 +0,0 @@ ---- -- hosts: localhost - gather_facts: no - collections: - - community.kubernetes - tasks: - - name: Get the decrypted message variable - include_vars: - file: /opt/ansible/vars.yml - name: the_secret - - name: Create configmap - k8s: - definition: - apiVersion: v1 - kind: ConfigMap - metadata: - name: '{{ meta.name }}' - namespace: '{{ meta.namespace }}' - data: - msg: The decrypted value is {{the_secret.the_secret}} diff --git a/test/ansible/playbooks/casetest.yml b/test/ansible/playbooks/casetest.yml deleted file mode 100644 index 083416793a1..00000000000 --- a/test/ansible/playbooks/casetest.yml +++ /dev/null @@ -1,17 +0,0 @@ ---- -- hosts: localhost - gather_facts: no - collections: - - community.kubernetes - tasks: - - name: Create configmap - k8s: - definition: - apiVersion: v1 - kind: ConfigMap - metadata: - name: '{{ meta.name }}' - namespace: '{{ meta.namespace }}' - data: - shouldBeCamel: '{{ camelCaseVar | default("false") }}' - diff --git a/test/ansible/playbooks/inventorytest.yml b/test/ansible/playbooks/inventorytest.yml deleted file mode 100644 index 3f57edac2d8..00000000000 --- a/test/ansible/playbooks/inventorytest.yml +++ /dev/null @@ -1,12 +0,0 @@ ---- -- hosts: test - gather_facts: no - tasks: - - import_role: - name: "inventorytest" - -- hosts: localhost - gather_facts: no - tasks: - - command: echo hello - - debug: msg='{{ "hello" | test }}' diff --git a/test/ansible/playbooks/reconciliationtest.yml b/test/ansible/playbooks/reconciliationtest.yml deleted file mode 100644 index 9045f4441b3..00000000000 --- a/test/ansible/playbooks/reconciliationtest.yml +++ /dev/null @@ -1,50 +0,0 @@ ---- -- hosts: localhost - gather_facts: no - collections: - - community.kubernetes - tasks: - - name: retrieve configmap - k8s_info: - api_version: v1 - kind: ConfigMap - namespace: '{{ meta.namespace }}' - name: '{{ meta.name }}' - register: configmap - - - name: create configmap - k8s: - definition: - apiVersion: v1 - kind: ConfigMap - metadata: - name: '{{ meta.name }}' - namespace: '{{ meta.namespace }}' - data: - iterations: '1' - when: configmap.resources|length == 0 - - - name: Update ConfigMap - k8s: - definition: - apiVersion: v1 - kind: ConfigMap - metadata: - name: '{{ meta.name }}' - namespace: '{{ meta.namespace }}' - data: - iterations: '{{ (configmap.resources.0.data.iterations|int) + 1 }}' - when: configmap.resources|length > 0 and (configmap.resources.0.data.iterations|int) < 5 - - - name: retrieve configmap - k8s_info: - api_version: v1 - kind: ConfigMap - namespace: '{{ meta.namespace }}' - name: '{{ meta.name }}' - register: configmap - - - name: Using the requeue_after module - operator_sdk.util.requeue_after: - time: 1s - when: configmap.resources|length > 0 and (configmap.resources.0.data.iterations|int) < 5 diff --git a/test/ansible/playbooks/selectortest.yml b/test/ansible/playbooks/selectortest.yml deleted file mode 100644 index 0016b497b4e..00000000000 --- a/test/ansible/playbooks/selectortest.yml +++ /dev/null @@ -1,16 +0,0 @@ ---- -- hosts: localhost - gather_facts: no - collections: - - community.kubernetes - tasks: - - name: Create configmap - k8s: - definition: - apiVersion: v1 - kind: ConfigMap - metadata: - name: '{{ meta.name }}' - namespace: '{{ meta.namespace }}' - data: - hello: "world" diff --git a/test/ansible/playbooks/subresourcestest.yml b/test/ansible/playbooks/subresourcestest.yml deleted file mode 100644 index c5702951c7f..00000000000 --- a/test/ansible/playbooks/subresourcestest.yml +++ /dev/null @@ -1,51 +0,0 @@ ---- -- hosts: localhost - gather_facts: no - collections: - - community.kubernetes - - operator_sdk.util - - tasks: - - name: Deploy busybox pod - k8s: - definition: - apiVersion: v1 - kind: Pod - metadata: - name: '{{ meta.name }}-busybox' - namespace: '{{ meta.namespace }}' - spec: - containers: - - image: busybox - name: sleep - args: - - "/bin/sh" - - "-c" - - "while true ; do echo '{{ log_message }}' ; sleep 5 ; done" - wait: yes - - - name: Execute command in busybox pod - k8s_exec: - namespace: '{{ meta.namespace }}' - pod: '{{ meta.name }}-busybox' - command: '{{ exec_command }}' - register: exec_result - - - debug: var=exec_result - - - name: Get logs from busybox pod - k8s_log: - name: '{{ meta.name }}-busybox' - namespace: '{{ meta.namespace }}' - register: log_result - - - name: Write results to resource status - k8s_status: - api_version: test.example.com/v1alpha1 - kind: SubresourcesTest - name: '{{ meta.name }}' - namespace: '{{ meta.namespace }}' - status: - execCommandStdout: '{{ exec_result.stdout.strip() }}' - execCommandStderr: '{{ exec_result.stderr.strip() }}' - logs: '{{ log_result.log }}' diff --git a/test/ansible/requirements.yml b/test/ansible/requirements.yml deleted file mode 100644 index 8a661f8b95e..00000000000 --- a/test/ansible/requirements.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -collections: - - name: community.kubernetes - version: "<1.0.0" - - operator_sdk.util diff --git a/test/ansible/roles/inventorytest/tasks/main.yml b/test/ansible/roles/inventorytest/tasks/main.yml deleted file mode 100644 index a6ab21d46c2..00000000000 --- a/test/ansible/roles/inventorytest/tasks/main.yml +++ /dev/null @@ -1,13 +0,0 @@ ---- -- when: sentinel | test - block: - - community.kubernetes.k8s: - definition: - apiVersion: v1 - kind: ConfigMap - metadata: - name: inventory-cm - namespace: '{{ meta.namespace }}' - data: - sentinel: '{{ sentinel }}' - groups: '{{ groups | to_nice_yaml }}' From 42242135ced8eeaca6f5dc329c43890be9a3c5c3 Mon Sep 17 00:00:00 2001 From: Joe Lanford Date: Mon, 4 Jan 2021 15:19:37 -0500 Subject: [PATCH 258/376] testdata: bump samples to year 2021 (#4360) Signed-off-by: reinvantveer --- .../go/v2/memcached-operator/api/v1alpha1/groupversion_info.go | 2 +- .../go/v2/memcached-operator/api/v1alpha1/memcached_types.go | 2 +- .../go/v2/memcached-operator/api/v1alpha1/memcached_webhook.go | 2 +- .../v2/memcached-operator/api/v1alpha1/zz_generated.deepcopy.go | 2 +- .../v2/memcached-operator/controllers/memcached_controller.go | 2 +- testdata/go/v2/memcached-operator/controllers/suite_test.go | 2 +- testdata/go/v2/memcached-operator/hack/boilerplate.go.txt | 2 +- testdata/go/v2/memcached-operator/main.go | 2 +- .../go/v3/memcached-operator/api/v1alpha1/groupversion_info.go | 2 +- .../go/v3/memcached-operator/api/v1alpha1/memcached_types.go | 2 +- .../go/v3/memcached-operator/api/v1alpha1/memcached_webhook.go | 2 +- .../go/v3/memcached-operator/api/v1alpha1/webhook_suite_test.go | 2 +- .../v3/memcached-operator/api/v1alpha1/zz_generated.deepcopy.go | 2 +- .../v3/memcached-operator/controllers/memcached_controller.go | 2 +- testdata/go/v3/memcached-operator/controllers/suite_test.go | 2 +- testdata/go/v3/memcached-operator/hack/boilerplate.go.txt | 2 +- testdata/go/v3/memcached-operator/main.go | 2 +- 17 files changed, 17 insertions(+), 17 deletions(-) diff --git a/testdata/go/v2/memcached-operator/api/v1alpha1/groupversion_info.go b/testdata/go/v2/memcached-operator/api/v1alpha1/groupversion_info.go index cd34e142a1d..48db6c393f6 100644 --- a/testdata/go/v2/memcached-operator/api/v1alpha1/groupversion_info.go +++ b/testdata/go/v2/memcached-operator/api/v1alpha1/groupversion_info.go @@ -1,5 +1,5 @@ /* -Copyright 2020. +Copyright 2021. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/testdata/go/v2/memcached-operator/api/v1alpha1/memcached_types.go b/testdata/go/v2/memcached-operator/api/v1alpha1/memcached_types.go index 4ed5052101e..2affdfb7834 100644 --- a/testdata/go/v2/memcached-operator/api/v1alpha1/memcached_types.go +++ b/testdata/go/v2/memcached-operator/api/v1alpha1/memcached_types.go @@ -1,5 +1,5 @@ /* -Copyright 2020. +Copyright 2021. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/testdata/go/v2/memcached-operator/api/v1alpha1/memcached_webhook.go b/testdata/go/v2/memcached-operator/api/v1alpha1/memcached_webhook.go index e2063a6fc66..db29709442a 100644 --- a/testdata/go/v2/memcached-operator/api/v1alpha1/memcached_webhook.go +++ b/testdata/go/v2/memcached-operator/api/v1alpha1/memcached_webhook.go @@ -1,5 +1,5 @@ /* -Copyright 2020. +Copyright 2021. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/testdata/go/v2/memcached-operator/api/v1alpha1/zz_generated.deepcopy.go b/testdata/go/v2/memcached-operator/api/v1alpha1/zz_generated.deepcopy.go index 5edd2767bb0..7730cf55270 100644 --- a/testdata/go/v2/memcached-operator/api/v1alpha1/zz_generated.deepcopy.go +++ b/testdata/go/v2/memcached-operator/api/v1alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2020. +Copyright 2021. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/testdata/go/v2/memcached-operator/controllers/memcached_controller.go b/testdata/go/v2/memcached-operator/controllers/memcached_controller.go index 14ee7006471..1f5f0f3dbee 100644 --- a/testdata/go/v2/memcached-operator/controllers/memcached_controller.go +++ b/testdata/go/v2/memcached-operator/controllers/memcached_controller.go @@ -1,5 +1,5 @@ /* -Copyright 2020. +Copyright 2021. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/testdata/go/v2/memcached-operator/controllers/suite_test.go b/testdata/go/v2/memcached-operator/controllers/suite_test.go index c8409b4e5a4..349107d32f9 100644 --- a/testdata/go/v2/memcached-operator/controllers/suite_test.go +++ b/testdata/go/v2/memcached-operator/controllers/suite_test.go @@ -1,5 +1,5 @@ /* -Copyright 2020. +Copyright 2021. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/testdata/go/v2/memcached-operator/hack/boilerplate.go.txt b/testdata/go/v2/memcached-operator/hack/boilerplate.go.txt index 606681a693e..45dbbbbcf09 100644 --- a/testdata/go/v2/memcached-operator/hack/boilerplate.go.txt +++ b/testdata/go/v2/memcached-operator/hack/boilerplate.go.txt @@ -1,5 +1,5 @@ /* -Copyright 2020. +Copyright 2021. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/testdata/go/v2/memcached-operator/main.go b/testdata/go/v2/memcached-operator/main.go index c334f6d39cd..4e36eb8e714 100644 --- a/testdata/go/v2/memcached-operator/main.go +++ b/testdata/go/v2/memcached-operator/main.go @@ -1,5 +1,5 @@ /* -Copyright 2020. +Copyright 2021. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/testdata/go/v3/memcached-operator/api/v1alpha1/groupversion_info.go b/testdata/go/v3/memcached-operator/api/v1alpha1/groupversion_info.go index cd34e142a1d..48db6c393f6 100644 --- a/testdata/go/v3/memcached-operator/api/v1alpha1/groupversion_info.go +++ b/testdata/go/v3/memcached-operator/api/v1alpha1/groupversion_info.go @@ -1,5 +1,5 @@ /* -Copyright 2020. +Copyright 2021. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/testdata/go/v3/memcached-operator/api/v1alpha1/memcached_types.go b/testdata/go/v3/memcached-operator/api/v1alpha1/memcached_types.go index 4ed5052101e..2affdfb7834 100644 --- a/testdata/go/v3/memcached-operator/api/v1alpha1/memcached_types.go +++ b/testdata/go/v3/memcached-operator/api/v1alpha1/memcached_types.go @@ -1,5 +1,5 @@ /* -Copyright 2020. +Copyright 2021. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/testdata/go/v3/memcached-operator/api/v1alpha1/memcached_webhook.go b/testdata/go/v3/memcached-operator/api/v1alpha1/memcached_webhook.go index b9189aa44af..672a3a6830b 100644 --- a/testdata/go/v3/memcached-operator/api/v1alpha1/memcached_webhook.go +++ b/testdata/go/v3/memcached-operator/api/v1alpha1/memcached_webhook.go @@ -1,5 +1,5 @@ /* -Copyright 2020. +Copyright 2021. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/testdata/go/v3/memcached-operator/api/v1alpha1/webhook_suite_test.go b/testdata/go/v3/memcached-operator/api/v1alpha1/webhook_suite_test.go index d122eacf445..69c487c6aa1 100644 --- a/testdata/go/v3/memcached-operator/api/v1alpha1/webhook_suite_test.go +++ b/testdata/go/v3/memcached-operator/api/v1alpha1/webhook_suite_test.go @@ -1,5 +1,5 @@ /* -Copyright 2020. +Copyright 2021. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/testdata/go/v3/memcached-operator/api/v1alpha1/zz_generated.deepcopy.go b/testdata/go/v3/memcached-operator/api/v1alpha1/zz_generated.deepcopy.go index c9b4e97a164..06a3fb07876 100644 --- a/testdata/go/v3/memcached-operator/api/v1alpha1/zz_generated.deepcopy.go +++ b/testdata/go/v3/memcached-operator/api/v1alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2020. +Copyright 2021. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/testdata/go/v3/memcached-operator/controllers/memcached_controller.go b/testdata/go/v3/memcached-operator/controllers/memcached_controller.go index 0978d43bd4c..61d2c7599a4 100644 --- a/testdata/go/v3/memcached-operator/controllers/memcached_controller.go +++ b/testdata/go/v3/memcached-operator/controllers/memcached_controller.go @@ -1,5 +1,5 @@ /* -Copyright 2020. +Copyright 2021. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/testdata/go/v3/memcached-operator/controllers/suite_test.go b/testdata/go/v3/memcached-operator/controllers/suite_test.go index 03618e8b33f..2d7e46357c8 100644 --- a/testdata/go/v3/memcached-operator/controllers/suite_test.go +++ b/testdata/go/v3/memcached-operator/controllers/suite_test.go @@ -1,5 +1,5 @@ /* -Copyright 2020. +Copyright 2021. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/testdata/go/v3/memcached-operator/hack/boilerplate.go.txt b/testdata/go/v3/memcached-operator/hack/boilerplate.go.txt index 606681a693e..45dbbbbcf09 100644 --- a/testdata/go/v3/memcached-operator/hack/boilerplate.go.txt +++ b/testdata/go/v3/memcached-operator/hack/boilerplate.go.txt @@ -1,5 +1,5 @@ /* -Copyright 2020. +Copyright 2021. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/testdata/go/v3/memcached-operator/main.go b/testdata/go/v3/memcached-operator/main.go index bfd085027e7..44e9804ea83 100644 --- a/testdata/go/v3/memcached-operator/main.go +++ b/testdata/go/v3/memcached-operator/main.go @@ -1,5 +1,5 @@ /* -Copyright 2020. +Copyright 2021. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From ed793c1dda06a435f833dab9d5907218e39f9cf5 Mon Sep 17 00:00:00 2001 From: Joe Lanford Date: Mon, 4 Jan 2021 16:20:18 -0500 Subject: [PATCH 259/376] go.mod: Bump containerd dependency to correctly detect Apple Silicon ARM variant (#4359) Signed-off-by: reinvantveer --- changelog/fragments/fix-mac-m1.yaml | 3 ++ go.mod | 5 +++ go.sum | 67 ++--------------------------- 3 files changed, 11 insertions(+), 64 deletions(-) create mode 100644 changelog/fragments/fix-mac-m1.yaml diff --git a/changelog/fragments/fix-mac-m1.yaml b/changelog/fragments/fix-mac-m1.yaml new file mode 100644 index 00000000000..7b61dcf5b59 --- /dev/null +++ b/changelog/fragments/fix-mac-m1.yaml @@ -0,0 +1,3 @@ +entries: + - description: Update containerd dependency to correctly handle running the Operator SDK CLI on Apple Silicon. + kind: bugfix diff --git a/go.mod b/go.mod index 90c8b5fe6dd..d4459149378 100644 --- a/go.mod +++ b/go.mod @@ -40,6 +40,11 @@ require ( replace ( github.com/Azure/go-autorest => github.com/Azure/go-autorest v13.3.2+incompatible // Required by OLM + + // Using containerd 1.4.0+ resolves an issue with invalid error logging + // from an init function in containerd. This replace can be removed when + // one of our direct dependencies begins using containerd v1.4.0+ + github.com/containerd/containerd => github.com/containerd/containerd v1.4.3 github.com/mattn/go-sqlite3 => github.com/mattn/go-sqlite3 v1.10.0 golang.org/x/text => golang.org/x/text v0.3.3 // Required to fix CVE-2020-14040 ) diff --git a/go.sum b/go.sum index 8a11841724d..d13a76e29a3 100644 --- a/go.sum +++ b/go.sum @@ -2,7 +2,6 @@ bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxo cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw= -cloud.google.com/go v0.38.0 h1:ROfEUZz+Gh5pa62DJWXSaonyu3StP6EA6lPEXPI6mCo= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= @@ -20,20 +19,16 @@ github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7O github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-autorest v13.3.2+incompatible h1:VxzPyuhtnlBOzc4IWCZHqpyH2d+QMLQEuy3wREyY4oc= github.com/Azure/go-autorest v13.3.2+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.9.0 h1:MRvx8gncNaXJqOoLmhNjUAKh33JJF8LyxPhomEtOsjs= github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= github.com/Azure/go-autorest/autorest v0.9.6 h1:5YWtOnckcudzIw8lPPBcWOnmIFWMtHci1ZWAZulMSx0= github.com/Azure/go-autorest/autorest v0.9.6/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630= -github.com/Azure/go-autorest/autorest/adal v0.5.0 h1:q2gDruN08/guU9vAjuPWff0+QIrpH6ediguzdAzXAUU= github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= github.com/Azure/go-autorest/autorest/adal v0.8.2 h1:O1X4oexUxnZCaEUGsvMnr8ZGj8HI37tNezwY4npRqA0= github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= -github.com/Azure/go-autorest/autorest/date v0.1.0 h1:YGrhWfrgtFs84+h0o46rJrlmsZtyZRg470CqAXTZaGM= github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= github.com/Azure/go-autorest/autorest/date v0.2.0 h1:yW+Zlqf26583pE43KhfnhFcdmSWlm5Ew6bxipnr/tbM= github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= -github.com/Azure/go-autorest/autorest/mocks v0.2.0 h1:Ww5g4zThfD/6cLb4z6xxgeyDa7QDkizMkJKe0ysZXp0= github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.3.0 h1:qJumjCaCudz+OcqE9/XtEPfvtOjOmKaui4EOpFI6zZc= github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= @@ -82,10 +77,8 @@ github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/ github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4 h1:Hs82Z41s6SdL1CELW+XaDYmOH4hkBN4/N9og/AsOv7E= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q= @@ -150,12 +143,8 @@ github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f h1:tSNMc+rJDfmYntojat8lljbt1mgKNpTxUZJsSzJ9Y1s= github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= -github.com/containerd/containerd v1.2.7/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.2 h1:ForxmXkA6tPIvffbrDAcPUIB32QgXkt2XFj+F0UxetA= -github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.4 h1:3o0smo5SKY7H6AJCmJhsnCjR2/V2T8VmiHt7seN2/kI= -github.com/containerd/containerd v1.3.4/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.4.3 h1:ijQT13JedHSHrQGWFcGEwzcNKrAGIiZ+jSD5QQG07SY= +github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20200107194136-26c1120b8d41/go.mod h1:Dq467ZllaHgAtVp4p1xUQWBrFXR9s/wyoTpG8zOJGkY= github.com/containerd/continuity v0.0.0-20200413184840-d3ef23f19fbb h1:nXPkFq8X1a9ycY3GYQpFNxHh3j2JgY7zDZfq2EXMIzk= @@ -257,7 +246,6 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M= github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.9.0+incompatible h1:kLcOMZeuLAJvL2BPWLMIj5oaZQobrkAqrL+WFZwQses= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= @@ -282,7 +270,6 @@ github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= -github.com/go-bindata/go-bindata/v3 v3.1.3 h1:F0nVttLC3ws0ojc7p60veTurcOm//D4QBODNM7EGrCI= github.com/go-bindata/go-bindata/v3 v3.1.3/go.mod h1:1/zrpXsLD8YDIbhZRqXzm1Ghc7NhEvIN9+Z6R5/xH4I= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= @@ -292,12 +279,10 @@ github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgO github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logr/logr v0.1.0 h1:M1Tv3VzNlEHg6uyACnRdtrploV2P7wZqH8BoQMtz0cg= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v0.3.0 h1:q4c+kbcR0d5rSurhBR8dIgieOaYpXtsdTYfx22Cu6rs= github.com/go-logr/logr v0.3.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/zapr v0.1.0 h1:h+WVe9j6HAA01niTJPA/kKH0i7e0rLZBCwauQFcRE54= github.com/go-logr/zapr v0.1.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk= github.com/go-logr/zapr v0.2.0 h1:v6Ji8yBW77pva6NkJKQdHLAJKrIJKRHz0RXwPqCHSR4= github.com/go-logr/zapr v0.2.0/go.mod h1:qhKdvif7YF5GI9NWEpyxTSSBdGmzkNguibrdCNVPunU= @@ -391,9 +376,7 @@ github.com/golang-migrate/migrate/v4 v4.6.2/go.mod h1:JYi6reN3+Z734VZ0akNuyOJNcr github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef h1:veQD95Isof8w9/WXiA+pa3tz3fJXkt5B7QaRBrM62gk= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7 h1:5ZkaAPbicIKTF2I64qf5Fh8Aa83Q/dnOafMYV0OMwjA= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -427,7 +410,6 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -436,7 +418,6 @@ github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -449,12 +430,10 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= -github.com/googleapis/gnostic v0.3.1 h1:WeAefnSUHlBb0iJKwxFDZdbfGwkd7xRNuV+IpXMJhYk= github.com/googleapis/gnostic v0.3.1/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= github.com/googleapis/gnostic v0.5.1 h1:A8Yhf6EtqTv9RMsU6MQTyrtV1TjWlR6xU9BsZIwuTCM= github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= -github.com/gophercloud/gophercloud v0.1.0 h1:P/nh25+rzXouhytV2pUHBb65fnds26Ghl8/391+sT5o= github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= @@ -463,7 +442,6 @@ github.com/gorilla/handlers v1.4.2 h1:0QniY0USkHQ1RGCLfKxeNHK9bkDHGRYGNDFBCS+YAR github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.7.2 h1:zoNxOV7WjqXptQOVngLmcSQgXmgk4NMz1HibBchjl/I= github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= @@ -545,16 +523,12 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA= github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/errcheck v1.2.0 h1:reN85Pxc5larApoH1keMBiu2GWtPqXQ1nc9gx+jOU+E= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -603,7 +577,6 @@ github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzp github.com/mattn/go-shellwords v1.0.10/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o= github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= -github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= @@ -667,7 +640,6 @@ github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= -github.com/onsi/ginkgo v1.12.1 h1:mFwc4LvZ0xpSvDZ3E+k8Yte0hLOMxXUlP+yXtJqkYfQ= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.1 h1:jMU0WaQrP0a/YAEq8eJmJKjBoMs+pClEr1vDMlM/Do4= github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= @@ -678,14 +650,12 @@ github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= -github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.2 h1:aY/nuoWlKJud2J6U0E3NWsjlg+0GtwXxgEqthRdzlcs= github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= @@ -694,7 +664,6 @@ github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zM github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6 h1:yN8BPXVwMBAm3Cuvh1L5XE8XpvYRMdsVLd82ILprhUU= github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v0.1.1 h1:GlxAyO6x8rfZYN9Tt0Kti5a/cP41iuiO2yYT0IJGY8Y= github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700 h1:eNUVfm/RFLIi1G7flU5/ZRTHvd4kcVuzfRnL6OFlzCI= github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= @@ -809,7 +778,6 @@ github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvH github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= @@ -851,7 +819,6 @@ github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoH github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -907,31 +874,24 @@ go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qL go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2 h1:75k/FF0Q2YM8QYo07VPddOLBslDt1MZOdEslOHvmzAs= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.3.0 h1:sFPn2GLc3poCkfrpIXGhBD2X0CMIo4Q/zSULXrj/+uc= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.8.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.13.0 h1:nR6NoDBgAf67s68NhaXbsojM+2gxp3S1hWkHDl27pVU= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.15.0 h1:ZZCA22JRF2gQE5FoNmhmrf7jeJJ2uhqDUNRYKm8dvmM= go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= @@ -977,7 +937,6 @@ golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCc golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -1021,7 +980,6 @@ golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAG golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6 h1:pE8b58s1HRDMi8RDc79m0HISf9D4TzseP40cEA6IGfs= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1030,7 +988,6 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1088,9 +1045,7 @@ golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1130,7 +1085,6 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200403190813-44a64ad78b9b h1:AFZdJUT7jJYXQEC29hYH/WZkoV7+KhwxQGmdZ19yYoY= golang.org/x/tools v0.0.0-20200403190813-44a64ad78b9b/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200616195046-dc31b401abb5/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -1138,11 +1092,9 @@ golang.org/x/tools v0.0.0-20201014231627-1610a49f37af h1:VIUWFyOgzG3c0t9KYop5Ybp golang.org/x/tools v0.0.0-20201014231627-1610a49f37af/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gomodules.xyz/jsonpatch/v2 v2.0.1 h1:xyiBuvkD2g5n7cYzx6u2sxQvsAy4QJsZFCzGVdzOXZ0= gomodules.xyz/jsonpatch/v2 v2.0.1/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU= gomodules.xyz/jsonpatch/v2 v2.1.0 h1:Phva6wqu+xR//Njw6iorylFFgn/z547tw5Ne3HZPQ+k= gomodules.xyz/jsonpatch/v2 v2.1.0/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU= @@ -1164,7 +1116,6 @@ google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= @@ -1214,7 +1165,6 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= -gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1247,12 +1197,12 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20190905181640-827449938966/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +gotest.tools/v3 v3.0.2 h1:kG1BFyqVHuQoVQiR1bWGnfz/fmHvvuiSPIV7rvl360E= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= helm.sh/helm/v3 v3.4.1 h1:NIdlBGKFRTAkhz0ooYKw1VBbmTldxNAZRY1nH6Glk6I= helm.sh/helm/v3 v3.4.1/go.mod h1:MeRlXlmCr5CWYKvqIPgXrSmcIXJpv7qcsKV3uTvcZSM= @@ -1265,26 +1215,22 @@ honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXe honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= k8s.io/api v0.18.0/go.mod h1:q2HRQkfDzHMBZL9l/y9rH63PkQl4vae0xRT+8prbrK8= k8s.io/api v0.18.2/go.mod h1:SJCWI7OLzhZSvbY7U8zwNl9UA4o1fizoug34OV/2r78= -k8s.io/api v0.19.2 h1:q+/krnHWKsL7OBZg/rxnycsl9569Pud76UJ77MvKXms= k8s.io/api v0.19.2/go.mod h1:IQpK0zFQ1xc5iNIQPqzgoOwuFugaYHK4iCknlAQP9nI= k8s.io/api v0.19.3/go.mod h1:VF+5FT1B74Pw3KxMdKyinLo+zynBaMBiAfGMuldcNDs= k8s.io/api v0.19.4 h1:I+1I4cgJYuCDgiLNjKx7SLmIbwgj9w7N7Zr5vSIdwpo= k8s.io/api v0.19.4/go.mod h1:SbtJ2aHCItirzdJ36YslycFNzWADYH3tgOhvBEFtZAk= k8s.io/apiextensions-apiserver v0.18.2/go.mod h1:q3faSnRGmYimiocj6cHQ1I3WpLqmDgJFlKL37fC4ZvY= -k8s.io/apiextensions-apiserver v0.19.2 h1:oG84UwiDsVDu7dlsGQs5GySmQHCzMhknfhFExJMz9tA= k8s.io/apiextensions-apiserver v0.19.2/go.mod h1:EYNjpqIAvNZe+svXVx9j4uBaVhTB4C94HkY3w058qcg= k8s.io/apiextensions-apiserver v0.19.3/go.mod h1:igVEkrE9TzInc1tYE7qSqxaLg/rEAp6B5+k9Q7+IC8Q= k8s.io/apiextensions-apiserver v0.19.4 h1:D9ak9T012tb3vcGFWYmbQuj9SCC8YM4zhA4XZqsAQC4= k8s.io/apiextensions-apiserver v0.19.4/go.mod h1:B9rpH/nu4JBCtuUp3zTTk8DEjZUupZTBEec7/2zNRYw= k8s.io/apimachinery v0.18.0/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA= k8s.io/apimachinery v0.18.2/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA= -k8s.io/apimachinery v0.19.2 h1:5Gy9vQpAGTKHPVOh5c4plE274X8D/6cuEiTO2zve7tc= k8s.io/apimachinery v0.19.2/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= k8s.io/apimachinery v0.19.3/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= k8s.io/apimachinery v0.19.4 h1:+ZoddM7nbzrDCp0T3SWnyxqf8cbWPT2fkZImoyvHUG0= k8s.io/apimachinery v0.19.4/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= k8s.io/apiserver v0.18.2/go.mod h1:Xbh066NqrZO8cbsoenCwyDJ1OSi8Ag8I2lezeHxzwzw= -k8s.io/apiserver v0.19.2 h1:xq2dXAzsAoHv7S4Xc/p7PKhiowdHV/PgdePWo3MxIYM= k8s.io/apiserver v0.19.2/go.mod h1:FreAq0bJ2vtZFj9Ago/X0oNGC51GfubKK/ViOKfVAOA= k8s.io/apiserver v0.19.3/go.mod h1:bx6dMm+H6ifgKFpCQT/SAhPwhzoeIMlHIaibomUDec0= k8s.io/apiserver v0.19.4 h1:X40UuyVt6DcYWIh2olcePkyKO0LRJFvxWC0kLxYvkZU= @@ -1295,7 +1241,6 @@ k8s.io/cli-runtime v0.19.4 h1:FPpoqFbWsFzRbZNRI+o/+iiLFmWMYTmBueIj3OaNVTI= k8s.io/cli-runtime v0.19.4/go.mod h1:m8G32dVbKOeaX1foGhleLEvNd6REvU7YnZyWn5//9rw= k8s.io/client-go v0.18.0/go.mod h1:uQSYDYs4WhVZ9i6AIoEZuwUggLVEF64HOD37boKAtF8= k8s.io/client-go v0.18.2/go.mod h1:Xcm5wVGXX9HAA2JJ2sSBUn3tCJ+4SVlCbl2MNNv+CIU= -k8s.io/client-go v0.19.2 h1:gMJuU3xJZs86L1oQ99R4EViAADUPMHHtS9jFshasHSc= k8s.io/client-go v0.19.2/go.mod h1:S5wPhCqyDNAlzM9CnEdgTGV4OqhsW3jGO1UM1epwfJA= k8s.io/client-go v0.19.3/go.mod h1:+eEMktZM+MG0KO+PTkci8xnbCZHvj9TqR6Q1XDUIJOM= k8s.io/client-go v0.19.4 h1:85D3mDNoLF+xqpyE9Dh/OtrJDyJrSRKkHmDXIbEzer8= @@ -1307,9 +1252,7 @@ k8s.io/code-generator v0.19.3/go.mod h1:moqLn7w0t9cMs4+5CQyxnfA/HV8MF6aAVENF+WZZ k8s.io/code-generator v0.19.4/go.mod h1:moqLn7w0t9cMs4+5CQyxnfA/HV8MF6aAVENF+WZZhgk= k8s.io/component-base v0.18.0/go.mod h1:u3BCg0z1uskkzrnAKFzulmYaEpZF7XC9Pf/uFyb1v2c= k8s.io/component-base v0.18.2/go.mod h1:kqLlMuhJNHQ9lz8Z7V5bxUUtjFZnrypArGl58gmDfUM= -k8s.io/component-base v0.19.2 h1:jW5Y9RcZTb79liEhW3XDVTW7MuvEGP0tQZnfSX6/+gs= k8s.io/component-base v0.19.2/go.mod h1:g5LrsiTiabMLZ40AR6Hl45f088DevyGY+cCE2agEIVo= -k8s.io/component-base v0.19.3 h1:c+DzDNAQFlaoyX+yv8YuWi8xmlQvvY5DnJGbaz5U74o= k8s.io/component-base v0.19.3/go.mod h1:WhLWSIefQn8W8jxSLl5WNiR6z8oyMe/8Zywg7alOkRc= k8s.io/component-base v0.19.4 h1:HobPRToQ8KJ9ubRju6PUAk9I5V1GNMJZ4PyWbiWA0uI= k8s.io/component-base v0.19.4/go.mod h1:ZzuSLlsWhajIDEkKF73j64Gz/5o0AgON08FgRbEPI70= @@ -1321,7 +1264,6 @@ k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUc k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= -k8s.io/klog/v2 v2.0.0 h1:Foj74zO6RbjjP4hBEKjnYtjjAhGg4jNynUdYF6fJrok= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0 h1:XRvcwJozkgZ1UQJmfMGpvRthQHOvihEhYtDfAaxMz/A= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= @@ -1343,14 +1285,12 @@ k8s.io/utils v0.0.0-20200912215256-4140de9c8800/go.mod h1:jPW/WVKK9YHAvNhRxK0md/ rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/letsencrypt v0.0.3 h1:H7xDfhkaFFSYEJlKeq38RwX2jYcnTeHuDQyT+mMNMwM= rsc.io/letsencrypt v0.0.3/go.mod h1:buyQKZ6IXrRnB7TdkHP0RyEybLx18HHyOSoTyoOLqNY= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7 h1:uuHDyjllyzRyCIvvn0OBjiRB0SgBZGqHNYAmjR7fO50= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.9 h1:rusRLrDhjBp6aYtl9sGEvQJr6faoHoDLd0YcUBTZguI= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.9/go.mod h1:dzAXnQbTRyDlZPJX2SUPEqvnB+j7AJjtlox7PEwigU0= sigs.k8s.io/controller-runtime v0.6.0/go.mod h1:CpYf5pdNY/B352A1TFLAS2JVSlnGQ5O2cftPHndTroo= sigs.k8s.io/controller-runtime v0.7.0 h1:bU20IBBEPccWz5+zXpLnpVsgBYxqclaHu1pVDl/gEt8= sigs.k8s.io/controller-runtime v0.7.0/go.mod h1:pJ3YBrJiAqMAZKi6UVGuE98ZrroV1p+pIhoHsMm9wdU= -sigs.k8s.io/controller-tools v0.3.0 h1:y3YD99XOyWaXkiF1kd41uRvfp/64teWcrEZFuHxPhJ4= sigs.k8s.io/controller-tools v0.3.0/go.mod h1:enhtKGfxZD1GFEoMgP8Fdbu+uKQ/cq1/WGJhdVChfvI= sigs.k8s.io/controller-tools v0.4.1 h1:VkuV0MxlRPmRu5iTgBZU4UxUX2LiR99n3sdQGRxZF4w= sigs.k8s.io/controller-tools v0.4.1/go.mod h1:G9rHdZMVlBDocIxGkK3jHLWqcTMNvveypYJwrvYKjWU= @@ -1359,7 +1299,6 @@ sigs.k8s.io/kubebuilder/v2 v2.3.2-0.20201214213149-0a807f4e9428/go.mod h1:J/D/17 sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0= sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU= sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= -sigs.k8s.io/structured-merge-diff/v3 v3.0.0 h1:dOmIZBMfhcHS09XZkMyUgkq5trg3/jRyJYFZUiaOp8E= sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= sigs.k8s.io/structured-merge-diff/v4 v4.0.1 h1:YXTMot5Qz/X1iBRJhAt+vI+HVttY0WkSqqhKxQ0xVbA= sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= From 36fb97e423a52311ab7160bfce80bc795c269844 Mon Sep 17 00:00:00 2001 From: Camila Macedo Date: Fri, 8 Jan 2021 23:20:23 +0000 Subject: [PATCH 260/376] doc/cmd output: Improvements in the bundle validation desc (#4379) **Motivation for the change:** https://github.com/operator-framework/operator-sdk/issues/4375 Signed-off-by: reinvantveer --- internal/cmd/operator-sdk/bundle/validate/cmd.go | 12 ++++++++++++ .../en/docs/cli/operator-sdk_bundle_validate.md | 12 ++++++++++++ 2 files changed, 24 insertions(+) diff --git a/internal/cmd/operator-sdk/bundle/validate/cmd.go b/internal/cmd/operator-sdk/bundle/validate/cmd.go index 0f4dfd7f272..4104733e611 100644 --- a/internal/cmd/operator-sdk/bundle/validate/cmd.go +++ b/internal/cmd/operator-sdk/bundle/validate/cmd.go @@ -32,6 +32,11 @@ const ( image or an operator bundle directory on-disk containing operator metadata and manifests. This command will exit with an exit code of 1 if any validation errors arise, and 0 if only warnings arise or all validators pass. +A valid bundle is defined by the bundle spec (linked below), therefore the default validator ensures a bundle conforms to +that spec. If you want to ensure that your bundle is valid for an optional superset of requirements such as to those +required to publish your operator on operatorhub.io, then you will need to run one or more supported optional validators. +Set '--list-optional' to list which optional validators are supported, and how they are grouped by label. + More information about operator bundles and metadata: https://github.com/operator-framework/operator-registry/blob/master/docs/design/operator-bundle.md @@ -63,7 +68,14 @@ To list and run optional validators, which are specified by a label selector: NAME LABELS DESCRIPTION operatorhub name=operatorhub OperatorHub.io metadata validation suite=operatorframework + +To validate a bundle with a superset of requirements for Operator Framework: + $ operator-sdk bundle validate ./bundle --select-optional suite=operatorframework + +To validate a bundle with a superset of requirements for operatorhub.io specifically: + + $ operator-sdk bundle validate ./bundle --select-optional name=operatorhub ` ) diff --git a/website/content/en/docs/cli/operator-sdk_bundle_validate.md b/website/content/en/docs/cli/operator-sdk_bundle_validate.md index f858753fdfb..247debea3fc 100644 --- a/website/content/en/docs/cli/operator-sdk_bundle_validate.md +++ b/website/content/en/docs/cli/operator-sdk_bundle_validate.md @@ -11,6 +11,11 @@ The 'operator-sdk bundle validate' command can validate both content and format image or an operator bundle directory on-disk containing operator metadata and manifests. This command will exit with an exit code of 1 if any validation errors arise, and 0 if only warnings arise or all validators pass. +A valid bundle is defined by the bundle spec (linked below), therefore the default validator ensures a bundle conforms to +that spec. If you want to ensure that your bundle is valid for an optional superset of requirements such as to those +required to publish your operator on operatorhub.io, then you will need to run one or more supported optional validators. +Set '--list-optional' to list which optional validators are supported, and how they are grouped by label. + More information about operator bundles and metadata: https://github.com/operator-framework/operator-registry/blob/master/docs/design/operator-bundle.md @@ -49,8 +54,15 @@ To list and run optional validators, which are specified by a label selector: NAME LABELS DESCRIPTION operatorhub name=operatorhub OperatorHub.io metadata validation suite=operatorframework + +To validate a bundle with a superset of requirements for Operator Framework: + $ operator-sdk bundle validate ./bundle --select-optional suite=operatorframework +To validate a bundle with a superset of requirements for operatorhub.io specifically: + + $ operator-sdk bundle validate ./bundle --select-optional name=operatorhub + ``` ### Options From a3cdf9a15f7e5fa92003652fa068b11866dff4c2 Mon Sep 17 00:00:00 2001 From: blaqkube <64150653+blaqkube@users.noreply.github.com> Date: Mon, 11 Jan 2021 19:46:31 +0100 Subject: [PATCH 261/376] Fix panic with "operator-sdk bundle validate" and OCI (#4373) Signed-off-by: reinvantveer --- changelog/fragments/fix-bundle-validate-panic.yaml | 4 ++++ internal/cmd/operator-sdk/bundle/validate/validate.go | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 changelog/fragments/fix-bundle-validate-panic.yaml diff --git a/changelog/fragments/fix-bundle-validate-panic.yaml b/changelog/fragments/fix-bundle-validate-panic.yaml new file mode 100644 index 00000000000..9164ad2d352 --- /dev/null +++ b/changelog/fragments/fix-bundle-validate-panic.yaml @@ -0,0 +1,4 @@ +entries: + - description: Fix panic when "operator-sdk bundle validate" fails + kind: bugfix + breaking: false diff --git a/internal/cmd/operator-sdk/bundle/validate/validate.go b/internal/cmd/operator-sdk/bundle/validate/validate.go index 56a2776ef5c..fda65476cbc 100644 --- a/internal/cmd/operator-sdk/bundle/validate/validate.go +++ b/internal/cmd/operator-sdk/bundle/validate/validate.go @@ -111,7 +111,7 @@ func (c bundleValidateCmd) run(logger *log.Entry, bundleRaw string) (res *intern return res, err } defer func() { - if err = os.RemoveAll(c.directory); err != nil { + if err := os.RemoveAll(c.directory); err != nil { logger.Errorf("Error removing temp bundle dir: %v", err) } }() From af85277d7c259b8203f0425179cc184e6e2b7e27 Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Mon, 11 Jan 2021 12:08:49 -0800 Subject: [PATCH 262/376] *: replace defunct coreos.com/operators/ with kubernetes.io link (#4337) Signed-off-by: reinvantveer --- README.md | 2 +- website/content/en/_index.html | 2 +- website/content/en/docs/overview/_index.md | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 5b2096f52c7..8d57ea9c425 100644 --- a/README.md +++ b/README.md @@ -69,5 +69,5 @@ Operator SDK is under Apache 2.0 license. See the [LICENSE][license_file] file f [license_file]:./LICENSE [of-home]: https://github.com/operator-framework [of-blog]: https://coreos.com/blog/introducing-operator-framework -[operator-link]: https://coreos.com/operators/ +[operator-link]: https://kubernetes.io/docs/concepts/extend-kubernetes/operator/ [sdk-docs]: https://sdk.operatorframework.io diff --git a/website/content/en/_index.html b/website/content/en/_index.html index b7acb684a2d..5d1ff01fd41 100644 --- a/website/content/en/_index.html +++ b/website/content/en/_index.html @@ -10,7 +10,7 @@ Source -

Operators 🔗 +

Operators 🔗 are used to manage complex stateful applications on top of Kubernetes. The Operator SDK makes it easier to create them by providing high level APIs, useful abstractions, and project scaffolding. diff --git a/website/content/en/docs/overview/_index.md b/website/content/en/docs/overview/_index.md index 30d721e63e4..7845ed50664 100644 --- a/website/content/en/docs/overview/_index.md +++ b/website/content/en/docs/overview/_index.md @@ -6,7 +6,7 @@ description: > What is Operator SDK? Why should I use it? --- -## What is Operator SDK and why should I use it? +## What is Operator SDK and why should I use it? This project is a component of the [Operator Framework][of-home], an open source toolkit to manage Kubernetes native applications, called Operators, in an effective, automated, and scalable way. Read more in the [introduction blog post][of-blog]. @@ -91,7 +91,7 @@ Operator SDK is under Apache 2.0 license. See the [LICENSE][license_file] file f [license_file]:https://github.com/operator-framework/operator-sdk/blob/master/LICENSE [of-blog]: https://coreos.com/blog/introducing-operator-framework [of-home]: https://github.com/operator-framework -[operator_link]: https://coreos.com/operators/ +[operator_link]: https://kubernetes.io/docs/concepts/extend-kubernetes/operator/ [proposals_docs]: https://github.com/operator-framework/operator-sdk/tree/master/proposals [testdata_samples]: https://github.com/operator-framework/operator-sdk/tree/master/testdata [sdk_cli_ref]: /docs/cli/ From b8985f257c8012ce8c45e3dd1141d89bb7bd3245 Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Mon, 11 Jan 2021 15:56:02 -0800 Subject: [PATCH 263/376] Makefile: bump envtest version to v0.7.0 (#4390) Signed-off-by: reinvantveer --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 7d51a607c05..c6305d6a6e9 100644 --- a/Makefile +++ b/Makefile @@ -144,7 +144,7 @@ export KIND_CLUSTER := operator-sdk-e2e export KUBEBUILDER_ASSETS := $(PWD)/$(TOOLS_DIR) test-e2e-setup: build $(SCRIPTS_DIR)/fetch kind 0.9.0 - $(SCRIPTS_DIR)/fetch envtest 0.6.3 + $(SCRIPTS_DIR)/fetch envtest 0.7.0 $(SCRIPTS_DIR)/fetch kubectl $(K8S_VERSION) # Install kubectl AFTER envtest because envtest includes its own kubectl binary [[ "`$(TOOLS_DIR)/kind get clusters`" =~ "$(KIND_CLUSTER)" ]] || $(TOOLS_DIR)/kind create cluster --image="kindest/node:v$(K8S_VERSION)" --name $(KIND_CLUSTER) From 5e14cab8225cf0fd80c9fee2c2b55ce43db55675 Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Mon, 11 Jan 2021 19:50:13 -0800 Subject: [PATCH 264/376] images/scorecard-test-kuttl: upgrade kuttl to v0.8.0 (#4391) Signed-off-by: reinvantveer --- changelog/fragments/kuttl-v0.8.0.yaml | 4 ++++ images/scorecard-test-kuttl/Dockerfile | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 changelog/fragments/kuttl-v0.8.0.yaml diff --git a/changelog/fragments/kuttl-v0.8.0.yaml b/changelog/fragments/kuttl-v0.8.0.yaml new file mode 100644 index 00000000000..07421adb0d7 --- /dev/null +++ b/changelog/fragments/kuttl-v0.8.0.yaml @@ -0,0 +1,4 @@ +entries: + - description: > + Upgraded the `kudobuilder/kuttl` base image version in the `scorecard-test-kuttl` image to v0.8.0 + kind: change diff --git a/images/scorecard-test-kuttl/Dockerfile b/images/scorecard-test-kuttl/Dockerfile index e8d5fd87c85..acbf232f1a3 100644 --- a/images/scorecard-test-kuttl/Dockerfile +++ b/images/scorecard-test-kuttl/Dockerfile @@ -1,5 +1,5 @@ #FROM docker.io/kudobuilder/kuttl@sha256:c9c5edc27ba6e5e994ffd8cea03368c0d4e274f3c7a00f51c1e360feb573f24e -FROM kudobuilder/kuttl:v0.7.1 +FROM kudobuilder/kuttl:v0.8.0 ENV HOME=/opt/scorecard-test-kuttl \ USER_NAME=scorecard-test-kuttl \ From b85f1fa8b1b408d3060982368acf2737054faa61 Mon Sep 17 00:00:00 2001 From: Varsha Date: Wed, 13 Jan 2021 09:26:52 -0800 Subject: [PATCH 265/376] Align tutorial imports with test samples (#4393) Align sample project in tutorial with testdata Signed-off-by: reinvantveer --- .../en/docs/building-operators/ansible/quickstart.md | 4 ++-- .../en/docs/building-operators/golang/advanced-topics.md | 2 +- .../content/en/docs/building-operators/golang/migration.md | 2 +- .../content/en/docs/building-operators/golang/quickstart.md | 2 +- .../en/docs/building-operators/golang/references/client.md | 2 +- .../building-operators/golang/references/event-filtering.md | 2 +- .../content/en/docs/building-operators/golang/tutorial.md | 4 ++-- .../content/en/docs/building-operators/helm/quickstart.md | 4 ++-- .../en/docs/upgrading-sdk-version/v0.1.0-migration-guide.md | 6 +++--- 9 files changed, 14 insertions(+), 14 deletions(-) diff --git a/website/content/en/docs/building-operators/ansible/quickstart.md b/website/content/en/docs/building-operators/ansible/quickstart.md index e13406a4d94..8fa68418d40 100644 --- a/website/content/en/docs/building-operators/ansible/quickstart.md +++ b/website/content/en/docs/building-operators/ansible/quickstart.md @@ -32,7 +32,7 @@ This guide walks through an example of building a simple memcached-operator powe Make sure to define `IMG` when you call `make`: ```sh - export OPERATOR_IMG="quay.io/example-inc/memcached-operator:v0.0.1" + export OPERATOR_IMG="quay.io/example/memcached-operator:v0.0.1" make docker-build docker-push IMG=$OPERATOR_IMG ``` @@ -50,7 +50,7 @@ Make sure to define `IMG` when you call `make`: ```sh make bundle IMG=$OPERATOR_IMG # Note the "-bundle" component in the image name below. - export BUNDLE_IMG="quay.io/example-inc/memcached-operator-bundle:v0.0.1" + export BUNDLE_IMG="quay.io/example/memcached-operator-bundle:v0.0.1" make bundle-build BUNDLE_IMG=$BUNDLE_IMG make docker-push IMG=$BUNDLE_IMG ``` diff --git a/website/content/en/docs/building-operators/golang/advanced-topics.md b/website/content/en/docs/building-operators/golang/advanced-topics.md index ef319d96d8f..979023a8ed5 100644 --- a/website/content/en/docs/building-operators/golang/advanced-topics.md +++ b/website/content/en/docs/building-operators/golang/advanced-topics.md @@ -43,7 +43,7 @@ The operator's Manager supports the core Kubernetes resource types as found in t ```Go import ( - cachev1alpha1 "github.com/example-inc/memcached-operator/api/v1alpha1 + cachev1alpha1 "github.com/example/memcached-operator/api/v1alpha1 ... ) diff --git a/website/content/en/docs/building-operators/golang/migration.md b/website/content/en/docs/building-operators/golang/migration.md index 64dfbf43a33..10d5c1a81e5 100644 --- a/website/content/en/docs/building-operators/golang/migration.md +++ b/website/content/en/docs/building-operators/golang/migration.md @@ -61,7 +61,7 @@ So let's create a new project with the same domain (`example.com`): ```sh mkdir memcached-operator cd memcached-operator -operator-sdk init --domain example.com --repo github.com/example-inc/memcached-operator +operator-sdk init --domain example.com --repo github.com/example/memcached-operator ``` **Note**: `operator-sdk` attempts to automatically discover the Go module path of your project by looking for a `go.mod` file, or if in `$GOPATH`, by using the directory path. Use the `--repo` flag to explicitly set the module path. diff --git a/website/content/en/docs/building-operators/golang/quickstart.md b/website/content/en/docs/building-operators/golang/quickstart.md index 271b2673e24..853fd8a558c 100644 --- a/website/content/en/docs/building-operators/golang/quickstart.md +++ b/website/content/en/docs/building-operators/golang/quickstart.md @@ -19,7 +19,7 @@ This guide walks through an example of building a simple memcached-operator usin ```sh mkdir memcached-operator cd memcached-operator - operator-sdk init --domain example.com --repo github.com/example-inc/memcached-operator + operator-sdk init --domain example.com --repo github.com/example/memcached-operator ``` 1. Create a simple Memcached API: diff --git a/website/content/en/docs/building-operators/golang/references/client.md b/website/content/en/docs/building-operators/golang/references/client.md index b1a3cadb086..f8a76b30a23 100644 --- a/website/content/en/docs/building-operators/golang/references/client.md +++ b/website/content/en/docs/building-operators/golang/references/client.md @@ -316,7 +316,7 @@ Example: ```Go import ( "context" - cachev1alpha1 "github.com/example-inc/memcached-operator/pkg/apis/cache/v1alpha1" + cachev1alpha1 "github.com/example/memcached-operator/pkg/apis/cache/v1alpha1" ctrl "sigs.k8s.io/controller-runtime" ) diff --git a/website/content/en/docs/building-operators/golang/references/event-filtering.md b/website/content/en/docs/building-operators/golang/references/event-filtering.md index ea193ad2b93..3e46d122f1b 100644 --- a/website/content/en/docs/building-operators/golang/references/event-filtering.md +++ b/website/content/en/docs/building-operators/golang/references/event-filtering.md @@ -66,7 +66,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/predicate" - cachev1alpha1 "github.com/example-inc/app-operator/apis/cache/v1alpha1" + cachev1alpha1 "github.com/example/app-operator/apis/cache/v1alpha1" ) ... diff --git a/website/content/en/docs/building-operators/golang/tutorial.md b/website/content/en/docs/building-operators/golang/tutorial.md index d8799fb6828..7cf12a489da 100644 --- a/website/content/en/docs/building-operators/golang/tutorial.md +++ b/website/content/en/docs/building-operators/golang/tutorial.md @@ -23,7 +23,7 @@ mkdir -p $HOME/projects/memcached-operator cd $HOME/projects/memcached-operator # we'll use a domain of example.com # so all API groups will be .example.com -operator-sdk init --domain example.com --repo github.com/example-inc/memcached-operator +operator-sdk init --domain example.com --repo github.com/example/memcached-operator ``` To learn about the project directory structure, see [Kubebuilder project layout][kubebuilder_layout_doc] doc. @@ -217,7 +217,7 @@ Every Controller has a Reconciler object with a `Reconcile()` method that implem import ( ctrl "sigs.k8s.io/controller-runtime" - cachev1alpha1 "github.com/example-inc/memcached-operator/api/v1alpha1" + cachev1alpha1 "github.com/example/memcached-operator/api/v1alpha1" ... ) diff --git a/website/content/en/docs/building-operators/helm/quickstart.md b/website/content/en/docs/building-operators/helm/quickstart.md index ebc8b37ae99..1c6a1fa714e 100644 --- a/website/content/en/docs/building-operators/helm/quickstart.md +++ b/website/content/en/docs/building-operators/helm/quickstart.md @@ -32,7 +32,7 @@ This guide walks through an example of building a simple nginx-operator powered Make sure to define `IMG` when you call `make`: ```sh - export OPERATOR_IMG="quay.io/example-inc/nginx-operator:v0.0.1" + export OPERATOR_IMG="quay.io/example/nginx-operator:v0.0.1" make docker-build docker-push IMG=$OPERATOR_IMG ``` @@ -50,7 +50,7 @@ Make sure to define `IMG` when you call `make`: ```sh make bundle IMG=$OPERATOR_IMG # Note the "-bundle" component in the image name below. - export BUNDLE_IMG="quay.io/example-inc/nginx-operator-bundle:v0.0.1" + export BUNDLE_IMG="quay.io/example/nginx-operator-bundle:v0.0.1" make bundle-build BUNDLE_IMG=$BUNDLE_IMG make docker-push IMG=$BUNDLE_IMG ``` diff --git a/website/content/en/docs/upgrading-sdk-version/v0.1.0-migration-guide.md b/website/content/en/docs/upgrading-sdk-version/v0.1.0-migration-guide.md index aabdeb627fb..149d893c3b0 100644 --- a/website/content/en/docs/upgrading-sdk-version/v0.1.0-migration-guide.md +++ b/website/content/en/docs/upgrading-sdk-version/v0.1.0-migration-guide.md @@ -19,7 +19,7 @@ $ operator-sdk --version operator-sdk version 0.1.0 # Create new project -$ cd $GOPATH/src/github.com/example-inc/ +$ cd $GOPATH/src/github.com/example/ $ mv memcached-operator old-memcached-operator $ operator-sdk new memcached-operator --skip-git-init $ ls @@ -88,7 +88,7 @@ pkg/controller/ Inspect the `add()` function in your `pkg/controller//_controller.go` file: ```Go import ( - cachev1alpha1 "github.com/example-inc/memcached-operator/pkg/apis/cache/v1alpha1" + cachev1alpha1 "github.com/example/memcached-operator/pkg/apis/cache/v1alpha1" ... ) @@ -154,7 +154,7 @@ Be sure to keep the initial section in the `Reconcile()` code that looks up the ```Go import ( apierrors "k8s.io/apimachinery/pkg/api/errors" - cachev1alpha1 "github.com/example-inc/memcached-operator/pkg/apis/cache/v1alpha1" + cachev1alpha1 "github.com/example/memcached-operator/pkg/apis/cache/v1alpha1" ... ) func (r *ReconcileMemcached) Reconcile(request reconcile.Request) (reconcile.Result, error) { From 3e46e1ab2b687b26e01f5d45dfb52e186eb2dd8e Mon Sep 17 00:00:00 2001 From: Mike Ng <58747157+mikeshng@users.noreply.github.com> Date: Wed, 13 Jan 2021 13:57:54 -0500 Subject: [PATCH 266/376] fix: (helm) - do not add owner references to resources that contain the Helm keep resource-policy annotation (#4389) Signed-off-by: reinvantveer --- ...erator_fix_helm_keep_annotated_delete.yaml | 5 ++ internal/helm/client/client.go | 17 +++- internal/helm/client/client_test.go | 79 +++++++++++++++++++ 3 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 changelog/fragments/helm_operator_fix_helm_keep_annotated_delete.yaml create mode 100644 internal/helm/client/client_test.go diff --git a/changelog/fragments/helm_operator_fix_helm_keep_annotated_delete.yaml b/changelog/fragments/helm_operator_fix_helm_keep_annotated_delete.yaml new file mode 100644 index 00000000000..203f7341939 --- /dev/null +++ b/changelog/fragments/helm_operator_fix_helm_keep_annotated_delete.yaml @@ -0,0 +1,5 @@ +entries: + - description: > + For Helm-based operators, do not add owner references to resources that contain the Helm annotation: 'helm.sh/resource-policy: keep'. + kind: bugfix + breaking: false \ No newline at end of file diff --git a/internal/helm/client/client.go b/internal/helm/client/client.go index eb7787f696c..615ad882ad9 100644 --- a/internal/helm/client/client.go +++ b/internal/helm/client/client.go @@ -17,6 +17,7 @@ package client import ( "errors" "io" + "strings" "github.com/operator-framework/operator-lib/handler" "github.com/operator-framework/operator-sdk/internal/util/k8sutil" @@ -144,7 +145,9 @@ func (c *ownerRefInjectingClient) Build(reader io.Reader, validate bool) (kube.R return err } - if useOwnerRef { + // If the resource contains the Helm resource-policy keep annotation, then do not add + // the owner reference. So when the CR is deleted, Kubernetes won't GCs the resource. + if useOwnerRef && !containsResourcePolicyKeep(u.GetAnnotations()) { ownerRef := metav1.NewControllerRef(c.owner, c.owner.GroupVersionKind()) u.SetOwnerReferences([]metav1.OwnerReference{*ownerRef}) } else { @@ -160,3 +163,15 @@ func (c *ownerRefInjectingClient) Build(reader io.Reader, validate bool) (kube.R } return resourceList, nil } + +func containsResourcePolicyKeep(annotations map[string]string) bool { + if annotations == nil { + return false + } + resourcePolicyType, ok := annotations[kube.ResourcePolicyAnno] + if !ok { + return false + } + resourcePolicyType = strings.ToLower(strings.TrimSpace(resourcePolicyType)) + return resourcePolicyType == kube.KeepPolicy +} diff --git a/internal/helm/client/client_test.go b/internal/helm/client/client_test.go new file mode 100644 index 00000000000..c223da3339d --- /dev/null +++ b/internal/helm/client/client_test.go @@ -0,0 +1,79 @@ +// Copyright 2021 The Operator-SDK 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. + +package client + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "helm.sh/helm/v3/pkg/kube" +) + +func TestContainsResourcePolicyKeep(t *testing.T) { + tests := []struct { + input map[string]string + expectedVal bool + expectedOut string + name string + }{ + { + input: map[string]string{ + kube.ResourcePolicyAnno: kube.KeepPolicy, + }, + expectedVal: true, + name: "base case true", + }, + { + input: map[string]string{ + "not-" + kube.ResourcePolicyAnno: kube.KeepPolicy, + }, + expectedVal: false, + name: "base case annotation false", + }, + { + input: map[string]string{ + kube.ResourcePolicyAnno: "not-" + kube.KeepPolicy, + }, + expectedVal: false, + name: "base case value false", + }, + { + input: map[string]string{ + kube.ResourcePolicyAnno: strings.ToUpper(kube.KeepPolicy), + }, + expectedVal: true, + name: "true with upper case", + }, + { + input: map[string]string{ + kube.ResourcePolicyAnno: " " + kube.KeepPolicy + " ", + }, + expectedVal: true, + name: "true with spaces", + }, + { + input: map[string]string{ + kube.ResourcePolicyAnno: " " + strings.ToUpper(kube.KeepPolicy) + " ", + }, + expectedVal: true, + name: "true with upper case and spaces", + }, + } + + for _, test := range tests { + assert.Equal(t, test.expectedVal, containsResourcePolicyKeep(test.input), test.name) + } +} From d6b19716ebfef7facdf9a3bcbe4ae744707ada32 Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Wed, 13 Jan 2021 20:04:35 -0800 Subject: [PATCH 267/376] .github/workflows: add rerun-actions action to rerun other actions by comment (#4342) Signed-off-by: reinvantveer --- .github/workflows/rerun.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .github/workflows/rerun.yml diff --git a/.github/workflows/rerun.yml b/.github/workflows/rerun.yml new file mode 100644 index 00000000000..cb77d4d7f22 --- /dev/null +++ b/.github/workflows/rerun.yml @@ -0,0 +1,14 @@ +on: + issue_comment: + types: [created] + +jobs: + rerun_tests: + name: rerun_pr_tests + if: ${{ github.event.issue.pull_request }} + runs-on: ubuntu-18.04 + steps: + - uses: estroz/rerun-actions@v0.3.0 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + comment_id: ${{ github.event.comment.id }} From 4f149b7856c04b363fee8d6f905a4cd61859ace2 Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Wed, 13 Jan 2021 20:04:57 -0800 Subject: [PATCH 268/376] hack/ci: remove workflows dir from docs-only check (#4343) Signed-off-by: reinvantveer --- hack/ci/check-doc-only-update.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/hack/ci/check-doc-only-update.sh b/hack/ci/check-doc-only-update.sh index c768227a8c4..5bc6b9ad488 100755 --- a/hack/ci/check-doc-only-update.sh +++ b/hack/ci/check-doc-only-update.sh @@ -22,7 +22,6 @@ DOC_PATTERNS=( "^(MAINTAINERS)" "^(SECURITY)" "^(LICENSE)" - "^(\.github/workflows/)" ) if ! git diff --name-only $1 | grep -qvE "$(IFS="|"; echo "${DOC_PATTERNS[*]}")"; then From 617092a91933d1d6743c8ff07d68ffeffabfe103 Mon Sep 17 00:00:00 2001 From: Rashmi Gottipati Date: Thu, 14 Jan 2021 17:51:21 -0500 Subject: [PATCH 269/376] Upgrade operator bundle from traditional operator installation (#4399) * Handle use-case where operator bundle was installed traditionally using OLM * This functionality enables operator bundle upgrade even if an operator was not installed via `run bundle` command Signed-off-by: reinvantveer --- internal/olm/operator/registry/index_image.go | 40 ++++++++++++------- .../operator/registry/operator_installer.go | 13 ------ 2 files changed, 25 insertions(+), 28 deletions(-) diff --git a/internal/olm/operator/registry/index_image.go b/internal/olm/operator/registry/index_image.go index 831821474fd..2c98277c0cc 100644 --- a/internal/olm/operator/registry/index_image.go +++ b/internal/olm/operator/registry/index_image.go @@ -17,6 +17,7 @@ package registry import ( "context" "encoding/json" + "errors" "fmt" "time" @@ -74,7 +75,7 @@ func (c IndexImageCatalogCreator) CreateCatalog(ctx context.Context, name string } newItems := []index.BundleItem{{ImageTag: c.BundleImage, AddMode: c.BundleAddMode}} - if err := c.createAnnotatedRegistry(ctx, cs, newItems, updateFeildsNoOp); err != nil { + if err := c.createAnnotatedRegistry(ctx, cs, newItems, updateFieldsNoOp); err != nil { return nil, fmt.Errorf("error creating registry pod: %v", err) } @@ -91,6 +92,22 @@ func (c IndexImageCatalogCreator) UpdateCatalog(ctx context.Context, cs *v1alpha } prevRegistryPodName = annotations[registryPodNameAnnotation] } + + existingItems, err := getExistingBundleItems(cs.GetAnnotations()) + if err != nil { + return fmt.Errorf("error getting existing bundles from CatalogSource %s annotations: %v", cs.GetName(), err) + } + annotationsNotFound := len(existingItems) == 0 + + if annotationsNotFound { + if cs.Spec.Image == "" { + // if no annotations exist and image reference is empty, error out + return errors.New("cannot upgrade: no catalog image reference exists in catalog source spec or annotations") + } + // if no annotations exist and image reference exists, set it to index image + c.IndexImage = cs.Spec.Image + } + // Default add mode here since it depends on an existing annotation. if c.BundleAddMode == "" { if c.IndexImage == index.DefaultIndexImage { @@ -100,22 +117,16 @@ func (c IndexImageCatalogCreator) UpdateCatalog(ctx context.Context, cs *v1alpha } } - existingItems, err := getExistingBundleItems(cs.GetAnnotations()) - if err != nil { - return fmt.Errorf("error getting existing bundles from CatalogSource %s annotations: %v", cs.GetName(), err) - } - imageReferenceExists := len(existingItems) == 0 - newItem := index.BundleItem{ImageTag: c.BundleImage, AddMode: c.BundleAddMode} existingItems = append(existingItems, newItem) - updateFields := func(*v1alpha1.CatalogSource) { - // set `spec.Image` field to empty as we will be setting the address field in - // catalog source to point to the new new registry pod - if imageReferenceExists { - cs.Spec.Image = "" - } + updateFields := func(cs *v1alpha1.CatalogSource) { + // set `spec.Image` field to empty as we set the address in + // catalog source to registry pod IP + cs.Spec.Image = "" + } + if err := c.createAnnotatedRegistry(ctx, cs, existingItems, updateFields); err != nil { return fmt.Errorf("error creating registry pod: %v", err) } @@ -135,7 +146,6 @@ func (c IndexImageCatalogCreator) UpdateCatalog(ctx context.Context, cs *v1alpha // from items and that pod, then applies updateFields. func (c IndexImageCatalogCreator) createAnnotatedRegistry(ctx context.Context, cs *v1alpha1.CatalogSource, items []index.BundleItem, updateFields func(*v1alpha1.CatalogSource)) (err error) { - // Initialize and create registry pod registryPod := index.RegistryPod{ BundleItems: items, @@ -182,7 +192,7 @@ func (c IndexImageCatalogCreator) createAnnotatedRegistry(ctx context.Context, c } // Use if no extra updates need to be made to an annotated CatalogSource. -func updateFeildsNoOp(*v1alpha1.CatalogSource) {} +func updateFieldsNoOp(*v1alpha1.CatalogSource) {} // getDBPath returns the database path from the index image's labels. func (c IndexImageCatalogCreator) getDBPath(ctx context.Context) (string, error) { diff --git a/internal/olm/operator/registry/operator_installer.go b/internal/olm/operator/registry/operator_installer.go index 14c5c32fce8..301a04f625a 100644 --- a/internal/olm/operator/registry/operator_installer.go +++ b/internal/olm/operator/registry/operator_installer.go @@ -119,19 +119,6 @@ func (o OperatorInstaller) UpgradeOperator(ctx context.Context) (*v1alpha1.Clust log.Infof("Found existing subscription with name %s and namespace %s", subscription.Name, subscription.Namespace) - // todo: attempt #1 to trigger install plan for the subscription and - // to make it detect catalog changes, as per OLM suggestion - if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error { - // set the startingCSV to empty - subscription.Spec.StartingCSV = "" - if err := o.cfg.Client.Update(ctx, subscription); err != nil { - return fmt.Errorf("error updating subscription: %v", err) - } - return nil - }); err != nil { - return nil, err - } - // Get existing catalog source from the subsription catsrcKey := types.NamespacedName{ Namespace: subscription.Spec.CatalogSourceNamespace, From 0272d479073c2779e489833126852919910d16eb Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Thu, 14 Jan 2021 18:08:52 -0800 Subject: [PATCH 270/376] internal/testutils: fix bad err check (#4400) Signed-off-by: reinvantveer --- internal/testutils/utils.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/testutils/utils.go b/internal/testutils/utils.go index 81b39c7e49b..adb8cf658b7 100644 --- a/internal/testutils/utils.go +++ b/internal/testutils/utils.go @@ -148,7 +148,7 @@ func ReplaceRegexInFile(path, match, replace string) error { return err } s := matcher.ReplaceAllString(string(b), replace) - if err != nil { + if s == string(b) { return errors.New("unable to find the content to be replaced") } err = ioutil.WriteFile(path, []byte(s), info.Mode()) From 4931f32ec7d28faeec37d70ff26430a56b823f7e Mon Sep 17 00:00:00 2001 From: Jeff Geerling Date: Tue, 19 Jan 2021 16:47:17 -0600 Subject: [PATCH 271/376] Fix a tiny typo in Ansible tutorial. (#4404) Signed-off-by: reinvantveer --- website/content/en/docs/building-operators/ansible/tutorial.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/content/en/docs/building-operators/ansible/tutorial.md b/website/content/en/docs/building-operators/ansible/tutorial.md index b95d1b62ac1..460b07366e7 100644 --- a/website/content/en/docs/building-operators/ansible/tutorial.md +++ b/website/content/en/docs/building-operators/ansible/tutorial.md @@ -52,7 +52,7 @@ See [scaffolded files reference][layout-doc] and [watches reference][ansible-wat Now we need to provide the reconcile logic, in the form of an Ansible Role, which will run every time a `Memcached` resource is created, -updated, or delete. +updated, or deleted. Update `roles/memcached/tasks/main.yml`: From 4542eaa36b631dfe420fb9723379847972fa85d7 Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Tue, 19 Jan 2021 21:45:08 -0800 Subject: [PATCH 272/376] docs/upgrading-sdk-version/v0.19.0.md: add link to and note about v0.19.x migration guide (#4408) Signed-off-by: Eric Stroczynski Signed-off-by: reinvantveer --- website/content/en/docs/upgrading-sdk-version/v0.19.0.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/website/content/en/docs/upgrading-sdk-version/v0.19.0.md b/website/content/en/docs/upgrading-sdk-version/v0.19.0.md index 9b20584e4cd..44dee06393e 100644 --- a/website/content/en/docs/upgrading-sdk-version/v0.19.0.md +++ b/website/content/en/docs/upgrading-sdk-version/v0.19.0.md @@ -22,8 +22,12 @@ _See [#3265](https://github.com/operator-framework/operator-sdk/pull/3265) for m ## Migrating Go projects to the new Kubebuilder aligned project layout -See the [migration guide][migration-guide] that walks through an example of how -to migrate a Go based operator project from the old layout to the new layout. +See the [v0.19.0 project migration guide][migration-guide-v0.19.0] that walks through an example of how +to migrate a Go based operator project from the old layout to the v0.19.0 layout. Migrating to v0.19.0 +before v1.0.0 is practical if you plan to migrate your project between one minor version at a time. + +If you wish to migrate directly from the old layout to the latest v1.0.0+ layout, see +the [latest migration guide][migration-guide]. _See [#3190](https://github.com/operator-framework/operator-sdk/pull/3190) for more details._ @@ -48,3 +52,4 @@ to use `UpgradeError` instead of `UpdateError`. _See [#3269](https://github.com/operator-framework/operator-sdk/pull/3269) for more details._ [migration-guide]: /docs/building-operators/golang/migration/ +[migration-guide-v0.19.0]: https://v0-19-x.sdk.operatorframework.io/docs/golang/project_migration_guide/ From 538276f257d201ab58be274efe1dfd08f1800381 Mon Sep 17 00:00:00 2001 From: Martin Hickey Date: Wed, 20 Jan 2021 17:16:03 +0000 Subject: [PATCH 273/376] Updates to the tutorial docs (#4395) Fix issues in the operaor-sdk docs.. Signed-off-by: Martin Hickey Signed-off-by: reinvantveer --- .../docs/building-operators/ansible/quickstart.md | 1 - .../en/docs/building-operators/ansible/tutorial.md | 2 -- .../en/docs/building-operators/golang/quickstart.md | 8 +++++++- .../en/docs/building-operators/golang/tutorial.md | 13 +++++++++---- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/website/content/en/docs/building-operators/ansible/quickstart.md b/website/content/en/docs/building-operators/ansible/quickstart.md index 8fa68418d40..890ab13a701 100644 --- a/website/content/en/docs/building-operators/ansible/quickstart.md +++ b/website/content/en/docs/building-operators/ansible/quickstart.md @@ -36,7 +36,6 @@ Make sure to define `IMG` when you call `make`: make docker-build docker-push IMG=$OPERATOR_IMG ``` - ### OLM deployment 1. Install [OLM][doc-olm]: diff --git a/website/content/en/docs/building-operators/ansible/tutorial.md b/website/content/en/docs/building-operators/ansible/tutorial.md index 460b07366e7..55a50e8eee3 100644 --- a/website/content/en/docs/building-operators/ansible/tutorial.md +++ b/website/content/en/docs/building-operators/ansible/tutorial.md @@ -235,7 +235,6 @@ Ensure that the memcached operator creates the deployment for the sample CR with ```console $ kubectl get deployment NAME READY UP-TO-DATE AVAILABLE AGE -memcached-operator-controller-manager 1/1 1 1 8m memcached-sample 3/3 3 3 1m ``` @@ -284,7 +283,6 @@ Confirm that the operator changes the deployment size: ```console $ kubectl get deployment NAME READY UP-TO-DATE AVAILABLE AGE -memcached-operator-controller-manager 1/1 1 1 10m memcached-sample 5/5 5 5 3m ``` diff --git a/website/content/en/docs/building-operators/golang/quickstart.md b/website/content/en/docs/building-operators/golang/quickstart.md index 853fd8a558c..9dd16fdf604 100644 --- a/website/content/en/docs/building-operators/golang/quickstart.md +++ b/website/content/en/docs/building-operators/golang/quickstart.md @@ -10,7 +10,7 @@ This guide walks through an example of building a simple memcached-operator usin ## Prerequisites - Go through the [installation guide][install-guide]. -- User authorized with `cluster-admin` permissions +- User authorized with `cluster-admin` permissions. ## Steps @@ -37,6 +37,12 @@ Make sure to define `IMG` when you call `make`: make docker-build docker-push IMG=$OPERATOR_IMG ``` +**Note**: If using an OS which does not point `sh` to the `bash` shell (Ubuntu for example) then you should add the following line to the `Makefile`: + +`SHELL := /bin/bash` + +This will fix potential issues when the `docker-build` target runs the controller test suite. Issues maybe similar to following error: +`failed to start the controlplane. retried 5 times: fork/exec /usr/local/kubebuilder/bin/etcd: no such file or directory occurred` ### OLM deployment diff --git a/website/content/en/docs/building-operators/golang/tutorial.md b/website/content/en/docs/building-operators/golang/tutorial.md index 7cf12a489da..cddd79660fb 100644 --- a/website/content/en/docs/building-operators/golang/tutorial.md +++ b/website/content/en/docs/building-operators/golang/tutorial.md @@ -10,9 +10,9 @@ please [migrate][migration-guide], or consult the [legacy docs][legacy-quickstar ## Prerequisites -- [Install operator-sdk][operator_install] and its prequisites. +- Go through the [installation guide][install-guide]. - Access to a Kubernetes v1.11.3+ cluster (v1.16.0+ if using `apiextensions.k8s.io/v1` CRDs). -- User logged with admin permission. See [how to grant yourself cluster-admin privileges or be logged in as admin][role-based-access-control] +- User authorized with `cluster-admin` permissions. ## Create a new project @@ -314,6 +314,13 @@ make docker-build docker-push IMG=quay.io/$USERNAME/memcached-operator:v0.0.1 **Note**: The name and tag of the image (`IMG=/:tag`) in both the commands can also be set in the Makefile. Modify the line which has `IMG ?= controller:latest` to set your desired default image name. +**Note**: If using an OS which does not point `sh` to the `bash` shell (Ubuntu for example) then you should add the following line to the `Makefile`: + +`SHELL := /bin/bash` + +This will fix potential issues when the `docker-build` target runs the controller test suite. Issues maybe similar to following error: +`failed to start the controlplane. retried 5 times: fork/exec /usr/local/kubebuilder/bin/etcd: no such file or directory occurred` + #### Deploy the operator By default, a new namespace is created with name `-system`, i.e. memcached-operator-system and will be used for the deployment. @@ -386,7 +393,6 @@ Ensure that the memcached operator creates the deployment for the sample CR with ```console $ kubectl get deployment NAME READY UP-TO-DATE AVAILABLE AGE -memcached-operator-controller-manager 1/1 1 1 8m memcached-sample 3/3 3 3 1m ``` @@ -435,7 +441,6 @@ Confirm that the operator changes the deployment size: ```console $ kubectl get deployment NAME READY UP-TO-DATE AVAILABLE AGE -memcached-operator-controller-manager 1/1 1 1 10m memcached-sample 5/5 5 5 3m ``` From c890b29a2b2b37c84e7f9fd5224f1505af7e7c34 Mon Sep 17 00:00:00 2001 From: Camila Macedo Date: Wed, 20 Jan 2021 18:47:15 +0000 Subject: [PATCH 274/376] add better doc/description for bundle options in the Makefile (#4398) * add better doc/description for bundle options in the Makefile Signed-off-by: reinvantveer --- internal/plugins/manifests/init.go | 25 ++++++++++++++++---- testdata/ansible/memcached-operator/Makefile | 25 ++++++++++++++++---- testdata/go/v2/memcached-operator/Makefile | 25 ++++++++++++++++---- testdata/go/v3/memcached-operator/Makefile | 25 ++++++++++++++++---- testdata/helm/memcached-operator/Makefile | 25 ++++++++++++++++---- 5 files changed, 105 insertions(+), 20 deletions(-) diff --git a/internal/plugins/manifests/init.go b/internal/plugins/manifests/init.go index f8e78148f44..7061dd02fe3 100644 --- a/internal/plugins/manifests/init.go +++ b/internal/plugins/manifests/init.go @@ -71,18 +71,35 @@ func initUpdateMakefile(cfg *config.Config, filePath string) error { // Makefile fragments to add to the base Makefile. const ( - makefileBundleVarFragment = `# Current Operator version + makefileBundleVarFragment = `# VERSION defines the project version for the bundle. +# Update this value when you upgrade the version of your project. +# To re-generate a bundle for another specific version without changing the standard setup, you can: +# - use the VERSION as arg of the bundle target (e.g make bundle VERSION=0.0.2) +# - use environment variables to overwrite this value (e.g export VERSION=0.0.2) VERSION ?= 0.0.1 -# Default bundle image tag -BUNDLE_IMG ?= controller-bundle:$(VERSION) -# Options for 'bundle-build' + +# CHANNELS define the bundle channels used in the bundle. +# Add a new line here if you would like to change its default config. (E.g CHANNELS = "preview,fast,stable") +# To re-generate a bundle for other specific channels without changing the standard setup, you can: +# - use the CHANNELS as arg of the bundle target (e.g make bundle CHANNELS=preview,fast,stable) +# - use environment variables to overwrite this value (e.g export CHANNELS="preview,fast,stable") ifneq ($(origin CHANNELS), undefined) BUNDLE_CHANNELS := --channels=$(CHANNELS) endif + +# DEFAULT_CHANNEL defines the default channel used in the bundle. +# Add a new line here if you would like to change its default config. (E.g DEFAULT_CHANNEL = "stable") +# To re-generate a bundle for any other default channel without changing the default setup, you can: +# - use the DEFAULT_CHANNEL as arg of the bundle target (e.g make bundle DEFAULT_CHANNEL=stable) +# - use environment variables to overwrite this value (e.g export DEFAULT_CHANNEL="stable") ifneq ($(origin DEFAULT_CHANNEL), undefined) BUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL) endif BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL) + +# BUNDLE_IMG defines the image:tag used for the bundle. +# You can use it as an arg. (E.g make bundle-build BUNDLE_IMG=/:) +BUNDLE_IMG ?= controller-bundle:$(VERSION) ` makefileBundleFragmentGo = ` diff --git a/testdata/ansible/memcached-operator/Makefile b/testdata/ansible/memcached-operator/Makefile index 3aeddf1d189..4c91806f45a 100644 --- a/testdata/ansible/memcached-operator/Makefile +++ b/testdata/ansible/memcached-operator/Makefile @@ -1,16 +1,33 @@ -# Current Operator version +# VERSION defines the project version for the bundle. +# Update this value when you upgrade the version of your project. +# To re-generate a bundle for another specific version without changing the standard setup, you can: +# - use the VERSION as arg of the bundle target (e.g make bundle VERSION=0.0.2) +# - use environment variables to overwrite this value (e.g export VERSION=0.0.2) VERSION ?= 0.0.1 -# Default bundle image tag -BUNDLE_IMG ?= controller-bundle:$(VERSION) -# Options for 'bundle-build' + +# CHANNELS define the bundle channels used in the bundle. +# Add a new line here if you would like to change its default config. (E.g CHANNELS = "preview,fast,stable") +# To re-generate a bundle for other specific channels without changing the standard setup, you can: +# - use the CHANNELS as arg of the bundle target (e.g make bundle CHANNELS=preview,fast,stable) +# - use environment variables to overwrite this value (e.g export CHANNELS="preview,fast,stable") ifneq ($(origin CHANNELS), undefined) BUNDLE_CHANNELS := --channels=$(CHANNELS) endif + +# DEFAULT_CHANNEL defines the default channel used in the bundle. +# Add a new line here if you would like to change its default config. (E.g DEFAULT_CHANNEL = "stable") +# To re-generate a bundle for any other default channel without changing the default setup, you can: +# - use the DEFAULT_CHANNEL as arg of the bundle target (e.g make bundle DEFAULT_CHANNEL=stable) +# - use environment variables to overwrite this value (e.g export DEFAULT_CHANNEL="stable") ifneq ($(origin DEFAULT_CHANNEL), undefined) BUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL) endif BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL) +# BUNDLE_IMG defines the image:tag used for the bundle. +# You can use it as an arg. (E.g make bundle-build BUNDLE_IMG=/:) +BUNDLE_IMG ?= controller-bundle:$(VERSION) + # Image URL to use all building/pushing image targets IMG ?= controller:latest diff --git a/testdata/go/v2/memcached-operator/Makefile b/testdata/go/v2/memcached-operator/Makefile index 12c07cdaee4..aa657472947 100644 --- a/testdata/go/v2/memcached-operator/Makefile +++ b/testdata/go/v2/memcached-operator/Makefile @@ -1,16 +1,33 @@ -# Current Operator version +# VERSION defines the project version for the bundle. +# Update this value when you upgrade the version of your project. +# To re-generate a bundle for another specific version without changing the standard setup, you can: +# - use the VERSION as arg of the bundle target (e.g make bundle VERSION=0.0.2) +# - use environment variables to overwrite this value (e.g export VERSION=0.0.2) VERSION ?= 0.0.1 -# Default bundle image tag -BUNDLE_IMG ?= controller-bundle:$(VERSION) -# Options for 'bundle-build' + +# CHANNELS define the bundle channels used in the bundle. +# Add a new line here if you would like to change its default config. (E.g CHANNELS = "preview,fast,stable") +# To re-generate a bundle for other specific channels without changing the standard setup, you can: +# - use the CHANNELS as arg of the bundle target (e.g make bundle CHANNELS=preview,fast,stable) +# - use environment variables to overwrite this value (e.g export CHANNELS="preview,fast,stable") ifneq ($(origin CHANNELS), undefined) BUNDLE_CHANNELS := --channels=$(CHANNELS) endif + +# DEFAULT_CHANNEL defines the default channel used in the bundle. +# Add a new line here if you would like to change its default config. (E.g DEFAULT_CHANNEL = "stable") +# To re-generate a bundle for any other default channel without changing the default setup, you can: +# - use the DEFAULT_CHANNEL as arg of the bundle target (e.g make bundle DEFAULT_CHANNEL=stable) +# - use environment variables to overwrite this value (e.g export DEFAULT_CHANNEL="stable") ifneq ($(origin DEFAULT_CHANNEL), undefined) BUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL) endif BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL) +# BUNDLE_IMG defines the image:tag used for the bundle. +# You can use it as an arg. (E.g make bundle-build BUNDLE_IMG=/:) +BUNDLE_IMG ?= controller-bundle:$(VERSION) + # Image URL to use all building/pushing image targets IMG ?= controller:latest # Produce CRDs that work back to Kubernetes 1.11 (no version conversion) diff --git a/testdata/go/v3/memcached-operator/Makefile b/testdata/go/v3/memcached-operator/Makefile index 4a517477bf3..4d63bd71bbb 100644 --- a/testdata/go/v3/memcached-operator/Makefile +++ b/testdata/go/v3/memcached-operator/Makefile @@ -1,16 +1,33 @@ -# Current Operator version +# VERSION defines the project version for the bundle. +# Update this value when you upgrade the version of your project. +# To re-generate a bundle for another specific version without changing the standard setup, you can: +# - use the VERSION as arg of the bundle target (e.g make bundle VERSION=0.0.2) +# - use environment variables to overwrite this value (e.g export VERSION=0.0.2) VERSION ?= 0.0.1 -# Default bundle image tag -BUNDLE_IMG ?= controller-bundle:$(VERSION) -# Options for 'bundle-build' + +# CHANNELS define the bundle channels used in the bundle. +# Add a new line here if you would like to change its default config. (E.g CHANNELS = "preview,fast,stable") +# To re-generate a bundle for other specific channels without changing the standard setup, you can: +# - use the CHANNELS as arg of the bundle target (e.g make bundle CHANNELS=preview,fast,stable) +# - use environment variables to overwrite this value (e.g export CHANNELS="preview,fast,stable") ifneq ($(origin CHANNELS), undefined) BUNDLE_CHANNELS := --channels=$(CHANNELS) endif + +# DEFAULT_CHANNEL defines the default channel used in the bundle. +# Add a new line here if you would like to change its default config. (E.g DEFAULT_CHANNEL = "stable") +# To re-generate a bundle for any other default channel without changing the default setup, you can: +# - use the DEFAULT_CHANNEL as arg of the bundle target (e.g make bundle DEFAULT_CHANNEL=stable) +# - use environment variables to overwrite this value (e.g export DEFAULT_CHANNEL="stable") ifneq ($(origin DEFAULT_CHANNEL), undefined) BUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL) endif BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL) +# BUNDLE_IMG defines the image:tag used for the bundle. +# You can use it as an arg. (E.g make bundle-build BUNDLE_IMG=/:) +BUNDLE_IMG ?= controller-bundle:$(VERSION) + # Image URL to use all building/pushing image targets IMG ?= controller:latest # Produce CRDs that work back to Kubernetes 1.11 (no version conversion) diff --git a/testdata/helm/memcached-operator/Makefile b/testdata/helm/memcached-operator/Makefile index 4fdc5c786eb..0dcd6e4bf12 100644 --- a/testdata/helm/memcached-operator/Makefile +++ b/testdata/helm/memcached-operator/Makefile @@ -1,16 +1,33 @@ -# Current Operator version +# VERSION defines the project version for the bundle. +# Update this value when you upgrade the version of your project. +# To re-generate a bundle for another specific version without changing the standard setup, you can: +# - use the VERSION as arg of the bundle target (e.g make bundle VERSION=0.0.2) +# - use environment variables to overwrite this value (e.g export VERSION=0.0.2) VERSION ?= 0.0.1 -# Default bundle image tag -BUNDLE_IMG ?= controller-bundle:$(VERSION) -# Options for 'bundle-build' + +# CHANNELS define the bundle channels used in the bundle. +# Add a new line here if you would like to change its default config. (E.g CHANNELS = "preview,fast,stable") +# To re-generate a bundle for other specific channels without changing the standard setup, you can: +# - use the CHANNELS as arg of the bundle target (e.g make bundle CHANNELS=preview,fast,stable) +# - use environment variables to overwrite this value (e.g export CHANNELS="preview,fast,stable") ifneq ($(origin CHANNELS), undefined) BUNDLE_CHANNELS := --channels=$(CHANNELS) endif + +# DEFAULT_CHANNEL defines the default channel used in the bundle. +# Add a new line here if you would like to change its default config. (E.g DEFAULT_CHANNEL = "stable") +# To re-generate a bundle for any other default channel without changing the default setup, you can: +# - use the DEFAULT_CHANNEL as arg of the bundle target (e.g make bundle DEFAULT_CHANNEL=stable) +# - use environment variables to overwrite this value (e.g export DEFAULT_CHANNEL="stable") ifneq ($(origin DEFAULT_CHANNEL), undefined) BUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL) endif BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL) +# BUNDLE_IMG defines the image:tag used for the bundle. +# You can use it as an arg. (E.g make bundle-build BUNDLE_IMG=/:) +BUNDLE_IMG ?= controller-bundle:$(VERSION) + # Image URL to use all building/pushing image targets IMG ?= controller:latest From 84e4a8503c88633bcb781b8c559556b0b08fe3a9 Mon Sep 17 00:00:00 2001 From: Varsha Date: Wed, 20 Jan 2021 10:54:02 -0800 Subject: [PATCH 275/376] Update doc with upstream conditions (#4410) Update doc with upstream conditions Signed-off-by: varshaprasad96 Signed-off-by: reinvantveer --- .../golang/advanced-topics.md | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/website/content/en/docs/building-operators/golang/advanced-topics.md b/website/content/en/docs/building-operators/golang/advanced-topics.md index 979023a8ed5..1e1d71116a0 100644 --- a/website/content/en/docs/building-operators/golang/advanced-topics.md +++ b/website/content/en/docs/building-operators/golang/advanced-topics.md @@ -6,7 +6,7 @@ weight: 80 ### Manage CR status conditions -An often-used pattern is to include `Conditions` in the status of custom resources. Conditions represent the latest available observations of an object's state (see the [Kubernetes API conventions documentation][typical-status-properties] for more information). +An often-used pattern is to include `Conditions` in the status of custom resources. A [`Condition`][apimachinery_condition] represents the latest available observations of an object's state (see the [Kubernetes API conventions documentation][typical-status-properties] for more information). The `Conditions` field added to the `MemcachedStatus` struct simplifies the management of your CR's conditions. It: - Enables callers to add and remove conditions. @@ -19,22 +19,16 @@ To use conditions in your custom resource, add a Conditions field to the Status ```Go import ( - "github.com/operator-framework/operator-lib/status" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) type MyAppStatus struct { // Conditions represent the latest available observations of an object's state - Conditions status.Conditions `json:"conditions"` + Conditions []metav1.Condition `json:"conditions"` } ``` -Then, in your controller, you can use [`Conditions`][godoc-conditions] methods to make it easier to set and remove conditions or check their current values. - -**NOTE:** The `status` package was removed in operator-lib `v0.2.0` in deference to the upstream [`metav1.Condition`][apimachinery_condition] type, so your project must depend on version [`v0.1.0`][operator-lib-0.1.0] to use `status.Conditions`: - -```sh -go get github.com/operator-framework/operator-lib@v0.1.0 -``` +Then, in your controller, you can use [`Conditions`][helpers-conditions] methods to make it easier to set and remove conditions or check their current values. ### Adding 3rd Party Resources To Your Operator @@ -292,7 +286,6 @@ func main() { When the operator is not running in a cluster, the Manager will return an error on starting since it can't detect the operator's namespace in order to create the configmap for leader election. You can override this namespace by setting the Manager's `LeaderElectionNamespace` option. [typical-status-properties]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties -[godoc-conditions]: https://pkg.go.dev/github.com/operator-framework/operator-lib@v0.1.0/status#Conditions [scheme_package]:https://github.com/kubernetes/client-go/blob/master/kubernetes/scheme/register.go [deployments_register]: https://github.com/kubernetes/api/blob/master/apps/v1/register.go#L41 [runtime_package]: https://godoc.org/k8s.io/apimachinery/pkg/runtime @@ -304,4 +297,4 @@ When the operator is not running in a cluster, the Manager will return an error [pod_eviction_timeout]: https://kubernetes.io/docs/reference/command-line-tools-reference/kube-controller-manager/#options [manager_options]: https://godoc.org/github.com/kubernetes-sigs/controller-runtime/pkg/manager#Options [apimachinery_condition]: https://github.com/kubernetes/apimachinery/blob/d4f471b82f0a17cda946aeba446770563f92114d/pkg/apis/meta/v1/types.go#L1368 -[operator-lib-0.1.0]: https://github.com/operator-framework/operator-lib/releases/tag/v0.1.0 +[helpers-conditions]: https://github.com/kubernetes/apimachinery/blob/master/pkg/api/meta/conditions.go From fbaf1539614897be810377e4ed07bbd054a8e0eb Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Wed, 20 Jan 2021 11:20:07 -0800 Subject: [PATCH 276/376] (helm/v1,ansible/v1) fix download URLs and order of binary checks (#4407) Signed-off-by: Eric Stroczynski Signed-off-by: reinvantveer --- .../helm-ansible-download-makefile.yaml | 18 +++++++++ .../scaffolds/internal/templates/makefile.go | 38 +++++++++++-------- .../scaffolds/internal/templates/makefile.go | 38 +++++++++++-------- testdata/ansible/memcached-operator/Makefile | 38 +++++++++++-------- testdata/helm/memcached-operator/Makefile | 38 +++++++++++-------- 5 files changed, 106 insertions(+), 64 deletions(-) create mode 100644 changelog/fragments/helm-ansible-download-makefile.yaml diff --git a/changelog/fragments/helm-ansible-download-makefile.yaml b/changelog/fragments/helm-ansible-download-makefile.yaml new file mode 100644 index 00000000000..7de2f2cb411 --- /dev/null +++ b/changelog/fragments/helm-ansible-download-makefile.yaml @@ -0,0 +1,18 @@ +entries: + - description: > + Corrected the download URL for helm-operator and ansible-operator in their respective project types. + kind: bugfix + migration: + header: For Helm and Ansible projects, fix the helm-operator and ansible-operator URLs in the Makefile + body: > + Helm projects: `https://github.com/operator-framework/operator-sdk/releases/download/v1.3.0/helm-operator-v1.3.0-$(ARCHOPER)-$(OSOPER)` + -> `https://github.com/operator-framework/operator-sdk/releases/download/v1.3.0/helm-operator_$(OS)_$(ARCH)` + Ansible projects: `https://github.com/operator-framework/operator-sdk/releases/download/v1.3.0/ansible-operator-v1.3.0-$(ARCHOPER)-$(OSOPER)` + -> `https://github.com/operator-framework/operator-sdk/releases/download/v1.3.0/ansible-operator_$(OS)_$(ARCH)` + - description: > + Fixed the order of helm-operator, ansible-operator, and kustomize binary checks in the Makefile. + kind: bugfix + migration: + header: For Helm and Ansible projects, fix the helm-operator, ansible-operator, and kustomize Makefile rules + body: > + See the diff in [this PR](https://github.com/operator-framework/operator-sdk/pull/4407) for details. diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/makefile.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/makefile.go index 2a927b26faf..fcf32617f41 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/makefile.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/makefile.go @@ -101,34 +101,40 @@ docker-push: PATH := $(PATH):$(PWD)/bin SHELL := env PATH=$(PATH) /bin/sh -OS = $(shell uname -s | tr '[:upper:]' '[:lower:]') -ARCH = $(shell uname -m | sed 's/x86_64/amd64/') -OSOPER = $(shell uname -s | tr '[:upper:]' '[:lower:]' | sed 's/darwin/apple-darwin/' | sed 's/linux/linux-gnu/') -ARCHOPER = $(shell uname -m ) +OS := $(shell uname -s | tr '[:upper:]' '[:lower:]') +ARCH := $(shell uname -m | sed 's/x86_64/amd64/') +# Download kustomize locally if necessary, preferring the $(pwd)/bin path over global if both exist. +.PHONY: kustomize +KUSTOMIZE = $(shell pwd)/bin/kustomize kustomize: -ifeq (, $(shell which kustomize 2>/dev/null)) +ifeq (,$(wildcard $(KUSTOMIZE))) +ifeq (,$(shell which kustomize 2>/dev/null)) @{ \ set -e ;\ - mkdir -p bin ;\ - curl -sSLo - https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/{{ .KustomizeVersion }}/kustomize_{{ .KustomizeVersion }}_$(OS)_$(ARCH).tar.gz | tar xzf - -C bin/ ;\ + mkdir -p $(dir $(KUSTOMIZE)) ;\ + curl -sSLo - https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/{{ .KustomizeVersion }}/kustomize_{{ .KustomizeVersion }}_$(OS)_$(ARCH).tar.gz | \ + tar xzf - -C bin/ ;\ } -KUSTOMIZE=$(realpath ./bin/kustomize) else -KUSTOMIZE=$(shell which kustomize) +KUSTOMIZE = $(shell which kustomize) +endif endif +# Download ansible-operator locally if necessary, preferring the $(pwd)/bin path over global if both exist. +.PHONY: ansible-operator +ANSIBLE_OPERATOR = $(shell pwd)/bin/ansible-operator ansible-operator: -ifeq (, $(shell which ansible-operator 2>/dev/null)) +ifeq (,$(wildcard $(ANSIBLE_OPERATOR))) +ifeq (,$(shell which ansible-operator 2>/dev/null)) @{ \ set -e ;\ - mkdir -p bin ;\ - curl -LO https://github.com/operator-framework/operator-sdk/releases/download/{{ .AnsibleOperatorVersion}}/ansible-operator-{{ .AnsibleOperatorVersion}}-$(ARCHOPER)-$(OSOPER) ;\ - mv ansible-operator-{{ .AnsibleOperatorVersion}}-$(ARCHOPER)-$(OSOPER) ./bin/ansible-operator ;\ - chmod +x ./bin/ansible-operator ;\ + mkdir -p $(dir $(ANSIBLE_OPERATOR)) ;\ + curl -sSLo $(ANSIBLE_OPERATOR) https://github.com/operator-framework/operator-sdk/releases/download/{{ .AnsibleOperatorVersion }}/ansible-operator_$(OS)_$(ARCH) ;\ + chmod +x $(ANSIBLE_OPERATOR) ;\ } -ANSIBLE_OPERATOR=$(realpath ./bin/ansible-operator) else -ANSIBLE_OPERATOR=$(shell which ansible-operator) +ANSIBLE_OPERATOR = $(shell which ansible-operator) +endif endif ` diff --git a/internal/plugins/helm/v1/scaffolds/internal/templates/makefile.go b/internal/plugins/helm/v1/scaffolds/internal/templates/makefile.go index f5af0f1039b..c530b16970d 100644 --- a/internal/plugins/helm/v1/scaffolds/internal/templates/makefile.go +++ b/internal/plugins/helm/v1/scaffolds/internal/templates/makefile.go @@ -101,34 +101,40 @@ docker-push: PATH := $(PATH):$(PWD)/bin SHELL := env PATH=$(PATH) /bin/sh -OS = $(shell uname -s | tr '[:upper:]' '[:lower:]') -ARCH = $(shell uname -m | sed 's/x86_64/amd64/') -OSOPER = $(shell uname -s | tr '[:upper:]' '[:lower:]' | sed 's/darwin/apple-darwin/' | sed 's/linux/linux-gnu/') -ARCHOPER = $(shell uname -m ) +OS := $(shell uname -s | tr '[:upper:]' '[:lower:]') +ARCH := $(shell uname -m | sed 's/x86_64/amd64/') +# Download kustomize locally if necessary, preferring the $(pwd)/bin path over global if both exist. +.PHONY: kustomize +KUSTOMIZE = $(shell pwd)/bin/kustomize kustomize: -ifeq (, $(shell which kustomize 2>/dev/null)) +ifeq (,$(wildcard $(KUSTOMIZE))) +ifeq (,$(shell which kustomize 2>/dev/null)) @{ \ set -e ;\ - mkdir -p bin ;\ - curl -sSLo - https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/{{ .KustomizeVersion }}/kustomize_{{ .KustomizeVersion }}_$(OS)_$(ARCH).tar.gz | tar xzf - -C bin/ ;\ + mkdir -p $(dir $(KUSTOMIZE)) ;\ + curl -sSLo - https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/{{ .KustomizeVersion }}/kustomize_{{ .KustomizeVersion }}_$(OS)_$(ARCH).tar.gz | \ + tar xzf - -C bin/ ;\ } -KUSTOMIZE=$(realpath ./bin/kustomize) else -KUSTOMIZE=$(shell which kustomize) +KUSTOMIZE = $(shell which kustomize) +endif endif +# Download helm-operator locally if necessary, preferring the $(pwd)/bin path over global if both exist. +.PHONY: helm-operator +HELM_OPERATOR = $(shell pwd)/bin/helm-operator helm-operator: -ifeq (, $(shell which helm-operator 2>/dev/null)) +ifeq (,$(wildcard $(HELM_OPERATOR))) +ifeq (,$(shell which helm-operator 2>/dev/null)) @{ \ set -e ;\ - mkdir -p bin ;\ - curl -LO https://github.com/operator-framework/operator-sdk/releases/download/{{ .HelmOperatorVersion }}/helm-operator-{{ .HelmOperatorVersion }}-$(ARCHOPER)-$(OSOPER) ;\ - mv helm-operator-{{ .HelmOperatorVersion }}-$(ARCHOPER)-$(OSOPER) ./bin/helm-operator ;\ - chmod +x ./bin/helm-operator ;\ + mkdir -p $(dir $(HELM_OPERATOR)) ;\ + curl -sSLo $(HELM_OPERATOR) https://github.com/operator-framework/operator-sdk/releases/download/{{ .HelmOperatorVersion }}/helm-operator_$(OS)_$(ARCH) ;\ + chmod +x $(HELM_OPERATOR) ;\ } -HELM_OPERATOR=$(realpath ./bin/helm-operator) else -HELM_OPERATOR=$(shell which helm-operator) +HELM_OPERATOR = $(shell which helm-operator) +endif endif ` diff --git a/testdata/ansible/memcached-operator/Makefile b/testdata/ansible/memcached-operator/Makefile index 4c91806f45a..f667456f0f1 100644 --- a/testdata/ansible/memcached-operator/Makefile +++ b/testdata/ansible/memcached-operator/Makefile @@ -64,35 +64,41 @@ docker-push: PATH := $(PATH):$(PWD)/bin SHELL := env PATH=$(PATH) /bin/sh -OS = $(shell uname -s | tr '[:upper:]' '[:lower:]') -ARCH = $(shell uname -m | sed 's/x86_64/amd64/') -OSOPER = $(shell uname -s | tr '[:upper:]' '[:lower:]' | sed 's/darwin/apple-darwin/' | sed 's/linux/linux-gnu/') -ARCHOPER = $(shell uname -m ) +OS := $(shell uname -s | tr '[:upper:]' '[:lower:]') +ARCH := $(shell uname -m | sed 's/x86_64/amd64/') +# Download kustomize locally if necessary, preferring the $(pwd)/bin path over global if both exist. +.PHONY: kustomize +KUSTOMIZE = $(shell pwd)/bin/kustomize kustomize: -ifeq (, $(shell which kustomize 2>/dev/null)) +ifeq (,$(wildcard $(KUSTOMIZE))) +ifeq (,$(shell which kustomize 2>/dev/null)) @{ \ set -e ;\ - mkdir -p bin ;\ - curl -sSLo - https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/v3.5.4/kustomize_v3.5.4_$(OS)_$(ARCH).tar.gz | tar xzf - -C bin/ ;\ + mkdir -p $(dir $(KUSTOMIZE)) ;\ + curl -sSLo - https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/v3.5.4/kustomize_v3.5.4_$(OS)_$(ARCH).tar.gz | \ + tar xzf - -C bin/ ;\ } -KUSTOMIZE=$(realpath ./bin/kustomize) else -KUSTOMIZE=$(shell which kustomize) +KUSTOMIZE = $(shell which kustomize) +endif endif +# Download ansible-operator locally if necessary, preferring the $(pwd)/bin path over global if both exist. +.PHONY: ansible-operator +ANSIBLE_OPERATOR = $(shell pwd)/bin/ansible-operator ansible-operator: -ifeq (, $(shell which ansible-operator 2>/dev/null)) +ifeq (,$(wildcard $(ANSIBLE_OPERATOR))) +ifeq (,$(shell which ansible-operator 2>/dev/null)) @{ \ set -e ;\ - mkdir -p bin ;\ - curl -LO https://github.com/operator-framework/operator-sdk/releases/download/v1.3.0/ansible-operator-v1.3.0-$(ARCHOPER)-$(OSOPER) ;\ - mv ansible-operator-v1.3.0-$(ARCHOPER)-$(OSOPER) ./bin/ansible-operator ;\ - chmod +x ./bin/ansible-operator ;\ + mkdir -p $(dir $(ANSIBLE_OPERATOR)) ;\ + curl -sSLo $(ANSIBLE_OPERATOR) https://github.com/operator-framework/operator-sdk/releases/download/v1.3.0/ansible-operator_$(OS)_$(ARCH) ;\ + chmod +x $(ANSIBLE_OPERATOR) ;\ } -ANSIBLE_OPERATOR=$(realpath ./bin/ansible-operator) else -ANSIBLE_OPERATOR=$(shell which ansible-operator) +ANSIBLE_OPERATOR = $(shell which ansible-operator) +endif endif # Generate bundle manifests and metadata, then validate generated files. diff --git a/testdata/helm/memcached-operator/Makefile b/testdata/helm/memcached-operator/Makefile index 0dcd6e4bf12..a23f8fca9e6 100644 --- a/testdata/helm/memcached-operator/Makefile +++ b/testdata/helm/memcached-operator/Makefile @@ -64,35 +64,41 @@ docker-push: PATH := $(PATH):$(PWD)/bin SHELL := env PATH=$(PATH) /bin/sh -OS = $(shell uname -s | tr '[:upper:]' '[:lower:]') -ARCH = $(shell uname -m | sed 's/x86_64/amd64/') -OSOPER = $(shell uname -s | tr '[:upper:]' '[:lower:]' | sed 's/darwin/apple-darwin/' | sed 's/linux/linux-gnu/') -ARCHOPER = $(shell uname -m ) +OS := $(shell uname -s | tr '[:upper:]' '[:lower:]') +ARCH := $(shell uname -m | sed 's/x86_64/amd64/') +# Download kustomize locally if necessary, preferring the $(pwd)/bin path over global if both exist. +.PHONY: kustomize +KUSTOMIZE = $(shell pwd)/bin/kustomize kustomize: -ifeq (, $(shell which kustomize 2>/dev/null)) +ifeq (,$(wildcard $(KUSTOMIZE))) +ifeq (,$(shell which kustomize 2>/dev/null)) @{ \ set -e ;\ - mkdir -p bin ;\ - curl -sSLo - https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/v3.5.4/kustomize_v3.5.4_$(OS)_$(ARCH).tar.gz | tar xzf - -C bin/ ;\ + mkdir -p $(dir $(KUSTOMIZE)) ;\ + curl -sSLo - https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/v3.5.4/kustomize_v3.5.4_$(OS)_$(ARCH).tar.gz | \ + tar xzf - -C bin/ ;\ } -KUSTOMIZE=$(realpath ./bin/kustomize) else -KUSTOMIZE=$(shell which kustomize) +KUSTOMIZE = $(shell which kustomize) +endif endif +# Download helm-operator locally if necessary, preferring the $(pwd)/bin path over global if both exist. +.PHONY: helm-operator +HELM_OPERATOR = $(shell pwd)/bin/helm-operator helm-operator: -ifeq (, $(shell which helm-operator 2>/dev/null)) +ifeq (,$(wildcard $(HELM_OPERATOR))) +ifeq (,$(shell which helm-operator 2>/dev/null)) @{ \ set -e ;\ - mkdir -p bin ;\ - curl -LO https://github.com/operator-framework/operator-sdk/releases/download/v1.3.0/helm-operator-v1.3.0-$(ARCHOPER)-$(OSOPER) ;\ - mv helm-operator-v1.3.0-$(ARCHOPER)-$(OSOPER) ./bin/helm-operator ;\ - chmod +x ./bin/helm-operator ;\ + mkdir -p $(dir $(HELM_OPERATOR)) ;\ + curl -sSLo $(HELM_OPERATOR) https://github.com/operator-framework/operator-sdk/releases/download/v1.3.0/helm-operator_$(OS)_$(ARCH) ;\ + chmod +x $(HELM_OPERATOR) ;\ } -HELM_OPERATOR=$(realpath ./bin/helm-operator) else -HELM_OPERATOR=$(shell which helm-operator) +HELM_OPERATOR = $(shell which helm-operator) +endif endif # Generate bundle manifests and metadata, then validate generated files. From 975e1fda2a045469a860cdd5d0baf4dde6ed03d9 Mon Sep 17 00:00:00 2001 From: Varsha Date: Thu, 21 Jan 2021 11:08:41 -0800 Subject: [PATCH 277/376] Bump controller runtime 0.8.0 (#4405) Bump controller-runtime and related dependencies. Signed-off-by: varshaprasad96 Signed-off-by: reinvantveer --- go.mod | 27 +- go.sum | 232 +++++++++++++++--- internal/clientbuilder/clientbuilder.go | 52 ++++ internal/cmd/ansible-operator/run/cmd.go | 3 +- internal/cmd/helm-operator/run/cmd.go | 3 +- .../operator-sdk/generate/internal/genutil.go | 2 +- .../clusterserviceversion.go | 2 +- .../clusterserviceversion_test.go | 2 +- internal/olm/client/client.go | 2 +- internal/olm/installer/client.go | 2 +- .../registry/configmap/configmap_test.go | 2 +- .../registry/configmap/registry_test.go | 2 +- release/changelog/gen-changelog.go | 2 +- release/changelog/internal/changelog.go | 2 +- release/changelog/internal/changelog_test.go | 2 +- release/changelog/internal/migration_guide.go | 2 +- .../internal/migration_guide_test.go | 2 +- .../en/docs/cli/operator-sdk_completion.md | 4 - .../docs/cli/operator-sdk_completion_bash.md | 4 - .../docs/cli/operator-sdk_completion_zsh.md | 4 - .../cli/operator-sdk_generate_kustomize.md | 4 - .../content/en/docs/cli/operator-sdk_olm.md | 4 - .../en/docs/cli/operator-sdk_olm_install.md | 4 - .../en/docs/cli/operator-sdk_olm_status.md | 4 - .../en/docs/cli/operator-sdk_olm_uninstall.md | 4 - .../cli/operator-sdk_run_bundle-upgrade.md | 4 - .../en/docs/cli/operator-sdk_run_bundle.md | 4 - 27 files changed, 278 insertions(+), 103 deletions(-) create mode 100644 internal/clientbuilder/clientbuilder.go diff --git a/go.mod b/go.mod index d4459149378..74021f652f3 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/operator-framework/operator-sdk go 1.15 require ( - github.com/blang/semver v3.5.1+incompatible + github.com/blang/semver/v4 v4.0.0 github.com/fatih/structtag v1.1.0 github.com/go-logr/logr v0.3.0 github.com/iancoleman/strcase v0.0.0-20191112232945-16388991a334 @@ -11,36 +11,35 @@ require ( github.com/markbates/inflect v1.0.4 github.com/onsi/ginkgo v1.14.1 github.com/onsi/gomega v1.10.2 - github.com/operator-framework/api v0.4.0 - github.com/operator-framework/operator-lib v0.3.0 + github.com/operator-framework/api v0.5.2 + github.com/operator-framework/operator-lib v0.4.0 github.com/operator-framework/operator-registry v1.15.3 github.com/prometheus/client_golang v1.7.1 github.com/sergi/go-diff v1.0.0 github.com/sirupsen/logrus v1.7.0 github.com/spf13/afero v1.2.2 - github.com/spf13/cobra v1.0.0 + github.com/spf13/cobra v1.1.1 github.com/spf13/pflag v1.0.5 - github.com/spf13/viper v1.4.0 + github.com/spf13/viper v1.7.0 github.com/stretchr/testify v1.6.1 golang.org/x/tools v0.0.0-20201014231627-1610a49f37af gomodules.xyz/jsonpatch/v3 v3.0.1 helm.sh/helm/v3 v3.4.1 - k8s.io/api v0.19.4 - k8s.io/apiextensions-apiserver v0.19.4 - k8s.io/apimachinery v0.19.4 - k8s.io/cli-runtime v0.19.4 - k8s.io/client-go v0.19.4 - k8s.io/kubectl v0.19.4 + k8s.io/api v0.20.1 + k8s.io/apiextensions-apiserver v0.20.1 + k8s.io/apimachinery v0.20.1 + k8s.io/cli-runtime v0.20.1 + k8s.io/client-go v0.20.1 + k8s.io/kubectl v0.20.1 rsc.io/letsencrypt v0.0.3 // indirect - sigs.k8s.io/controller-runtime v0.7.0 + sigs.k8s.io/controller-runtime v0.8.0 sigs.k8s.io/controller-tools v0.4.1 sigs.k8s.io/kubebuilder/v2 v2.3.2-0.20201214213149-0a807f4e9428 sigs.k8s.io/yaml v1.2.0 ) replace ( - github.com/Azure/go-autorest => github.com/Azure/go-autorest v13.3.2+incompatible // Required by OLM - + github.com/Azure/go-autorest => github.com/Azure/go-autorest v14.2.0+incompatible // Required by OLM // Using containerd 1.4.0+ resolves an issue with invalid error logging // from an init function in containerd. This replace can be removed when // one of our direct dependencies begins using containerd v1.4.0+ diff --git a/go.sum b/go.sum index d13a76e29a3..8c487d1a8af 100644 --- a/go.sum +++ b/go.sum @@ -7,35 +7,62 @@ cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6A cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= cloud.google.com/go v0.51.0 h1:PvKAVQWCtlGUSlZkGW3QLelKaWq7KYv/MW1EboG8bfM= cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0 h1:3ithwDMr7/3vpAMXiH+ZQnYbuIsh+OPhUPMFC9enmn0= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= -github.com/Azure/go-autorest v13.3.2+incompatible h1:VxzPyuhtnlBOzc4IWCZHqpyH2d+QMLQEuy3wREyY4oc= -github.com/Azure/go-autorest v13.3.2+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= +github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= github.com/Azure/go-autorest/autorest v0.9.6 h1:5YWtOnckcudzIw8lPPBcWOnmIFWMtHci1ZWAZulMSx0= github.com/Azure/go-autorest/autorest v0.9.6/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630= +github.com/Azure/go-autorest/autorest v0.11.1 h1:eVvIXUKiTgv++6YnWb42DUA1YL7qDugnKP0HljexdnQ= +github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= github.com/Azure/go-autorest/autorest/adal v0.8.2 h1:O1X4oexUxnZCaEUGsvMnr8ZGj8HI37tNezwY4npRqA0= github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= +github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= +github.com/Azure/go-autorest/autorest/adal v0.9.5 h1:Y3bBUV4rTuxenJJs41HU3qmqsb+auo+a3Lz+PlJPpL0= +github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= github.com/Azure/go-autorest/autorest/date v0.2.0 h1:yW+Zlqf26583pE43KhfnhFcdmSWlm5Ew6bxipnr/tbM= github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= +github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= +github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.3.0 h1:qJumjCaCudz+OcqE9/XtEPfvtOjOmKaui4EOpFI6zZc= github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= +github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= +github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/logger v0.1.0 h1:ruG4BSDXONFRrZZJ2GUXDiUyVpayPmb1GnWeHDdaNKY= github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= +github.com/Azure/go-autorest/logger v0.2.0 h1:e4RVHVZKC5p6UANLJHkM4OfR1UKZPj8Wt8Pcx+3oqrE= +github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/tracing v0.5.0 h1:TRn4WjSnkcSy5AEG3pnbtFSwNtwzjr4VYyQflFE619k= github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= +github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= +github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= @@ -107,10 +134,13 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k= github.com/bitly/go-simplejson v0.5.0 h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkNEM+Y= github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= +github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= github.com/bshuster-repo/logrus-logstash-hook v0.4.1 h1:pgAtgj+A31JBVtEHu2uHuEx0n+2ukqUJnS2vVe5pQNA= @@ -158,6 +188,7 @@ github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd h1:JNn81o/xG+8N github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -254,14 +285,19 @@ github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZM github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/structtag v1.1.0 h1:6j4mUV/ES2duvnAzKMFkN6/A5mCaNYPD3xfbAkLLOF8= github.com/fatih/structtag v1.1.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= +github.com/form3tech-oss/jwt-go v3.2.2+incompatible h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk= +github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsouza/fake-gcs-server v1.7.0/go.mod h1:5XIRs4YvwNbNoz+1JF8j6KLAyDh7RHGAyAK3EP2EsNk= +github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= github.com/garyburd/redigo v1.6.0 h1:0VruCpn7yAIIu7pWVClQC8wxCJEcG3nyzpMSHKi1PQc= github.com/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= @@ -270,8 +306,11 @@ github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= +github.com/go-bindata/go-bindata/v3 v3.1.3 h1:F0nVttLC3ws0ojc7p60veTurcOm//D4QBODNM7EGrCI= github.com/go-bindata/go-bindata/v3 v3.1.3/go.mod h1:1/zrpXsLD8YDIbhZRqXzm1Ghc7NhEvIN9+Z6R5/xH4I= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -339,6 +378,8 @@ github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+ github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= github.com/go-openapi/validate v0.19.5 h1:QhCBKRYqZR+SKo4gl1lPhPahope8/RLt6EVgY8X80w0= github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4= +github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= @@ -359,6 +400,8 @@ github.com/gobuffalo/packr/v2 v2.7.1 h1:n3CIW5T17T8v4GGK5sWXLVWJhCz7b5aNLSxW6gYi github.com/gobuffalo/packr/v2 v2.7.1/go.mod h1:qYEvAazPaVxy7Y7KR0W8qYEE+RymX74kETFqjFoFlOc= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/goccy/go-yaml v1.8.1 h1:JuZRFlqLM5cWF6A+waL8AKVuCcqvKOuhJtUQI+L3ez0= +github.com/goccy/go-yaml v1.8.1/go.mod h1:wS4gNoLalDSJxo/SpngzPQ2BN4uuZVLCmbM4S3vd4+Y= github.com/gocql/gocql v0.0.0-20190301043612-f6df8288f9b4/go.mod h1:4Fw1eo5iaEhDUs8XyuhSVCVy52Jq3L+/3GJgYkwc+/0= github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godror/godror v0.13.3/go.mod h1:2ouUT4kdhUBk7TAkHWD4SN0CdI0pgEQbo8FVHhbSKWg= @@ -380,15 +423,21 @@ github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4er github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7 h1:5ZkaAPbicIKTF2I64qf5Fh8Aa83Q/dnOafMYV0OMwjA= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1 h1:qGJ6qTW+x6xX/my+8YUVl4WNpX9B7+/l2tRsHGZ7f2s= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1 h1:ocYkMQY5RrXTYgXl7ICpV0IXwlEQGwKIsery4gyXa1U= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -397,6 +446,8 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -422,10 +473,14 @@ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXi github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= @@ -435,6 +490,7 @@ github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3i github.com/googleapis/gnostic v0.5.1 h1:A8Yhf6EtqTv9RMsU6MQTyrtV1TjWlR6xU9BsZIwuTCM= github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= @@ -447,6 +503,7 @@ github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY= github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM= @@ -458,7 +515,9 @@ github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-health-probe v0.3.2/go.mod h1:izVOQ4RWbjUR6lm4nn+VLJyQ+FyaiGmprEYgI04Gs7U= github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= +github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= +github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -518,11 +577,13 @@ github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA= github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.2.0 h1:reN85Pxc5larApoH1keMBiu2GWtPqXQ1nc9gx+jOU+E= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -537,10 +598,13 @@ github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kshvakov/clickhouse v1.3.5/go.mod h1:DMzX7FxRymoNkVgizH0DWAL8Cur7wHLgx3MUnGwJqpE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw= github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o= github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk= github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= +github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.8.0 h1:9xohqzkUwzR4Ga4ivdTcawVS89YSDVxXMa3xJX3cGzg= @@ -553,6 +617,8 @@ github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= +github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -566,10 +632,17 @@ github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHef github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.7 h1:bQGKb3vps/j0E9GfJQ03JyhRuxsvdAanXlT9BTw3mdw= +github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-oci8 v0.0.7/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mNXJwGI= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y= @@ -584,6 +657,8 @@ github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88J github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mikefarah/yaml/v2 v2.4.0/go.mod h1:ahVqZF4n1W4NqwvVnZzC4es67xsW9uR/RRf2RRxieJU= github.com/mikefarah/yq/v2 v2.4.1/go.mod h1:i8SYf1XdgUvY2OFwSqGAtWOOgimD2McJ6iutoxRm4k0= +github.com/mikefarah/yq/v3 v3.0.0-20201202084205-8846255d1c37 h1:lPmsut5Sk7eK2BmDXuvNEvMbT7MkAJBu64Yxr7iJ6nk= +github.com/mikefarah/yq/v3 v3.0.0-20201202084205-8846255d1c37/go.mod h1:dYWq+UWoFCDY1TndvFUQuhBbIYmZpjreC8adEAx93zE= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= @@ -677,10 +752,10 @@ github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJ github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/operator-framework/api v0.3.22/go.mod h1:GVNiB6AQucwdZz3ZFXNv9HtcLOzcFnr6O/QldzKG93g= -github.com/operator-framework/api v0.4.0 h1:OeuGMXScjwosNKXttH3uorywr7APT5luTNPWy3zvqXs= -github.com/operator-framework/api v0.4.0/go.mod h1:xXYReW8+PpSBHMxsf0e7uhtfQTLqIM1iz4X6zUs20+c= -github.com/operator-framework/operator-lib v0.3.0 h1:eGJv0k7dEHIT9vfArWPo6U4eVurAOqhYUzXiHEaZq9g= -github.com/operator-framework/operator-lib v0.3.0/go.mod h1:LTp5UQd8ivq4MXqm/W/XHulHQ0RRoZXsAj73sNMAQxc= +github.com/operator-framework/api v0.5.2 h1:NLgOoi70+iyz4vVJeeJUKaFT8wZaCbCHzS1eExCqX7A= +github.com/operator-framework/api v0.5.2/go.mod h1:L7IvLd/ckxJEJg/t4oTTlnHKAJIP/p51AvEslW3wYdY= +github.com/operator-framework/operator-lib v0.4.0 h1:g7tGRo+FikHgFZDmRdHkOxyTv3sViI+Ujiqbfd9Tfsk= +github.com/operator-framework/operator-lib v0.4.0/go.mod h1:kOjV7h01DCSw3RZAqYdHyHyVwuJL8hvG53tSZoDZfsQ= github.com/operator-framework/operator-registry v1.15.3 h1:C+u+zjDh6yQAKN+DbUvPeLjojZtJftvp/J28rRqiWWU= github.com/operator-framework/operator-registry v1.15.3/go.mod h1:CI7cu5ANoSQB54XWr/hXefm1PbKNJztSrhGBEDLCNCg= github.com/otiai10/copy v1.2.0 h1:HvG945u96iNadPoG2/Ja2+AUJeW5YuFQMixq9yirC+k= @@ -750,6 +825,8 @@ github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDa github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4= +github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= @@ -781,8 +858,10 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= @@ -799,6 +878,8 @@ github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tL github.com/spf13/cobra v0.0.7/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= +github.com/spf13/cobra v1.1.1 h1:KfztREH0tPxJJ+geloSLaAkaPkr4ki2Er5quFV1TDo4= +github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= @@ -809,6 +890,8 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= +github.com/spf13/viper v1.7.0 h1:xVKxvI7ouOI5I+U9s2eeiUfMaWBVoXA3AWskkrqK0VM= +github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= @@ -822,6 +905,8 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= @@ -866,6 +951,7 @@ go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= go.etcd.io/etcd v0.5.0-alpha.5.0.20200819165624-17cef6e3e9d5/go.mod h1:skWido08r9w6Lq/w70DO5XYIKMu4QFu1+4VsqLQuJy8= +go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.0/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= @@ -877,6 +963,8 @@ go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2 h1:75k/FF0Q2YM8QYo07VPddOLBslDt1MZOdEslOHvmzAs= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= @@ -916,11 +1004,18 @@ golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 h1:hb9wdF1z5waM+dSIICn1l0DkLVDT3hqhhQsDNUmHPRE= +golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -932,11 +1027,15 @@ golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f h1:J5lckAjkw6qYlOZNj90mLYNTEKDvWeuc1yieZ8qUzUE= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -965,17 +1064,24 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191021144547-ec77196f6094/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -983,6 +1089,8 @@ golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6 h1:pE8b58s1HRDMi8RDc79m0HISf9D4TzseP40cEA6IGfs= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1023,7 +1131,10 @@ golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191020212454-3e7259c5e7c2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1032,8 +1143,13 @@ golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1041,6 +1157,9 @@ golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae h1:Ih9Yo4hSPImZOpfGuA4bR/ORKTAbhZo2AbWNRCnevdo= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201112073958-5cba982894dd h1:5CtCZbICpIOFdgO940moixOPjc0178IU44m4EjOO5IY= +golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1081,11 +1200,25 @@ golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191030203535-5e247c9ad0a0/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200403190813-44a64ad78b9b/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200616195046-dc31b401abb5/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20201014231627-1610a49f37af h1:VIUWFyOgzG3c0t9KYop5Ybp4m56LupfOnFYX7Ipnz+I= @@ -1109,7 +1242,12 @@ google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEt google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1131,11 +1269,22 @@ google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= google.golang.org/genproto v0.0.0-20191009194640-548a555dbc03/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200117163144-32f20d992d24/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200701001935-0939c5918c31 h1:Of4QP8bfRqzDROen6+s2j/p0jCPgzvQRd9nHiactfn4= google.golang.org/genproto v0.0.0-20200701001935-0939c5918c31/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a h1:pOwg4OoaRYScjmR4LlLgdtnyoHYTSAVhhqe5uPdpII8= +google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -1150,6 +1299,7 @@ google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRn google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.30.0 h1:M5a8xTlYTxwMn5ZFkwhRabsygDY5G8TYLyQDBxJNAxE= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc/cmd/protoc-gen-go-grpc v0.0.0-20200709232328-d8193ee9cc3e/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= @@ -1176,12 +1326,17 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= +gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= +gopkg.in/go-playground/validator.v9 v9.30.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= gopkg.in/gorp.v1 v1.7.2 h1:j3DWlAyGVv8whO7AcIWznQ2Yj7yJkn34B8s63GViAAw= gopkg.in/gorp.v1 v1.7.2/go.mod h1:Wo3h+DBQZIxATwftsglhdD/62zRFPhGhTiu5jUJmCaw= gopkg.in/imdario/mergo.v0 v0.3.7/go.mod h1:9qPP6AGrlC1G2PTNXko614FwGZvorN7MiBU0Eppok+U= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= +gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473 h1:6D+BvnJ/j6e222UW8s2qTSe3wGBtvo0MbVQG/c5k8RE= gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473/go.mod h1:N1eN2tsCx0Ydtgjl4cqmbRCsY4/+z4cYDeqwZTk6zog= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= @@ -1213,53 +1368,50 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/api v0.18.0/go.mod h1:q2HRQkfDzHMBZL9l/y9rH63PkQl4vae0xRT+8prbrK8= k8s.io/api v0.18.2/go.mod h1:SJCWI7OLzhZSvbY7U8zwNl9UA4o1fizoug34OV/2r78= -k8s.io/api v0.19.2/go.mod h1:IQpK0zFQ1xc5iNIQPqzgoOwuFugaYHK4iCknlAQP9nI= k8s.io/api v0.19.3/go.mod h1:VF+5FT1B74Pw3KxMdKyinLo+zynBaMBiAfGMuldcNDs= -k8s.io/api v0.19.4 h1:I+1I4cgJYuCDgiLNjKx7SLmIbwgj9w7N7Zr5vSIdwpo= -k8s.io/api v0.19.4/go.mod h1:SbtJ2aHCItirzdJ36YslycFNzWADYH3tgOhvBEFtZAk= +k8s.io/api v0.20.1 h1:ud1c3W3YNzGd6ABJlbFfKXBKXO+1KdGfcgGGNgFR03E= +k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= k8s.io/apiextensions-apiserver v0.18.2/go.mod h1:q3faSnRGmYimiocj6cHQ1I3WpLqmDgJFlKL37fC4ZvY= -k8s.io/apiextensions-apiserver v0.19.2/go.mod h1:EYNjpqIAvNZe+svXVx9j4uBaVhTB4C94HkY3w058qcg= k8s.io/apiextensions-apiserver v0.19.3/go.mod h1:igVEkrE9TzInc1tYE7qSqxaLg/rEAp6B5+k9Q7+IC8Q= -k8s.io/apiextensions-apiserver v0.19.4 h1:D9ak9T012tb3vcGFWYmbQuj9SCC8YM4zhA4XZqsAQC4= -k8s.io/apiextensions-apiserver v0.19.4/go.mod h1:B9rpH/nu4JBCtuUp3zTTk8DEjZUupZTBEec7/2zNRYw= +k8s.io/apiextensions-apiserver v0.20.1 h1:ZrXQeslal+6zKM/HjDXLzThlz/vPSxrfK3OqL8txgVQ= +k8s.io/apiextensions-apiserver v0.20.1/go.mod h1:ntnrZV+6a3dB504qwC5PN/Yg9PBiDNt1EVqbW2kORVk= k8s.io/apimachinery v0.18.0/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA= k8s.io/apimachinery v0.18.2/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA= -k8s.io/apimachinery v0.19.2/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= k8s.io/apimachinery v0.19.3/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= -k8s.io/apimachinery v0.19.4 h1:+ZoddM7nbzrDCp0T3SWnyxqf8cbWPT2fkZImoyvHUG0= -k8s.io/apimachinery v0.19.4/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= +k8s.io/apimachinery v0.20.1 h1:LAhz8pKbgR8tUwn7boK+b2HZdt7MiTu2mkYtFMUjTRQ= +k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= k8s.io/apiserver v0.18.2/go.mod h1:Xbh066NqrZO8cbsoenCwyDJ1OSi8Ag8I2lezeHxzwzw= -k8s.io/apiserver v0.19.2/go.mod h1:FreAq0bJ2vtZFj9Ago/X0oNGC51GfubKK/ViOKfVAOA= k8s.io/apiserver v0.19.3/go.mod h1:bx6dMm+H6ifgKFpCQT/SAhPwhzoeIMlHIaibomUDec0= -k8s.io/apiserver v0.19.4 h1:X40UuyVt6DcYWIh2olcePkyKO0LRJFvxWC0kLxYvkZU= -k8s.io/apiserver v0.19.4/go.mod h1:X8WRHCR1UGZDd7HpV0QDc1h/6VbbpAeAGyxSh8yzZXw= +k8s.io/apiserver v0.20.1 h1:yEqdkxlnQbxi/3e74cp0X16h140fpvPrNnNRAJBDuBk= +k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= k8s.io/cli-runtime v0.18.0/go.mod h1:1eXfmBsIJosjn9LjEBUd2WVPoPAY9XGTqTFcPMIBsUQ= k8s.io/cli-runtime v0.19.3/go.mod h1:q+l845i5/uWzcUpCrl+L4f3XLaJi8ZeLVQ/decwty0A= -k8s.io/cli-runtime v0.19.4 h1:FPpoqFbWsFzRbZNRI+o/+iiLFmWMYTmBueIj3OaNVTI= -k8s.io/cli-runtime v0.19.4/go.mod h1:m8G32dVbKOeaX1foGhleLEvNd6REvU7YnZyWn5//9rw= +k8s.io/cli-runtime v0.20.1 h1:fJhRQ9EfTpJpCqSFOAqnYLuu5aAM7yyORWZ26qW1jJc= +k8s.io/cli-runtime v0.20.1/go.mod h1:6wkMM16ZXTi7Ow3JLYPe10bS+XBnIkL6V9dmEz0mbuY= k8s.io/client-go v0.18.0/go.mod h1:uQSYDYs4WhVZ9i6AIoEZuwUggLVEF64HOD37boKAtF8= k8s.io/client-go v0.18.2/go.mod h1:Xcm5wVGXX9HAA2JJ2sSBUn3tCJ+4SVlCbl2MNNv+CIU= -k8s.io/client-go v0.19.2/go.mod h1:S5wPhCqyDNAlzM9CnEdgTGV4OqhsW3jGO1UM1epwfJA= k8s.io/client-go v0.19.3/go.mod h1:+eEMktZM+MG0KO+PTkci8xnbCZHvj9TqR6Q1XDUIJOM= -k8s.io/client-go v0.19.4 h1:85D3mDNoLF+xqpyE9Dh/OtrJDyJrSRKkHmDXIbEzer8= -k8s.io/client-go v0.19.4/go.mod h1:ZrEy7+wj9PjH5VMBCuu/BDlvtUAku0oVFk4MmnW9mWA= +k8s.io/client-go v0.20.1 h1:Qquik0xNFbK9aUG92pxHYsyfea5/RPO9o9bSywNor+M= +k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y= k8s.io/code-generator v0.18.0/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc= k8s.io/code-generator v0.18.2/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc= -k8s.io/code-generator v0.19.2/go.mod h1:moqLn7w0t9cMs4+5CQyxnfA/HV8MF6aAVENF+WZZhgk= k8s.io/code-generator v0.19.3/go.mod h1:moqLn7w0t9cMs4+5CQyxnfA/HV8MF6aAVENF+WZZhgk= -k8s.io/code-generator v0.19.4/go.mod h1:moqLn7w0t9cMs4+5CQyxnfA/HV8MF6aAVENF+WZZhgk= +k8s.io/code-generator v0.20.1/go.mod h1:UsqdF+VX4PU2g46NC2JRs4gc+IfrctnwHb76RNbWHJg= k8s.io/component-base v0.18.0/go.mod h1:u3BCg0z1uskkzrnAKFzulmYaEpZF7XC9Pf/uFyb1v2c= k8s.io/component-base v0.18.2/go.mod h1:kqLlMuhJNHQ9lz8Z7V5bxUUtjFZnrypArGl58gmDfUM= -k8s.io/component-base v0.19.2/go.mod h1:g5LrsiTiabMLZ40AR6Hl45f088DevyGY+cCE2agEIVo= k8s.io/component-base v0.19.3/go.mod h1:WhLWSIefQn8W8jxSLl5WNiR6z8oyMe/8Zywg7alOkRc= -k8s.io/component-base v0.19.4 h1:HobPRToQ8KJ9ubRju6PUAk9I5V1GNMJZ4PyWbiWA0uI= -k8s.io/component-base v0.19.4/go.mod h1:ZzuSLlsWhajIDEkKF73j64Gz/5o0AgON08FgRbEPI70= +k8s.io/component-base v0.20.1 h1:6OQaHr205NSl24t5wOF2IhdrlxZTWEZwuGlLvBgaeIg= +k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk= +k8s.io/component-helpers v0.20.1/go.mod h1:Q8trCj1zyLNdeur6pD2QvsF8d/nWVfK71YjN5+qVXy4= k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200114144118-36b2048a9120/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20201113003025-83324d819ded/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= @@ -1267,30 +1419,38 @@ k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0 h1:XRvcwJozkgZ1UQJmfMGpvRthQHOvihEhYtDfAaxMz/A= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/klog/v2 v2.4.0 h1:7+X0fUguPyrKEC4WjH8iGDg3laWgMo5tMnRTIGTTxGQ= +k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E= k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6 h1:+WnxoVtG8TMiudHBSEtrVL1egv36TkkJm+bA8AxicmQ= k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= +k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd h1:sOHNzJIkytDF6qadMNKhhDRpc6ODik8lVC6nOur7B2c= +k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= k8s.io/kubectl v0.18.0/go.mod h1:LOkWx9Z5DXMEg5KtOjHhRiC1fqJPLyCr3KtQgEolCkU= k8s.io/kubectl v0.19.3/go.mod h1:t5cscfrAuHUvEGNyNJjPKt+rGlaJzk8jrKYHXxEsANE= -k8s.io/kubectl v0.19.4 h1:XFrHibf5fS4Ot8h3EnzdVsKrYj+pndlzKbwPkfra5hI= -k8s.io/kubectl v0.19.4/go.mod h1:XPmlu4DJEYgD83pvZFeKF8+MSvGnYGqunbFSrJsqHv0= +k8s.io/kubectl v0.20.1 h1:7h1vSrL/B3hLrhlCJhbTADElPKDbx+oVUt3+QDSXxBo= +k8s.io/kubectl v0.20.1/go.mod h1:2bE0JLYTRDVKDiTREFsjLAx4R2GvUtL/mGYFXfFFMzY= k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= k8s.io/metrics v0.18.0/go.mod h1:8aYTW18koXqjLVKL7Ds05RPMX9ipJZI3mywYvBOxXd4= k8s.io/metrics v0.19.3/go.mod h1:Eap/Lk1FiAIjkaArFuv41v+ph6dbDpVGwAg7jMI+4vg= -k8s.io/metrics v0.19.4/go.mod h1:a0gvAzrxQPw2ouBqnXI7X9qlggpPkKAFgWU/Py+KZiU= +k8s.io/metrics v0.20.1/go.mod h1:JhpBE/fad3yRGsgEpiZz5FQQM5wJ18OTLkD7Tv40c0s= k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= k8s.io/utils v0.0.0-20200729134348-d5654de09c73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20200912215256-4140de9c8800 h1:9ZNvfPvVIEsp/T1ez4GQuzCcCTEQWhovSofhqR73A6g= -k8s.io/utils v0.0.0-20200912215256-4140de9c8800/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20201110183641-67b214c5f920 h1:CbnUZsM497iRC5QMVkHwyl8s2tB3g7yaSHkYPkpgelw= +k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/letsencrypt v0.0.3 h1:H7xDfhkaFFSYEJlKeq38RwX2jYcnTeHuDQyT+mMNMwM= rsc.io/letsencrypt v0.0.3/go.mod h1:buyQKZ6IXrRnB7TdkHP0RyEybLx18HHyOSoTyoOLqNY= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.9 h1:rusRLrDhjBp6aYtl9sGEvQJr6faoHoDLd0YcUBTZguI= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.9/go.mod h1:dzAXnQbTRyDlZPJX2SUPEqvnB+j7AJjtlox7PEwigU0= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14 h1:TihvEz9MPj2u0KWds6E2OBUXfwaL4qRJ33c7HGiJpqk= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= sigs.k8s.io/controller-runtime v0.6.0/go.mod h1:CpYf5pdNY/B352A1TFLAS2JVSlnGQ5O2cftPHndTroo= -sigs.k8s.io/controller-runtime v0.7.0 h1:bU20IBBEPccWz5+zXpLnpVsgBYxqclaHu1pVDl/gEt8= -sigs.k8s.io/controller-runtime v0.7.0/go.mod h1:pJ3YBrJiAqMAZKi6UVGuE98ZrroV1p+pIhoHsMm9wdU= +sigs.k8s.io/controller-runtime v0.8.0 h1:s0dYdo7lQgJiAf+alP82PRwbz+oAqL3oSyMQ18XRDOc= +sigs.k8s.io/controller-runtime v0.8.0/go.mod h1:v9Lbj5oX443uR7GXYY46E0EE2o7k2YxQ58GxVNeXSW4= sigs.k8s.io/controller-tools v0.3.0/go.mod h1:enhtKGfxZD1GFEoMgP8Fdbu+uKQ/cq1/WGJhdVChfvI= sigs.k8s.io/controller-tools v0.4.1 h1:VkuV0MxlRPmRu5iTgBZU4UxUX2LiR99n3sdQGRxZF4w= sigs.k8s.io/controller-tools v0.4.1/go.mod h1:G9rHdZMVlBDocIxGkK3jHLWqcTMNvveypYJwrvYKjWU= @@ -1302,6 +1462,8 @@ sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= sigs.k8s.io/structured-merge-diff/v4 v4.0.1 h1:YXTMot5Qz/X1iBRJhAt+vI+HVttY0WkSqqhKxQ0xVbA= sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/structured-merge-diff/v4 v4.0.2 h1:YHQV7Dajm86OuqnIR6zAelnDWBRjo+YhYV9PmGrh1s8= +sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/internal/clientbuilder/clientbuilder.go b/internal/clientbuilder/clientbuilder.go new file mode 100644 index 00000000000..0c1017263c2 --- /dev/null +++ b/internal/clientbuilder/clientbuilder.go @@ -0,0 +1,52 @@ +// Copyright 2021 The Operator-SDK 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. + +package clientbuilder + +import ( + "k8s.io/client-go/rest" + "sigs.k8s.io/controller-runtime/pkg/cache" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/manager" +) + +// NewUnstructedCached returns a builder to build new client clients. +// The new delegating client allows caching of unstructured objects. +func NewUnstructedCached() manager.ClientBuilder { + return &newUnstructedCached{} +} + +type newUnstructedCached struct { + uncached []client.Object +} + +func (n *newUnstructedCached) WithUncached(objs ...client.Object) manager.ClientBuilder { + n.uncached = append(n.uncached, objs...) + return n +} + +func (n *newUnstructedCached) Build(cache cache.Cache, config *rest.Config, options client.Options) (client.Client, error) { + // Create the Client for Write operations. + c, err := client.New(config, options) + if err != nil { + return nil, err + } + + return client.NewDelegatingClient(client.NewDelegatingClientInput{ + CacheReader: cache, + Client: c, + UncachedObjects: n.uncached, + CacheUnstructured: true, + }) +} diff --git a/internal/cmd/ansible-operator/run/cmd.go b/internal/cmd/ansible-operator/run/cmd.go index d09fa3ba065..257361a662a 100644 --- a/internal/cmd/ansible-operator/run/cmd.go +++ b/internal/cmd/ansible-operator/run/cmd.go @@ -41,6 +41,7 @@ import ( "github.com/operator-framework/operator-sdk/internal/ansible/proxy/controllermap" "github.com/operator-framework/operator-sdk/internal/ansible/runner" "github.com/operator-framework/operator-sdk/internal/ansible/watches" + "github.com/operator-framework/operator-sdk/internal/clientbuilder" "github.com/operator-framework/operator-sdk/internal/util/k8sutil" sdkVersion "github.com/operator-framework/operator-sdk/internal/version" ) @@ -107,7 +108,7 @@ func run(cmd *cobra.Command, f *flags.Flags) { LeaderElectionID: f.LeaderElectionID, LeaderElectionResourceLock: resourcelock.ConfigMapsResourceLock, LeaderElectionNamespace: f.LeaderElectionNamespace, - ClientBuilder: manager.NewClientBuilder(), + ClientBuilder: clientbuilder.NewUnstructedCached(), } namespace, found := os.LookupEnv(k8sutil.WatchNamespaceEnvVar) diff --git a/internal/cmd/helm-operator/run/cmd.go b/internal/cmd/helm-operator/run/cmd.go index b10bf950c0e..e8802af3c43 100644 --- a/internal/cmd/helm-operator/run/cmd.go +++ b/internal/cmd/helm-operator/run/cmd.go @@ -33,6 +33,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/manager/signals" crmetrics "sigs.k8s.io/controller-runtime/pkg/metrics" + "github.com/operator-framework/operator-sdk/internal/clientbuilder" "github.com/operator-framework/operator-sdk/internal/helm/controller" "github.com/operator-framework/operator-sdk/internal/helm/flags" "github.com/operator-framework/operator-sdk/internal/helm/metrics" @@ -102,7 +103,7 @@ func run(cmd *cobra.Command, f *flags.Flags) { LeaderElectionID: f.LeaderElectionID, LeaderElectionResourceLock: resourcelock.ConfigMapsResourceLock, LeaderElectionNamespace: f.LeaderElectionNamespace, - ClientBuilder: manager.NewClientBuilder(), + ClientBuilder: clientbuilder.NewUnstructedCached(), } namespace, found := os.LookupEnv(k8sutil.WatchNamespaceEnvVar) diff --git a/internal/cmd/operator-sdk/generate/internal/genutil.go b/internal/cmd/operator-sdk/generate/internal/genutil.go index 0b6f6672cb3..37845a5e3fb 100644 --- a/internal/cmd/operator-sdk/generate/internal/genutil.go +++ b/internal/cmd/operator-sdk/generate/internal/genutil.go @@ -23,7 +23,7 @@ import ( "path/filepath" "strings" - "github.com/blang/semver" + "github.com/blang/semver/v4" apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" apiextv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" "sigs.k8s.io/controller-runtime/pkg/client" diff --git a/internal/generate/clusterserviceversion/clusterserviceversion.go b/internal/generate/clusterserviceversion/clusterserviceversion.go index f921e752857..cc6ab1da637 100644 --- a/internal/generate/clusterserviceversion/clusterserviceversion.go +++ b/internal/generate/clusterserviceversion/clusterserviceversion.go @@ -20,7 +20,7 @@ import ( "path/filepath" "strings" - "github.com/blang/semver" + "github.com/blang/semver/v4" "github.com/operator-framework/api/pkg/operators/v1alpha1" operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1" "github.com/operator-framework/operator-registry/pkg/lib/bundle" diff --git a/internal/generate/clusterserviceversion/clusterserviceversion_test.go b/internal/generate/clusterserviceversion/clusterserviceversion_test.go index 13e5f95d260..f66f9c450f3 100644 --- a/internal/generate/clusterserviceversion/clusterserviceversion_test.go +++ b/internal/generate/clusterserviceversion/clusterserviceversion_test.go @@ -20,7 +20,7 @@ import ( "os" "path/filepath" - "github.com/blang/semver" + "github.com/blang/semver/v4" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "github.com/onsi/gomega/format" diff --git a/internal/olm/client/client.go b/internal/olm/client/client.go index 8cfcb443bd0..dbd23c3a4c1 100644 --- a/internal/olm/client/client.go +++ b/internal/olm/client/client.go @@ -25,7 +25,7 @@ import ( "sync" "time" - "github.com/blang/semver" + "github.com/blang/semver/v4" olmapiv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1" log "github.com/sirupsen/logrus" appsv1 "k8s.io/api/apps/v1" diff --git a/internal/olm/installer/client.go b/internal/olm/installer/client.go index 75a1defeac2..1398fa5f7df 100644 --- a/internal/olm/installer/client.go +++ b/internal/olm/installer/client.go @@ -28,7 +28,7 @@ import ( "path/filepath" "time" - "github.com/blang/semver" + "github.com/blang/semver/v4" olmapiv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1" olmmanifests "github.com/operator-framework/operator-sdk/internal/bindata/olm" log "github.com/sirupsen/logrus" diff --git a/internal/olm/operator/registry/configmap/configmap_test.go b/internal/olm/operator/registry/configmap/configmap_test.go index 434e4855555..6e4dea65b9e 100644 --- a/internal/olm/operator/registry/configmap/configmap_test.go +++ b/internal/olm/operator/registry/configmap/configmap_test.go @@ -21,7 +21,7 @@ import ( "fmt" "strings" - "github.com/blang/semver" + "github.com/blang/semver/v4" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "github.com/operator-framework/api/pkg/lib/version" diff --git a/internal/olm/operator/registry/configmap/registry_test.go b/internal/olm/operator/registry/configmap/registry_test.go index 7ca7c3d0a02..4cab73e7b12 100644 --- a/internal/olm/operator/registry/configmap/registry_test.go +++ b/internal/olm/operator/registry/configmap/registry_test.go @@ -18,7 +18,7 @@ import ( "context" "fmt" - "github.com/blang/semver" + "github.com/blang/semver/v4" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "github.com/operator-framework/api/pkg/lib/version" diff --git a/release/changelog/gen-changelog.go b/release/changelog/gen-changelog.go index fd0dfd272c1..dfa8bb0c6e4 100644 --- a/release/changelog/gen-changelog.go +++ b/release/changelog/gen-changelog.go @@ -6,7 +6,7 @@ import ( "path/filepath" "strings" - "github.com/blang/semver" + "github.com/blang/semver/v4" log "github.com/sirupsen/logrus" util "github.com/operator-framework/operator-sdk/release/changelog/internal" diff --git a/release/changelog/internal/changelog.go b/release/changelog/internal/changelog.go index b04d8fca164..31302a0daf4 100644 --- a/release/changelog/internal/changelog.go +++ b/release/changelog/internal/changelog.go @@ -9,7 +9,7 @@ import ( "strings" "text/template" - "github.com/blang/semver" + "github.com/blang/semver/v4" ) type Changelog struct { diff --git a/release/changelog/internal/changelog_test.go b/release/changelog/internal/changelog_test.go index a5d261a7272..4a75a1dc582 100644 --- a/release/changelog/internal/changelog_test.go +++ b/release/changelog/internal/changelog_test.go @@ -6,7 +6,7 @@ import ( "os" "testing" - "github.com/blang/semver" + "github.com/blang/semver/v4" "github.com/stretchr/testify/assert" ) diff --git a/release/changelog/internal/migration_guide.go b/release/changelog/internal/migration_guide.go index b123c9df6de..e987caca691 100644 --- a/release/changelog/internal/migration_guide.go +++ b/release/changelog/internal/migration_guide.go @@ -7,7 +7,7 @@ import ( "strings" "text/template" - "github.com/blang/semver" + "github.com/blang/semver/v4" ) type MigrationGuide struct { diff --git a/release/changelog/internal/migration_guide_test.go b/release/changelog/internal/migration_guide_test.go index 3f08b666206..8979b341c02 100644 --- a/release/changelog/internal/migration_guide_test.go +++ b/release/changelog/internal/migration_guide_test.go @@ -5,7 +5,7 @@ import ( "os" "testing" - "github.com/blang/semver" + "github.com/blang/semver/v4" "github.com/stretchr/testify/assert" ) diff --git a/website/content/en/docs/cli/operator-sdk_completion.md b/website/content/en/docs/cli/operator-sdk_completion.md index a1a5d31e089..1ced5f6cf23 100644 --- a/website/content/en/docs/cli/operator-sdk_completion.md +++ b/website/content/en/docs/cli/operator-sdk_completion.md @@ -5,10 +5,6 @@ title: "operator-sdk completion" Generators for shell completions -### Synopsis - -Generators for shell completions - ### Options ``` diff --git a/website/content/en/docs/cli/operator-sdk_completion_bash.md b/website/content/en/docs/cli/operator-sdk_completion_bash.md index fc4e7aedb81..1aec4b8c12e 100644 --- a/website/content/en/docs/cli/operator-sdk_completion_bash.md +++ b/website/content/en/docs/cli/operator-sdk_completion_bash.md @@ -5,10 +5,6 @@ title: "operator-sdk completion bash" Generate bash completions -### Synopsis - -Generate bash completions - ``` operator-sdk completion bash [flags] ``` diff --git a/website/content/en/docs/cli/operator-sdk_completion_zsh.md b/website/content/en/docs/cli/operator-sdk_completion_zsh.md index ffc73a02e75..fc8b1802064 100644 --- a/website/content/en/docs/cli/operator-sdk_completion_zsh.md +++ b/website/content/en/docs/cli/operator-sdk_completion_zsh.md @@ -5,10 +5,6 @@ title: "operator-sdk completion zsh" Generate zsh completions -### Synopsis - -Generate zsh completions - ``` operator-sdk completion zsh [flags] ``` diff --git a/website/content/en/docs/cli/operator-sdk_generate_kustomize.md b/website/content/en/docs/cli/operator-sdk_generate_kustomize.md index 2e529b7d146..7578b8a9423 100644 --- a/website/content/en/docs/cli/operator-sdk_generate_kustomize.md +++ b/website/content/en/docs/cli/operator-sdk_generate_kustomize.md @@ -5,10 +5,6 @@ title: "operator-sdk generate kustomize" Contains subcommands that generate operator-framework kustomize data for the operator -### Synopsis - -Contains subcommands that generate operator-framework kustomize data for the operator - ### Options ``` diff --git a/website/content/en/docs/cli/operator-sdk_olm.md b/website/content/en/docs/cli/operator-sdk_olm.md index b49bb71a514..7f54ef16376 100644 --- a/website/content/en/docs/cli/operator-sdk_olm.md +++ b/website/content/en/docs/cli/operator-sdk_olm.md @@ -5,10 +5,6 @@ title: "operator-sdk olm" Manage the Operator Lifecycle Manager installation in your cluster -### Synopsis - -Manage the Operator Lifecycle Manager installation in your cluster - ### Options ``` diff --git a/website/content/en/docs/cli/operator-sdk_olm_install.md b/website/content/en/docs/cli/operator-sdk_olm_install.md index 3c62a057159..9772858c361 100644 --- a/website/content/en/docs/cli/operator-sdk_olm_install.md +++ b/website/content/en/docs/cli/operator-sdk_olm_install.md @@ -5,10 +5,6 @@ title: "operator-sdk olm install" Install Operator Lifecycle Manager in your cluster -### Synopsis - -Install Operator Lifecycle Manager in your cluster - ``` operator-sdk olm install [flags] ``` diff --git a/website/content/en/docs/cli/operator-sdk_olm_status.md b/website/content/en/docs/cli/operator-sdk_olm_status.md index 09c2c039171..c377a18ce30 100644 --- a/website/content/en/docs/cli/operator-sdk_olm_status.md +++ b/website/content/en/docs/cli/operator-sdk_olm_status.md @@ -5,10 +5,6 @@ title: "operator-sdk olm status" Get the status of the Operator Lifecycle Manager installation in your cluster -### Synopsis - -Get the status of the Operator Lifecycle Manager installation in your cluster - ``` operator-sdk olm status [flags] ``` diff --git a/website/content/en/docs/cli/operator-sdk_olm_uninstall.md b/website/content/en/docs/cli/operator-sdk_olm_uninstall.md index 867a44e3257..1d9ff59bbc6 100644 --- a/website/content/en/docs/cli/operator-sdk_olm_uninstall.md +++ b/website/content/en/docs/cli/operator-sdk_olm_uninstall.md @@ -5,10 +5,6 @@ title: "operator-sdk olm uninstall" Uninstall Operator Lifecycle Manager from your cluster -### Synopsis - -Uninstall Operator Lifecycle Manager from your cluster - ``` operator-sdk olm uninstall [flags] ``` diff --git a/website/content/en/docs/cli/operator-sdk_run_bundle-upgrade.md b/website/content/en/docs/cli/operator-sdk_run_bundle-upgrade.md index 05dcbb8bd0b..60a7b527b0c 100644 --- a/website/content/en/docs/cli/operator-sdk_run_bundle-upgrade.md +++ b/website/content/en/docs/cli/operator-sdk_run_bundle-upgrade.md @@ -5,10 +5,6 @@ title: "operator-sdk run bundle-upgrade" Upgrade an Operator previously installed in the bundle format with OLM -### Synopsis - -Upgrade an Operator previously installed in the bundle format with OLM - ``` operator-sdk run bundle-upgrade [flags] ``` diff --git a/website/content/en/docs/cli/operator-sdk_run_bundle.md b/website/content/en/docs/cli/operator-sdk_run_bundle.md index 5708e291873..539dd2da44b 100644 --- a/website/content/en/docs/cli/operator-sdk_run_bundle.md +++ b/website/content/en/docs/cli/operator-sdk_run_bundle.md @@ -5,10 +5,6 @@ title: "operator-sdk run bundle" Deploy an Operator in the bundle format with OLM -### Synopsis - -Deploy an Operator in the bundle format with OLM - ``` operator-sdk run bundle [flags] ``` From 316b6ea2482dccd8df6014897eba1306a6f1f186 Mon Sep 17 00:00:00 2001 From: Martin Hickey Date: Thu, 21 Jan 2021 23:24:38 +0000 Subject: [PATCH 278/376] docs: Add useful links to the README (#4416) Signed-off-by: Martin Hickey Signed-off-by: reinvantveer --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index 8d57ea9c425..13f6aeb14cf 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,16 @@ The following matrix defines which architectures are supported for MacOS Darwin: Support for the Windows platform is not on the roadmap at this time. +## Community and how to get involved + +- [Operator framework community][operator-framework-community] +- [Communication channels][operator-framework-communication] +- [Project meetings][operator-framework-meetings] + +## How to contribute + +Check out the [contributor documentation][contribution-docs]. + ## License Operator SDK is under Apache 2.0 license. See the [LICENSE][license_file] file for details. @@ -71,3 +81,7 @@ Operator SDK is under Apache 2.0 license. See the [LICENSE][license_file] file f [of-blog]: https://coreos.com/blog/introducing-operator-framework [operator-link]: https://kubernetes.io/docs/concepts/extend-kubernetes/operator/ [sdk-docs]: https://sdk.operatorframework.io +[operator-framework-community]: https://github.com/operator-framework/community +[operator-framework-communication]: https://github.com/operator-framework/community#get-involved +[operator-framework-meetings]: https://github.com/operator-framework/community#meetings +[contribution-docs]: https://sdk.operatorframework.io/docs/contribution-guidelines/ From 1cdedc37aa0a9c76dbfab6f8432b1c44926a1170 Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Thu, 21 Jan 2021 16:04:51 -0800 Subject: [PATCH 279/376] internal/plugins/scorecard: refactor init plugin code for easier reading (#4420) Signed-off-by: Eric Stroczynski Signed-off-by: reinvantveer --- internal/plugins/scorecard/init.go | 341 +++++++++++------------------ 1 file changed, 128 insertions(+), 213 deletions(-) diff --git a/internal/plugins/scorecard/init.go b/internal/plugins/scorecard/init.go index 7747d8bd070..977bf8f6811 100644 --- a/internal/plugins/scorecard/init.go +++ b/internal/plugins/scorecard/init.go @@ -15,61 +15,27 @@ package scorecard import ( - "bytes" "fmt" "io/ioutil" "os" "path/filepath" - "text/template" - "github.com/operator-framework/api/pkg/apis/scorecard/v1alpha3" - "k8s.io/apimachinery/pkg/runtime/schema" "sigs.k8s.io/kubebuilder/v2/pkg/model/config" - "sigs.k8s.io/yaml" + "sigs.k8s.io/kubebuilder/v2/pkg/model/file" "github.com/operator-framework/operator-sdk/internal/plugins/util/kustomize" "github.com/operator-framework/operator-sdk/internal/scorecard" "github.com/operator-framework/operator-sdk/internal/version" ) -// scorecardVersion is set to the version of scorecard at compile-time. -var scorecardVersion = version.ImageVersion +var ( + // defaultTestImageTag points to the latest released scorecard-test image. + defaultTestImageTag = fmt.Sprintf("quay.io/operator-framework/scorecard-test:%s", version.ImageVersion) -const ( - // kustomization.yaml file template for the scorecard componentconfig. This should always be written to - // config/scorecard/kustomization.yaml since it only references files in config. - scorecardKustomizationTemplate = `resources: -{{- range $i, $path := .ResourcePaths }} -- {{ $path }} -{{- end }} -patchesJson6902: -{{- range $i, $patch := .JSONPatches }} -- path: {{ $patch.Path }} - target: - group: {{ $patch.Target.Group }} - version: {{ $patch.Target.Version }} - kind: {{ $patch.Target.Kind }} - name: {{ $patch.Target.Name }} -{{- end }} -` - - // YAML file fragment to append to kustomization.yaml files. - kubebuilderScaffoldMarkerFragment = "# +kubebuilder:scaffold:patchesJson6902\n" -) - -const ( - // defaultConfigName is the default scorecard componentconfig's metadata.name, - // which must be set on all kustomize-able bases. This name is only used for - // `kustomize build` pattern match and not for on-cluster creation. - defaultConfigName = "config" + // defaultDir is the default directory in which to generate kustomize bases and the kustomization.yaml. + defaultDir = filepath.Join("config", "scorecard") ) -// defaultTestImageTag points to the latest-released image. -var defaultTestImageTag = fmt.Sprintf("quay.io/operator-framework/scorecard-test:%s", scorecardVersion) - -// defaultDir is the default directory in which to generate kustomize bases and the kustomization.yaml. -var defaultDir = filepath.Join("config", "scorecard") - // RunInit scaffolds kustomize files for kustomizing a scorecard componentconfig. func RunInit(cfg *config.Config) error { // Only run these if project version is v3. @@ -77,198 +43,147 @@ func RunInit(cfg *config.Config) error { return nil } - return generate(defaultTestImageTag, defaultDir) -} - -// scorecardKustomizationValues holds data required to generate a scorecard's kustomization.yaml. -type scorecardKustomizationValues struct { - ResourcePaths []string - JSONPatches []kustomizationJSON6902Patch + return generateInit(defaultDir) } -// kustomizationJSON6902Patch holds path and target data to write a patchesJson6902 list in a kustomization.yaml. -type kustomizationJSON6902Patch struct { - Path string - Target patchTarget -} - -// patchTarget holds target data for a kustomize patch. -type patchTarget struct { - schema.GroupVersionKind - Name string -} - -// generate scaffolds kustomize bundle bases and a kustomization.yaml. +// generateInit scaffolds kustomize bundle bases and a kustomization.yaml. // TODO(estroz): refactor this to be testable (in-mem fs) and easier to read. -func generate(testImageTag, outputDir string) error { - - kustomizationValues := scorecardKustomizationValues{} +func generateInit(outputDir string) error { - // Config bases. basesDir := filepath.Join(outputDir, "bases") - if err := os.MkdirAll(basesDir, 0755); err != nil { - return err - } - - configBase := newConfigurationBase(defaultConfigName) - b, err := yaml.Marshal(configBase) - if err != nil { - return fmt.Errorf("error marshaling default config: %v", err) - } - relBasePath := filepath.Join("bases", scorecard.ConfigFileName) - basePath := filepath.Join(basesDir, scorecard.ConfigFileName) - if err := ioutil.WriteFile(basePath, b, 0666); err != nil { - return fmt.Errorf("error writing default scorecard config: %v", err) - } - kustomizationValues.ResourcePaths = append(kustomizationValues.ResourcePaths, relBasePath) - scorecardConfigTarget := patchTarget{ - GroupVersionKind: v1alpha3.GroupVersion.WithKind(v1alpha3.ConfigurationKind), - Name: defaultConfigName, - } - - // Config patches. patchesDir := filepath.Join(outputDir, "patches") - if err := os.MkdirAll(patchesDir, 0755); err != nil { - return err + for _, dir := range []string{basesDir, patchesDir} { + if err := os.MkdirAll(dir, 0755); err != nil { + return err + } } - // Basic scorecard tests patch. - basicPatch := newBasicConfigurationPatch(testImageTag) - b, err = yaml.Marshal(basicPatch) - if err != nil { - return fmt.Errorf("error marshaling basic patch config: %v", err) - } - basicPatchFileName := fmt.Sprintf("basic.%s", scorecard.ConfigFileName) - if err := ioutil.WriteFile(filepath.Join(patchesDir, basicPatchFileName), b, 0666); err != nil { - return fmt.Errorf("error writing basic scorecard config patch: %v", err) - } - kustomizationValues.JSONPatches = append(kustomizationValues.JSONPatches, kustomizationJSON6902Patch{ - Path: filepath.Join("patches", basicPatchFileName), - Target: scorecardConfigTarget, - }) - - // OLM scorecard tests patch. - olmPatch := newOLMConfigurationPatch(testImageTag) - b, err = yaml.Marshal(olmPatch) - if err != nil { - return fmt.Errorf("error marshaling OLM patch config: %v", err) - } - olmPatchFileName := fmt.Sprintf("olm.%s", scorecard.ConfigFileName) - if err := ioutil.WriteFile(filepath.Join(patchesDir, olmPatchFileName), b, 0666); err != nil { + // Write the scorecard config base. + baseFilePath := filepath.Join(basesDir, scorecard.ConfigFileName) + if err := ioutil.WriteFile(baseFilePath, []byte(configBaseFile), 0666); err != nil { return fmt.Errorf("error writing default scorecard config: %v", err) } - kustomizationValues.JSONPatches = append(kustomizationValues.JSONPatches, kustomizationJSON6902Patch{ - Path: filepath.Join("patches", olmPatchFileName), - Target: scorecardConfigTarget, - }) - // Write a kustomization.yaml to outputDir if one does not exist. - t, err := template.New("scorecard").Parse(scorecardKustomizationTemplate) - if err != nil { - return fmt.Errorf("error parsing default kustomize template: %v", err) - } - buf := bytes.Buffer{} - if err = t.Execute(&buf, kustomizationValues); err != nil { - return fmt.Errorf("error executing on default kustomize template: %v", err) + // Write each patch in patchSet to ".config.yaml" + patchSet := map[string]string{ + "basic": fmt.Sprintf(basicPatchFile, defaultTestImageTag), + "olm": fmt.Sprintf(olmPatchFile, defaultTestImageTag), } - // Append the kubebuilder scaffold marker to make updates to this file in the future. - buf.Write([]byte(kubebuilderScaffoldMarkerFragment)) - if err := kustomize.Write(outputDir, buf.String()); err != nil { - return fmt.Errorf("error writing default scorecard kustomization.yaml: %v", err) + for name, patchStr := range patchSet { + patchFileName := fmt.Sprintf("%s.config.yaml", name) + if err := ioutil.WriteFile(filepath.Join(patchesDir, patchFileName), []byte(patchStr), 0666); err != nil { + return fmt.Errorf("error writing %s scorecard config patch: %v", name, err) + } } - return nil -} - -// jsonPatches is a list of JSON patch objects. -type jsonPatches []jsonPatchObject - -// jsonPatchObject is a JSON 6902 patch object specific to the scorecard's test configuration. -// https://kubernetes-sigs.github.io/kustomize/api-reference/kustomization/patchesjson6902/ for details. -type jsonPatchObject struct { - Op string `json:"op"` - Path string `json:"path"` - Value v1alpha3.TestConfiguration `json:"value"` -} - -// newConfigurationBase returns a scorecard componentconfig object with one parallel stage. -// The returned object is intended to be marshaled and written to disk as a kustomize base. -func newConfigurationBase(configName string) (cfg v1alpha3.Configuration) { - cfg.SetGroupVersionKind(v1alpha3.GroupVersion.WithKind(v1alpha3.ConfigurationKind)) - cfg.Metadata.Name = configName - cfg.Stages = []v1alpha3.StageConfiguration{ - { - Parallel: true, - Tests: []v1alpha3.TestConfiguration{}, - }, + // Write a kustomization.yaml to outputDir. + markerStr := file.NewMarkerFor("kustomization.yaml", patchesJSON6902Marker).String() + if err := kustomize.Write(outputDir, fmt.Sprintf(scorecardKustomizationFile, markerStr)); err != nil { + return fmt.Errorf("error writing scorecard kustomization.yaml: %v", err) } - return cfg -} -const defaultJSONPath = "/stages/0/tests/-" - -// newBasicConfigurationPatch returns default "basic" test configurations as JSON patch objects -// to be inserted into the componentconfig base as a first stage test element. -// The returned patches are intended to be marshaled and written to disk as in a kustomize patch file. -func newBasicConfigurationPatch(testImageTag string) (ps jsonPatches) { - for _, cfg := range makeDefaultBasicTestConfigs(testImageTag) { - ps = append(ps, jsonPatchObject{ - Op: "add", - Path: defaultJSONPath, - Value: cfg, - }) - } - return ps + return nil } -// makeDefaultBasicTestConfigs returns all default "basic" test configurations. -func makeDefaultBasicTestConfigs(testImageTag string) (cfgs []v1alpha3.TestConfiguration) { - for _, testName := range []string{"basic-check-spec"} { - cfgs = append(cfgs, v1alpha3.TestConfiguration{ - Image: testImageTag, - Entrypoint: []string{"scorecard-test", testName}, - Labels: map[string]string{ - "suite": "basic", - "test": fmt.Sprintf("%s-test", testName), - }, - }) - } - - return cfgs -} +const ( + // scorecardKustomizationFile is a kustomization.yaml file for the scorecard componentconfig. + // This should always be written to config/scorecard/kustomization.yaml. + scorecardKustomizationFile = `resources: +- bases/config.yaml +patchesJson6902: +- path: patches/basic.config.yaml + target: + group: scorecard.operatorframework.io + version: v1alpha3 + kind: Configuration + name: config +- path: patches/olm.config.yaml + target: + group: scorecard.operatorframework.io + version: v1alpha3 + kind: Configuration + name: config +%[1]s +` -// newOLMConfigurationPatch returns default "olm" test configurations as JSON patch objects -// to be inserted into the componentconfig base as a first stage test element. -// The returned patches are intended to be marshaled and written to disk as in a kustomize patch file. -func newOLMConfigurationPatch(testImageTag string) (ps jsonPatches) { - for _, cfg := range makeDefaultOLMTestConfigs(testImageTag) { - ps = append(ps, jsonPatchObject{ - Op: "add", - Path: defaultJSONPath, - Value: cfg, - }) - } - return ps -} + // YAML file marker to append to kustomization.yaml files. + patchesJSON6902Marker = "patchesJson6902" +) -// makeDefaultOLMTestConfigs returns all default "olm" test configurations. -func makeDefaultOLMTestConfigs(testImageTag string) (cfgs []v1alpha3.TestConfiguration) { - for _, testName := range []string{ - "olm-bundle-validation", - "olm-crds-have-validation", - "olm-crds-have-resources", - "olm-spec-descriptors", - "olm-status-descriptors"} { +const ( + // configBaseFile is an empty scorecard componentconfig with parallel stages. + configBaseFile = `apiVersion: scorecard.operatorframework.io/v1alpha3 +kind: Configuration +metadata: + name: config +stages: +- parallel: true + tests: [] +` - cfgs = append(cfgs, v1alpha3.TestConfiguration{ - Image: testImageTag, - Entrypoint: []string{"scorecard-test", testName}, - Labels: map[string]string{ - "suite": "olm", - "test": fmt.Sprintf("%s-test", testName), - }, - }) - } + // basicPatchFile contains all default "basic" test configurations. + basicPatchFile = `- op: add + path: /stages/0/tests/- + value: + entrypoint: + - scorecard-test + - basic-check-spec + image: %[1]s + labels: + suite: basic + test: basic-check-spec-test +` - return cfgs -} + // olmPatchFile contains all default "olm" test configurations. + olmPatchFile = `- op: add + path: /stages/0/tests/- + value: + entrypoint: + - scorecard-test + - olm-bundle-validation + image: %[1]s + labels: + suite: olm + test: olm-bundle-validation-test +- op: add + path: /stages/0/tests/- + value: + entrypoint: + - scorecard-test + - olm-crds-have-validation + image: %[1]s + labels: + suite: olm + test: olm-crds-have-validation-test +- op: add + path: /stages/0/tests/- + value: + entrypoint: + - scorecard-test + - olm-crds-have-resources + image: %[1]s + labels: + suite: olm + test: olm-crds-have-resources-test +- op: add + path: /stages/0/tests/- + value: + entrypoint: + - scorecard-test + - olm-spec-descriptors + image: %[1]s + labels: + suite: olm + test: olm-spec-descriptors-test +- op: add + path: /stages/0/tests/- + value: + entrypoint: + - scorecard-test + - olm-status-descriptors + image: %[1]s + labels: + suite: olm + test: olm-status-descriptors-test +` +) From 5c540a249c08bed30e318d2d20a9ed126f5a4064 Mon Sep 17 00:00:00 2001 From: Joseph DuVall Date: Mon, 25 Jan 2021 13:34:03 -0500 Subject: [PATCH 280/376] Removed trailing double-asterisks on a several headers (#4429) Signed-off-by: Joseph DuVall Signed-off-by: reinvantveer --- .../operator-capabilities/operator-capabilities.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/website/content/en/docs/advanced-topics/operator-capabilities/operator-capabilities.md b/website/content/en/docs/advanced-topics/operator-capabilities/operator-capabilities.md index 777e55a7ca9..7dbaec3107b 100644 --- a/website/content/en/docs/advanced-topics/operator-capabilities/operator-capabilities.md +++ b/website/content/en/docs/advanced-topics/operator-capabilities/operator-capabilities.md @@ -72,13 +72,13 @@ Automated application provisioning and configuration management. This first capa Seamless upgrades mean the upgrade is as easy as possible for the user. You should support seamless upgrades of both your operator and operand, these would normally go hand in hand, an upgrade of the operator would automatically ensure the instantiated resources for each CR are in the new desired state and which would upgrade your operand. Upgrade may also be defined in multiple ways, such as updating the software of the operand - and other internals specific to the application - such as schema migrations. It should be very clear what is upgraded when this takes place, and what is not. -### Upgrade of the managed workload** +### Upgrade of the managed workload - Operand can be upgraded in the process of upgrading the Operator, or - Operand can be upgraded as part of changing the CR - Operator understands how to upgrade older versions of the Operand, managed previously by an older version of the Operator -### Upgrade of the Operator** +### Upgrade of the Operator - Operator can be upgraded seamlessly and can either still manage older versions of the Operand or update them - Operator conveys inability to manage an unsupported version of the Operand in the `status` section of the CR @@ -105,7 +105,7 @@ Seamless upgrades mean the upgrade is as easy as possible for the user. You shou It should be possible to backup and restore the operand from the operator itself without any additional manual intervention other than triggering these operations. The operand data that should be backed up is any stateful data managed by the operand. You don’t need to backup the CR itself or the k8s resources created by the operator as the operator should return all resources to the same state if the CR is recreated. If your operator does not already setup the operand with other k8s resilient best practices, this should be completed to achieve this capability level. This includes liveness and readiness probes, multiple replicas, rolling deployment strategies, pod disruption budgets, CPU and memory requests and limits. -### Lifecycle features** +### Lifecycle features - Operator provides the ability to create backups of the Operand - Operator is able to restore a backup of an Operand From 2ab6eff64ddab4793399716ca7618a80ba0d16cb Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Wed, 27 Jan 2021 07:49:25 -0800 Subject: [PATCH 281/376] docs: add ubuntu keyserver to installation instructions, remove gpg requirement from release guide (#4437) Signed-off-by: Eric Stroczynski Signed-off-by: reinvantveer --- .../en/docs/contribution-guidelines/releasing.md | 14 +++++--------- website/content/en/docs/installation/_index.md | 4 ++-- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/website/content/en/docs/contribution-guidelines/releasing.md b/website/content/en/docs/contribution-guidelines/releasing.md index d590fdd03af..34699151480 100644 --- a/website/content/en/docs/contribution-guidelines/releasing.md +++ b/website/content/en/docs/contribution-guidelines/releasing.md @@ -9,16 +9,16 @@ Replace these versions with the current and new version you are releasing, respe ## Prerequisites -- [`git`][git] -- [`gpg`][gpg] v2.0+ and a [GPG key][gpg-key-create]. -- Your GPG key is publicly available in a [public key server][gpg-upload], like https://keyserver.ubuntu.com/. +- [`git`](https://git-scm.com/downloads) +- [`make`](https://www.gnu.org/software/make/) +- [`sed`](https://www.gnu.org/software/sed/) ##### MacOS users -Install GNU `sed`, `make`, and `gpg` which may not be by default: +Install GNU `sed` and `make` which may not be by default: ```sh -brew install gnu-sed make gnupg +brew install gnu-sed make ``` ## Major and Minor releases @@ -233,10 +233,6 @@ Create and merge a PR from your branch to `v1.3.x`. GitHub releases live under the [`Releases` tab][release-page] in the operator-sdk repo. -[git]:https://git-scm.com/downloads -[gpg]:https://gnupg.org/download/ -[gpg-key-create]:https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/managing-commit-signature-verification -[gpg-upload]:https://www.gnupg.org/gph/en/manual/x457.html [netlify-deploy]:https://docs.netlify.com/site-deploys/overview/#deploy-summary [doc-owners]: https://github.com/operator-framework/operator-sdk/blob/master/OWNERS [release-page]:https://github.com/operator-framework/operator-sdk/releases diff --git a/website/content/en/docs/installation/_index.md b/website/content/en/docs/installation/_index.md index 5b8f7ccbdd0..b2e9a6e46e3 100644 --- a/website/content/en/docs/installation/_index.md +++ b/website/content/en/docs/installation/_index.md @@ -42,10 +42,10 @@ curl -LO ${OPERATOR_SDK_DL_URL}/operator-sdk_${OS}_${ARCH} #### 2. Verify the downloaded binary -Import the operator-sdk release GPG key: +Import the operator-sdk release GPG key from `keyserver.ubuntu.com`: ```sh -gpg --recv-keys 052996E2A20B5C7E +gpg --keyserver keyserver.ubuntu.com --recv-keys 052996E2A20B5C7E ``` Download the checksums file and its signature, then verify the signature: From 5468ede5e5dfaf49ba14a1f0b0eacdda89c71779 Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Wed, 27 Jan 2021 08:31:00 -0800 Subject: [PATCH 282/376] generate: respect project version when getting package name (#4431) Signed-off-by: reinvantveer --- .../bugfix-generate-no-project-name.yaml | 4 +++ .../operator-sdk/generate/bundle/bundle.go | 18 ++-------- .../operator-sdk/generate/internal/genutil.go | 35 +++++++++++++++++++ .../packagemanifests/packagemanifests.go | 20 +++-------- 4 files changed, 46 insertions(+), 31 deletions(-) create mode 100644 changelog/fragments/bugfix-generate-no-project-name.yaml diff --git a/changelog/fragments/bugfix-generate-no-project-name.yaml b/changelog/fragments/bugfix-generate-no-project-name.yaml new file mode 100644 index 00000000000..41032f33e86 --- /dev/null +++ b/changelog/fragments/bugfix-generate-no-project-name.yaml @@ -0,0 +1,4 @@ +entries: + - description: > + Project version now determines how package name is retrieved for a project + kind: bugfix diff --git a/internal/cmd/operator-sdk/generate/bundle/bundle.go b/internal/cmd/operator-sdk/generate/bundle/bundle.go index 051adf33c61..443c6c200cd 100644 --- a/internal/cmd/operator-sdk/generate/bundle/bundle.go +++ b/internal/cmd/operator-sdk/generate/bundle/bundle.go @@ -105,21 +105,9 @@ https://github.com/operator-framework/operator-registry/#manifest-format const defaultRootDir = "bundle" // setDefaults sets defaults useful to all modes of this subcommand. -func (c *bundleCmd) setDefaults() error { - if projutil.HasProjectFile() { - cfg, err := projutil.ReadConfig() - if err != nil { - return err - } - if c.packageName == "" { - c.packageName = cfg.ProjectName - } - c.layout = projutil.GetProjectLayout(cfg) - } else { - if c.packageName == "" { - return fmt.Errorf("package name is required if PROJECT config file is not present") - } - c.layout = "unknown" +func (c *bundleCmd) setDefaults() (err error) { + if c.packageName, c.layout, err = genutil.GetPackageNameAndLayout(c.packageName); err != nil { + return err } return nil } diff --git a/internal/cmd/operator-sdk/generate/internal/genutil.go b/internal/cmd/operator-sdk/generate/internal/genutil.go index 37845a5e3fb..d36e1185f60 100644 --- a/internal/cmd/operator-sdk/generate/internal/genutil.go +++ b/internal/cmd/operator-sdk/generate/internal/genutil.go @@ -24,6 +24,7 @@ import ( "strings" "github.com/blang/semver/v4" + "github.com/operator-framework/operator-sdk/internal/util/projutil" apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" apiextv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" "sigs.k8s.io/controller-runtime/pkg/client" @@ -158,3 +159,37 @@ func IsExist(path string) bool { _, err := os.Stat(path) return err == nil || errors.Is(err, os.ErrExist) } + +// GetPackageNameAndLayout returns packageName and layout, if any, for a project. +// These values are determined by project version and whether a PROJECT file exists. +func GetPackageNameAndLayout(defaultPackageName string) (packageName string, layout string, _ error) { + packageName = defaultPackageName + if projutil.HasProjectFile() { + cfg, err := projutil.ReadConfig() + if err != nil { + return "", "", err + } + if packageName == "" { + switch { + case cfg.IsV2(): + wd, err := os.Getwd() + if err != nil { + return "", "", err + } + packageName = strings.ToLower(filepath.Base(wd)) + default: + if cfg.ProjectName == "" { + return "", "", errors.New("--package-name must be set if \"projectName\" is not set in the PROJECT config file") + } + packageName = cfg.ProjectName + } + } + layout = projutil.GetProjectLayout(cfg) + } else { + if packageName == "" { + return "", "", errors.New("--package-name must be set if PROJECT config file is not present") + } + layout = "unknown" + } + return packageName, layout, nil +} diff --git a/internal/cmd/operator-sdk/generate/packagemanifests/packagemanifests.go b/internal/cmd/operator-sdk/generate/packagemanifests/packagemanifests.go index 7ef7b5bcf80..c99af553a9c 100644 --- a/internal/cmd/operator-sdk/generate/packagemanifests/packagemanifests.go +++ b/internal/cmd/operator-sdk/generate/packagemanifests/packagemanifests.go @@ -26,7 +26,6 @@ import ( "github.com/operator-framework/operator-sdk/internal/generate/clusterserviceversion/bases" "github.com/operator-framework/operator-sdk/internal/generate/collector" genpkg "github.com/operator-framework/operator-sdk/internal/generate/packagemanifest" - "github.com/operator-framework/operator-sdk/internal/util/projutil" ) const ( @@ -78,21 +77,9 @@ https://github.com/operator-framework/operator-registry/#manifest-format const defaultRootDir = "packagemanifests" // setDefaults sets command defaults. -func (c *packagemanifestsCmd) setDefaults() error { - if projutil.HasProjectFile() { - cfg, err := projutil.ReadConfig() - if err != nil { - return err - } - if c.packageName == "" { - c.packageName = cfg.ProjectName - } - c.layout = projutil.GetProjectLayout(cfg) - } else { - if c.packageName == "" { - return fmt.Errorf("package name is required if PROJECT config file is not present") - } - c.layout = "unknown" +func (c *packagemanifestsCmd) setDefaults() (err error) { + if c.packageName, c.layout, err = genutil.GetPackageNameAndLayout(c.packageName); err != nil { + return err } if c.inputDir == "" { @@ -103,6 +90,7 @@ func (c *packagemanifestsCmd) setDefaults() error { c.outputDir = defaultRootDir } } + return nil } From 1ac439c283ad18dab085b2626fe6b31978a7e4a0 Mon Sep 17 00:00:00 2001 From: Jonathan Berkhahn Date: Wed, 27 Jan 2021 19:08:09 -0800 Subject: [PATCH 283/376] add kubebuilder/operator-sdk FAQ (#4411) Signed-off-by: Jonathan Berkhahn Signed-off-by: reinvantveer --- website/content/en/docs/faqs/_index.md | 27 +++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/website/content/en/docs/faqs/_index.md b/website/content/en/docs/faqs/_index.md index cef4e89f9c6..b1fc6a80152 100644 --- a/website/content/en/docs/faqs/_index.md +++ b/website/content/en/docs/faqs/_index.md @@ -4,6 +4,18 @@ linkTitle: FAQ weight: 10 --- +## What are the the differences between Kubebuilder and Operator-SDK? + +Kubebuilder and Operator SDK are both projects that allow you to quickly create and manage an operator project. Operator SDK uses Kubebuilder under the hood to do so for Go projects, such that the `operator-sdk` CLI tool will work with a project created by `kubebuilder`. Therefore each project makes use of [controller-runtime][controller-runtime] and will have the same [basic layout][kb-doc-what-is-a-basic-project]. + +Operator SDK offers additional features on top of the basic project scaffolding that Kubebuilder provides. By default, `operator-sdk init` generates a project integrated with: +- [Operator Lifecycle Manager][olm], an installation and runtime management system for operators +- [OperatorHub][operatorhub.io], a community hub for publishing operators +- Operator SDK [scorecard][scorecard-doc], a tool for ensuring operator best-practices and developing cluster tests +Operator SDK supports operator types other than Go as well, such as Ansible and Helm. + +For further context about the relationship between Kubebuilder and Operator SDK, see [this blog post][operator-sdk-reaches-v1.0]. + ## Controller Runtime FAQ Please see the upstream [Controller Runtime FAQ][cr-faq] first for any questions related to runtime mechanics or controller-runtime APIs. @@ -110,11 +122,16 @@ by adding an RBAC directive to generate a `config/rbac/role.yaml` with `update` Now run `make manifests` to update your `role.yaml`. -[kube-apiserver_options]: https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/#options -[controller-runtime_faq]: https://github.com/kubernetes-sigs/controller-runtime/blob/master/FAQ.md#q-how-do-i-have-different-logic-in-my-reconciler-for-different-types-of-events-eg-create-update-delete -[finalizer]:/docs/building-operators/golang/advanced-topics/#handle-cleanup-on-deletion -[cr-faq]:https://github.com/kubernetes-sigs/controller-runtime/blob/master/FAQ.md [client.Reader]:https://godoc.org/sigs.k8s.io/controller-runtime/pkg/client#Reader -[rbac]:https://kubernetes.io/docs/reference/access-authn-authz/rbac/ +[controller-runtime]: https://github.com/kubernetes-sigs/controller-runtime +[cr-faq]:https://github.com/kubernetes-sigs/controller-runtime/blob/master/FAQ.md +[finalizer]:/docs/building-operators/golang/advanced-topics/#handle-cleanup-on-deletion +[kb-doc-what-is-a-basic-project]: https://book.kubebuilder.io/cronjob-tutorial/basic-project.html +[kube-apiserver_options]: https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/#options +[olm]: https://github.com/operator-framework/operator-lifecycle-manager +[operator-sdk-reaches-v1.0]: https://www.openshift.com/blog/operator-sdk-reaches-v1.0 +[operatorhub.io]: https://operatorhub.io/ [owner-references-permission-enforcement]: https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#ownerreferencespermissionenforcement [rbac-markers]: https://book.kubebuilder.io/reference/markers/rbac.html +[rbac]:https://kubernetes.io/docs/reference/access-authn-authz/rbac/ +[scorecard-doc]: https://sdk.operatorframework.io/docs/advanced-topics/scorecard/ From 9a61146c3331404d02f277d5c497ec9fa5dbfde9 Mon Sep 17 00:00:00 2001 From: Martin Hickey Date: Thu, 28 Jan 2021 10:25:18 +0000 Subject: [PATCH 284/376] Update memcached example implementation in Go tutorial (#4441) Example updated following changes to controller in controller-runtime v0.7.0. Tutorial pointing to previous controller logic. Signed-off-by: Martin Hickey Signed-off-by: reinvantveer --- website/content/en/docs/building-operators/golang/tutorial.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/content/en/docs/building-operators/golang/tutorial.md b/website/content/en/docs/building-operators/golang/tutorial.md index cddd79660fb..1c2d2e28602 100644 --- a/website/content/en/docs/building-operators/golang/tutorial.md +++ b/website/content/en/docs/building-operators/golang/tutorial.md @@ -486,7 +486,7 @@ Also see the [advanced topics][advanced_topics] doc for more use cases and under [generating-crd]: https://book.kubebuilder.io/reference/generating-crd.html [markers]: https://book.kubebuilder.io/reference/markers.html [crd-markers]: https://book.kubebuilder.io/reference/markers/crd-validation.html -[memcached_controller]: https://github.com/operator-framework/operator-sdk/blob/v1.2.0/testdata/go/memcached-operator/controllers/memcached_controller.go +[memcached_controller]: https://github.com/operator-framework/operator-sdk/blob/v1.3.0/testdata/go/v3/memcached-operator/controllers/memcached_controller.go [builder_godocs]: https://godoc.org/github.com/kubernetes-sigs/controller-runtime/pkg/builder#example-Builder [activate_modules]: https://github.com/golang/go/wiki/Modules#how-to-install-and-activate-module-support [advanced_topics]: /docs/building-operators/golang/advanced-topics/ From 6bd56b885bbafcfb0160e948c1365a0f960e44c9 Mon Sep 17 00:00:00 2001 From: Camila Macedo Date: Thu, 28 Jan 2021 19:22:37 +0000 Subject: [PATCH 285/376] doc: improve/fix memcached go tutorial (#4021) * doc: improve/fix memcached tutorial * fix link Signed-off-by: reinvantveer --- .../building-operators/ansible/tutorial.md | 8 + .../golang/references/openapi-validation.md | 18 +++ .../building-operators/golang/tutorial.md | 149 ++++++++---------- .../docs/building-operators/helm/tutorial.md | 8 + 4 files changed, 100 insertions(+), 83 deletions(-) create mode 100644 website/content/en/docs/building-operators/golang/references/openapi-validation.md diff --git a/website/content/en/docs/building-operators/ansible/tutorial.md b/website/content/en/docs/building-operators/ansible/tutorial.md index 55a50e8eee3..061f0374cbf 100644 --- a/website/content/en/docs/building-operators/ansible/tutorial.md +++ b/website/content/en/docs/building-operators/ansible/tutorial.md @@ -13,6 +13,14 @@ please [migrate][migration-guide], or consult the [legacy docs][legacy-quickstar - Go through the [installation guide][install-guide]. - User authorized with `cluster-admin` permissions. +## Overview + +We will create a sample project to let you know how it works and this sample will: + +- Create a Memcached Deployment if it doesn't exist +- Ensure that the Deployment size is the same as specified by the Memcached CR spec +- Update the Memcached CR status using the status writer with the names of the memcached pods + ## Create a new project Use the CLI to create a new memcached-operator project: diff --git a/website/content/en/docs/building-operators/golang/references/openapi-validation.md b/website/content/en/docs/building-operators/golang/references/openapi-validation.md new file mode 100644 index 00000000000..31f54ae71c1 --- /dev/null +++ b/website/content/en/docs/building-operators/golang/references/openapi-validation.md @@ -0,0 +1,18 @@ +--- +title: OpenAPI validation +linkTitle: OpenAPI validation +weight: 70 +--- + +OpenAPIv3 schemas are added to CRD manifests in the `spec.validation` block when the manifests are generated. This validation block allows Kubernetes to validate the properties in a Memcached Custom Resource when it is created or updated. + +[Markers][markers] (annotations) are available to configure validations for your API. These markers will always have a `+kubebuilder:validation` prefix. + +Usage of markers in API code is discussed in the kubebuilder [CRD generation][generating-crd] and [marker][markers] documentation. A full list of OpenAPIv3 validation markers can be found [here][crd-markers]. + +To learn more about OpenAPI v3.0 validation schemas in CRDs, refer to the [Kubernetes Documentation][doc-validation-schema]. + +[markers]: https://book.kubebuilder.io/reference/markers.html +[crd-markers]: https://book.kubebuilder.io/reference/markers/crd-validation.html +[generating-crd]: https://book.kubebuilder.io/reference/generating-crd.html +[doc-validation-schema]: https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#specifying-a-structural-schema diff --git a/website/content/en/docs/building-operators/golang/tutorial.md b/website/content/en/docs/building-operators/golang/tutorial.md index 1c2d2e28602..05786196115 100644 --- a/website/content/en/docs/building-operators/golang/tutorial.md +++ b/website/content/en/docs/building-operators/golang/tutorial.md @@ -14,6 +14,14 @@ please [migrate][migration-guide], or consult the [legacy docs][legacy-quickstar - Access to a Kubernetes v1.11.3+ cluster (v1.16.0+ if using `apiextensions.k8s.io/v1` CRDs). - User authorized with `cluster-admin` permissions. +## Overview + +We will create a sample project to let you know how it works and this sample will: + +- Create a Memcached Deployment if it doesn't exist +- Ensure that the Deployment size is the same as specified by the Memcached CR spec +- Update the Memcached CR status using the status writer with the names of the memcached pods + ## Create a new project Use the CLI to create a new memcached-operator project: @@ -48,33 +56,8 @@ By default this will be the namespace that the operator is running in. To watch mgr, err := ctrl.NewManager(cfg, manager.Options{Namespace: ""}) ``` -It is also possible to use the [MultiNamespacedCacheBuilder][multi-namespaced-cache-builder] to watch a specific set of namespaces: -```Go -var namespaces []string // List of Namespaces -// Create a new Cmd to provide shared dependencies and start components -mgr, err := ctrl.NewManager(cfg, manager.Options{ - NewCache: cache.MultiNamespacedCacheBuilder(namespaces), -}) -``` - -#### Operator scope - Read the [operator scope][operator_scope] documentation on how to run your operator as namespace-scoped vs cluster-scoped. -### Multi-Group APIs - -Before creating an API and controller, consider if your operator requires multiple API [groups][api-groups]. Then to change the layout of your project to support multi-group run the command `operator-sdk edit --multigroup`. It will update the `PROJECT` file which should look like the following: - -```YAML -domain: example.com -layout: go.kubebuilder.io/v3 -multigroup: true -... -``` -For multi-group projects, the API Go type files are created under `apis///` and the controllers under `controllers//` and then, the Dockerfile will be updated accordingly. For further information see the [multi-group migration doc][multigroup-kubebuilder-doc] - -This guide will cover the default case of a single group API. - ## Create a new API and Controller Create a new Custom Resource Definition(CRD) API with group `cache` version `v1alpha1` and Kind Memcached. @@ -90,12 +73,21 @@ controllers/memcached_controller.go This will scaffold the Memcached resource API at `api/v1alpha1/memcached_types.go` and the controller at `controllers/memcached_controller.go`. -See the [API terminology doc][api_terms_doc] for details on the CRD API conventions. +**Note:** This guide will cover the default case of a single group API. If you would like to support Multi-Group APIs see the [Single Group to Multi-Group][multigroup-kubebuilder-doc] doc. + +#### Understanding Kubernetes APIs -To understand the API Go types and controller scaffolding see the Kubebuilder [api doc][kb_api_doc] and [controller doc][kb_controller_doc]. +For an in-depth explanation of Kubernetes APIs and the group-version-kind model, check out these [kubebuilder docs][kb-doc-gkvs]. + +In general, it's recommended to have one controller responsible for manage each API created for the project to +properly follow the design goals set by [controller-runtime][controller-runtime]. ### Define the API +To begin, we will represent our API by defining the `Memcached` type, which will have a `MemcachedSpec.Size` field to set the quantity of memcached instances (CRs) to be deployed, and a `MemcachedStatus.Nodes` field to store a CR's Pod names. + +**Note** The Node field is just to illustrate an example of a Status field. In real cases, it would be recommended to use [Conditions][conditionals]. + Define the API for the Memcached Custom Resource(CR) by modifying the Go type definitions at `api/v1alpha1/memcached_types.go` to have the following spec and status: ```Go @@ -143,30 +135,20 @@ Once the API is defined with spec/status fields and CRD validation markers, the make manifests ``` -This makefile target will invoke controller-gen to generate the CRD manifests at `config/crd/bases/cache.example.com_memcacheds.yaml`. - -#### OpenAPI validation - -OpenAPIv3 schemas are added to CRD manifests in the `spec.validation` block when the manifests are generated. This validation block allows Kubernetes to validate the properties in a Memcached Custom Resource when it is created or updated. +This makefile target will invoke [controller-gen][controller_tools] to generate the CRD manifests at `config/crd/bases/cache.example.com_memcacheds.yaml`. -Markers (annotations) are available to configure validations for your API. These markers will always have a `+kubebuilder:validation` prefix. +### OpenAPI validation -Usage of markers in API code is discussed in the kubebuilder [CRD generation][generating-crd] and [marker][markers] documentation. A full list of OpenAPIv3 validation markers can be found [here][crd-markers]. +OpenAPI validation defined in a CRD ensures CRs are validated based on a set of declarative rules. All CRDs should have validation. +See the [OpenAPI valiation][openapi-validation] doc for details. -To learn more about OpenAPI v3.0 validation schemas in CRDs, refer to the [Kubernetes Documentation][doc-validation-schema]. - -### Implement the Controller +## Implement the Controller For this example replace the generated controller file `controllers/memcached_controller.go` with the example [`memcached_controller.go`][memcached_controller] implementation. -The example controller executes the following reconciliation logic for each Memcached CR: -- Create a memcached Deployment if it doesn't exist -- Ensure that the Deployment size is the same as specified by the Memcached CR spec -- Update the Memcached CR status using the status writer with the names of the memcached pods - -The next two subsections explain how the controller watches resources and how the reconcile loop is triggered. Skip to the ["run the Operator"](#run-the-operator) section to see how to build and run the operator. +**Note**: The next two subsections explain how the controller watches resources and how the reconcile loop is triggered. Skip to the [Build](#build-and-push-the-image) section to see how to build and run the operator. -#### Resources watched by the Controller +### Resources watched by the Controller The `SetupWithManager()` function in `controllers/memcached_controller.go` specifies how the controller is built to watch a CR and other resources that are owned and managed by that controller. @@ -191,7 +173,7 @@ The `NewControllerManagedBy()` provides a controller builder that allows various `Owns(&appsv1.Deployment{})` specifies the Deployments type as the secondary resource to watch. For each Deployment type Add/Update/Delete event, the event handler will map each event to a reconcile `Request` for the owner of the Deployment. Which in this case is the Memcached object for which the Deployment was created. -#### Controller Configurations +### Controller Configurations There are a number of other useful configurations that can be made when initialzing a controller. For more details on these configurations consult the upstream [builder][builder_godocs] and [controller][controller_godocs] godocs. @@ -208,10 +190,11 @@ There are a number of other useful configurations that can be made when initialz - Filter watch events using [predicates][event_filtering] - Choose the type of [EventHandler][event_handler_godocs] to change how a watch event will translate to reconcile requests for the reconcile loop. For operator relationships that are more complex than primary and secondary resources, the [`EnqueueRequestsFromMapFunc`][enqueue_requests_from_map_func] handler can be used to transform a watch event into an arbitrary set of reconcile requests. +### Reconcile loop -#### Reconcile loop +The reconcile function is responsible for enforcing the desired CR state on the actual state of the system. It runs each time an event occurs on a watched CR or resource, and will return some value depending on whether those states match or not. -Every Controller has a Reconciler object with a `Reconcile()` method that implements the reconcile loop. The reconcile loop is passed the [`Request`][request-go-doc] argument which is a Namespace/Name key used to lookup the primary resource object, Memcached, from the cache: +In this way, every Controller has a Reconciler object with a `Reconcile()` method that implements the reconcile loop. The reconcile loop is passed the [`Request`][request-go-doc] argument which is a Namespace/Name key used to lookup the primary resource object, Memcached, from the cache: ```Go import ( @@ -229,32 +212,32 @@ func (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) ( } ``` -Based on the return values, [`Result`][result_go_doc] and error, the `Request` may be requeued and the reconcile loop may be triggered again: - -```Go -// Reconcile successful - don't requeue -return ctrl.Result{}, nil -// Reconcile failed due to error - requeue -return ctrl.Result{}, err -// Requeue for any reason other than an error -return ctrl.Result{Requeue: true}, nil -``` - -You can set the `Result.RequeueAfter` to requeue the `Request` after a grace period as well: -```Go -import "time" +For a guide on Reconcilers, Clients, and interacting with resource Events, see the [Client API doc][doc_client_api]. -// Reconcile for any reason other than an error after 5 seconds -return ctrl.Result{RequeueAfter: time.Second*5}, nil -``` +The following are a few possible return options for a Reconciler: -**Note:** Returning `Result` with `RequeueAfter` set is how you can periodically reconcile a CR. +- With the error: + ```go + return ctrl.Result{}, err + ``` +- Without an error: + ```go + return ctrl.Result{Requeue: true}, nil + ``` +- Therefore, to stop the Reconcile, use: + ```go + return ctrl.Result{}, nil + ``` +- Reconcile again after X time: + ```go + return ctrl.Result{RequeueAfter: nextRun.Sub(r.Now())}, nil + ``` -For a guide on Reconcilers, Clients, and interacting with resource Events, see the [Client API doc][doc_client_api]. +For more details, check the Reconcile and its [Reconcile godoc][reconcile-godoc]. ### Specify permissions and generate RBAC manifests -The controller needs certain RBAC permissions to interact with the resources it manages. These are specified via [RBAC markers][rbac_markers] like the following: +The controller needs certain [RBAC][rbac-k8s-doc] permissions to interact with the resources it manages. These are specified via [RBAC markers][rbac_markers] like the following: ```Go // +kubebuilder:rbac:groups=cache.example.com,resources=memcacheds,verbs=get;list;watch;create;update;patch;delete @@ -284,15 +267,11 @@ There are three ways to run the operator: ### 1. Run locally outside the cluster -Execute the following command, which install your CRDs and run the manager locally: - -```sh -make install run ENABLE_WEBHOOKS=false -``` +The following steps will show how to deploy the operator on the Cluster. However, to run locally for development purposes and outside of a Cluster use the target `make install run`. ### 2. Run as a Deployment inside the cluster -#### Build and push the image +### Build and push the image Before building the operator image, ensure the generated Dockerfile references the base image you want. You can change the default "runner" image `gcr.io/distroless/static:nonroot` @@ -331,9 +310,6 @@ Run the following to deploy the operator. This will also install the RBAC manife make deploy IMG=quay.io/$USERNAME/memcached-operator:v0.0.1 ``` -*NOTE* If you have enabled webhooks in your deployments, you will need to have cert-manager already installed -in the cluster or `make deploy` will fail when creating the cert-manager resources. - Verify that the memcached-operator is up and running: ```console @@ -368,7 +344,6 @@ operator-sdk run bundle $BUNDLE_IMG Check out the [docs][quickstart-bundle] for a deep dive into `operator-sdk`'s OLM integration. - ## Create a Memcached CR Update the sample Memcached CR manifest at `config/samples/cache_v1alpha1_memcached.yaml` and define the `spec` as the following: @@ -454,12 +429,11 @@ make undeploy ## Further steps -The following guides build off the operator created in this example, adding advanced features: - -- [Create a validating or mutating Admission Webhook][create_a_webhook] - -Also see the [advanced topics][advanced_topics] doc for more use cases and under the hood details. +Next, try adding the following to your project: +1. Validating and mutating [admission webhooks][create_a_webhook]. +2. Operator packaging and distribution with [OLM][olm-integration]. +Also see the [advanced topics][advanced_topics] doc for more use cases and under the hood details. [legacy-quickstart-doc]:https://v0-19-x.sdk.operatorframework.io/docs/golang/legacy/quickstart/ [migration-guide]:/docs/building-operators/golang/migration @@ -493,8 +467,17 @@ Also see the [advanced topics][advanced_topics] doc for more use cases and under [create_a_webhook]: https://book.kubebuilder.io/cronjob-tutorial/webhook-implementation.html [status_marker]: https://book.kubebuilder.io/reference/generating-crd.html#status [status_subresource]: https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#status-subresource -[env-test-setup]: /docs/building-operators/golang/references/envtest-setup +[API-groups]:https://kubernetes.io/docs/concepts/overview/kubernetes-api/#api-groups +[legacy_CLI]:https://v0-19-x.sdk.operatorframework.io/docs/cli/ [role-based-access-control]: https://cloud.google.com/kubernetes-engine/docs/how-to/role-based-access-control#iam-rolebinding-bootstrap [multigroup-kubebuilder-doc]: https://book.kubebuilder.io/migration/multi-group.html [quickstart-bundle]:/docs/olm-integration/quickstart-bundle [doc-olm]:/docs/olm-integration/quickstart-bundle/#enabling-olm +[conditionals]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties +[kubernetes-extend-api]: https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/ +[reconcile-godoc]: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/reconcile +[rbac-k8s-doc]: https://kubernetes.io/docs/reference/access-authn-authz/rbac/ +[olm-integration]: /docs/olm-integration +[openapi-validation]: /docs/building-operators/golang/references/openapi-validation +[controller-runtime]: https://github.com/kubernetes-sigs/controller-runtime +[kb-doc-gkvs]: https://book.kubebuilder.io/cronjob-tutorial/gvks.html \ No newline at end of file diff --git a/website/content/en/docs/building-operators/helm/tutorial.md b/website/content/en/docs/building-operators/helm/tutorial.md index 472953f80e2..0e46618f1a1 100644 --- a/website/content/en/docs/building-operators/helm/tutorial.md +++ b/website/content/en/docs/building-operators/helm/tutorial.md @@ -13,6 +13,14 @@ please [migrate][migration-guide], or consult the [legacy docs][legacy-quickstar - Go through the [installation guide][install-guide]. - User authorized with `cluster-admin` permissions. +## Overview + +We will create a sample project to let you know how it works and this sample will: + +- Create a Memcached Deployment if it doesn't exist +- Ensure that the Deployment size is the same as specified by the Memcached CR spec +- Update the Memcached CR status using the status writer with the names of the memcached pods + ## Create a new project Use the CLI to create a new Helm-based nginx-operator project: From 6627b63d3940a0c9a68fd12fe73972f9aaf770d6 Mon Sep 17 00:00:00 2001 From: Rashmi Gottipati Date: Thu, 28 Jan 2021 17:36:56 -0500 Subject: [PATCH 286/376] Bug 1921458: `run bundle-upgrade` should handle error gracefully when a previous operator version doesn't exist (#4448) * `run bundle-upgrade` should handle error gracefully when a previous operator version doesn't exist Signed-off-by: rashmigottipati Signed-off-by: reinvantveer --- changelog/fragments/bugfix-run-bundle-upgrade.yaml | 4 ++++ internal/olm/operator/registry/operator_installer.go | 6 ++++++ 2 files changed, 10 insertions(+) create mode 100644 changelog/fragments/bugfix-run-bundle-upgrade.yaml diff --git a/changelog/fragments/bugfix-run-bundle-upgrade.yaml b/changelog/fragments/bugfix-run-bundle-upgrade.yaml new file mode 100644 index 00000000000..af0a6ccf6e9 --- /dev/null +++ b/changelog/fragments/bugfix-run-bundle-upgrade.yaml @@ -0,0 +1,4 @@ +entries: + - description: > + `run bundle-upgrade` handles error gracefully when a previous operator version doesn't exist + kind: bugfix diff --git a/internal/olm/operator/registry/operator_installer.go b/internal/olm/operator/registry/operator_installer.go index 301a04f625a..dd1bbe9a164 100644 --- a/internal/olm/operator/registry/operator_installer.go +++ b/internal/olm/operator/registry/operator_installer.go @@ -16,6 +16,7 @@ package registry import ( "context" + "errors" "fmt" "time" @@ -108,6 +109,11 @@ func (o OperatorInstaller) UpgradeOperator(ctx context.Context) (*v1alpha1.Clust return nil, fmt.Errorf("error getting list of subscriptions: %v", err) } + // If there are no subscriptions found, then the previous operator version doesn't exist, so return error + if len(subList.Items) == 0 { + return nil, errors.New("no existing operator found in the cluster to upgrade") + } + var subscription *v1alpha1.Subscription for i := range subList.Items { s := subList.Items[i] From 4fd6c5db00a56a3b7390b7830d394afe491da5e7 Mon Sep 17 00:00:00 2001 From: Jesus Rodriguez Date: Fri, 29 Jan 2021 09:51:11 -0500 Subject: [PATCH 287/376] Bug 1921727: Bundle validate should not fail because of warnings. (#4449) Bumped to operator-framework/api. Signed-off-by: jesus m. rodriguez Signed-off-by: reinvantveer --- .../fragments/fix-bundle-validate-failure-on-warnings.yaml | 6 ++++++ go.mod | 2 +- go.sum | 2 ++ 3 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 changelog/fragments/fix-bundle-validate-failure-on-warnings.yaml diff --git a/changelog/fragments/fix-bundle-validate-failure-on-warnings.yaml b/changelog/fragments/fix-bundle-validate-failure-on-warnings.yaml new file mode 100644 index 00000000000..a48643e8f46 --- /dev/null +++ b/changelog/fragments/fix-bundle-validate-failure-on-warnings.yaml @@ -0,0 +1,6 @@ +entries: + - description: > + Bump operator-framework/api to fix "operator-sdk bundle validate" failure when bundle has warnings. + When a warning is detected during validation it should be logged to the CLI but the validation should still pass. + kind: bugfix + breaking: false diff --git a/go.mod b/go.mod index 74021f652f3..0f2f81c95a0 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/markbates/inflect v1.0.4 github.com/onsi/ginkgo v1.14.1 github.com/onsi/gomega v1.10.2 - github.com/operator-framework/api v0.5.2 + github.com/operator-framework/api v0.5.3 github.com/operator-framework/operator-lib v0.4.0 github.com/operator-framework/operator-registry v1.15.3 github.com/prometheus/client_golang v1.7.1 diff --git a/go.sum b/go.sum index 8c487d1a8af..1f60e99095b 100644 --- a/go.sum +++ b/go.sum @@ -754,6 +754,8 @@ github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnh github.com/operator-framework/api v0.3.22/go.mod h1:GVNiB6AQucwdZz3ZFXNv9HtcLOzcFnr6O/QldzKG93g= github.com/operator-framework/api v0.5.2 h1:NLgOoi70+iyz4vVJeeJUKaFT8wZaCbCHzS1eExCqX7A= github.com/operator-framework/api v0.5.2/go.mod h1:L7IvLd/ckxJEJg/t4oTTlnHKAJIP/p51AvEslW3wYdY= +github.com/operator-framework/api v0.5.3 h1:1RDw2FbuEDtSC7ONKLKgAxtq+iRsV7rRTumD4RLQfSI= +github.com/operator-framework/api v0.5.3/go.mod h1:L7IvLd/ckxJEJg/t4oTTlnHKAJIP/p51AvEslW3wYdY= github.com/operator-framework/operator-lib v0.4.0 h1:g7tGRo+FikHgFZDmRdHkOxyTv3sViI+Ujiqbfd9Tfsk= github.com/operator-framework/operator-lib v0.4.0/go.mod h1:kOjV7h01DCSw3RZAqYdHyHyVwuJL8hvG53tSZoDZfsQ= github.com/operator-framework/operator-registry v1.15.3 h1:C+u+zjDh6yQAKN+DbUvPeLjojZtJftvp/J28rRqiWWU= From 2dab5549bd45ca8dc17e4af4d1cbd417f6c42c59 Mon Sep 17 00:00:00 2001 From: Rashmi Gottipati Date: Fri, 29 Jan 2021 11:27:06 -0500 Subject: [PATCH 288/376] bugfix for `run bundle-upgrade` to handle subscription not matching package name (#4452) Signed-off-by: rashmigottipati Signed-off-by: reinvantveer --- internal/olm/operator/registry/operator_installer.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/internal/olm/operator/registry/operator_installer.go b/internal/olm/operator/registry/operator_installer.go index dd1bbe9a164..882a5a19bce 100644 --- a/internal/olm/operator/registry/operator_installer.go +++ b/internal/olm/operator/registry/operator_installer.go @@ -123,6 +123,10 @@ func (o OperatorInstaller) UpgradeOperator(ctx context.Context) (*v1alpha1.Clust } } + if subscription == nil { + return nil, fmt.Errorf("subscription for package %q not found", o.PackageName) + } + log.Infof("Found existing subscription with name %s and namespace %s", subscription.Name, subscription.Namespace) // Get existing catalog source from the subsription From 08a31318fe8ea5b6547c9ecb06a7f0733592fa80 Mon Sep 17 00:00:00 2001 From: Martin Hickey Date: Sun, 31 Jan 2021 03:25:34 +0000 Subject: [PATCH 289/376] Add issues template for documentation (#4444) Signed-off-by: Martin Hickey Signed-off-by: reinvantveer --- .github/ISSUE_TEMPLATE/doc-report.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/doc-report.md diff --git a/.github/ISSUE_TEMPLATE/doc-report.md b/.github/ISSUE_TEMPLATE/doc-report.md new file mode 100644 index 00000000000..f0e68901e38 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/doc-report.md @@ -0,0 +1,28 @@ +--- +name: Doc Report +about: Raise an issue with the documentation. +title: '' +labels: kind/documentation +assignees: '' + +--- + + + +### What is the URL of the document? + + + +### Which section(s) is the issue in? + + + +### What needs fixing? + + + +#### Additional context + + From 787f99771a38f9f3134ee87585acfe3302407888 Mon Sep 17 00:00:00 2001 From: Mike Ng Date: Mon, 1 Feb 2021 13:16:05 -0500 Subject: [PATCH 290/376] Bug fix: helm operator uninstall is not properly checking for existing release (#3431) Signed-off-by: reinvantveer --- changelog/fragments/helm-uninstall-fix.yaml | 4 ++++ internal/helm/release/manager.go | 12 ------------ 2 files changed, 4 insertions(+), 12 deletions(-) create mode 100644 changelog/fragments/helm-uninstall-fix.yaml diff --git a/changelog/fragments/helm-uninstall-fix.yaml b/changelog/fragments/helm-uninstall-fix.yaml new file mode 100644 index 00000000000..e8b6ce88518 --- /dev/null +++ b/changelog/fragments/helm-uninstall-fix.yaml @@ -0,0 +1,4 @@ +entries: + - description: Fixed a bug that caused the Helm operator to remove the finalizer without doing a helm uninstall. + kind: "bugfix" + breaking: false \ No newline at end of file diff --git a/internal/helm/release/manager.go b/internal/helm/release/manager.go index d72c2a0c0c5..c2968e4ddf8 100644 --- a/internal/helm/release/manager.go +++ b/internal/helm/release/manager.go @@ -351,18 +351,6 @@ func createJSONMergePatch(existingJSON, expectedJSON []byte) ([]byte, error) { // UninstallRelease performs a Helm release uninstall. func (m manager) UninstallRelease(ctx context.Context, opts ...UninstallOption) (*rpb.Release, error) { - // Get history of this release - h, err := m.storageBackend.History(m.releaseName) - if err != nil { - return nil, fmt.Errorf("failed to get release history: %w", err) - } - - // If there is no history, the release has already been uninstalled, - // so return ErrReleaseNotFound. - if len(h) == 0 { - return nil, driver.ErrReleaseNotFound - } - uninstall := action.NewUninstall(m.actionConfig) for _, o := range opts { if err := o(uninstall); err != nil { From 346ef0af59fd207515fb5659545dfc373dd41a7e Mon Sep 17 00:00:00 2001 From: Jonathan Berkhahn Date: Mon, 1 Feb 2021 13:21:42 -0800 Subject: [PATCH 291/376] Refactor pkg manifest generator as interface (#3747) Signed-off-by: Jonathan Berkhahn Signed-off-by: reinvantveer --- Makefile | 1 + go.sum | 1 + .../generate/packagemanifests/cmd.go | 4 + .../generate/packagemanifests/cmd_test.go | 86 ++++ .../packagemanifests/packagemanifests.go | 19 +- .../packagemanifests_suite_test.go | 27 ++ .../packagemanifests/packagemanifests_test.go | 269 ++++++++++++ .../packagemanifests/testdata/PROJECT | 14 + .../packagemanifest/bases/packagemanifest.go | 67 --- .../packagemanifest/packagemanifest.go | 190 +++++---- .../packagemanifest_suite_test.go | 27 ++ .../packagemanifest/packagemanifest_test.go | 383 ++++++++---------- .../packagemanifestfakes/fake_generator.go | 116 ++++++ 13 files changed, 818 insertions(+), 386 deletions(-) create mode 100644 internal/cmd/operator-sdk/generate/packagemanifests/cmd_test.go create mode 100644 internal/cmd/operator-sdk/generate/packagemanifests/packagemanifests_suite_test.go create mode 100644 internal/cmd/operator-sdk/generate/packagemanifests/packagemanifests_test.go create mode 100644 internal/cmd/operator-sdk/generate/packagemanifests/testdata/PROJECT delete mode 100644 internal/generate/packagemanifest/bases/packagemanifest.go create mode 100644 internal/generate/packagemanifest/packagemanifest_suite_test.go create mode 100644 internal/generate/packagemanifest/packagemanifestfakes/fake_generator.go diff --git a/Makefile b/Makefile index c6305d6a6e9..1a23bf53681 100644 --- a/Makefile +++ b/Makefile @@ -39,6 +39,7 @@ generate: build # Generate CLI docs and samples go run ./hack/generate/cncf-maintainers/main.go go run ./hack/generate/cli-doc/gen-cli-doc.go go run ./hack/generate/samples/generate_testdata.go + go generate ./... .PHONY: bindata OLM_VERSIONS = 0.16.1 0.15.1 0.17.0 diff --git a/go.sum b/go.sum index 1f60e99095b..057aefe6a13 100644 --- a/go.sum +++ b/go.sum @@ -653,6 +653,7 @@ github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsO github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2 h1:g+4J5sZg6osfvEfkRZxJ1em0VT95/UOZgi/l7zi1/oE= github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mikefarah/yaml/v2 v2.4.0/go.mod h1:ahVqZF4n1W4NqwvVnZzC4es67xsW9uR/RRf2RRxieJU= diff --git a/internal/cmd/operator-sdk/generate/packagemanifests/cmd.go b/internal/cmd/operator-sdk/generate/packagemanifests/cmd.go index d75488d3c4f..9e3e2e4636a 100644 --- a/internal/cmd/operator-sdk/generate/packagemanifests/cmd.go +++ b/internal/cmd/operator-sdk/generate/packagemanifests/cmd.go @@ -21,6 +21,8 @@ import ( log "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/spf13/pflag" + + "github.com/operator-framework/operator-sdk/internal/generate/packagemanifest" ) //nolint:maligned @@ -44,6 +46,8 @@ type packagemanifestsCmd struct { // These are set if a PROJECT config is not present. layout string packageName string + // Backend generator + generator packagemanifest.Generator } // NewCmd returns the 'packagemanifests' command configured for the new project layout. diff --git a/internal/cmd/operator-sdk/generate/packagemanifests/cmd_test.go b/internal/cmd/operator-sdk/generate/packagemanifests/cmd_test.go new file mode 100644 index 00000000000..b360ef72ac7 --- /dev/null +++ b/internal/cmd/operator-sdk/generate/packagemanifests/cmd_test.go @@ -0,0 +1,86 @@ +// Copyright 2021 The Operator-SDK 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. + +package packagemanifests + +import ( + "path/filepath" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("Creating a generate packagemanifests command", func() { + Describe("NewCmd", func() { + It("builds and returns a cobra command", func() { + cmd := NewCmd() + Expect(cmd).NotTo(BeNil()) + + flag := cmd.Flags().Lookup("version") + Expect(flag).NotTo(BeNil()) + Expect(flag.Shorthand).To(Equal("v")) + Expect(flag.Usage).ToNot(Equal("")) + + flag = cmd.Flags().Lookup("from-version") + Expect(flag).NotTo(BeNil()) + Expect(flag.Usage).ToNot(Equal("")) + + flag = cmd.Flags().Lookup("input-dir") + Expect(flag).NotTo(BeNil()) + Expect(flag.Usage).ToNot(Equal("")) + + flag = cmd.Flags().Lookup("output-dir") + Expect(flag).NotTo(BeNil()) + Expect(flag.Usage).ToNot(Equal("")) + + flag = cmd.Flags().Lookup("kustomize-dir") + Expect(flag).NotTo(BeNil()) + Expect(flag.DefValue).To(Equal(filepath.Join("config", "manifests"))) + Expect(flag.Usage).ToNot(Equal("")) + + flag = cmd.Flags().Lookup("deploy-dir") + Expect(flag).NotTo(BeNil()) + Expect(flag.Usage).ToNot(Equal("")) + + flag = cmd.Flags().Lookup("crds-dir") + Expect(flag).NotTo(BeNil()) + Expect(flag.Usage).ToNot(Equal("")) + + flag = cmd.Flags().Lookup("channel") + Expect(flag).NotTo(BeNil()) + Expect(flag.Usage).ToNot(Equal("")) + + flag = cmd.Flags().Lookup("default-channel") + Expect(flag).NotTo(BeNil()) + Expect(flag.DefValue).To(Equal("false")) + Expect(flag.Usage).ToNot(Equal("")) + + flag = cmd.Flags().Lookup("update-objects") + Expect(flag).NotTo(BeNil()) + Expect(flag.DefValue).To(Equal("true")) + Expect(flag.Usage).ToNot(Equal("")) + + flag = cmd.Flags().Lookup("quiet") + Expect(flag).NotTo(BeNil()) + Expect(flag.Shorthand).To(Equal("q")) + Expect(flag.DefValue).To(Equal("false")) + Expect(flag.Usage).ToNot(Equal("")) + + flag = cmd.Flags().Lookup("stdout") + Expect(flag).NotTo(BeNil()) + Expect(flag.DefValue).To(Equal("false")) + Expect(flag.Usage).ToNot(Equal("")) + }) + }) +}) diff --git a/internal/cmd/operator-sdk/generate/packagemanifests/packagemanifests.go b/internal/cmd/operator-sdk/generate/packagemanifests/packagemanifests.go index c99af553a9c..53f3c728fc6 100644 --- a/internal/cmd/operator-sdk/generate/packagemanifests/packagemanifests.go +++ b/internal/cmd/operator-sdk/generate/packagemanifests/packagemanifests.go @@ -90,6 +90,7 @@ func (c *packagemanifestsCmd) setDefaults() (err error) { c.outputDir = defaultRootDir } } + c.generator = genpkg.NewGenerator() return nil } @@ -216,17 +217,19 @@ func (c packagemanifestsCmd) run() error { } func (c packagemanifestsCmd) generatePackageManifest() error { - pkgGen := genpkg.Generator{ - OperatorName: c.packageName, - Version: c.version, + //copy of genpkg withfilewriter() + //move out of internal util pkg? + if err := os.MkdirAll(c.outputDir, 0755); err != nil { + return err + } + + opts := genpkg.Options{ + BaseDir: c.inputDir, ChannelName: c.channelName, IsDefaultChannel: c.isDefaultChannel, } - opts := []genpkg.Option{ - genpkg.WithBase(c.inputDir), - genpkg.WithFileWriter(c.outputDir), - } - if err := pkgGen.Generate(opts...); err != nil { + + if err := c.generator.Generate(c.packageName, c.version, c.outputDir, opts); err != nil { return err } return nil diff --git a/internal/cmd/operator-sdk/generate/packagemanifests/packagemanifests_suite_test.go b/internal/cmd/operator-sdk/generate/packagemanifests/packagemanifests_suite_test.go new file mode 100644 index 00000000000..4da023c453c --- /dev/null +++ b/internal/cmd/operator-sdk/generate/packagemanifests/packagemanifests_suite_test.go @@ -0,0 +1,27 @@ +// Copyright 2021 The Operator-SDK 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. + +package packagemanifests + +import ( + "testing" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +func TestPackagemanifests(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Packagemanifests Suite") +} diff --git a/internal/cmd/operator-sdk/generate/packagemanifests/packagemanifests_test.go b/internal/cmd/operator-sdk/generate/packagemanifests/packagemanifests_test.go new file mode 100644 index 00000000000..86e6a0771b3 --- /dev/null +++ b/internal/cmd/operator-sdk/generate/packagemanifests/packagemanifests_test.go @@ -0,0 +1,269 @@ +// Copyright 2021 The Operator-SDK 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. + +package packagemanifests + +import ( + "errors" + "os" + "path/filepath" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "github.com/operator-framework/operator-sdk/internal/generate/packagemanifest" + "github.com/operator-framework/operator-sdk/internal/generate/packagemanifest/packagemanifestfakes" +) + +var _ = Describe("Running a generate packagemanifests command", func() { + var ( + c packagemanifestsCmd + crdsDir string + deployDir string + inputDir string + kustomizeDir string + versionOne string + + originalDir string + testDataDir string + ) + BeforeEach(func() { + c = packagemanifestsCmd{} + crdsDir = "crds" + deployDir = "deploy" + inputDir = "input" + kustomizeDir = "kustomize" + versionOne = "1.0.0" + + originalDir = filepath.Join("..", "..", "..", "..", "internal", "cmd", "operator-sdk", "generate", "packagemanifests") + testDataDir = filepath.Join("..", "..", "..", "..", "..", "testdata", "go", "v3", "memcached-operator") + }) + Describe("validate", func() { + It("fails if no version is provided", func() { + err := c.validate() + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("version must be set")) + }) + It("fails if a non-parsable version is provided", func() { + c.version = "potato" + + err := c.validate() + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("potato is not a valid semantic version")) + }) + It("fails if an a non-parsable from-version is provided", func() { + c.version = versionOne + c.fromVersion = "1.0.a" + + err := c.validate() + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("1.0.a is not a valid semantic version")) + }) + It("fails if an input-dir is not provided", func() { + c.version = versionOne + + err := c.validate() + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("input-dir must be set")) + }) + It("fails if a kuztomize-dir is not provided", func() { + c.version = versionOne + c.inputDir = inputDir + + err := c.validate() + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("kustomize-dir must be set")) + }) + It("fails if a deploy-dir is not provided while not reading from stdin", func() { + c.version = versionOne + c.inputDir = inputDir + c.kustomizeDir = kustomizeDir + + err := c.validate() + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("deploy-dir must be set if not reading from stdin")) + }) + It("fails if a crds-dir is not provided while not reading from stdin", func() { + c.version = versionOne + c.inputDir = inputDir + c.kustomizeDir = kustomizeDir + c.deployDir = deployDir + + err := c.validate() + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("must be set if not reading from stdin")) + }) + It("allows deply-dir and crds-dir to not be set if reading from a pipe such as stdin", func() { + c.version = versionOne + c.inputDir = inputDir + c.kustomizeDir = kustomizeDir + r, _, err := os.Pipe() + Expect(err).NotTo(HaveOccurred()) + origStdin := os.Stdin + defer func() { os.Stdin = origStdin }() + os.Stdin = r + + err = c.validate() + Expect(err).NotTo(HaveOccurred()) + }) + It("fails if an output-dir is set while set to write to stdout", func() { + c.version = versionOne + c.inputDir = inputDir + c.kustomizeDir = kustomizeDir + c.deployDir = deployDir + c.crdsDir = crdsDir + c.stdout = true + c.outputDir = "output/" + + err := c.validate() + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("output-dir cannot be set if writing to stdout")) + }) + It("fails if default-channel is set but channel is not provided", func() { + c.version = versionOne + c.inputDir = inputDir + c.kustomizeDir = kustomizeDir + c.deployDir = deployDir + c.crdsDir = crdsDir + c.isDefaultChannel = true + + err := c.validate() + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("default-channel can only be set if --channel is set")) + }) + It("validates successfully", func() { + c.version = versionOne + c.fromVersion = "0.1.2" + c.inputDir = inputDir + c.kustomizeDir = kustomizeDir + c.deployDir = deployDir + c.crdsDir = "crds/" + + err := c.validate() + Expect(err).NotTo(HaveOccurred()) + }) + It("succeeds if both default-channel and channel are set", func() { + c.version = versionOne + c.inputDir = inputDir + c.kustomizeDir = kustomizeDir + c.deployDir = deployDir + c.crdsDir = crdsDir + c.isDefaultChannel = true + c.channelName = "alpha" + + err := c.validate() + Expect(err).NotTo(HaveOccurred()) + }) + }) + Describe("setDefaults", func() { + Context("no project file is present", func() { + It("fails if no correct operator name can be found", func() { + err := c.setDefaults() + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("package-name must be set if PROJECT config file is not present")) + }) + It("sets fields on the command to default values", func() { + c.packageName = "apricot" + + err := c.setDefaults() + Expect(err).NotTo(HaveOccurred()) + Expect(c.inputDir).To(Equal(defaultRootDir)) + Expect(c.outputDir).To(Equal(defaultRootDir)) + Expect(c.generator).ToNot(BeNil()) + Expect(c.layout).To(Equal("unknown")) + }) + It("does not set output if stdout has been set", func() { + c.packageName = "banana" + c.stdout = true + + err := c.setDefaults() + Expect(err).NotTo(HaveOccurred()) + Expect(c.inputDir).To(Equal(defaultRootDir)) + Expect(c.outputDir).To(Equal("")) + }) + }) + Context("a valid project file is present", func() { + BeforeEach(func() { + err := os.Chdir(testDataDir) + Expect(err).NotTo(HaveOccurred()) + }) + AfterEach(func() { + err := os.Chdir(originalDir) + Expect(err).NotTo(HaveOccurred()) + }) + It("reads the data from the project file", func() { + err := c.setDefaults() + Expect(err).NotTo(HaveOccurred()) + Expect(c.packageName).To(Equal("memcached-operator")) + Expect(c.layout).To(Equal("go.kubebuilder.io/v3")) + }) + It("doesn't overwrite the package name if it's already set", func() { + c.packageName = "cherry" + + err := c.setDefaults() + Expect(err).NotTo(HaveOccurred()) + Expect(c.packageName).To(Equal("cherry")) + Expect(c.layout).To(Equal("go.kubebuilder.io/v3")) + }) + }) + Context("an invalid project file is present", func() { + BeforeEach(func() { + err := os.Chdir("testdata") + Expect(err).NotTo(HaveOccurred()) + }) + AfterEach(func() { + err := os.Chdir("..") + Expect(err).NotTo(HaveOccurred()) + }) + It("reads the data from the project file", func() { + err := c.setDefaults() + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("error unmarshalling project configuration")) + }) + }) + }) + Describe("generatePackageManifest", func() { + var fakeGen packagemanifestfakes.FakeGenerator + BeforeEach(func() { + c.channelName = "apple" + c.generator = &fakeGen + c.inputDir = "banana/" + c.isDefaultChannel = true + c.outputDir = os.TempDir() + c.packageName = "cherry" + c.version = "1.2.3" + }) + It("calls the package manifest generator with the correct params", func() { + err := c.generatePackageManifest() + Expect(err).NotTo(HaveOccurred()) + Expect(fakeGen.GenerateCallCount()).To(Equal(1)) + paramName, paramVersion, paramOutputDir, paramOpt := fakeGen.GenerateArgsForCall(0) + Expect(paramName).To(Equal(c.packageName)) + Expect(paramVersion).To(Equal(c.version)) + Expect(paramOutputDir).To(Equal(c.outputDir)) + Expect((paramOpt)).To(Equal(packagemanifest.Options{ + BaseDir: c.inputDir, + ChannelName: c.channelName, + IsDefaultChannel: c.isDefaultChannel, + })) + }) + It("bubbles up errors from the generator", func() { + potatoErr := errors.New("potato error") + fakeGen.GenerateReturns(potatoErr) + + err := c.generatePackageManifest() + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring(potatoErr.Error())) + }) + }) +}) diff --git a/internal/cmd/operator-sdk/generate/packagemanifests/testdata/PROJECT b/internal/cmd/operator-sdk/generate/packagemanifests/testdata/PROJECT new file mode 100644 index 00000000000..8116502abb3 --- /dev/null +++ b/internal/cmd/operator-sdk/generate/packagemanifests/testdata/PROJECT @@ -0,0 +1,14 @@ +domain: example.com +layout: go.kubebuilder.io/v3-alpha +projectName: memcached-operator +repo: github.com/example/memcached-operator +resources: + - crdVersion: v1 + group: cache + kind: Memcached + version: v1alpha1 + webhookVersion: v1 +version: 3-alpha +plugins: + manifests.sdk.operatorframework.io/v2: {} + scorecard.sdk.operatorframework.io/v2: {} diff --git a/internal/generate/packagemanifest/bases/packagemanifest.go b/internal/generate/packagemanifest/bases/packagemanifest.go deleted file mode 100644 index 0a598837b08..00000000000 --- a/internal/generate/packagemanifest/bases/packagemanifest.go +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2020 The Operator-SDK 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. - -package bases - -import ( - "fmt" - "io/ioutil" - - apimanifests "github.com/operator-framework/api/pkg/manifests" - "sigs.k8s.io/yaml" -) - -// PackageManifest configures the PackageManifest that GetBase() returns. -type PackageManifest struct { - PackageName string - BasePath string -} - -// GetBase returns a base PackageManifest, populated either with default -// values or, if b.BasePath is set, bytes from disk. -func (b PackageManifest) GetBase() (base *apimanifests.PackageManifest, err error) { - if b.BasePath != "" { - if base, err = readPackageManifestBase(b.BasePath); err != nil { - return nil, fmt.Errorf("error reading existing PackageManifest base %s: %v", b.BasePath, err) - } - } else { - base = b.makeNewBase() - } - - return base, nil -} - -// makeNewBase returns a base makeNewBase to modify. -func (b PackageManifest) makeNewBase() *apimanifests.PackageManifest { - return &apimanifests.PackageManifest{ - PackageName: b.PackageName, - } -} - -// readPackageManifestBase returns the PackageManifest base at path. -// If no base is found, readPackageManifestBase returns an error. -func readPackageManifestBase(path string) (*apimanifests.PackageManifest, error) { - b, err := ioutil.ReadFile(path) - if err != nil { - return nil, err - } - pkg := &apimanifests.PackageManifest{} - if err := yaml.Unmarshal(b, pkg); err != nil { - return nil, fmt.Errorf("error unmarshalling PackageManifest from %s: %w", path, err) - } - if pkg.PackageName == "" { - return nil, fmt.Errorf("no PackageManifest in %s", path) - } - return pkg, nil -} diff --git a/internal/generate/packagemanifest/packagemanifest.go b/internal/generate/packagemanifest/packagemanifest.go index cd1506b97ba..2fc751e570f 100644 --- a/internal/generate/packagemanifest/packagemanifest.go +++ b/internal/generate/packagemanifest/packagemanifest.go @@ -17,16 +17,16 @@ package packagemanifest import ( "errors" "fmt" - "io" + "io/ioutil" "path/filepath" "sort" apimanifests "github.com/operator-framework/api/pkg/manifests" "github.com/operator-framework/api/pkg/validation" log "github.com/sirupsen/logrus" + "sigs.k8s.io/yaml" genutil "github.com/operator-framework/operator-sdk/internal/generate/internal" - "github.com/operator-framework/operator-sdk/internal/generate/packagemanifest/bases" ) const ( @@ -34,20 +34,45 @@ const ( packageManifestFileExt = ".package.yaml" ) +// generator is an implementation of the Generator interface +type generator struct{} + +// NewGenerator returns a new generator object +func NewGenerator() Generator { + return generator{} +} + +// Generator is an interface that specifies the Generate methods +// to generate and write various package manifests +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . Generator +type Generator interface { + Generate(operatorName, version, outputDir string, opts Options) error +} + +// PackageManifest configures the PackageManifest that GetBase() returns. +type PackageManifest struct { + PackageName string + BasePath string +} + var ( // User-facing errors. - errNoVersion = errors.New("version must be set") + + // ErrNoVersion if no version # has been provided + ErrNoVersion = errors.New("version must be set") // Internal errors. - errNoGetBase = genutil.InternalError("getBase must be set") - errNoGetWriter = genutil.InternalError("getWriter must be set") + + // ErrNoOpName if the operator name has not been set + ErrNoOpName = genutil.InternalError("operator name must be set") + // ErrNoOutputDir if the directory to write the package manifest to has not been set + ErrNoOutputDir = genutil.InternalError("output directory must be set") ) -type Generator struct { - // OperatorName is the operator's name, ex. app-operator. - OperatorName string - // Version is the version of the operator being updated. - Version string +type Options struct { + // BaseDir is a directory to look for an existing base package manifest + // to update. + BaseDir string // ChannelName is operator's PackageManifest channel. If a new PackageManifest is generated // or ChannelName is the only channel in the generated PackageManifest, // this channel will be set to the PackageManifest's default. @@ -56,91 +81,56 @@ type Generator struct { // generated PackageManifest. If true, ChannelName will be the PackageManifest's default channel. // Setting this field is only necessary when more than one channel exists. IsDefaultChannel bool - - // Func that returns a base PackageManifest. - getBase getBaseFunc - // Func that returns the writer the generated PackageManifest's bytes are written to. - getWriter func() (io.Writer, error) -} - -// Type of Generator.getBase. -type getBaseFunc func() (*apimanifests.PackageManifest, error) - -// Option is a function that modifies a Generator. -type Option func(*Generator) error - -// WithBase sets a Generator's base PackageManifest to one that either exists or a default. -func WithBase(inputDir string) Option { - return func(g *Generator) error { - g.getBase = g.makeBaseGetter(inputDir) - return nil - } -} - -// WithWriter sets a Generator's writer to w. -func WithWriter(w io.Writer) Option { - return func(g *Generator) error { - g.getWriter = func() (io.Writer, error) { - return w, nil - } - return nil - } -} - -// WithFileWriter sets a Generator's writer to a PackageManifest file under

. -func WithFileWriter(dir string) Option { - return func(g *Generator) (err error) { - g.getWriter = func() (io.Writer, error) { - return genutil.Open(dir, makePkgManFileName(g.OperatorName)) - } - return nil - } } // Generate configures the Generator with opts then runs it. -func (g *Generator) Generate(opts ...Option) error { - for _, opt := range opts { - if err := opt(g); err != nil { - return err - } +func (g generator) Generate(operatorName, version, outputDir string, opts Options) error { + if operatorName == "" { + return ErrNoOpName } - - if g.getWriter == nil { - return errNoGetWriter + if version == "" { + return ErrNoVersion + } + if outputDir == "" { + return ErrNoOutputDir } - pkg, err := g.generate() + pkg, err := g.generate(operatorName, version, opts) if err != nil { return err } - w, err := g.getWriter() + outputWriter, err := genutil.Open(outputDir, makePkgManFileName(operatorName)) if err != nil { return err } - return genutil.WriteYAML(w, pkg) + + return genutil.WriteYAML(outputWriter, pkg) } -// generate runs a configured Generator. -func (g *Generator) generate() (*apimanifests.PackageManifest, error) { - if g.getBase == nil { - return nil, errNoGetBase +// generate takes the input and generates the populated package manifest object +func (g generator) generate(operatorName, version string, opts Options) (*apimanifests.PackageManifest, error) { + b := PackageManifest{ + PackageName: operatorName, } - if g.Version == "" { - return nil, errNoVersion + if opts.BaseDir != "" { + basePath := filepath.Join(opts.BaseDir, makePkgManFileName(operatorName)) + if genutil.IsNotExist(basePath) { + basePath = "" + } + b.BasePath = basePath } - - base, err := g.getBase() + base, err := b.GetBase() if err != nil { return nil, fmt.Errorf("error getting PackageManifest base: %v", err) } - csvName := genutil.MakeCSVName(g.OperatorName, g.Version) - if g.ChannelName != "" { - setChannels(base, g.ChannelName, csvName) + csvName := genutil.MakeCSVName(operatorName, version) + if opts.ChannelName != "" { + setChannels(base, opts.ChannelName, csvName) sortChannelsByName(base) - if g.IsDefaultChannel || len(base.Channels) == 1 { - base.DefaultChannelName = g.ChannelName + if opts.IsDefaultChannel || len(base.Channels) == 1 { + base.DefaultChannelName = opts.ChannelName } } else if len(base.Channels) == 0 { setChannels(base, "alpha", csvName) @@ -154,22 +144,6 @@ func (g *Generator) generate() (*apimanifests.PackageManifest, error) { return base, nil } -// makeBaseGetter returns a function that gets a base from inputDir. -func (g Generator) makeBaseGetter(inputDir string) func() (*apimanifests.PackageManifest, error) { - basePath := filepath.Join(inputDir, makePkgManFileName(g.OperatorName)) - if genutil.IsNotExist(basePath) { - basePath = "" - } - - return func() (*apimanifests.PackageManifest, error) { - b := bases.PackageManifest{ - PackageName: g.OperatorName, - BasePath: basePath, - } - return b.GetBase() - } -} - // makePkgManFileName will return the file name of a PackageManifest. func makePkgManFileName(operatorName string) string { return operatorName + packageManifestFileExt @@ -227,3 +201,41 @@ func setChannels(pkg *apimanifests.PackageManifest, channelName, csvName string) }) } } + +// GetBase returns a base PackageManifest, populated either with default +// values or, if b.BasePath is set, bytes from disk. +func (b PackageManifest) GetBase() (base *apimanifests.PackageManifest, err error) { + if b.BasePath != "" { + if base, err = readPackageManifestBase(b.BasePath); err != nil { + return nil, fmt.Errorf("error reading existing PackageManifest base %s: %v", b.BasePath, err) + } + } else { + base = b.makeNewBase() + } + + return base, nil +} + +// makeNewBase returns a base makeNewBase to modify. +func (b PackageManifest) makeNewBase() *apimanifests.PackageManifest { + return &apimanifests.PackageManifest{ + PackageName: b.PackageName, + } +} + +// readPackageManifestBase returns the PackageManifest base at path. +// If no base is found, readPackageManifestBase returns an error. +func readPackageManifestBase(path string) (*apimanifests.PackageManifest, error) { + b, err := ioutil.ReadFile(path) + if err != nil { + return nil, err + } + pkg := &apimanifests.PackageManifest{} + if err := yaml.Unmarshal(b, pkg); err != nil { + return nil, fmt.Errorf("error unmarshalling PackageManifest from %s: %w", path, err) + } + if pkg.PackageName == "" { + return nil, fmt.Errorf("no PackageManifest in %s", path) + } + return pkg, nil +} diff --git a/internal/generate/packagemanifest/packagemanifest_suite_test.go b/internal/generate/packagemanifest/packagemanifest_suite_test.go new file mode 100644 index 00000000000..83ebaf0d874 --- /dev/null +++ b/internal/generate/packagemanifest/packagemanifest_suite_test.go @@ -0,0 +1,27 @@ +// Copyright 2021 The Operator-SDK 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. + +package packagemanifest_test + +import ( + "testing" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +func TestGenerate(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Generate Suite") +} diff --git a/internal/generate/packagemanifest/packagemanifest_test.go b/internal/generate/packagemanifest/packagemanifest_test.go index d617292c677..0787ecfab1a 100644 --- a/internal/generate/packagemanifest/packagemanifest_test.go +++ b/internal/generate/packagemanifest/packagemanifest_test.go @@ -1,4 +1,4 @@ -// Copyright 2020 The Operator-SDK Authors +// Copyright 2021 The Operator-SDK Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,263 +12,202 @@ // See the License for the specific language governing permissions and // limitations under the License. -package packagemanifest +package packagemanifest_test import ( - "bytes" "io/ioutil" "os" "path/filepath" - "testing" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - "github.com/onsi/gomega/format" - - apimanifests "github.com/operator-framework/api/pkg/manifests" - "sigs.k8s.io/yaml" - - genutil "github.com/operator-framework/operator-sdk/internal/generate/internal" + . "github.com/operator-framework/operator-sdk/internal/generate/packagemanifest" ) -func TestGenerator(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Generator Suite") -} - -const ( - pkgManDefaultContent = `channels: - - currentCSV: memcached-operator.v0.0.1 - name: alpha +var _ = Describe("A package manifest generator", func() { + var ( + testDataDir string + ) + BeforeEach(func() { + testDataDir = filepath.Join("..", "testdata") + }) + Describe("Generate", func() { + var ( + g Generator + blankOpts Options + operatorName string + outputDir string + pkgManFilename string + pkgManDefault string + pkgManOneChannel string + pkgManUpdatedOneChannel string + pkgManUpdatedSecondChannel string + pkgManUpdatedSecondChannelNewDefault string + ) + BeforeEach(func() { + g = NewGenerator() + operatorName = "memcached-operator" + blankOpts = Options{} + pkgManFilename = operatorName + ".package.yaml" + outputDir = os.TempDir() + pkgManDefault = `channels: +- currentCSV: memcached-operator.v0.0.1 + name: alpha defaultChannel: alpha packageName: memcached-operator ` - - pkgManSingleChannelContent = `channels: - - currentCSV: memcached-operator.v0.0.1 - name: stable + pkgManOneChannel = `channels: +- currentCSV: memcached-operator.v0.0.1 + name: stable defaultChannel: stable packageName: memcached-operator ` -) - -var ( - testDataDir = filepath.Join("..", "testdata") - - pkgManDefault, pkgManSingleChannel *apimanifests.PackageManifest -) - -var _ = BeforeSuite(func() { - initTestPackageManifestsHelper() -}) - -var _ = Describe("Generating a PackageManifest", func() { - format.UseStringerRepresentation = true - - var ( - g Generator - buf *bytes.Buffer - operatorName = "memcached-operator" - version = "0.0.1" - ) - - BeforeEach(func() { - buf = &bytes.Buffer{} - }) - - Describe("for the new Go project layout", func() { - - Context("with correct Options", func() { - - var ( - tmp string - err error - ) - - BeforeEach(func() { - tmp, err = ioutil.TempDir(".", "") - Expect(err).ToNot(HaveOccurred()) + pkgManUpdatedOneChannel = `channels: +- currentCSV: memcached-operator.v0.0.2 + name: alpha +defaultChannel: alpha +packageName: memcached-operator +` + pkgManUpdatedSecondChannel = `channels: +- currentCSV: memcached-operator.v0.0.1 + name: alpha +- currentCSV: memcached-operator.v0.0.2 + name: stable +defaultChannel: alpha +packageName: memcached-operator +` + pkgManUpdatedSecondChannelNewDefault = `channels: +- currentCSV: memcached-operator.v0.0.1 + name: alpha +- currentCSV: memcached-operator.v0.0.2 + name: stable +defaultChannel: stable +packageName: memcached-operator +` + }) + Context("when writing a new package manifest", func() { + It("writes a package manifest", func() { + err := g.Generate(operatorName, "0.0.1", outputDir, blankOpts) + Expect(err).NotTo(HaveOccurred()) + file, err := ioutil.ReadFile(outputDir + string(os.PathSeparator) + pkgManFilename) + Expect(err).NotTo(HaveOccurred()) + Expect(string(file)).To(Equal(pkgManDefault)) }) - - AfterEach(func() { - if tmp != "" { - os.RemoveAll(tmp) + It("writes a package manifest with a non-default channel", func() { + opts := Options{ + ChannelName: "stable", } - }) - It("should write a PackageManifest to an io.Writer", func() { - g = Generator{ - OperatorName: operatorName, - Version: version, - } - opts := []Option{ - WithBase(testDataDir), - WithWriter(buf), - } - Expect(g.Generate(opts...)).ToNot(HaveOccurred()) - Expect(buf.String()).To(MatchYAML(pkgManDefaultContent)) - }) - It("should write a PackageManifest to disk", func() { - g = Generator{ - OperatorName: operatorName, - Version: version, - } - opts := []Option{ - WithBase(testDataDir), - WithFileWriter(tmp), - } - Expect(g.Generate(opts...)).ToNot(HaveOccurred()) - outputFile := filepath.Join(tmp, makePkgManFileName(operatorName)) - Expect(outputFile).To(BeAnExistingFile()) - Expect(string(readFileHelper(outputFile))).To(MatchYAML(pkgManDefaultContent)) + err := g.Generate(operatorName, "0.0.1", outputDir, opts) + Expect(err).NotTo(HaveOccurred()) + file, err := ioutil.ReadFile(outputDir + string(os.PathSeparator) + pkgManFilename) + Expect(err).NotTo(HaveOccurred()) + Expect(string(file)).To(Equal(pkgManOneChannel)) }) }) - - Context("with incorrect configuration", func() { - - BeforeEach(func() { - g = Generator{ - OperatorName: operatorName, - Version: version, + Context("when updating an existing package manifest", func() { + It("creates a new package manifest if provided an existing packagemanifest that doesn't exist", func() { + opts := Options{ + BaseDir: "testpotato", + ChannelName: "stable", } - }) - It("should return an error without any Options", func() { - opts := []Option{} - Expect(g.Generate(opts...)).To(MatchError(errNoGetWriter)) + err := g.Generate(operatorName, "0.0.1", outputDir, opts) + Expect(err).NotTo(HaveOccurred()) + file, err := ioutil.ReadFile(outputDir + string(os.PathSeparator) + pkgManFilename) + Expect(err).NotTo(HaveOccurred()) + Expect(string(file)).To(Equal(pkgManOneChannel)) }) - It("should return an error without a getWriter", func() { - opts := []Option{ - WithBase(testDataDir), + It("updates an existing package manifest with a updated channel", func() { + opts := Options{ + BaseDir: testDataDir, + ChannelName: "alpha", } - Expect(g.Generate(opts...)).To(MatchError(errNoGetWriter)) - }) - It("should return an error without a getBase", func() { - opts := []Option{ - WithWriter(&bytes.Buffer{}), - } - Expect(g.Generate(opts...)).To(MatchError(errNoGetBase)) + + err := g.Generate(operatorName, "0.0.2", outputDir, opts) + Expect(err).NotTo(HaveOccurred()) + file, err := ioutil.ReadFile(outputDir + string(os.PathSeparator) + pkgManFilename) + Expect(err).NotTo(HaveOccurred()) + Expect(string(file)).To(Equal(pkgManUpdatedOneChannel)) }) - It("should return an error without a Version", func() { - g.Version = "" - opts := []Option{ - WithBase(testDataDir), - WithWriter(&bytes.Buffer{}), + It("updates an existing package manifest with a new channel", func() { + opts := Options{ + BaseDir: testDataDir, + ChannelName: "stable", } - Expect(g.Generate(opts...)).To(MatchError(errNoVersion)) - }) - }) - Context("to create a new PackageManifest", func() { - It("should return the default file", func() { - g = Generator{ - OperatorName: operatorName, - Version: version, - getBase: makeBaseGetter(pkgManDefaultContent), - } - pkg, err := g.generate() - Expect(err).ToNot(HaveOccurred()) - Expect(pkg).To(Equal(pkgManDefault)) + err := g.Generate(operatorName, "0.0.2", outputDir, opts) + Expect(err).NotTo(HaveOccurred()) + file, err := ioutil.ReadFile(outputDir + string(os.PathSeparator) + pkgManFilename) + Expect(err).NotTo(HaveOccurred()) + Expect(string(file)).To(Equal(pkgManUpdatedSecondChannel)) }) - It("should return a PackageManifest with a non-default channel", func() { - g = Generator{ - OperatorName: operatorName, - Version: version, - ChannelName: "stable", - getBase: makeBaseGetter(pkgManSingleChannelContent), + It("updates an existing package manifest with a new channel and an updated default channel", func() { + opts := Options{ + BaseDir: testDataDir, + ChannelName: "stable", + IsDefaultChannel: true, } - pkg, err := g.generate() - Expect(err).ToNot(HaveOccurred()) - Expect(pkg).To(Equal(pkgManSingleChannel)) + + err := g.Generate(operatorName, "0.0.2", outputDir, opts) + Expect(err).NotTo(HaveOccurred()) + file, err := ioutil.ReadFile(outputDir + string(os.PathSeparator) + pkgManFilename) + Expect(err).NotTo(HaveOccurred()) + Expect(string(file)).To(Equal(pkgManUpdatedSecondChannelNewDefault)) }) }) - - Context("to update an existing PackageManifest file", func() { - It("should return a PackageManifest with one updated channel CSV name", func() { - g = Generator{ - OperatorName: operatorName, - Version: "0.0.2", - ChannelName: "alpha", - getBase: makeBaseGetter(pkgManDefaultContent), - } - pkg, err := g.generate() - Expect(err).ToNot(HaveOccurred()) - Expect(pkg).To(Equal(&apimanifests.PackageManifest{ - Channels: []apimanifests.PackageChannel{ - {Name: "alpha", CurrentCSVName: genutil.MakeCSVName(operatorName, "0.0.2")}, - }, - DefaultChannelName: "alpha", - PackageName: operatorName, - })) + Context("when incorrect params are provided", func() { + It("fails if no operator name is specified", func() { + err := g.Generate("", "", "", blankOpts) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring(ErrNoOpName.Error())) }) - It("should return a PackageManifest with two channels", func() { - g = Generator{ - OperatorName: operatorName, - Version: "0.0.2", - ChannelName: "stable", - getBase: makeBaseGetter(pkgManDefaultContent), - } - pkg, err := g.generate() - Expect(err).ToNot(HaveOccurred()) - Expect(pkg).To(Equal(&apimanifests.PackageManifest{ - Channels: []apimanifests.PackageChannel{ - {Name: "alpha", CurrentCSVName: genutil.MakeCSVName(operatorName, version)}, - {Name: "stable", CurrentCSVName: genutil.MakeCSVName(operatorName, "0.0.2")}, - }, - DefaultChannelName: "alpha", - PackageName: operatorName, - })) + It("fails if no version is specified", func() { + err := g.Generate(operatorName, "", "", blankOpts) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring(ErrNoVersion.Error())) }) - It("should return a PackageManifest with two channels and an updated default channel", func() { - g = Generator{ - OperatorName: operatorName, - Version: "0.0.2", - ChannelName: "stable", - IsDefaultChannel: true, - getBase: makeBaseGetter(pkgManDefaultContent), - } - pkg, err := g.generate() - Expect(err).ToNot(HaveOccurred()) - Expect(pkg).To(Equal(&apimanifests.PackageManifest{ - Channels: []apimanifests.PackageChannel{ - {Name: "alpha", CurrentCSVName: genutil.MakeCSVName(operatorName, version)}, - {Name: "stable", CurrentCSVName: genutil.MakeCSVName(operatorName, "0.0.2")}, - }, - DefaultChannelName: "stable", - PackageName: operatorName, - })) + It("fails if no output directory is set", func() { + err := g.Generate(operatorName, "0.0.1", "", blankOpts) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring(ErrNoOutputDir.Error())) }) }) - }) + Describe("GetBase", func() { + var ( + b PackageManifest + ) + BeforeEach(func() { + b = PackageManifest{} + }) + It("returns a new blank packagemanifest", func() { + b.PackageName = "sweetsop" -}) - -func makeBaseGetter(content string) getBaseFunc { - return func() (*apimanifests.PackageManifest, error) { - return marshalContent(content) - } -} - -func initTestPackageManifestsHelper() { - var err error - pkgManDefault, err = marshalContent(pkgManDefaultContent) - ExpectWithOffset(1, err).ToNot(HaveOccurred()) - pkgManSingleChannel, err = marshalContent(pkgManSingleChannelContent) - ExpectWithOffset(1, err).ToNot(HaveOccurred()) -} - -func readFileHelper(path string) []byte { - b, err := ioutil.ReadFile(path) - ExpectWithOffset(1, err).ToNot(HaveOccurred()) - return b -} + pm, err := b.GetBase() + Expect(err).NotTo(HaveOccurred()) + Expect(pm).NotTo(BeNil()) + Expect(pm.PackageName).To(Equal(b.PackageName)) + }) + It("reads an existing packagemanifest from disk", func() { + b.BasePath = filepath.Join(testDataDir, "memcached-operator.package.yaml") + + pm, err := b.GetBase() + Expect(err).NotTo(HaveOccurred()) + Expect(pm).NotTo(BeNil()) + Expect(pm.PackageName).To(Equal("memcached-operator")) + Expect(len(pm.Channels)).To(Equal(1)) + Expect(pm.Channels[0].Name).To(Equal("alpha")) + Expect(pm.Channels[0].CurrentCSVName).To(Equal("memcached-operator.v0.0.1")) + Expect(pm.DefaultChannelName).To(Equal("alpha")) + }) + It("fails if provided a non-existent base path", func() { + b.BasePath = "not-a-real-thing.yaml" -func marshalContent(content string) (*apimanifests.PackageManifest, error) { - base := &apimanifests.PackageManifest{} - if content == "" { - return base, nil - } - err := yaml.Unmarshal([]byte(content), base) - return base, err -} + pm, err := b.GetBase() + Expect(pm).To(BeNil()) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("error reading existing")) + }) + }) +}) diff --git a/internal/generate/packagemanifest/packagemanifestfakes/fake_generator.go b/internal/generate/packagemanifest/packagemanifestfakes/fake_generator.go new file mode 100644 index 00000000000..d563545621f --- /dev/null +++ b/internal/generate/packagemanifest/packagemanifestfakes/fake_generator.go @@ -0,0 +1,116 @@ +// Code generated by counterfeiter. DO NOT EDIT. +package packagemanifestfakes + +import ( + "sync" + + "github.com/operator-framework/operator-sdk/internal/generate/packagemanifest" +) + +type FakeGenerator struct { + GenerateStub func(string, string, string, packagemanifest.Options) error + generateMutex sync.RWMutex + generateArgsForCall []struct { + arg1 string + arg2 string + arg3 string + arg4 packagemanifest.Options + } + generateReturns struct { + result1 error + } + generateReturnsOnCall map[int]struct { + result1 error + } + invocations map[string][][]interface{} + invocationsMutex sync.RWMutex +} + +func (fake *FakeGenerator) Generate(arg1 string, arg2 string, arg3 string, arg4 packagemanifest.Options) error { + fake.generateMutex.Lock() + ret, specificReturn := fake.generateReturnsOnCall[len(fake.generateArgsForCall)] + fake.generateArgsForCall = append(fake.generateArgsForCall, struct { + arg1 string + arg2 string + arg3 string + arg4 packagemanifest.Options + }{arg1, arg2, arg3, arg4}) + fake.recordInvocation("Generate", []interface{}{arg1, arg2, arg3, arg4}) + fake.generateMutex.Unlock() + if fake.GenerateStub != nil { + return fake.GenerateStub(arg1, arg2, arg3, arg4) + } + if specificReturn { + return ret.result1 + } + fakeReturns := fake.generateReturns + return fakeReturns.result1 +} + +func (fake *FakeGenerator) GenerateCallCount() int { + fake.generateMutex.RLock() + defer fake.generateMutex.RUnlock() + return len(fake.generateArgsForCall) +} + +func (fake *FakeGenerator) GenerateCalls(stub func(string, string, string, packagemanifest.Options) error) { + fake.generateMutex.Lock() + defer fake.generateMutex.Unlock() + fake.GenerateStub = stub +} + +func (fake *FakeGenerator) GenerateArgsForCall(i int) (string, string, string, packagemanifest.Options) { + fake.generateMutex.RLock() + defer fake.generateMutex.RUnlock() + argsForCall := fake.generateArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4 +} + +func (fake *FakeGenerator) GenerateReturns(result1 error) { + fake.generateMutex.Lock() + defer fake.generateMutex.Unlock() + fake.GenerateStub = nil + fake.generateReturns = struct { + result1 error + }{result1} +} + +func (fake *FakeGenerator) GenerateReturnsOnCall(i int, result1 error) { + fake.generateMutex.Lock() + defer fake.generateMutex.Unlock() + fake.GenerateStub = nil + if fake.generateReturnsOnCall == nil { + fake.generateReturnsOnCall = make(map[int]struct { + result1 error + }) + } + fake.generateReturnsOnCall[i] = struct { + result1 error + }{result1} +} + +func (fake *FakeGenerator) Invocations() map[string][][]interface{} { + fake.invocationsMutex.RLock() + defer fake.invocationsMutex.RUnlock() + fake.generateMutex.RLock() + defer fake.generateMutex.RUnlock() + copiedInvocations := map[string][][]interface{}{} + for key, value := range fake.invocations { + copiedInvocations[key] = value + } + return copiedInvocations +} + +func (fake *FakeGenerator) recordInvocation(key string, args []interface{}) { + fake.invocationsMutex.Lock() + defer fake.invocationsMutex.Unlock() + if fake.invocations == nil { + fake.invocations = map[string][][]interface{}{} + } + if fake.invocations[key] == nil { + fake.invocations[key] = [][]interface{}{} + } + fake.invocations[key] = append(fake.invocations[key], args) +} + +var _ packagemanifest.Generator = new(FakeGenerator) From bf879d089a270f9dc90f33efe4868d306675f4c5 Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Tue, 2 Feb 2021 00:30:35 +0100 Subject: [PATCH 292/376] Pin docker base images (#4417) Signed-off-by: reinvantveer --- changelog/fragments/pin-docker-base-images.yaml | 12 ++++++++++++ images/ansible-operator/Dockerfile | 2 +- images/custom-scorecard-tests/Dockerfile | 3 +-- images/helm-operator/Dockerfile | 2 +- images/operator-sdk/Dockerfile | 2 +- images/scorecard-test/Dockerfile | 2 +- 6 files changed, 17 insertions(+), 6 deletions(-) create mode 100644 changelog/fragments/pin-docker-base-images.yaml diff --git a/changelog/fragments/pin-docker-base-images.yaml b/changelog/fragments/pin-docker-base-images.yaml new file mode 100644 index 00000000000..3ed740c7529 --- /dev/null +++ b/changelog/fragments/pin-docker-base-images.yaml @@ -0,0 +1,12 @@ +# entries is a list of entries to include in +# release notes and/or the migration guide +entries: + - description: > + For Ansible-based and Helm-based operators, as well as for the + Operator SDK and the (custom) scorecard tests, the Docker base images + are pinned to improve the reproducibility of builds using Docker. + + kind: addition + + # Is this a breaking change? + breaking: false diff --git a/images/ansible-operator/Dockerfile b/images/ansible-operator/Dockerfile index 0b813e706f7..8b0768dcb65 100644 --- a/images/ansible-operator/Dockerfile +++ b/images/ansible-operator/Dockerfile @@ -1,4 +1,4 @@ -FROM registry.access.redhat.com/ubi8/ubi:latest +FROM registry.access.redhat.com/ubi8/ubi:8.3-227 RUN mkdir -p /etc/ansible \ && echo "localhost ansible_connection=local" > /etc/ansible/hosts \ diff --git a/images/custom-scorecard-tests/Dockerfile b/images/custom-scorecard-tests/Dockerfile index 80c14912af9..e5dcabaf95f 100644 --- a/images/custom-scorecard-tests/Dockerfile +++ b/images/custom-scorecard-tests/Dockerfile @@ -1,5 +1,4 @@ -# Base image -FROM registry.access.redhat.com/ubi8/ubi-minimal:latest +FROM registry.access.redhat.com/ubi8/ubi-minimal:8.3-230 ENV HOME=/opt/custom-scorecard-tests \ USER_NAME=custom-scorecard-tests \ diff --git a/images/helm-operator/Dockerfile b/images/helm-operator/Dockerfile index af530209f77..8ad5e303805 100644 --- a/images/helm-operator/Dockerfile +++ b/images/helm-operator/Dockerfile @@ -1,4 +1,4 @@ -FROM registry.access.redhat.com/ubi8/ubi-minimal:latest +FROM registry.access.redhat.com/ubi8/ubi-minimal:8.3-230 ENV HOME=/opt/helm \ USER_NAME=helm \ diff --git a/images/operator-sdk/Dockerfile b/images/operator-sdk/Dockerfile index 5faf37c7fbd..c98e82457dd 100644 --- a/images/operator-sdk/Dockerfile +++ b/images/operator-sdk/Dockerfile @@ -1,4 +1,4 @@ -FROM registry.access.redhat.com/ubi8/ubi-minimal:latest +FROM registry.access.redhat.com/ubi8/ubi-minimal:8.3-230 RUN microdnf install -y golang make which diff --git a/images/scorecard-test/Dockerfile b/images/scorecard-test/Dockerfile index 402c1f7a8ca..cdac4696296 100644 --- a/images/scorecard-test/Dockerfile +++ b/images/scorecard-test/Dockerfile @@ -1,4 +1,4 @@ -FROM registry.access.redhat.com/ubi8/ubi-minimal:latest +FROM registry.access.redhat.com/ubi8/ubi-minimal:8.3-230 ENV HOME=/opt/scorecard-test \ USER_NAME=scorecard-test \ From e30f18f499aa63e59fd767bdb60ed26d3646bda0 Mon Sep 17 00:00:00 2001 From: Stephen Cuppett Date: Tue, 2 Feb 2021 12:35:24 -0500 Subject: [PATCH 293/376] Use controllerutil.AddFinalizer (#4455) Changes addFinalizer explicit code to controllerutil.AddFinalizer to stay consistent with the example (RemoveFinalizer called just above) Signed-off-by: Stephen Cuppett Signed-off-by: reinvantveer --- .../golang/advanced-topics.md | 30 ++++--------------- 1 file changed, 5 insertions(+), 25 deletions(-) diff --git a/website/content/en/docs/building-operators/golang/advanced-topics.md b/website/content/en/docs/building-operators/golang/advanced-topics.md index 1e1d71116a0..2527a9255a5 100644 --- a/website/content/en/docs/building-operators/golang/advanced-topics.md +++ b/website/content/en/docs/building-operators/golang/advanced-topics.md @@ -162,7 +162,7 @@ func (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) ( // indicated by the deletion timestamp being set. isMemcachedMarkedToBeDeleted := memcached.GetDeletionTimestamp() != nil if isMemcachedMarkedToBeDeleted { - if contains(memcached.GetFinalizers(), memcachedFinalizer) { + if controllerutil.ContainsFinalizer(memcached, memcachedFinalizer) { // Run finalization logic for memcachedFinalizer. If the // finalization logic fails, don't remove the finalizer so // that we can retry during the next reconciliation. @@ -182,8 +182,10 @@ func (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) ( } // Add finalizer for this CR - if !contains(memcached.GetFinalizers(), memcachedFinalizer) { - if err := r.addFinalizer(reqLogger, memcached); err != nil { + if !controllerutil.ContainsFinalizer(memcached, memcachedFinalizer) { + controllerutil.AddFinalizer(memcached, memcachedFinalizer) + err = r.Update(ctx, memcached) + if err != nil { return ctrl.Result{}, err } } @@ -201,28 +203,6 @@ func (r *MemcachedReconciler) finalizeMemcached(reqLogger logr.Logger, m *cachev reqLogger.Info("Successfully finalized memcached") return nil } - -func (r *MemcachedReconciler) addFinalizer(reqLogger logr.Logger, m *cachev1alpha1.Memcached) error { - reqLogger.Info("Adding Finalizer for the Memcached") - controllerutil.AddFinalizer(m, memcachedFinalizer) - - // Update CR - err := r.Update(context.TODO(), m) - if err != nil { - reqLogger.Error(err, "Failed to update Memcached with finalizer") - return err - } - return nil -} - -func contains(list []string, s string) bool { - for _, v := range list { - if v == s { - return true - } - } - return false -} ``` ### Leader election From 82283dca240d07d7bb0aa5a891c896acb557a64e Mon Sep 17 00:00:00 2001 From: Jonathan Berkhahn Date: Tue, 2 Feb 2021 10:24:08 -0800 Subject: [PATCH 294/376] add line about deleting resources before uninstalling controller to helm tutorial (#4461) Co-authored-by: Eric Stroczynski Signed-off-by: reinvantveer --- .../content/en/docs/building-operators/helm/tutorial.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/website/content/en/docs/building-operators/helm/tutorial.md b/website/content/en/docs/building-operators/helm/tutorial.md index 0e46618f1a1..6b87dcfe4a5 100644 --- a/website/content/en/docs/building-operators/helm/tutorial.md +++ b/website/content/en/docs/building-operators/helm/tutorial.md @@ -330,6 +330,13 @@ Clean up the resources: ```sh kubectl delete -f config/samples/demo_v1alpha1_nginx.yaml +``` + +**Note:** Make sure the above custom resource has been deleted before proceeding to +run `make undeploy`, as helm-operator's controller adds finalizers to the custom resources. +Otherwise your cluster may have dangling custom resource objects that cannot be deleted. + +```sh make undeploy ``` From 8446b01442dbc30ac3043bcfb4c3d91f5f35015d Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Tue, 2 Feb 2021 10:35:26 -0800 Subject: [PATCH 295/376] `run bundle{-upgrade}`: validate `--mode` before running a bundle (#4462) Signed-off-by: Eric Stroczynski Signed-off-by: reinvantveer --- .../fragments/bugfix-validate-add-mode.yaml | 5 +++ internal/olm/operator/bundle/install.go | 21 ++++++---- .../olm/operator/bundleupgrade/upgrade.go | 11 ++++- .../registry/index/bundle_add_mode.go | 41 +++++++++++++++++++ .../operator/registry/index/registry_pod.go | 17 +------- .../registry/index/registry_pod_test.go | 2 +- 6 files changed, 73 insertions(+), 24 deletions(-) create mode 100644 changelog/fragments/bugfix-validate-add-mode.yaml create mode 100644 internal/olm/operator/registry/index/bundle_add_mode.go diff --git a/changelog/fragments/bugfix-validate-add-mode.yaml b/changelog/fragments/bugfix-validate-add-mode.yaml new file mode 100644 index 00000000000..dc5578c3bff --- /dev/null +++ b/changelog/fragments/bugfix-validate-add-mode.yaml @@ -0,0 +1,5 @@ +entries: + - description: > + `run bundle` and `run bundle-upgrade` now validate the value passed to the hidden flag `--mode` before + running a bundle. + kind: bugfix diff --git a/internal/olm/operator/bundle/install.go b/internal/olm/operator/bundle/install.go index fa293c25b54..daeb9d0977d 100644 --- a/internal/olm/operator/bundle/install.go +++ b/internal/olm/operator/bundle/install.go @@ -49,7 +49,9 @@ func NewInstall(cfg *operator.Configuration) Install { func (i *Install) BindFlags(fs *pflag.FlagSet) { fs.StringVar(&i.IndexImage, "index-image", index.DefaultIndexImage, "index image in which to inject bundle") fs.Var(&i.InstallMode, "install-mode", "install mode") - fs.StringVar(&i.BundleAddMode, "mode", "", "mode to use for adding bundle to index") + + // --mode is hidden so only users who know what they're doing can alter add mode. + fs.StringVar((*string)(&i.BundleAddMode), "mode", "", "mode to use for adding bundle to index") _ = fs.MarkHidden("mode") } @@ -61,6 +63,17 @@ func (i Install) Run(ctx context.Context) (*v1alpha1.ClusterServiceVersion, erro } func (i *Install) setup(ctx context.Context) error { + // Default bundle add mode then validate in case it was set by a user. + if i.BundleAddMode == "" { + i.BundleAddMode = index.ReplacesBundleAddMode + if i.IndexImage == index.DefaultIndexImage { + i.BundleAddMode = index.SemverBundleAddMode + } + } else if err := i.BundleAddMode.Validate(); err != nil { + return err + } + + // Load bundle labels and set label-dependent values. labels, bundle, err := operator.LoadBundle(ctx, i.BundleImage) if err != nil { return err @@ -79,12 +92,6 @@ func (i *Install) setup(ctx context.Context) error { i.IndexImageCatalogCreator.PackageName = i.OperatorInstaller.PackageName i.IndexImageCatalogCreator.BundleImage = i.BundleImage - if i.IndexImageCatalogCreator.BundleAddMode == "" { - i.IndexImageCatalogCreator.BundleAddMode = index.ReplacesBundleAddMode - if i.IndexImageCatalogCreator.IndexImage == index.DefaultIndexImage { - i.IndexImageCatalogCreator.BundleAddMode = index.SemverBundleAddMode - } - } return nil } diff --git a/internal/olm/operator/bundleupgrade/upgrade.go b/internal/olm/operator/bundleupgrade/upgrade.go index e0b8e3ed8e8..516c4a49abe 100644 --- a/internal/olm/operator/bundleupgrade/upgrade.go +++ b/internal/olm/operator/bundleupgrade/upgrade.go @@ -47,7 +47,8 @@ func NewUpgrade(cfg *operator.Configuration) Upgrade { } func (u *Upgrade) BindFlags(fs *pflag.FlagSet) { - fs.StringVar(&u.BundleAddMode, "mode", "", "mode to use for adding new bundle version to index") + // --mode is hidden so only users who know what they're doing can alter add mode. + fs.StringVar((*string)(&u.BundleAddMode), "mode", "", "mode to use for adding new bundle version to index") _ = fs.MarkHidden("mode") } @@ -59,6 +60,14 @@ func (u Upgrade) Run(ctx context.Context) (*v1alpha1.ClusterServiceVersion, erro } func (u *Upgrade) setup(ctx context.Context) error { + // Bundle add mode is defaulted based on in-cluster metadata in u.UpgradeOperator(), + // so validate only if it was set by a user. + if u.BundleAddMode != "" { + if err := u.BundleAddMode.Validate(); err != nil { + return err + } + } + labels, bundle, err := operator.LoadBundle(ctx, u.BundleImage) if err != nil { return err diff --git a/internal/olm/operator/registry/index/bundle_add_mode.go b/internal/olm/operator/registry/index/bundle_add_mode.go new file mode 100644 index 00000000000..cafca845315 --- /dev/null +++ b/internal/olm/operator/registry/index/bundle_add_mode.go @@ -0,0 +1,41 @@ +// Copyright 2021 The Operator-SDK 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. + +package index + +import "fmt" + +// BundleAddMode is the mode to add a bundle to an index. +type BundleAddMode string + +const ( + // SemverBundleAddMode - bundle add mode for semver + SemverBundleAddMode BundleAddMode = "semver" + // ReplacesBundleAddMode - bundle add mode for replaces + ReplacesBundleAddMode BundleAddMode = "replaces" +) + +var modes = []BundleAddMode{SemverBundleAddMode, ReplacesBundleAddMode} + +func (m BundleAddMode) Validate() error { + switch m { + case SemverBundleAddMode, ReplacesBundleAddMode: + case "": + return fmt.Errorf("bundle add mode cannot be empty, must be one of: %+q", modes) + default: + return fmt.Errorf("bundle add mode %q does not exist, must be one of: %+q", m, modes) + } + + return nil +} diff --git a/internal/olm/operator/registry/index/registry_pod.go b/internal/olm/operator/registry/index/registry_pod.go index 33f686455e2..cc2d94d7a30 100644 --- a/internal/olm/operator/registry/index/registry_pod.go +++ b/internal/olm/operator/registry/index/registry_pod.go @@ -35,15 +35,6 @@ import ( "github.com/operator-framework/operator-sdk/internal/util/k8sutil" ) -// BundleAddMode - type of BundleAddMode in RegistryPod struct -type BundleAddMode = string - -const ( - // SemverBundleAddMode - bundle add mode for semver - SemverBundleAddMode BundleAddMode = "semver" - // ReplacesBundleAddMode - bundle add mode for replaces - ReplacesBundleAddMode BundleAddMode = "replaces" -) const ( // DefaultIndexImage is the index base image used if none is specified. It contains no bundles. DefaultIndexImage = "quay.io/operator-framework/upstream-opm-builder:latest" @@ -175,12 +166,8 @@ func (rp *RegistryPod) validate() error { if item.ImageTag == "" { return errors.New("bundle image cannot be empty") } - if item.AddMode == "" { - return fmt.Errorf("bundle add mode for %q cannot be empty", item.ImageTag) - } - if item.AddMode != SemverBundleAddMode && item.AddMode != ReplacesBundleAddMode { - return fmt.Errorf("invalid bundle mode %q: must be one of [%q, %q]", - item.AddMode, ReplacesBundleAddMode, SemverBundleAddMode) + if err := item.AddMode.Validate(); err != nil { + return fmt.Errorf("invalid bundle add mode: %v", err) } } diff --git a/internal/olm/operator/registry/index/registry_pod_test.go b/internal/olm/operator/registry/index/registry_pod_test.go index c306a34d38d..316bffb5d0d 100644 --- a/internal/olm/operator/registry/index/registry_pod_test.go +++ b/internal/olm/operator/registry/index/registry_pod_test.go @@ -138,7 +138,7 @@ var _ = Describe("RegistryPod", func() { }) It("should not accept any other bundle add mode other than semver or replaces", func() { - expectedErr := "invalid bundle mode" + expectedErr := `bundle add mode "invalid" does not exist` rp := &RegistryPod{ BundleItems: []BundleItem{{ImageTag: "quay.io/example/example-operator-bundle:0.2.0", AddMode: "invalid"}}, } From 557cbfdb7fd0740cedd231653a6d17885af21d17 Mon Sep 17 00:00:00 2001 From: magreenberg <51196972+magreenberg@users.noreply.github.com> Date: Tue, 2 Feb 2021 21:41:57 +0200 Subject: [PATCH 296/376] fixed typo anisible->ansible (#4256) Signed-off-by: reinvantveer --- website/content/en/docs/building-operators/ansible/migration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/content/en/docs/building-operators/ansible/migration.md b/website/content/en/docs/building-operators/ansible/migration.md index a06099b2437..4ec8b1917a4 100644 --- a/website/content/en/docs/building-operators/ansible/migration.md +++ b/website/content/en/docs/building-operators/ansible/migration.md @@ -185,7 +185,7 @@ https://github.com/operator-framework/operator-sdk/issues/3447 New projects are configured to watch all namespaces by default, so they need a `ClusterRole` to have the necessary permissions. Ensure that `config/rbac/role.yaml` remains a `ClusterRole` if you want to retain the default behavior of the new project conventions. -The following rules were used in earlier versions of anisible-operator to automatically create and manage services and `servicemonitors` for metrics collection. If your operator's don't require these rules, they can safely be left out of the new `config/rbac/role.yaml` file: +The following rules were used in earlier versions of ansible-operator to automatically create and manage services and `servicemonitors` for metrics collection. If your operator's don't require these rules, they can safely be left out of the new `config/rbac/role.yaml` file: ```yaml - apiGroups: From e27c8eb468244afa5c5290fe2a3ad39b067bccd4 Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Tue, 2 Feb 2021 12:11:04 -0800 Subject: [PATCH 297/376] internal/plugins: add `manifests` and `scorecard` plugin keys to all projects (#4419) Signed-off-by: reinvantveer --- changelog/fragments/phase-2-plugin-keys.yaml | 48 ++++++++++++++++++++ internal/plugins/ansible/v1/api.go | 21 ++++++++- internal/plugins/ansible/v1/init.go | 8 ++-- internal/plugins/golang/v2/api.go | 22 ++++++--- internal/plugins/golang/v2/config.go | 1 + internal/plugins/golang/v2/init.go | 18 ++------ internal/plugins/helm/v1/api.go | 21 ++++++++- internal/plugins/helm/v1/init.go | 8 ++-- internal/plugins/manifests/v2/plugin.go | 6 +-- testdata/ansible/memcached-operator/PROJECT | 3 ++ testdata/go/v2/memcached-operator/PROJECT | 3 +- testdata/helm/memcached-operator/PROJECT | 3 ++ 12 files changed, 126 insertions(+), 36 deletions(-) create mode 100644 changelog/fragments/phase-2-plugin-keys.yaml diff --git a/changelog/fragments/phase-2-plugin-keys.yaml b/changelog/fragments/phase-2-plugin-keys.yaml new file mode 100644 index 00000000000..c13517a1a2d --- /dev/null +++ b/changelog/fragments/phase-2-plugin-keys.yaml @@ -0,0 +1,48 @@ +entries: + - description: > + (go/v2) Changed `go` PROJECT plugin object to `manifests` and `scorecard` objects (`.sdk.operatorframework.io` suffix) + kind: change + breaking: false + migration: + header: (go/v2) Change `go` PROJECT plugin object to `manifests` and `scorecard` objects + body: > + The `manifests` and `scorecard` plugins that create OLM and scorecard manifests, respectively, + now have plugin objects that direct `create` subcommands to create related files. + While the old `go` plugin configuration object is still supported, these new objects will be useful + in the future as configuration options are added to their respective plugins: + + Old: + ```yaml + version: 3-alpha + ... + plugins: + go.sdk.operatorframework.io/v2-alpha: {} + ``` + + New: + ```yaml + version: 3-alpha + ... + plugins: + manifests.sdk.operatorframework.io/v2: {} + scorecard.sdk.operatorframework.io/v2: {} + ``` + + - description: > + (ansible/v1, helm/v1) Added plugin objects for the `manifests` and `scorecard` phase 2 plugins + kind: addition + migration: + header: (ansible/v1, helm/v1) Add `manifests` and `scorecard` plugin objects to your PROJECT + body: > + The `manifests` and `scorecard` plugins that create OLM and scorecard manifests, respectively, + now have plugin objects that direct `create` subcommands to create related files. While not necessary + to add, these new plugin configuration objects in the PROJECT file will be useful in the future + as configuration options are added to their respective plugins: + + ```yaml + version: 3-alpha + ... + plugins: + manifests.sdk.operatorframework.io/v2: {} + scorecard.sdk.operatorframework.io/v2: {} + ``` diff --git a/internal/plugins/ansible/v1/api.go b/internal/plugins/ansible/v1/api.go index 6fa7f33c6a2..059afc4ed0d 100644 --- a/internal/plugins/ansible/v1/api.go +++ b/internal/plugins/ansible/v1/api.go @@ -26,6 +26,7 @@ import ( "github.com/operator-framework/operator-sdk/internal/kubebuilder/cmdutil" "github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/scaffolds" "github.com/operator-framework/operator-sdk/internal/plugins/manifests" + manifestsv2 "github.com/operator-framework/operator-sdk/internal/plugins/manifests/v2" ) const ( @@ -118,8 +119,24 @@ func (p *createAPIPSubcommand) Run() error { // SDK phase 2 plugins. func (p *createAPIPSubcommand) runPhase2() error { - gvk := p.createOptions.GVK - return manifests.RunCreateAPI(p.config, config.GVK{Group: gvk.Group, Version: gvk.Version, Kind: gvk.Kind}) + ogvk := p.createOptions.GVK + gvk := config.GVK{Group: ogvk.Group, Version: ogvk.Version, Kind: ogvk.Kind} + + // Initially the ansible/v1 plugin was written to not create a "plugins" config entry + // for any phase 2 plugin because they did not have their own keys. Now there are phase 2 + // plugin keys, so those plugins should be run if keys exist. Otherwise, enact old behavior. + + if manifestsv2.HasPluginConfig(p.config) { + if err := manifestsv2.RunCreateAPI(p.config, gvk); err != nil { + return err + } + } else { + if err := manifests.RunCreateAPI(p.config, gvk); err != nil { + return err + } + } + + return nil } func (p *createAPIPSubcommand) Validate() error { diff --git a/internal/plugins/ansible/v1/init.go b/internal/plugins/ansible/v1/init.go index 48eb1390967..89b7d50b0f2 100644 --- a/internal/plugins/ansible/v1/init.go +++ b/internal/plugins/ansible/v1/init.go @@ -27,8 +27,8 @@ import ( "github.com/operator-framework/operator-sdk/internal/kubebuilder/cmdutil" "github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/scaffolds" - "github.com/operator-framework/operator-sdk/internal/plugins/manifests" - "github.com/operator-framework/operator-sdk/internal/plugins/scorecard" + manifestsv2 "github.com/operator-framework/operator-sdk/internal/plugins/manifests/v2" + scorecardv2 "github.com/operator-framework/operator-sdk/internal/plugins/scorecard/v2" ) type initSubcommand struct { @@ -118,10 +118,10 @@ func (p *initSubcommand) Run() error { // SDK phase 2 plugins. func (p *initSubcommand) runPhase2() error { - if err := manifests.RunInit(p.config); err != nil { + if err := manifestsv2.RunInit(p.config); err != nil { return err } - if err := scorecard.RunInit(p.config); err != nil { + if err := scorecardv2.RunInit(p.config); err != nil { return err } diff --git a/internal/plugins/golang/v2/api.go b/internal/plugins/golang/v2/api.go index 8823b6293e2..605f03bf717 100644 --- a/internal/plugins/golang/v2/api.go +++ b/internal/plugins/golang/v2/api.go @@ -20,6 +20,7 @@ import ( "sigs.k8s.io/kubebuilder/v2/pkg/plugin" "github.com/operator-framework/operator-sdk/internal/plugins/manifests" + manifestsv2 "github.com/operator-framework/operator-sdk/internal/plugins/manifests/v2" ) type createAPISubcommand struct { @@ -46,15 +47,11 @@ func (p *createAPISubcommand) Run() error { for _, r := range p.config.Resources { oldResources[r] = struct{}{} } + if err := p.CreateAPISubcommand.Run(); err != nil { return err } - // Emulate plugins phase 2 behavior by checking the config for this plugin's config object. - if !hasPluginConfig(p.config) { - return nil - } - // Find the new resource. Here we shouldn't worry about checking if one was found, // since downstream plugins will do so. var newResource config.GVK @@ -71,5 +68,18 @@ func (p *createAPISubcommand) Run() error { // SDK phase 2 plugins. func (p *createAPISubcommand) runPhase2(gvk config.GVK) error { - return manifests.RunCreateAPI(p.config, gvk) + // Check if the generic "go" operator-sdk plugin (legacy) exists first. + if hasPluginConfig(p.config) { + if err := manifests.RunCreateAPI(p.config, gvk); err != nil { + return err + } + return nil + } + + // v2 plugins will handle checking p.config for their key so we can call all of them below. + if err := manifestsv2.RunCreateAPI(p.config, gvk); err != nil { + return err + } + + return nil } diff --git a/internal/plugins/golang/v2/config.go b/internal/plugins/golang/v2/config.go index d2de599e07a..d0bed614f85 100644 --- a/internal/plugins/golang/v2/config.go +++ b/internal/plugins/golang/v2/config.go @@ -17,6 +17,7 @@ package v2 import "sigs.k8s.io/kubebuilder/v2/pkg/model/config" // Config configures this plugin, and is saved in the project config file. +// Deprecated: use scorecard and manifests plugin configs directly. type Config struct{} // hasPluginConfig returns true if cfg.Plugins contains an exact match for this plugin's key. diff --git a/internal/plugins/golang/v2/init.go b/internal/plugins/golang/v2/init.go index 1b9dc774820..dfd5c80c0d9 100644 --- a/internal/plugins/golang/v2/init.go +++ b/internal/plugins/golang/v2/init.go @@ -15,15 +15,13 @@ package v2 import ( - "fmt" - "github.com/spf13/pflag" "sigs.k8s.io/kubebuilder/v2/pkg/model/config" "sigs.k8s.io/kubebuilder/v2/pkg/plugin" "github.com/operator-framework/operator-sdk/internal/plugins/envtest" - "github.com/operator-framework/operator-sdk/internal/plugins/manifests" - "github.com/operator-framework/operator-sdk/internal/plugins/scorecard" + manifestsv2 "github.com/operator-framework/operator-sdk/internal/plugins/manifests/v2" + scorecardv2 "github.com/operator-framework/operator-sdk/internal/plugins/scorecard/v2" ) type initSubcommand struct { @@ -52,14 +50,6 @@ func (p *initSubcommand) Run() error { return err } - // Update plugin config section with this plugin's configuration for v3 projects. - if p.config.IsV3() { - cfg := Config{} - if err := p.config.EncodePluginConfig(pluginConfigKey, cfg); err != nil { - return fmt.Errorf("error writing plugin config for %s: %v", pluginConfigKey, err) - } - } - return nil } @@ -68,10 +58,10 @@ func (p *initSubcommand) runPhase2() error { if err := envtest.RunInit(p.config); err != nil { return err } - if err := manifests.RunInit(p.config); err != nil { + if err := manifestsv2.RunInit(p.config); err != nil { return err } - if err := scorecard.RunInit(p.config); err != nil { + if err := scorecardv2.RunInit(p.config); err != nil { return err } return nil diff --git a/internal/plugins/helm/v1/api.go b/internal/plugins/helm/v1/api.go index 4f9ece79428..52ddc6c2bda 100644 --- a/internal/plugins/helm/v1/api.go +++ b/internal/plugins/helm/v1/api.go @@ -27,6 +27,7 @@ import ( "github.com/operator-framework/operator-sdk/internal/plugins/helm/v1/chartutil" "github.com/operator-framework/operator-sdk/internal/plugins/helm/v1/scaffolds" "github.com/operator-framework/operator-sdk/internal/plugins/manifests" + manifestsv2 "github.com/operator-framework/operator-sdk/internal/plugins/manifests/v2" ) type createAPISubcommand struct { @@ -136,8 +137,24 @@ func (p *createAPISubcommand) Run() error { // SDK phase 2 plugins. func (p *createAPISubcommand) runPhase2() error { - gvk := p.createOptions.GVK - return manifests.RunCreateAPI(p.config, config.GVK{Group: gvk.Group, Version: gvk.Version, Kind: gvk.Kind}) + ogvk := p.createOptions.GVK + gvk := config.GVK{Group: ogvk.Group, Version: ogvk.Version, Kind: ogvk.Kind} + + // Initially the helm/v1 plugin was written to not create a "plugins" config entry + // for any phase 2 plugin because they did not have their own keys. Now there are phase 2 + // plugin keys, so those plugins should be run if keys exist. Otherwise, enact old behavior. + + if manifestsv2.HasPluginConfig(p.config) { + if err := manifestsv2.RunCreateAPI(p.config, gvk); err != nil { + return err + } + } else { + if err := manifests.RunCreateAPI(p.config, gvk); err != nil { + return err + } + } + + return nil } // Validate perform the required validations for this plugin diff --git a/internal/plugins/helm/v1/init.go b/internal/plugins/helm/v1/init.go index 0729fc70edf..719e46f88a7 100644 --- a/internal/plugins/helm/v1/init.go +++ b/internal/plugins/helm/v1/init.go @@ -28,8 +28,8 @@ import ( "github.com/operator-framework/operator-sdk/internal/kubebuilder/cmdutil" "github.com/operator-framework/operator-sdk/internal/plugins/helm/v1/chartutil" "github.com/operator-framework/operator-sdk/internal/plugins/helm/v1/scaffolds" - "github.com/operator-framework/operator-sdk/internal/plugins/manifests" - "github.com/operator-framework/operator-sdk/internal/plugins/scorecard" + manifestsv2 "github.com/operator-framework/operator-sdk/internal/plugins/manifests/v2" + scorecardv2 "github.com/operator-framework/operator-sdk/internal/plugins/scorecard/v2" ) type initSubcommand struct { @@ -147,10 +147,10 @@ func (p *initSubcommand) Run() error { // SDK phase 2 plugins. func (p *initSubcommand) runPhase2() error { - if err := manifests.RunInit(p.config); err != nil { + if err := manifestsv2.RunInit(p.config); err != nil { return err } - if err := scorecard.RunInit(p.config); err != nil { + if err := scorecardv2.RunInit(p.config); err != nil { return err } diff --git a/internal/plugins/manifests/v2/plugin.go b/internal/plugins/manifests/v2/plugin.go index 7e06f492d54..1827fdc410e 100644 --- a/internal/plugins/manifests/v2/plugin.go +++ b/internal/plugins/manifests/v2/plugin.go @@ -36,8 +36,8 @@ var ( // Config configures this plugin, and is saved in the project config file. type Config struct{} -// hasPluginConfig returns true if cfg.Plugins contains an exact match for this plugin's key. -func hasPluginConfig(cfg *config.Config) bool { +// HasPluginConfig returns true if cfg.Plugins contains an exact match for this plugin's key. +func HasPluginConfig(cfg *config.Config) bool { if !cfg.IsV3() || len(cfg.Plugins) == 0 { return false } @@ -63,7 +63,7 @@ func RunInit(cfg *config.Config) error { // RunCreateAPI runs the manifests SDK phase 2 plugin. func RunCreateAPI(cfg *config.Config, gvk config.GVK) error { - if !hasPluginConfig(cfg) { + if !HasPluginConfig(cfg) { return nil } return manifests.RunCreateAPI(cfg, gvk) diff --git a/testdata/ansible/memcached-operator/PROJECT b/testdata/ansible/memcached-operator/PROJECT index 8c79d65b2f5..2eeaedf5b9c 100644 --- a/testdata/ansible/memcached-operator/PROJECT +++ b/testdata/ansible/memcached-operator/PROJECT @@ -6,3 +6,6 @@ resources: kind: Memcached version: v1alpha1 version: 3-alpha +plugins: + manifests.sdk.operatorframework.io/v2: {} + scorecard.sdk.operatorframework.io/v2: {} diff --git a/testdata/go/v2/memcached-operator/PROJECT b/testdata/go/v2/memcached-operator/PROJECT index 29a8478d6fd..cef09ae8999 100644 --- a/testdata/go/v2/memcached-operator/PROJECT +++ b/testdata/go/v2/memcached-operator/PROJECT @@ -8,4 +8,5 @@ resources: version: v1alpha1 version: 3-alpha plugins: - go.sdk.operatorframework.io/v2-alpha: {} + manifests.sdk.operatorframework.io/v2: {} + scorecard.sdk.operatorframework.io/v2: {} diff --git a/testdata/helm/memcached-operator/PROJECT b/testdata/helm/memcached-operator/PROJECT index 75a957c7b4b..b6dbee32d49 100644 --- a/testdata/helm/memcached-operator/PROJECT +++ b/testdata/helm/memcached-operator/PROJECT @@ -6,3 +6,6 @@ resources: kind: Memcached version: v1alpha1 version: 3-alpha +plugins: + manifests.sdk.operatorframework.io/v2: {} + scorecard.sdk.operatorframework.io/v2: {} From 26c9548f554498083ec8ebabf7c2d909e6ad581c Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Tue, 2 Feb 2021 12:50:30 -0800 Subject: [PATCH 298/376] generate: make CSV generator for Go GVKs package-aware (#4445) internal/generatel/clusterserviceversion/bases/definitions: make the owned CRD generator package- and type-aware so multiple packages containing the same type names can be used. Signed-off-by: Eric Stroczynski Signed-off-by: reinvantveer --- .../fragments/csv-gen-package-aware.yaml | 6 + .../bases/definitions/ast.go | 167 +++++++++++++---- .../bases/definitions/crd.go | 12 +- .../bases/definitions/definitions.go | 175 ++++++++---------- .../bases/definitions/definitions_test.go | 88 +++++---- .../bases/definitions/markers.go | 24 ++- .../clusterserviceversion_updaters.go | 29 --- .../generate/testdata/go/api/shared/doc.go | 15 ++ .../testdata/go/api/shared/memcached_types.go | 25 +++ .../go/api/v1alpha1/memcached_types.go | 5 + .../testdata/go/api/v1alpha2/dummy_types.go | 8 + .../go/api/v1alpha2/memcached_types.go | 13 +- 12 files changed, 349 insertions(+), 218 deletions(-) create mode 100644 changelog/fragments/csv-gen-package-aware.yaml create mode 100644 internal/generate/testdata/go/api/shared/doc.go create mode 100644 internal/generate/testdata/go/api/shared/memcached_types.go diff --git a/changelog/fragments/csv-gen-package-aware.yaml b/changelog/fragments/csv-gen-package-aware.yaml new file mode 100644 index 00000000000..85715ed46a9 --- /dev/null +++ b/changelog/fragments/csv-gen-package-aware.yaml @@ -0,0 +1,6 @@ +entries: + - description: > + For Go-based projects, `generate ` subcommands now consider package and type names + when parsing Go API types files to generate a CSV's `owned.customresourcedefinitions`, such that types in + different packages and files will not overwrite each other. + kind: bugfix diff --git a/internal/generate/clusterserviceversion/bases/definitions/ast.go b/internal/generate/clusterserviceversion/bases/definitions/ast.go index bdfad9fb42f..b3717b6799a 100644 --- a/internal/generate/clusterserviceversion/bases/definitions/ast.go +++ b/internal/generate/clusterserviceversion/bases/definitions/ast.go @@ -18,15 +18,90 @@ import ( "errors" "fmt" "go/ast" + "strconv" "strings" + "sigs.k8s.io/controller-tools/pkg/crd" + "sigs.k8s.io/controller-tools/pkg/loader" "sigs.k8s.io/controller-tools/pkg/markers" ) -// getMarkedChildrenOfField collects all marked fields from type declarations starting at root in depth-first order. -func (g generator) getMarkedChildrenOfField(root markers.FieldInfo) (map[string][]*fieldInfo, error) { +// importIdents maps import identifiers to a list of corresponding path and file containing that path. +// For example, consider the set of 2 files, one containing 'import foo "my/foo"' and the other 'import foo "your/foo"'. +// Then the map would be: map["foo"][]struct{{f: (file 1), path: "my/foo"},{f: (file 2), path: "your/foo"}}. +type importIdents map[string][]struct { + f *ast.File + path string +} + +// newImportIdents creates an importIdents from all imports in pkg. +func newImportIdents(pkg *loader.Package) (importIdents, error) { + importIDs := make(map[string][]struct { + f *ast.File + path string + }) + for _, file := range pkg.Syntax { + for _, impSpec := range file.Imports { + val, err := strconv.Unquote(impSpec.Path.Value) + if err != nil { + return nil, err + } + // Most imports are not locally named, so the real package name should be used. + var impName string + if imp, hasImp := pkg.Imports()[val]; hasImp { + impName = imp.Name + } + // impSpec.Name will not be empty for locally named imports + if impSpec.Name != nil { + impName = impSpec.Name.Name + } + importIDs[impName] = append(importIDs[impName], struct { + f *ast.File + path string + }{file, val}) + } + } + return importIDs, nil +} + +// findPackagePathForSelExpr returns the package path corresponding to the package name used in expr if it exists in im. +func (im importIdents) findPackagePathForSelExpr(expr *ast.SelectorExpr) (pkgPath string) { + // X contains the name being selected from. + xIdent, isIdent := expr.X.(*ast.Ident) + if !isIdent { + return "" + } + // Imports for all import statements where local import name == name being selected from. + imports, hasImports := im[xIdent.String()] + if !hasImports { + return "" + } + + // Short-circuit if only one import. + if len(imports) == 1 { + return imports[0].path + } + + // If multiple files contain the same local import name, check to see which file contains the selector expression. + for _, imp := range imports { + if imp.f.Pos() <= expr.Pos() && imp.f.End() >= expr.End() { + return imp.path + } + } + return "" +} + +// getMarkedChildrenOfField collects all marked fields from type declarations starting at rootField in depth-first order. +func (g generator) getMarkedChildrenOfField(rootPkg *loader.Package, rootField markers.FieldInfo) (map[string][]*fieldInfo, error) { + // Gather all types and imports needed to build the BFS tree. + rootPkg.NeedTypesInfo() + importIDs, err := newImportIdents(rootPkg) + if err != nil { + return nil, err + } + // ast.Inspect will not traverse into fields, so iteratively collect them and to check for markers. - nextFields := []*fieldInfo{{FieldInfo: root}} + nextFields := []*fieldInfo{{FieldInfo: rootField}} markedFields := map[string][]*fieldInfo{} for len(nextFields) > 0 { fields := []*fieldInfo{} @@ -36,49 +111,65 @@ func (g generator) getMarkedChildrenOfField(root markers.FieldInfo) (map[string] if n == nil { return true } - switch expr := n.(type) { + + var info *markers.TypeInfo + var hasInfo bool + switch nt := n.(type) { + case *ast.SelectorExpr: + // Case of a type definition in an imported package. + + pkgPath := importIDs.findPackagePathForSelExpr(nt) + if pkgPath == "" { + // Found no reference to pkgPath in any file. + return true + } + if pkg, hasImport := rootPkg.Imports()[loader.NonVendorPath(pkgPath)]; hasImport { + // Check if the field's type exists in the known types. + info, hasInfo = g.types[crd.TypeIdent{Package: pkg, Name: nt.Sel.Name}] + } case *ast.Ident: + // Case of a local type definition. + // Only look at type names. - if expr.Obj == nil || expr.Obj.Kind != ast.Typ { - return true + if nt.Obj != nil && nt.Obj.Kind == ast.Typ { + // Check if the field's type exists in the known types. + info, hasInfo = g.types[crd.TypeIdent{Package: rootPkg, Name: nt.Name}] } - // Check if the field's type exists in the known types. - info, hasInfo := g.types[expr.Name] - if !hasInfo { + } + if !hasInfo { + return true + } + + // Add all child fields to the list to search next. + for _, finfo := range info.Fields { + segment, err := getPathSegmentForField(finfo) + if err != nil { + errs = append(errs, fmt.Errorf("error getting path from type %s field %s: %v", info.Name, finfo.Name, err)) return true } - // Add all child fields to the list to search next. - for _, finfo := range info.Fields { - segment, err := getPathSegmentForField(finfo) - if err != nil { - errs = append(errs, fmt.Errorf("error getting path from type %s field %s: %v", - info.Name, finfo.Name, err), - ) - return true - } - // Add extra information to the segment if it comes from a certain field type. - switch finfo.RawField.Type.(type) { - case (*ast.ArrayType): - // arrayFieldGroup case. - if segment != ignoredTag && segment != inlinedTag { - segment += "[0]" - } - } - // Create a new set of path segments using the parent's segments - // and add the field to the next fields to search. - parentSegments := make([]string, len(field.pathSegments), len(field.pathSegments)+1) - copy(parentSegments, field.pathSegments) - f := &fieldInfo{ - FieldInfo: finfo, - pathSegments: append(parentSegments, segment), - } - fields = append(fields, f) - // Marked fields get collected for the caller to parse. - if len(finfo.Markers) != 0 { - markedFields[info.Name] = append(markedFields[info.Name], f) + // Add extra information to the segment if it comes from a certain field type. + switch finfo.RawField.Type.(type) { + case *ast.ArrayType: + // arrayFieldGroup case. + if segment != ignoredTag && segment != inlinedTag { + segment += "[0]" } } + // Create a new set of path segments using the parent's segments + // and add the field to the next fields to search. + parentSegments := make([]string, len(field.pathSegments), len(field.pathSegments)+1) + copy(parentSegments, field.pathSegments) + f := &fieldInfo{ + FieldInfo: finfo, + pathSegments: append(parentSegments, segment), + } + fields = append(fields, f) + // Marked fields get collected for the caller to parse. + if len(finfo.Markers) != 0 { + markedFields[info.Name] = append(markedFields[info.Name], f) + } } + return true }) if err := fmtParseErrors(errs); err != nil { diff --git a/internal/generate/clusterserviceversion/bases/definitions/crd.go b/internal/generate/clusterserviceversion/bases/definitions/crd.go index 5167b790952..0f0c01036f2 100644 --- a/internal/generate/clusterserviceversion/bases/definitions/crd.go +++ b/internal/generate/clusterserviceversion/bases/definitions/crd.go @@ -26,7 +26,9 @@ import ( "github.com/operator-framework/api/pkg/operators/v1alpha1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/version" + "sigs.k8s.io/controller-tools/pkg/crd" crdmarkers "sigs.k8s.io/controller-tools/pkg/crd/markers" + "sigs.k8s.io/controller-tools/pkg/loader" "sigs.k8s.io/controller-tools/pkg/markers" "github.com/operator-framework/operator-sdk/internal/util/k8sutil" @@ -54,7 +56,7 @@ func getHalfBySep(s, sep string, half uint) string { // buildCRDDescriptionFromType builds a crdDescription for the Go API defined // by key from markers and type information in g.types. -func (g generator) buildCRDDescriptionFromType(gvk schema.GroupVersionKind, kindType *markers.TypeInfo) (v1alpha1.CRDDescription, int, error) { +func (g generator) buildCRDDescriptionFromType(gvk schema.GroupVersionKind, typeIdent crd.TypeIdent, kindType *markers.TypeInfo) (v1alpha1.CRDDescription, int, error) { // Initialize the description. description := v1alpha1.CRDDescription{ @@ -96,7 +98,7 @@ func (g generator) buildCRDDescriptionFromType(gvk schema.GroupVersionKind, kind } sortResources(description.Resources) - specDescriptors, err := g.getTypedDescriptors(kindType, reflect.TypeOf(v1alpha1.SpecDescriptor{}), spec) + specDescriptors, err := g.getTypedDescriptors(typeIdent.Package, kindType, reflect.TypeOf(v1alpha1.SpecDescriptor{}), spec) if err != nil { return v1alpha1.CRDDescription{}, 0, err } @@ -104,7 +106,7 @@ func (g generator) buildCRDDescriptionFromType(gvk schema.GroupVersionKind, kind description.SpecDescriptors = append(description.SpecDescriptors, d.(v1alpha1.SpecDescriptor)) } - statusDescriptors, err := g.getTypedDescriptors(kindType, reflect.TypeOf(v1alpha1.StatusDescriptor{}), status) + statusDescriptors, err := g.getTypedDescriptors(typeIdent.Package, kindType, reflect.TypeOf(v1alpha1.StatusDescriptor{}), status) if err != nil { return v1alpha1.CRDDescription{}, 0, err } @@ -115,7 +117,7 @@ func (g generator) buildCRDDescriptionFromType(gvk schema.GroupVersionKind, kind return description, descriptionOrder, nil } -func (g generator) getTypedDescriptors(kindType *markers.TypeInfo, t reflect.Type, descType string) ([]interface{}, error) { +func (g generator) getTypedDescriptors(pkg *loader.Package, kindType *markers.TypeInfo, t reflect.Type, descType string) ([]interface{}, error) { // Find child in the kind type. child, err := findChildForDescType(kindType, descType) if err != nil { @@ -123,7 +125,7 @@ func (g generator) getTypedDescriptors(kindType *markers.TypeInfo, t reflect.Typ } // Find annotated fields of child and parse them into descriptors. - markedFields, err := g.getMarkedChildrenOfField(child) + markedFields, err := g.getMarkedChildrenOfField(pkg, child) if err != nil { return nil, err } diff --git a/internal/generate/clusterserviceversion/bases/definitions/definitions.go b/internal/generate/clusterserviceversion/bases/definitions/definitions.go index 7efd5b471bd..a51855b78c4 100644 --- a/internal/generate/clusterserviceversion/bases/definitions/definitions.go +++ b/internal/generate/clusterserviceversion/bases/definitions/definitions.go @@ -24,6 +24,8 @@ import ( log "github.com/sirupsen/logrus" "golang.org/x/tools/go/packages" "k8s.io/apimachinery/pkg/runtime/schema" + apiversion "k8s.io/apimachinery/pkg/version" + "sigs.k8s.io/controller-tools/pkg/crd" "sigs.k8s.io/controller-tools/pkg/genall" "sigs.k8s.io/controller-tools/pkg/loader" "sigs.k8s.io/controller-tools/pkg/markers" @@ -39,77 +41,60 @@ type descriptionValues struct { // to populate csv spec fields. Go code with relevant markers and information is expected to be // in a package under apisRootDir and match a GVK in keys. func ApplyDefinitionsForKeysGo(csv *v1alpha1.ClusterServiceVersion, apisRootDir string, gvks []schema.GroupVersionKind) error { - - // Construct a set of probable paths under apisRootDir for types defined by gvks. - // These are usually '(pkg/)?apis/(/)?'. - // NB(estroz): using "leaf" packages prevents type builders from searching other packages. - // It would be nice to implement extra-package traversal in the future. - paths, err := makeAPIPaths(apisRootDir, gvks) + wd, err := os.Getwd() if err != nil { return err } - // Some APIs may not exist under apisRootDir, so skip loading packages if no paths are found - if len(paths) == 0 { - return nil - } - // Collect Go types from roots. + // Create a generator context for type-checking and loading all packages under apisRootDir. + // The "$(pwd)//..." syntax directs the loader to load all packages under apisRootDir. g := &generator{} - ctx, err := g.contextForRoots(paths...) + ctx, err := g.contextForRoots(filepath.Join(wd, apisRootDir) + "/...") if err != nil { return err } + // Collect Go types from the API root. g.needTypes(ctx) if loader.PrintErrors(ctx.Roots, packages.TypeError) { return errors.New("one or more API packages had type errors") } + gvkSet := make(map[schema.GroupVersionKind]struct{}, len(gvks)) + for _, gvk := range gvks { + gvkSet[gvk] = struct{}{} + } + // Create definitions for kind types found under the collected roots. definitionsByGVK := make(map[schema.GroupVersionKind]*descriptionValues) - for _, gvk := range gvks { - kindType, hasKind := g.types[gvk.Kind] - if !hasKind { - log.Warnf("Skipping CSV annotation parsing for API %s: type %s not found", gvk, gvk.Kind) - continue - } - crd, crdOrder, err := g.buildCRDDescriptionFromType(gvk, kindType) - if err != nil { - return err - } - definitionsByGVK[gvk] = &descriptionValues{ - crdOrder: crdOrder, - crd: crd, + for typeIdent, typeInfo := range g.types { + if gv, hasGV := g.groupVersions[typeIdent.Package]; hasGV { + gvk := gv.WithKind(typeIdent.Name) + // Type is one of the GVKs specified by the caller. + if _, hasGVK := gvkSet[gvk]; hasGVK { + crd, crdOrder, err := g.buildCRDDescriptionFromType(gvk, typeIdent, typeInfo) + if err != nil { + return err + } + definitionsByGVK[gvk] = &descriptionValues{ + crdOrder: crdOrder, + crd: crd, + } + delete(gvkSet, gvk) + } } } + // Leftover GVKs are ignored because their types can't be found. + for _, gvk := range gvkSet { + log.Warnf("Skipping CSV annotation parsing for API %s: type not found", gvk) + } + // Update csv with all values parsed. updateDefinitionsByKey(csv, definitionsByGVK) return nil } -// makeAPIPaths creates a set of API directory paths with apisRootDir as their parent. -func makeAPIPaths(apisRootDir string, gvks []schema.GroupVersionKind) (paths []string, err error) { - if apisRootDir, err = filepath.Abs(apisRootDir); err != nil { - return nil, err - } - - for _, gvk := range gvks { - // Check if the kind pkg is at the expected layout. - group := MakeGroupFromFullGroup(gvk.Group) - expectedPkgPath, err := getExpectedPkgLayout(apisRootDir, group, gvk.Version) - if err != nil { - return nil, err - } - if expectedPkgPath == "" { - log.Warnf("Skipping CSV annotation parsing for API %s: directory does not exist", gvk) - continue - } - paths = append(paths, expectedPkgPath) - } - return paths, nil -} - // updateDefinitionsByKey updates owned definitions that already exist in csv or adds new definitions that do not. func updateDefinitionsByKey(csv *v1alpha1.ClusterServiceVersion, defsByGVK map[schema.GroupVersionKind]*descriptionValues) { // Create a set of buckets for all generated descriptions. @@ -122,9 +107,7 @@ func updateDefinitionsByKey(csv *v1alpha1.ClusterServiceVersion, defsByGVK map[s // Sort generated buckets before adding non-generated descriptions so users can // set their order manually. for _, bucket := range crdBuckets { - sort.Slice(bucket, func(i, j int) bool { - return bucket[i].Name < bucket[j].Name - }) + sort.Slice(bucket, lessForCRDDescription(bucket)) } // Append non-generated descriptions to the end of their buckets, @@ -149,6 +132,19 @@ func updateDefinitionsByKey(csv *v1alpha1.ClusterServiceVersion, defsByGVK map[s } } +// lessForCRDDescription returns a less func for descs. Used for sorting a list of CRDDescriptions. +func lessForCRDDescription(descs []v1alpha1.CRDDescription) func(i, j int) bool { + return func(i, j int) bool { + if descs[i].Name == descs[j].Name { + if descs[i].Kind == descs[j].Kind { + return apiversion.CompareKubeAwareVersionStrings(descs[i].Version, descs[j].Version) > 0 + } + return descs[i].Kind < descs[j].Kind + } + return descs[i].Name < descs[j].Name + } +} + // descToGVK convert desc to a GVK type. func descToGVK(desc v1alpha1.CRDDescription) (gvk schema.GroupVersionKind) { gvk.Group = MakeFullGroupFromName(desc.Name) @@ -157,47 +153,10 @@ func descToGVK(desc v1alpha1.CRDDescription) (gvk schema.GroupVersionKind) { return gvk } -func isDirExist(path string) (bool, error) { - fileInfo, err := os.Stat(path) - if err != nil { - if os.IsNotExist(err) { - return false, nil - } - return false, err - } - return fileInfo.IsDir(), nil -} - -// getExpectedPkgLayout checks the directory layout in apisRootDir for single and multi group layouts and returns -// the expected pkg path for the group and version. Returns empty string if neither single or multi group layout -// is detected. -// - multi-group layout: apis// -// - single-group layout: api/ -func getExpectedPkgLayout(apisRootDir, group, version string) (expectedPkgPath string, err error) { - if group == "" || version == "" { - return "", nil - } - groupVersionDir := filepath.Join(apisRootDir, group, version) - if isMultiGroupLayout, err := isDirExist(groupVersionDir); isMultiGroupLayout { - if err != nil { - return "", err - } - return groupVersionDir, nil - } - versionDir := filepath.Join(apisRootDir, version) - if isSingleGroupLayout, err := isDirExist(versionDir); isSingleGroupLayout { - if err != nil { - return "", err - } - return versionDir, nil - } - // Neither multi nor single group layout - return "", nil -} - // generator creates API definitions from type information for a set of roots. type generator struct { - types map[string]*markers.TypeInfo + types map[crd.TypeIdent]*markers.TypeInfo + groupVersions map[*loader.Package]schema.GroupVersion } // contextForRoots creates a context that can populate a generator for a set of roots loaded from dirs. @@ -222,13 +181,41 @@ func (g *generator) contextForRoots(dirs ...string) (ctx *genall.GenerationConte } // needTypes sets types in the generator for a given context. +// Adapted from https://github.com/kubernetes-sigs/controller-tools/blob/868d39a/pkg/crd/parser.go#L121 func (g *generator) needTypes(ctx *genall.GenerationContext) { - g.types = make(map[string]*markers.TypeInfo) - cb := func(info *markers.TypeInfo) { - g.types[info.Name] = info - } + g.types = make(map[crd.TypeIdent]*markers.TypeInfo) + g.groupVersions = make(map[*loader.Package]schema.GroupVersion) for _, root := range ctx.Roots { - if err := markers.EachType(ctx.Collector, root, cb); err != nil { + pkgMarkers, err := markers.PackageMarkers(ctx.Collector, root) + if err != nil { + root.AddError(err) + } else { + // Explicitly skip this package. + if skipPkg := pkgMarkers.Get("kubebuilder:skip"); skipPkg != nil { + return + } + // Get group name and optionall version name from package markers. + if nameVal := pkgMarkers.Get("groupName"); nameVal != nil { + versionVal := root.Name + if versionMarker := pkgMarkers.Get("versionName"); versionMarker != nil { + versionVal = versionMarker.(string) + } + + g.groupVersions[root] = schema.GroupVersion{ + Version: versionVal, + Group: nameVal.(string), + } + } + } + // Add all types indexed by their package and type name. + f := func(info *markers.TypeInfo) { + ident := crd.TypeIdent{ + Package: root, + Name: info.Name, + } + g.types[ident] = info + } + if err := markers.EachType(ctx.Collector, root, f); err != nil { root.AddError(err) } } diff --git a/internal/generate/clusterserviceversion/bases/definitions/definitions_test.go b/internal/generate/clusterserviceversion/bases/definitions/definitions_test.go index c1f7c689c95..7828dfea2f4 100644 --- a/internal/generate/clusterserviceversion/bases/definitions/definitions_test.go +++ b/internal/generate/clusterserviceversion/bases/definitions/definitions_test.go @@ -78,8 +78,10 @@ func TestApplyDefinitionsForKeysGo(t *testing.T) { {Name: "dummy-replicaset", Kind: "ReplicaSet", Version: "v1beta2"}, }, SpecDescriptors: []v1alpha1.SpecDescriptor{ + {Path: "sideCar", DisplayName: "Side Car"}, {Path: "size", DisplayName: "dummy-size", Description: "Should be in spec", XDescriptors: []string{"urn:alm:descriptor:com.tectonic.ui:podCount"}}, + {Path: "useful.containers", DisplayName: "Containers"}, {Path: "wheels", DisplayName: "Wheels", Description: "Should be in spec, but should not have array index in path", XDescriptors: []string{"urn:alm:descriptor:com.tectonic.ui:text"}}, @@ -134,47 +136,58 @@ func TestApplyDefinitionsForKeysGo(t *testing.T) { }, }, { - description: "Do not change definitions with non-existent package dir", - apisDir: filepath.Join("pkg", "notexist"), - csv: &v1alpha1.ClusterServiceVersion{ - Spec: v1alpha1.ClusterServiceVersionSpec{ - CustomResourceDefinitions: v1alpha1.CustomResourceDefinitions{ - Owned: []v1alpha1.CRDDescription{ - { - Name: "dummys.cache.example.com", Version: "v1alpha2", Kind: "Dummy", - DisplayName: "Dummy App", - Description: "Dummy is the Schema for the other dummy API", - Resources: []v1alpha1.APIResourceReference{ - {Name: "dummy-pod", Kind: "Pod", Version: "v1"}, - }, - SpecDescriptors: []v1alpha1.SpecDescriptor{ - {Path: "foo", DisplayName: "Foo", Description: "Should not be removed"}, - }, - StatusDescriptors: []v1alpha1.StatusDescriptor{ - {Path: "bar", DisplayName: "Bar", Description: "Should not be removed"}, - }, - }, - }, - }, - }, - }, + description: "Populate CRDDescription with GVKs with same GK and different versions", + apisDir: "api", + csv: &v1alpha1.ClusterServiceVersion{}, gvks: []schema.GroupVersionKind{ - {Group: "cache.example.com", Version: "v1alpha2", Kind: "Dummy"}, + {Group: "cache.example.com", Version: "v1alpha1", Kind: "Memcached"}, + {Group: "cache.example.com", Version: "v1alpha2", Kind: "Memcached"}, }, expectedCRDs: v1alpha1.CustomResourceDefinitions{ Owned: []v1alpha1.CRDDescription{ { - Name: "dummys.cache.example.com", Version: "v1alpha2", Kind: "Dummy", - DisplayName: "Dummy App", - Description: "Dummy is the Schema for the other dummy API", - Resources: []v1alpha1.APIResourceReference{ - {Name: "dummy-pod", Kind: "Pod", Version: "v1"}, - }, + Name: "memcacheds.cache.example.com", Version: "v1alpha2", Kind: "Memcached", + DisplayName: "Memcached App", + Description: "Memcached is the Schema for the memcacheds API", SpecDescriptors: []v1alpha1.SpecDescriptor{ - {Path: "foo", DisplayName: "Foo", Description: "Should not be removed"}, + {Path: "size", DisplayName: "Size", Description: "Size is the size of the memcached deployment"}, }, StatusDescriptors: []v1alpha1.StatusDescriptor{ - {Path: "bar", DisplayName: "Bar", Description: "Should not be removed"}, + {Path: "nodes", DisplayName: "Nodes", Description: "Nodes are the names of the memcached pods"}, + }, + }, + { + Name: "memcacheds.cache.example.com", Version: "v1alpha1", Kind: "Memcached", + DisplayName: "Memcached App Display Name", + Description: "Memcached is the Schema for the memcacheds API", + StatusDescriptors: []v1alpha1.StatusDescriptor{ + {Path: "nodes", DisplayName: "Nodes", Description: "Nodes are the names of the memcached pods"}, + }, + SpecDescriptors: []v1alpha1.SpecDescriptor{ + {Path: "containers", DisplayName: "Containers"}, + {Path: "providers", DisplayName: "Providers", Description: "List of Providers"}, + {Path: "providers[0].foo", DisplayName: "Foo Provider", Description: "Foo represents the Foo provider"}, + {Path: "providers[0].foo.credentialsSecret", DisplayName: "Secret Containing the Credentials", + Description: "CredentialsSecret is a reference to a secret containing authentication details for the Foo server", + XDescriptors: []string{"urn:alm:descriptor:io.kubernetes:Secret"}, + }, + { + Path: "providers[0].foo.credentialsSecret.key", DisplayName: "Key within the secret", + Description: "Key represents the specific key to reference from the secret", + XDescriptors: []string{"urn:alm:descriptor:com.tectonic.ui:advanced", "urn:alm:descriptor:com.tectonic.ui:text"}, + }, + { + Path: "providers[0].foo.credentialsSecret.name", DisplayName: "Name of the secret", + Description: "Name represents the name of the secret", + XDescriptors: []string{"urn:alm:descriptor:com.tectonic.ui:advanced", "urn:alm:descriptor:com.tectonic.ui:text"}, + }, + { + Path: "providers[0].foo.credentialsSecret.namespace", DisplayName: "Namespace containing the secret", + Description: "Namespace represents the namespace containing the secret", + XDescriptors: []string{"urn:alm:descriptor:com.tectonic.ui:advanced", "urn:alm:descriptor:com.tectonic.ui:text"}, + }, + { + Path: "size", DisplayName: "Size", Description: "Size is the size of the memcached deployment"}, }, }, }, @@ -227,6 +240,15 @@ func TestApplyDefinitionsForKeysGo(t *testing.T) { }, }, }, + { + description: "Return error for non-existent package dir", + apisDir: filepath.Join("pkg", "notexist"), + csv: &v1alpha1.ClusterServiceVersion{}, + gvks: []schema.GroupVersionKind{ + {Group: "cache.example.com", Version: "v1alpha2", Kind: "Dummy"}, + }, + wantErr: true, + }, } for _, c := range cases { diff --git a/internal/generate/clusterserviceversion/bases/definitions/markers.go b/internal/generate/clusterserviceversion/bases/definitions/markers.go index 4865631d0b5..7bdb24a5c2d 100644 --- a/internal/generate/clusterserviceversion/bases/definitions/markers.go +++ b/internal/generate/clusterserviceversion/bases/definitions/markers.go @@ -37,17 +37,20 @@ const ( crdMarkerName = csvPrefix + ":customresourcedefinitions" ) -// +operator-sdk:csv:customresourcedefinitions:displayName="string",resources={ {kind,version,name} , ... } -var typeDefinition = markers.Must(markers.MakeDefinition(crdMarkerName, markers.DescribesType, Description{})) - -// +operator-sdk:csv:customresourcedefinitions:type=,displayName="name",xDescriptors="ui:elements:foo:bar" -var fieldDefinition = markers.Must(markers.MakeDefinition(crdMarkerName, markers.DescribesField, Descriptor{})) - -// See https://github.com/kubernetes-sigs/controller-tools/blob/92e95c1/pkg/crd/markers/crd.go#L40 -var crdResourceDefinition = markers.Must(markers.MakeDefinition("kubebuilder:resource", markers.DescribesType, crdmarkers.Resource{})) +var ( + // +operator-sdk:csv:customresourcedefinitions:displayName="string",resources={ {kind,version,name} , ... } + typeDefinition = markers.Must(markers.MakeDefinition(crdMarkerName, markers.DescribesType, Description{})) + // +operator-sdk:csv:customresourcedefinitions:type=,displayName="name",xDescriptors="ui:elements:foo:bar" + fieldDefinition = markers.Must(markers.MakeDefinition(crdMarkerName, markers.DescribesField, Descriptor{})) +) // registerMarkers adds type and field marker definitions to a registry. func registerMarkers(into *markers.Registry) error { + // External definitions. + if err := crdmarkers.Register(into); err != nil { + return fmt.Errorf("error registering external marker definition: %v", err) + } + if err := into.Register(typeDefinition); err != nil { return fmt.Errorf("error registering type definition: %v", err) } @@ -57,11 +60,6 @@ func registerMarkers(into *markers.Registry) error { } into.AddHelp(fieldDefinition, Descriptor{}.Help()) - // External definitions. - if err := into.Register(crdResourceDefinition); err != nil { - return fmt.Errorf("error registering CRD resource definition: %v", err) - } - into.AddHelp(crdResourceDefinition, crdmarkers.Resource{}.Help()) return nil } diff --git a/internal/generate/clusterserviceversion/clusterserviceversion_updaters.go b/internal/generate/clusterserviceversion/clusterserviceversion_updaters.go index faf8911686c..233bb3484f0 100644 --- a/internal/generate/clusterserviceversion/clusterserviceversion_updaters.go +++ b/internal/generate/clusterserviceversion/clusterserviceversion_updaters.go @@ -18,7 +18,6 @@ import ( "encoding/json" "errors" "fmt" - "sort" "strings" operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1" @@ -29,7 +28,6 @@ import ( appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" - "k8s.io/apimachinery/pkg/version" "github.com/operator-framework/operator-sdk/internal/generate/collector" "github.com/operator-framework/operator-sdk/internal/util/k8sutil" @@ -46,9 +44,6 @@ func ApplyTo(c *collector.Manifests, csv *operatorsv1alpha1.ClusterServiceVersio // Set fields required by namespaced operators. This is a no-op for cluster-scoped operators. setNamespacedFields(csv) - // Sort all updated fields. - sortUpdates(csv) - return validate(csv) } @@ -474,30 +469,6 @@ func applyCustomResources(c *collector.Manifests, csv *operatorsv1alpha1.Cluster return nil } -// sortUpdates sorts all fields updated in csv. -// TODO(estroz): sort other modified fields. -func sortUpdates(csv *operatorsv1alpha1.ClusterServiceVersion) { - sort.Sort(descSorter(csv.Spec.CustomResourceDefinitions.Owned)) - sort.Sort(descSorter(csv.Spec.CustomResourceDefinitions.Required)) -} - -// descSorter sorts a set of crdDescriptions. -type descSorter []operatorsv1alpha1.CRDDescription - -var _ sort.Interface = descSorter{} - -func (descs descSorter) Len() int { return len(descs) } -func (descs descSorter) Less(i, j int) bool { - if descs[i].Name == descs[j].Name { - if descs[i].Kind == descs[j].Kind { - return version.CompareKubeAwareVersionStrings(descs[i].Version, descs[j].Version) > 0 - } - return descs[i].Kind < descs[j].Kind - } - return descs[i].Name < descs[j].Name -} -func (descs descSorter) Swap(i, j int) { descs[i], descs[j] = descs[j], descs[i] } - // validate will validate csv using the api validation library. // More info: https://github.com/operator-framework/api func validate(csv *operatorsv1alpha1.ClusterServiceVersion) error { diff --git a/internal/generate/testdata/go/api/shared/doc.go b/internal/generate/testdata/go/api/shared/doc.go new file mode 100644 index 00000000000..6a46e8b5d68 --- /dev/null +++ b/internal/generate/testdata/go/api/shared/doc.go @@ -0,0 +1,15 @@ +// Copyright 2021 The Operator-SDK 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. + +package shared diff --git a/internal/generate/testdata/go/api/shared/memcached_types.go b/internal/generate/testdata/go/api/shared/memcached_types.go new file mode 100644 index 00000000000..8e61f8fa0c0 --- /dev/null +++ b/internal/generate/testdata/go/api/shared/memcached_types.go @@ -0,0 +1,25 @@ +// Copyright 2021 The Operator-SDK 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. + +package shared + +import ( + v1 "k8s.io/api/core/v1" +) + +// UsefulType is a type shared between APIs. +type UsefulType struct { + // +operator-sdk:csv:customresourcedefinitions:type=spec + Containers []v1.Container `json:"containers"` +} diff --git a/internal/generate/testdata/go/api/v1alpha1/memcached_types.go b/internal/generate/testdata/go/api/v1alpha1/memcached_types.go index ea5b3d6dd35..d6bcb6ce4a2 100644 --- a/internal/generate/testdata/go/api/v1alpha1/memcached_types.go +++ b/internal/generate/testdata/go/api/v1alpha1/memcached_types.go @@ -16,6 +16,8 @@ package v1alpha1 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/operator-framework/operator-sdk/internal/generate/testdata/go/api/shared" ) // MemcachedSpec defines the desired state of Memcached @@ -27,6 +29,9 @@ type MemcachedSpec struct { // List of Providers // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Providers" Providers []Provider `json:"providers,omitempty"` + + // A useful shared type. + Useful shared.UsefulType `json:",inline"` } // Provider represents the container for a single provider diff --git a/internal/generate/testdata/go/api/v1alpha2/dummy_types.go b/internal/generate/testdata/go/api/v1alpha2/dummy_types.go index 9f70963c53f..de32b5fe3f4 100644 --- a/internal/generate/testdata/go/api/v1alpha2/dummy_types.go +++ b/internal/generate/testdata/go/api/v1alpha2/dummy_types.go @@ -15,7 +15,11 @@ package v1alpha2 import ( + v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + // Has the same name as a different import in memcached_types.go to test duplicate package names. + foo "github.com/operator-framework/operator-sdk/internal/generate/testdata/go/api/shared" ) // +k8s:deepcopy-gen=false @@ -47,6 +51,10 @@ type DummySpec struct { // Should be in spec, but should not have array index in path // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Wheels",xDescriptors="urn:alm:descriptor:com.tectonic.ui:text" Wheels []Wheel `json:"wheels"` + // A useful shared type. + Useful foo.UsefulType `json:"useful"` + // +operator-sdk:csv:customresourcedefinitions:type=spec + SideCar v1.Container `json:"sideCar"` } // +k8s:deepcopy-gen=false diff --git a/internal/generate/testdata/go/api/v1alpha2/memcached_types.go b/internal/generate/testdata/go/api/v1alpha2/memcached_types.go index 28c8588f9c6..c26a3cb36aa 100644 --- a/internal/generate/testdata/go/api/v1alpha2/memcached_types.go +++ b/internal/generate/testdata/go/api/v1alpha2/memcached_types.go @@ -15,7 +15,8 @@ package v1alpha2 import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + // Has the same name as a different import in dummy_types.go to test duplicate package names. + foo "k8s.io/apimachinery/pkg/apis/meta/v1" ) // MemcachedSpec defines the desired state of Memcached @@ -40,8 +41,8 @@ type MemcachedStatus struct { // +kubebuilder:storageversion // +operator-sdk:csv:customresourcedefinitions:displayName="Memcached App" type Memcached struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` + foo.TypeMeta `json:",inline"` + foo.ObjectMeta `json:"metadata,omitempty"` Spec MemcachedSpec `json:"spec,omitempty"` Status MemcachedStatus `json:"status,omitempty"` @@ -51,7 +52,7 @@ type Memcached struct { // MemcachedList contains a list of Memcached type MemcachedList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []Memcached `json:"items"` + foo.TypeMeta `json:",inline"` + foo.ListMeta `json:"metadata,omitempty"` + Items []Memcached `json:"items"` } From b22ac8f86a8ad4690bfdb89826d7deec8a86f7b1 Mon Sep 17 00:00:00 2001 From: Jesus Rodriguez Date: Tue, 2 Feb 2021 16:09:12 -0500 Subject: [PATCH 299/376] docs: add `run bundle` documentation (#4424) * Add run bundle to CLI Overview * Add run bundle to Quickstart: Testing bundles * Add run bundle to testing deployments * Reword run packagemanifests and Add cleanup command. * State that namespace is optional and will default to KUBECONFIG context * Add example CLIs to give more context. * Call out that install-mode is required if CSV does not support default mode. * Use a specific version instead of the generic on image names * Reword a few items to make them clearer * Link to the OLM docs regarding Subscriptions * Add $ to console commands & re-add newline removed earlier. Signed-off-by: jesus m. rodriguez Signed-off-by: reinvantveer --- .../en/docs/olm-integration/cli-overview.md | 3 + .../docs/olm-integration/quickstart-bundle.md | 57 +++++-- .../olm-integration/testing-deployment.md | 142 ++++++++++++++---- 3 files changed, 163 insertions(+), 39 deletions(-) diff --git a/website/content/en/docs/olm-integration/cli-overview.md b/website/content/en/docs/olm-integration/cli-overview.md index 52af83e203b..3bb6bb0f537 100644 --- a/website/content/en/docs/olm-integration/cli-overview.md +++ b/website/content/en/docs/olm-integration/cli-overview.md @@ -34,6 +34,8 @@ The following `make` recipes and `operator-sdk` subcommands create or interact w directory. This command generates both manifests and metadata. - [`bundle validate`][cli-bundle-validate]: validates an Operator bundle image or unpacked manifests and metadata. - `make bundle-build`: builds a bundle image using the `bundle.Dockerfile` generated by `make bundle`. +- [`run bundle`][cli-run-bundle]: runs the given Operator's bundle image with an + existing OLM installation. ##### Package Manifests @@ -50,6 +52,7 @@ with an existing OLM installation. [cli-olm-status]:/docs/cli/operator-sdk_olm_status [cli-olm-uninstall]:/docs/cli/operator-sdk_olm_uninstall [cli-gen-bundle]:/docs/cli/operator-sdk_generate_bundle +[cli-run-bundle]:/docs/cli/operator-sdk_run_bundle [cli-gen-packagemanifests]:/docs/cli/operator-sdk_generate_packagemanifests [cli-gen-kustomize-manifests]:/docs/cli/operator-sdk_generate_kustomize_manifests [cli-bundle-validate]:/docs/cli/operator-sdk_bundle_validate diff --git a/website/content/en/docs/olm-integration/quickstart-bundle.md b/website/content/en/docs/olm-integration/quickstart-bundle.md index 5c5eae53b41..f6c319a26d0 100644 --- a/website/content/en/docs/olm-integration/quickstart-bundle.md +++ b/website/content/en/docs/olm-integration/quickstart-bundle.md @@ -88,10 +88,10 @@ We will now create bundle manifests by running `make bundle` in the root of the $ make bundle /home/user/go/bin/controller-gen "crd:trivialVersions=true" rbac:roleName=manager-role webhook paths="./..." output:crd:artifacts:config=config/crd/bases operator-sdk generate kustomize manifests -q -kustomize build config/manifests | operator-sdk generate bundle -q --overwrite --version 0.0.1 -INFO[0000] Building annotations.yaml +kustomize build config/manifests | operator-sdk generate bundle -q --overwrite --version 0.0.1 +INFO[0000] Building annotations.yaml INFO[0000] Writing annotations.yaml in /home/user/go/src/github.com/test-org/memcached-operator/bundle/metadata -INFO[0000] Building Dockerfile +INFO[0000] Building Dockerfile INFO[0000] Writing bundle.Dockerfile in /home/user/go/src/github.com/test-org/memcached-operator operator-sdk bundle validate ./bundle INFO[0000] Found annotations file bundle-dir=bundle container-tool=docker @@ -99,10 +99,11 @@ INFO[0000] Could not find optional dependencies file bundle-dir=bundle conta INFO[0000] All validation tests have completed successfully ``` -A bundle manifests directory `bundle/manifests` containing a CSV and all CRDs in `config/crds`, a bundle -[metadata][bundle-metadata] directory `bundle/metadata`, and a [Dockerfile][bundle-dockerfile] `bundle.Dockerfile` -have been created in the Operator project. These files have been statically validated by -`operator-sdk bundle validate` to ensure the on-disk bundle representation is correct. +The above command will have created the following bundle artifacts: a manifests directory +(`bundle/manifests`) containing a CSV and all CRDs from `config/crds`, [metadata][bundle-metadata] +directory (`bundle/metadata`), and [`bundle.Dockerfile`][bundle-dockerfile] have been created in +the Operator project. These files have been statically validated by `operator-sdk bundle validate` +to ensure the on-disk bundle representation is correct. ## Deploying an Operator with OLM @@ -111,25 +112,53 @@ Now we're ready to test and deploy the Operator with OLM. ### Testing bundles - +Before proceeding, make sure you've [Installed OLM](#enabling-olm) onto your +cluster. + +First, we need to build our bundle. To build a memcached-operator bundle, run: + +```console +$ make bundle-build BUNDLE_IMG=/memcached-operator-bundle:v0.0.1 +$ make docker-push IMG=/memcached-operator-bundle:v0.0.1 +``` + +Now that the bundle image is present in a registry, [`operator-sdk run bundle`][cli-run-bundle] +can create a pod to serve that bundle to OLM via a [`Subscription`][install-your-operator], +along with other OLM objects, ephemerally. + +```console +$ operator-sdk run bundle /memcached-operator-bundle:v0.0.1 +INFO[0008] Successfully created registry pod: -memcached-operator-bundle-0-0-1 +INFO[0008] Created CatalogSource: memcached-operator-catalog +INFO[0008] OperatorGroup "operator-sdk-og" created +INFO[0008] Created Subscription: memcached-operator-v0-0-1-sub +INFO[0019] Approved InstallPlan install-krv7q for the Subscription: memcached-operator-v0-0-1-sub +INFO[0019] Waiting for ClusterServiceVersion "default/memcached-operator.v0.0.1" to reach 'Succeeded' phase +INFO[0019] Waiting for ClusterServiceVersion "default/memcached-operator.v0.0.1" to appear +INFO[0031] Found ClusterServiceVersion "default/memcached-operator.v0.0.1" phase: Pending +INFO[0032] Found ClusterServiceVersion "default/memcached-operator.v0.0.1" phase: Installing +INFO[0040] Found ClusterServiceVersion "default/memcached-operator.v0.0.1" phase: Succeeded +INFO[0040] OLM has successfully installed "memcached-operator.v0.0.1" +``` + -Coming soon. ### Deploying bundles in production OLM and Operator Registry consumes Operator bundles via an [index image][index-image], -which are composed of one or more bundles. To build a memcached-operator bundle, run: +which are composed of one or more bundles. To build a memcached-operator bundle for +version v0.0.1, run: ```console -make bundle-build BUNDLE_IMG=/memcached-operator-bundle: -docker push /memcached-operator-bundle: +$ make bundle-build BUNDLE_IMG=/memcached-operator-bundle:v0.0.1 +$ make docker-push IMG=/memcached-operator-bundle:v0.0.1 ``` Although we've validated on-disk manifests and metadata, we also must make sure the bundle itself is valid: ```console -$ operator-sdk bundle validate /memcached-operator-bundle: +$ operator-sdk bundle validate /memcached-operator-bundle:v0.0.1 INFO[0000] Unpacked image layers bundle-dir=/tmp/bundle-716785960 container-tool=docker INFO[0000] running docker pull bundle-dir=/tmp/bundle-716785960 container-tool=docker INFO[0002] running docker save bundle-dir=/tmp/bundle-716785960 container-tool=docker @@ -151,6 +180,7 @@ about your cataloged Operator. [bundle-metadata]:https://github.com/operator-framework/operator-registry/blob/v1.12.6/docs/design/operator-bundle.md#bundle-annotations [bundle-dockerfile]:https://github.com/operator-framework/operator-registry/blob/v1.12.6/docs/design/operator-bundle.md#bundle-dockerfile [cli-olm]:/docs/cli/operator-sdk_olm +[cli-run-bundle]:/docs/cli/operator-sdk_run_bundle [doc-cli-overview]:/docs/olm-integration/cli-overview [doc-olm-generate]:/docs/olm-integration/generation [opm]:https://github.com/operator-framework/operator-registry/blob/master/docs/design/opm-tooling.md @@ -158,3 +188,4 @@ about your cataloged Operator. [doc-index-build]:https://github.com/operator-framework/operator-registry#building-an-index-of-operators-using-opm [doc-olm-index]:https://github.com/operator-framework/operator-registry#using-the-index-with-operator-lifecycle-manager [doc-olm-discovery]:https://github.com/operator-framework/operator-lifecycle-manager/#discovery-catalogs-and-automated-upgrades +[install-your-operator]:https://olm.operatorframework.io/docs/tasks/install-operator-with-olm/#install-your-operator diff --git a/website/content/en/docs/olm-integration/testing-deployment.md b/website/content/en/docs/olm-integration/testing-deployment.md index 85911c3604c..0cf409926b1 100644 --- a/website/content/en/docs/olm-integration/testing-deployment.md +++ b/website/content/en/docs/olm-integration/testing-deployment.md @@ -8,51 +8,141 @@ This document discusses the behavior of `operator-sdk ` subcommands and assumes you are familiar with [OLM][olm], related terminology, and have read the SDK-OLM integration [design proposal][sdk-olm-design]. -Currently only the package manifests format is supported by `` subcommands. Bundle support is coming soon. - **Note:** before continuing, please read the [caveats](#caveats) section below. -## `operator-sdk packagemanifests` command overview +## `operator-sdk run bundle` command overview +`operator-sdk run bundle` assumes OLM is already installed and running on your +cluster. It also assumes that your Operator has a valid [bundle][bundle-format]. +See the [creating a bundle][creating-bundle] guide for more information. See the +[CLI overview][doc-cli-overview] for commands to work with an OLM installation +and generate a bundle. + +``` +operator-sdk run bundle [--index-image=] [--kubeconfig=] [--namespace=] [--timeout=] [--install-mode=(AllNamespace|OwnNamespace|SingleNamespace=)] +``` + +Let's look at the configuration shared between `run bundle`, `run +packagemanifests` and `cleanup`: + +- **kubeconfig**: the local path to a kubeconfig. This uses well-defined default + loading rules to load the config if empty. +- **namespace**: the cluster namespace in which Operator resources are created. + This namespace must already exist in the cluster. This is an optional field + which will default to the kubeconfig context if not provided. +- **timeout**: a time string dictating the maximum time that `run` can run. The + command will return an error if the timeout is exceeded. + +Let's look at the anatomy of the `run bundle` configuration model: + +- **bundle-image**: specifies the Operator bundle image, this is a + required parameter. The bundle image must be pullable. +- **index-image**: specifies an index image in which to inject the given bundle. + This is an optional field which will default to + `quay.io/operator-framework/upstream-opm-builder:latest` +- **install-mode**: specifies which supported [`installMode`][csv-install-modes] + should be used to create an `OperatorGroup` by configuring its + `spec.targetNamespaces` field. The `InstallModeType` string passed must be + marked as "supported" in the CSV being installed. + - This option understands the following strings (assuming your CSV does as + well): + - `AllNamespaces`: the Operator will watch all namespaces (cluster-scoped + Operators). This is the default. + - `OwnNamespace`: the Operator will watch its own namespace (from + **namespace** or the kubeconfig default). + - `SingleNamespace="my-ns"`: the Operator will watch a namespace, not + necessarily its own. + - This is an optional parameter, but if the CSV does not support + `AllNamespaces` then this parameter becomes **required** to instruct + `run bundle` with the appropriate `InstallModeType`. + +## `operator-sdk run packagemanifests` command overview -`operator-sdk packagemanifests` assumes OLM is already installed and running on your cluster, -and that your Operator has a valid [package manifests format][package-manifests]. -See the [CLI overview][doc-cli-overview] for commands to work with an OLM installation and generate a package manifests format. +`operator-sdk run packagemanifests` assumes OLM is already installed and +running on your cluster, and that your Operator has a valid +[package manifests format][package-manifests]. See the +[CLI overview][doc-cli-overview] for commands to work with an OLM installation +and generate a package manifests format. -Let's look at the anatomy of the `run packagemanifests` (which is the same for `cleanup`) configuration model: +``` +operator-sdk run packagemanifests [--version=] [--kubeconfig=] [--namespace=] [--timeout=] [--install-mode=(AllNamespace|OwnNamespace|SingleNamespace=)] +``` -- **kubeconfig-path**: the local path to a kubeconfig. - - This uses well-defined default loading rules to load the config if empty. +Let's look at the configuration shared between `run bundle`, `run +packagemanifests` and `cleanup`: + +- **kubeconfig**: the local path to a kubeconfig. This uses well-defined default + loading rules to load the config if empty. - **namespace**: the cluster namespace in which Operator resources are created. - - This namespace must already exist in the cluster. -- **manifests-dir**: a directory containing the Operator's package manifests. -- **version**: the version of the Operator to deploy. It must be a semantic version, ex. 0.0.1. - - This version must match the version of the CSV manifest found in **manifests-dir**, - ex. `packagemanifests/0.0.1` in an Operator SDK project. -- **install-mode**: specifies which supported [`installMode`][csv-install-modes] should be used to - create an `OperatorGroup` by configuring its `spec.targetNamespaces` field. - - The `InstallModeType` string passed must be marked as "supported" in the CSV being installed. - The namespaces passed must exist or be created by passing a `Namespace` manifest to IncludePaths. - - This option understands the following strings (assuming your CSV does as well): - - `AllNamespaces`: the Operator will watch all namespaces (cluster-scoped Operators). This is the default. - - `OwnNamespace`: the Operator will watch its own namespace (from **namespace** or the kubeconfig default). - - `SingleNamespace="my-ns"`: the Operator will watch a namespace, not necessarily its own. -- **timeout**: a time string dictating the maximum time that `run` can run. The command will - return an error if the timeout is exceeded. + This namespace must already exist in the cluster. This is an optional field + which will default to the kubeconfig context if not provided. +- **timeout**: a time string dictating the maximum time that `run` can run. The + command will return an error if the timeout is exceeded. + +Let's look at the anatomy of the `run packagemanifests` configuration model: + +- **packagemanifests-root-dir**: a directory containing the Operator's package + manifests, this is a required parameter. +- **install-mode**: specifies which supported [`installMode`][csv-install-modes] + should be used to create an `OperatorGroup` by configuring its + `spec.targetNamespaces` field. The `InstallModeType` string passed must be + marked as "supported" in the CSV being installed. + - This option understands the following strings (assuming your CSV does as + well): + - `AllNamespaces`: the Operator will watch all namespaces (cluster-scoped + Operators). This is the default. + - `OwnNamespace`: the Operator will watch its own namespace (from + **namespace** or the kubeconfig default). + - `SingleNamespace="my-ns"`: the Operator will watch a namespace, not + necessarily its own. + - This is an optional parameter, but if the CSV does not support + `AllNamespaces` then this parameter becomes **required** to instruct + `run packagemanifests` with the appropriate `InstallModeType`. +- **version**: the version of the Operator to deploy. It must be a semantic + version, ex. 0.0.1. This version must match the version of the CSV manifest + found in **manifests-dir**, e.g. `packagemanifests/0.0.1` in an Operator + SDK project. + +## `operator-sdk cleanup` command overview + +`operator-sdk cleanup` assumes an Operator was deployed using `run bundle` or +`run packagemanifests`. + +``` +operator-sdk cleanup [--kubeconfig=] [--namespace=] [--timeout=] +``` + +Let's look at the configuration shared between `run bundle`, `run +packagemanifests` and `cleanup`: + +- **kubeconfig**: the local path to a kubeconfig. This uses well-defined default + loading rules to load the config if empty. +- **namespace**: the cluster namespace in which Operator resources are created. + This namespace must already exist in the cluster. This is an optional field + which will default to the kubeconfig context if not provided. +- **timeout**: a time string dictating the maximum time that `run` can run. The + command will return an error if the timeout is exceeded. + +Let's look at the anatomy of the `cleanup` configuration model: + +- **operatorPackageName**: the Operator's package name which you want to remove + from the cluster, e.g. memcached-operator. This is a required parameter. ### Caveats -- ` packagemanifests` are intended to be used for testing purposes only, +- `run bundle`, `run packagemanifests`, and `cleanup` are intended to be used for testing purposes only, since this command creates a transient image registry that should not be used in production. Typically a registry is deployed separately and a set of catalog manifests are created in the cluster to inform OLM of that registry and which Operator versions it can deploy and where to deploy the Operator. -- `run packagemanifests` can only deploy one Operator and one version of that Operator at a time, +- `run bundle` and `run packagemanifests` can only deploy one Operator and one version of that Operator at a time, hence its intended purpose being testing only. [olm]:https://github.com/operator-framework/operator-lifecycle-manager/ [sdk-olm-design]:https://github.com/operator-framework/operator-sdk/blob/master/proposals/sdk-integration-with-olm.md [doc-cli-overview]:/docs/olm-integration/cli-overview +[bundle-format]:https://github.com/operator-framework/operator-registry/tree/v1.15.3#manifest-format [package-manifests]:https://github.com/operator-framework/operator-registry/tree/v1.5.3#manifest-format [csv-install-modes]:https://github.com/operator-framework/operator-lifecycle-manager/blob/master/doc/design/building-your-csv.md#operator-metadata [cli-olm-install]:/docs/cli/operator-sdk_olm_install [cli-olm-status]:/docs/cli/operator-sdk_olm_status +[creating-bundles]:/docs/olm-integration/quickstart-bundle/#creating-a-bundle From 85907d881cf1d595b4e5ef52d075c61597afaa72 Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Wed, 3 Feb 2021 12:45:56 -0800 Subject: [PATCH 300/376] docs: fix incorrect file path (#4473) Signed-off-by: Eric Stroczynski Signed-off-by: reinvantveer --- .../en/docs/building-operators/golang/advanced-topics.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/website/content/en/docs/building-operators/golang/advanced-topics.md b/website/content/en/docs/building-operators/golang/advanced-topics.md index 2527a9255a5..8567aee1a35 100644 --- a/website/content/en/docs/building-operators/golang/advanced-topics.md +++ b/website/content/en/docs/building-operators/golang/advanced-topics.md @@ -126,9 +126,10 @@ deleted until you remove the finalizer (ie, after your cleanup logic has success **Example:** -The following is a snippet from the controller file under `pkg/controller/memcached/memcached_controller.go` +The following is a snippet from a theoretical controller file `controllers/memcached_controller.go` +that implements a finalizer handler: -```Go +```go import ( ... "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" From 0e8061d25252ca28cf143082d856c3b59cfc386d Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Wed, 3 Feb 2021 14:26:41 -0800 Subject: [PATCH 301/376] internal/{helm,ansible}/controller: use correct context in client.Client calls (#4474) internal/{helm,ansible}/controller: use Reconcile()'s ctx argument in Client method calls Signed-off-by: Eric Stroczynski Signed-off-by: reinvantveer --- internal/ansible/controller/reconcile.go | 35 ++++++++-------- internal/helm/controller/reconcile.go | 52 ++++++++++++++---------- 2 files changed, 49 insertions(+), 38 deletions(-) diff --git a/internal/ansible/controller/reconcile.go b/internal/ansible/controller/reconcile.go index 60ba02f9ffd..9ba4488313b 100644 --- a/internal/ansible/controller/reconcile.go +++ b/internal/ansible/controller/reconcile.go @@ -87,7 +87,7 @@ func (r *AnsibleOperatorReconciler) Reconcile(ctx context.Context, request recon duration, err := time.ParseDuration(ds) if err != nil { // Should attempt to update to a failed condition - errmark := r.markError(u, request.NamespacedName, + errmark := r.markError(ctx, request.NamespacedName, u, fmt.Sprintf("Unable to parse reconcile period annotation: %v", err)) if errmark != nil { logger.Error(errmark, "Unable to mark error annotation") @@ -129,7 +129,7 @@ func (r *AnsibleOperatorReconciler) Reconcile(ctx context.Context, request recon } if r.ManageStatus { - errmark := r.markRunning(u, request.NamespacedName) + errmark := r.markRunning(ctx, request.NamespacedName, u) if errmark != nil { logger.Error(errmark, "Unable to update the status to mark cr as running") return reconcileResult, errmark @@ -145,7 +145,7 @@ func (r *AnsibleOperatorReconciler) Reconcile(ctx context.Context, request recon kc, err := kubeconfig.Create(ownerRef, "http://localhost:8888", u.GetNamespace()) if err != nil { - errmark := r.markError(u, request.NamespacedName, "Unable to run reconciliation") + errmark := r.markError(ctx, request.NamespacedName, u, "Unable to run reconciliation") if errmark != nil { logger.Error(errmark, "Unable to mark error to run reconciliation") } @@ -159,7 +159,7 @@ func (r *AnsibleOperatorReconciler) Reconcile(ctx context.Context, request recon }() result, err := r.Runner.Run(ident, u, kc.Name()) if err != nil { - errmark := r.markError(u, request.NamespacedName, "Unable to run reconciliation") + errmark := r.markError(ctx, request.NamespacedName, u, "Unable to run reconciliation") if errmark != nil { logger.Error(errmark, "Unable to mark error to run reconciliation") } @@ -219,7 +219,7 @@ func (r *AnsibleOperatorReconciler) Reconcile(ctx context.Context, request recon eventErr := errors.New("did not receive playbook_on_stats event") stdout, err := result.Stdout() if err != nil { - errmark := r.markError(u, request.NamespacedName, "Failed to get ansible-runner stdout") + errmark := r.markError(ctx, request.NamespacedName, u, "Failed to get ansible-runner stdout") if errmark != nil { logger.Error(errmark, "Unable to mark error to run reconciliation") } @@ -256,14 +256,14 @@ func (r *AnsibleOperatorReconciler) Reconcile(ctx context.Context, request recon } } u.SetFinalizers(finalizers) - err := r.Client.Update(context.TODO(), u) + err := r.Client.Update(ctx, u) if err != nil { logger.Error(err, "Failed to remove finalizer") return reconcileResult, err } } if r.ManageStatus { - errmark := r.markDone(u, request.NamespacedName, statusEvent, failureMessages) + errmark := r.markDone(ctx, request.NamespacedName, u, statusEvent, failureMessages) if errmark != nil { logger.Error(errmark, "Failed to mark status done") } @@ -299,11 +299,10 @@ func (r *AnsibleOperatorReconciler) printAnsibleResult(result runner.RunResult) } } -func (r *AnsibleOperatorReconciler) markRunning(u *unstructured.Unstructured, - namespacedName types.NamespacedName) error { +func (r *AnsibleOperatorReconciler) markRunning(ctx context.Context, nn types.NamespacedName, u *unstructured.Unstructured) error { // Get the latest resource to prevent updating a stale status. - if err := r.APIReader.Get(context.TODO(), namespacedName, u); err != nil { + if err := r.APIReader.Get(ctx, nn, u); err != nil { return err } crStatus := getStatus(u) @@ -327,19 +326,20 @@ func (r *AnsibleOperatorReconciler) markRunning(u *unstructured.Unstructured, ansiblestatus.SetCondition(&crStatus, *c) u.Object["status"] = crStatus.GetJSONMap() - return r.Client.Status().Update(context.TODO(), u) + return r.Client.Status().Update(ctx, u) } // markError - used to alert the user to the issues during the validation of a reconcile run. // i.e Annotations that could be incorrect -func (r *AnsibleOperatorReconciler) markError(u *unstructured.Unstructured, namespacedName types.NamespacedName, +func (r *AnsibleOperatorReconciler) markError(ctx context.Context, nn types.NamespacedName, u *unstructured.Unstructured, failureMessage string) error { + logger := logf.Log.WithName("markError") // Immediately update metrics with failed reconciliation, since Get() // may fail. metrics.ReconcileFailed(r.GVK.String()) // Get the latest resource to prevent updating a stale status. - if err := r.APIReader.Get(context.TODO(), namespacedName, u); err != nil { + if err := r.APIReader.Get(ctx, nn, u); err != nil { if apierrors.IsNotFound(err) { logger.Info("Resource not found, assuming it was deleted") return nil @@ -365,14 +365,15 @@ func (r *AnsibleOperatorReconciler) markError(u *unstructured.Unstructured, name // This needs the status subresource to be enabled by default. u.Object["status"] = crStatus.GetJSONMap() - return r.Client.Status().Update(context.TODO(), u) + return r.Client.Status().Update(ctx, u) } -func (r *AnsibleOperatorReconciler) markDone(u *unstructured.Unstructured, namespacedName types.NamespacedName, +func (r *AnsibleOperatorReconciler) markDone(ctx context.Context, nn types.NamespacedName, u *unstructured.Unstructured, statusEvent eventapi.StatusJobEvent, failureMessages eventapi.FailureMessages) error { + logger := logf.Log.WithName("markDone") // Get the latest resource to prevent updating a stale status. - if err := r.APIReader.Get(context.TODO(), namespacedName, u); err != nil { + if err := r.APIReader.Get(ctx, nn, u); err != nil { if apierrors.IsNotFound(err) { logger.Info("Resource not found, assuming it was deleted") return nil @@ -415,7 +416,7 @@ func (r *AnsibleOperatorReconciler) markDone(u *unstructured.Unstructured, names // This needs the status subresource to be enabled by default. u.Object["status"] = crStatus.GetJSONMap() - return r.Client.Status().Update(context.TODO(), u) + return r.Client.Status().Update(ctx, u) } func contains(l []string, s string) bool { diff --git a/internal/helm/controller/reconcile.go b/internal/helm/controller/reconcile.go index fb0e56d692b..0b731321b66 100644 --- a/internal/helm/controller/reconcile.go +++ b/internal/helm/controller/reconcile.go @@ -110,7 +110,9 @@ func (r HelmOperatorReconciler) Reconcile(ctx context.Context, request reconcile Reason: types.ReasonUninstallError, Message: err.Error(), }) - _ = r.updateResourceStatus(o, status) + if err := r.updateResourceStatus(ctx, o, status); err != nil { + log.Error(err, "Failed to update status after uninstall release failure") + } return reconcile.Result{}, err } status.RemoveCondition(types.ConditionReleaseFailed) @@ -129,13 +131,13 @@ func (r HelmOperatorReconciler) Reconcile(ctx context.Context, request reconcile }) status.DeployedRelease = nil } - if err := r.updateResourceStatus(o, status); err != nil { + if err := r.updateResourceStatus(ctx, o, status); err != nil { log.Info("Failed to update CR status") return reconcile.Result{}, err } controllerutil.RemoveFinalizer(o, finalizer) - if err := r.updateResource(o); err != nil { + if err := r.updateResource(ctx, o); err != nil { log.Info("Failed to remove CR uninstall finalizer") return reconcile.Result{}, err } @@ -144,7 +146,7 @@ func (r HelmOperatorReconciler) Reconcile(ctx context.Context, request reconcile // deletion here will guarantee that the next reconciliation // will see that the CR has been deleted and that there's // nothing left to do. - if err := r.waitForDeletion(o); err != nil { + if err := r.waitForDeletion(ctx, o); err != nil { log.Info("Failed waiting for CR deletion") return reconcile.Result{}, err } @@ -165,7 +167,9 @@ func (r HelmOperatorReconciler) Reconcile(ctx context.Context, request reconcile Reason: types.ReasonReconcileError, Message: err.Error(), }) - _ = r.updateResourceStatus(o, status) + if err := r.updateResourceStatus(ctx, o, status); err != nil { + log.Error(err, "Failed to update status after sync release failure") + } return reconcile.Result{}, err } status.RemoveCondition(types.ConditionIrreconcilable) @@ -184,14 +188,16 @@ func (r HelmOperatorReconciler) Reconcile(ctx context.Context, request reconcile Reason: types.ReasonInstallError, Message: err.Error(), }) - _ = r.updateResourceStatus(o, status) + if err := r.updateResourceStatus(ctx, o, status); err != nil { + log.Error(err, "Failed to update status after insatll release failure") + } return reconcile.Result{}, err } status.RemoveCondition(types.ConditionReleaseFailed) log.V(1).Info("Adding finalizer", "finalizer", finalizer) controllerutil.AddFinalizer(o, finalizer) - if err := r.updateResource(o); err != nil { + if err := r.updateResource(ctx, o); err != nil { log.Info("Failed to add CR uninstall finalizer") return reconcile.Result{}, err } @@ -222,14 +228,14 @@ func (r HelmOperatorReconciler) Reconcile(ctx context.Context, request reconcile Name: installedRelease.Name, Manifest: installedRelease.Manifest, } - err = r.updateResourceStatus(o, status) + err = r.updateResourceStatus(ctx, o, status) return reconcile.Result{RequeueAfter: r.ReconcilePeriod}, err } if !contains(o.GetFinalizers(), finalizer) { log.V(1).Info("Adding finalizer", "finalizer", finalizer) controllerutil.AddFinalizer(o, finalizer) - if err := r.updateResource(o); err != nil { + if err := r.updateResource(ctx, o); err != nil { log.Info("Failed to add CR uninstall finalizer") return reconcile.Result{}, err } @@ -250,7 +256,9 @@ func (r HelmOperatorReconciler) Reconcile(ctx context.Context, request reconcile Reason: types.ReasonUpgradeError, Message: err.Error(), }) - _ = r.updateResourceStatus(o, status) + if err := r.updateResourceStatus(ctx, o, status); err != nil { + log.Error(err, "Failed to update status after sync release failure") + } return reconcile.Result{}, err } status.RemoveCondition(types.ConditionReleaseFailed) @@ -281,7 +289,7 @@ func (r HelmOperatorReconciler) Reconcile(ctx context.Context, request reconcile Name: upgradedRelease.Name, Manifest: upgradedRelease.Manifest, } - err = r.updateResourceStatus(o, status) + err = r.updateResourceStatus(ctx, o, status) return reconcile.Result{RequeueAfter: r.ReconcilePeriod}, err } @@ -302,7 +310,9 @@ func (r HelmOperatorReconciler) Reconcile(ctx context.Context, request reconcile Reason: types.ReasonReconcileError, Message: err.Error(), }) - _ = r.updateResourceStatus(o, status) + if err := r.updateResourceStatus(ctx, o, status); err != nil { + log.Error(err, "Failed to update status after reconcile release failure") + } return reconcile.Result{}, err } status.RemoveCondition(types.ConditionIrreconcilable) @@ -333,7 +343,7 @@ func (r HelmOperatorReconciler) Reconcile(ctx context.Context, request reconcile Name: expectedRelease.Name, Manifest: expectedRelease.Manifest, } - err = r.updateResourceStatus(o, status) + err = r.updateResourceStatus(ctx, o, status) return reconcile.Result{RequeueAfter: r.ReconcilePeriod}, err } @@ -355,26 +365,26 @@ func hasHelmUpgradeForceAnnotation(o *unstructured.Unstructured) bool { return value } -func (r HelmOperatorReconciler) updateResource(o client.Object) error { +func (r HelmOperatorReconciler) updateResource(ctx context.Context, o client.Object) error { return retry.RetryOnConflict(retry.DefaultBackoff, func() error { - return r.Client.Update(context.TODO(), o) + return r.Client.Update(ctx, o) }) } -func (r HelmOperatorReconciler) updateResourceStatus(o *unstructured.Unstructured, status *types.HelmAppStatus) error { +func (r HelmOperatorReconciler) updateResourceStatus(ctx context.Context, o *unstructured.Unstructured, status *types.HelmAppStatus) error { return retry.RetryOnConflict(retry.DefaultBackoff, func() error { o.Object["status"] = status - return r.Client.Status().Update(context.TODO(), o) + return r.Client.Status().Update(ctx, o) }) } -func (r HelmOperatorReconciler) waitForDeletion(o client.Object) error { +func (r HelmOperatorReconciler) waitForDeletion(ctx context.Context, o client.Object) error { key := client.ObjectKeyFromObject(o) - ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) + tctx, cancel := context.WithTimeout(ctx, time.Second*5) defer cancel() return wait.PollImmediateUntil(time.Millisecond*10, func() (bool, error) { - err := r.Client.Get(ctx, key, o) + err := r.Client.Get(tctx, key, o) if apierrors.IsNotFound(err) { return true, nil } @@ -382,7 +392,7 @@ func (r HelmOperatorReconciler) waitForDeletion(o client.Object) error { return false, err } return false, nil - }, ctx.Done()) + }, tctx.Done()) } func contains(l []string, s string) bool { From 7ff6c79db07e5d68261142bc78220842a54370e2 Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Wed, 3 Feb 2021 16:11:34 -0800 Subject: [PATCH 302/376] docs/building-operators/golang: fix context.Context usage, imports, general formatting (#4475) Signed-off-by: Eric Stroczynski Signed-off-by: reinvantveer --- .../building-operators/golang/migration.md | 12 +- .../golang/references/client.md | 186 ++++++++++-------- .../golang/references/event-filtering.md | 2 +- .../building-operators/golang/tutorial.md | 6 +- 4 files changed, 112 insertions(+), 94 deletions(-) diff --git a/website/content/en/docs/building-operators/golang/migration.md b/website/content/en/docs/building-operators/golang/migration.md index 10d5c1a81e5..a1521759716 100644 --- a/website/content/en/docs/building-operators/golang/migration.md +++ b/website/content/en/docs/building-operators/golang/migration.md @@ -182,7 +182,8 @@ func main() { log.Error(err, "") os.Exit(1) } -.. +... +} ``` In order to use the previous one ensure that you have the [operator-lib][operator-lib] as a dependency of your project. @@ -202,6 +203,7 @@ func main() { LeaderElectionID: "f1c5ece8.example.com", }) ... +} ``` - Ensure that you copy all customizations made in `cmd/manager/main.go` to `main.go`. You’ll also need to ensure that all needed schemes have been registered, if you have been using third-party API's (i.e Route Api from OpenShift). @@ -244,7 +246,7 @@ If not, you can install Prometheus via [kube-prometheus](https://github.com/core kubectl apply -f https://raw.githubusercontent.com/coreos/prometheus-operator/release-0.33/bundle.yaml ``` - Now uncomment the line `- ../prometheus` in the `config/default/kustomization.yaml` file. It creates the `ServiceMonitor` resource which enables exporting the metrics: -```sh +```yaml # [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'. - ../prometheus ``` @@ -280,7 +282,7 @@ func (r *MemcachedReconciler) SetupWithManager(mgr ctrl.Manager) error { In this way, the following metric with the resource info will be exported: -```shell +``` resource_created_at_seconds{"name", "namespace", "group", "version", "kind"} ``` @@ -294,7 +296,7 @@ The Dockerfile image also changes and now it is a `multi-stage`, `distroless` an See that, you might need to port some customizations made in your old Dockerfile as well. Also, if you wish to still using the previous UBI image replace: -```sh +```docker # 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 @@ -302,7 +304,7 @@ FROM gcr.io/distroless/static:nonroot With: -```sh +```docker FROM registry.access.redhat.com/ubi8/ubi-minimal:latest ``` diff --git a/website/content/en/docs/building-operators/golang/references/client.md b/website/content/en/docs/building-operators/golang/references/client.md index f8a76b30a23..176fa0170cf 100644 --- a/website/content/en/docs/building-operators/golang/references/client.md +++ b/website/content/en/docs/building-operators/golang/references/client.md @@ -6,7 +6,7 @@ weight: 10 ## Overview -The [`controller-runtime`][repo-controller-runtime] library provides various abstractions to watch and reconcile resources in a Kubernetes cluster via CRUD (Create, Update, Delete, as well as Get and List in this case) operations. Operators use at least one controller to perform a coherent set of tasks within a cluster, usually through a combination of CRUD operations. The Operator SDK uses controller-runtime's [Client][doc-client-client] interface, which provides the interface for these operations. +The [`controller-runtime`][repo-controller-runtime] library provides various abstractions to watch and reconcile resources in a Kubernetes cluster via CRUD (Create, Update, Delete, as well as Get and List in this case) operations. Operators use at least one controller to perform a coherent set of tasks within a cluster, usually through a combination of CRUD operations. The Operator SDK uses controller-runtime's [Client][doc-client] interface, which provides the interface for these operations. controller-runtime defines several interfaces used for cluster interaction: - `client.Client`: implementers perform CRUD operations on a Kubernetes cluster. @@ -15,26 +15,35 @@ controller-runtime defines several interfaces used for cluster interaction: Clients are the focus of this document. A separate document will discuss Managers. +**Note:** this document uses parts of the sample [`memcached-operator`][memcached-testdata] for example code. +Import paths may be different for brevity. + ## Client Usage ### Default Client The SDK relies on a `manager.Manager` to create a `client.Client` interface that performs Create, Update, Delete, Get, and List operations within a `reconcile.Reconciler`'s Reconcile function. The SDK will generate code to create a Manager, which holds a Cache and a Client to be used in CRUD operations and communicate with the API server. By default a Controller's Reconciler will be populated with the Manager's Client which is a [split-client][doc-split-client]. -`controllers/_controller.go`: +The following code, found in `controllers/memcached_controller.go`, demonstrates how the Manager's client is passed to a reconciler. + ```Go -import ctrl "sigs.k8s.io/controller-runtime" +import ( + appsv1 "k8s.io/api/apps/v1" + ctrl "sigs.k8s.io/controller-runtime" + + cachev1alpha1 "github.com/example/memcached-operator/api/v1alpha1" +) -func (r *KindReconciler) SetupWithManager(mgr ctrl.Manager) error { - return ctrl.NewControllerManagedBy(mgr). - For(&cachev1alpha1.Kind{}). +func (r *MemcachedReconciler) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr). // mgr's Client is passed to r. + For(&cachev1alpha1.Memcached{}). Owns(&appsv1.Deployment{}). Complete(r) } -type KindReconciler struct { - // Populated above from a manager.Manager. - client.Client +type MemcachedReconciler struct { + client.Client // Populated above from a manager.Manager. + Log logr.Logger Scheme *runtime.Scheme } @@ -63,7 +72,9 @@ type Options struct { Mapper meta.RESTMapper } ``` + Example: + ```Go import ( "sigs.k8s.io/controller-runtime/pkg/client/config" @@ -85,8 +96,8 @@ Creating a new Client is not usually necessary nor advised, as the default Clien A Reconciler implements the [`reconcile.Reconciler`][doc-reconcile-reconciler] interface, which exposes the Reconcile method. Reconcilers are added to a corresponding Controller for a Kind; Reconcile is called in response to cluster or external Events, with a `reconcile.Request` object argument, to read and write cluster state by the Controller, and returns a `ctrl.Result`. SDK Reconcilers have access to a Client in order to make Kubernetes API calls. ```Go -// KindReconciler reconciles a Kind object -type KindReconciler struct { +// MemcachedReconciler reconciles a Memcached object +type MemcachedReconciler struct { // client, initialized using mgr.Client() above, is a split client // that reads objects from the cache and writes to the apiserver client.Client @@ -106,34 +117,37 @@ type KindReconciler struct { // The Controller will requeue the Request to be processed again if an error // is non-nil or Result.Requeue is true, otherwise upon completion it will // remove the work from the queue. -func (r *KindReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Result, error) +func (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) ``` -Reconcile is where Controller business logic lives, i.e. where Client API calls are made via `KindReconciler.client`. A `client.Client` implementer performs the following operations: +Reconcile is where Controller business logic lives, i.e. where Client API calls are made via `MemcachedReconciler.client`. A `client.Client` implementer performs the following operations: #### Get ```Go // Get retrieves an API object for a given object key from the Kubernetes cluster // and stores it in obj. -func (c Client) Get(ctx context.Context, key ObjectKey, obj runtime.Object) error +func (c Client) Get(ctx context.Context, key client.ObjectKey, obj client.Object) error ``` -**Note**: An `ObjectKey` is simply a `client` package alias for [`types.NamespacedName`][doc-types-nsname]. + +**Note**: A `client.ObjectKey` is simply an alias for [`types.NamespacedName`][doc-types-nsname]. Example: + ```Go import ( "context" - "github.com/example-org/app-operator/pkg/apis/cache/v1alpha1" + ctrl "sigs.k8s.io/controller-runtime" + + cachev1alpha1 "github.com/example/memcached-operator/api/v1alpha1" ) -func (r *AppReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Result, error) { +func (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { ... - app := &v1alpha1.App{} - ctx := context.TODO() - err := r.Get(ctx, request.NamespacedName, app) + memcached := &cachev1alpha1.Memcached{} + err := r.Get(ctx, request.NamespacedName, memcached) ... } @@ -144,7 +158,7 @@ func (r *AppReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Resul ```Go // List retrieves a list of objects for a given namespace and list options // and stores the list in obj. -func (c Client) List(ctx context.Context, list runtime.Object, opts ...client.ListOption) error +func (c Client) List(ctx context.Context, list client.Object, opts ...client.ListOption) error ``` A `client.ListOption` is an interface that sets [`client.ListOptions`][list-options] fields. A `client.ListOption` is created by using one of the provided implementations: [`MatchingLabels`][matching-labels], [`MatchingFields`][matching-fields], [`InNamespace`][in-namespace]. @@ -155,23 +169,23 @@ Example: import ( "context" "fmt" + "k8s.io/api/core/v1" - "sigs.k8s.io/controller-runtime/pkg/client" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" ) -func (r *AppReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Result, error) { +func (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { ... - // Return all pods in the request namespace with a label of `app=` + // Return all pods in the request namespace with a label of `instance=` // and phase `Running`. podList := &v1.PodList{} opts := []client.ListOption{ client.InNamespace(request.NamespacedName.Namespace), - client.MatchingLabels{"app": request.NamespacedName.Name}, + client.MatchingLabels{"instance": request.NamespacedName.Name}, client.MatchingFields{"status.phase": "Running"}, } - ctx := context.TODO() err := r.List(ctx, podList, opts...) ... @@ -188,7 +202,7 @@ func (r *AppReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Resul ```Go // Create saves the object obj in the Kubernetes cluster. // Returns an error -func (c Client) Create(ctx context.Context, obj runtime.Object, opts ...client.CreateOption) error +func (c Client) Create(ctx context.Context, obj client.Object, opts ...client.CreateOption) error ``` A `client.CreateOption` is an interface that sets [`client.CreateOptions`][create-options] fields. A `client.CreateOption` is created by using one of the provided implementations: [`DryRunAll`][dry-run-all], [`ForceOwnership`][force-ownership]. Generally these options are not needed. @@ -198,18 +212,18 @@ Example: ```Go import ( "context" + "k8s.io/api/apps/v1" ctrl "sigs.k8s.io/controller-runtime" ) -func (r *AppReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Result, error) { +func (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { ... - app := &v1.Deployment{ // Any cluster object you want to create. + dep := &v1.Deployment{ // Any cluster object you want to create. ... } - ctx := context.TODO() - err := r.Create(ctx, app) + err := r.Create(ctx, dep) ... } @@ -224,7 +238,7 @@ func (r *AppReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Resul // struct pointer so that obj can be updated with the content returned // by the API server. Update does *not* update the resource's status // subresource -func (c Client) Update(ctx context.Context, obj runtime.Object, opts ...client.UpdateOption) error +func (c Client) Update(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error ``` A `client.UpdateOption` is an interface that sets [`client.UpdateOptions`][update-options] fields. A `client.UpdateOption` is created by using one of the provided implementations: [`DryRunAll`][dry-run-all], [`ForceOwnership`][force-ownership]. Generally these options are not needed. @@ -234,19 +248,19 @@ Example: ```Go import ( "context" + "k8s.io/api/apps/v1" ctrl "sigs.k8s.io/controller-runtime" ) -func (r *AppReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Result, error) { +func (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { ... dep := &v1.Deployment{} - err := r.Get(context.TODO(), request.NamespacedName, dep) + err := r.Get(ctx, request.NamespacedName, dep) ... - ctx := context.TODO() dep.Spec.Selector.MatchLabels["is_running"] = "true" err := r.Update(ctx, dep) @@ -261,7 +275,7 @@ func (r *AppReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Resul ```Go // Patch patches the given obj in the Kubernetes cluster. obj must be a // struct pointer so that obj can be updated with the content returned by the Server. -func (c Client) Patch(ctx context.Context, obj runtime.Object, patch client.Patch, opts ...client.UpdateOption) error +func (c Client) Patch(ctx context.Context, obj client.Object, patch client.Patch, opts ...client.UpdateOption) error ``` A `client.PatchOption` is an interface that sets [`client.PatchOptions`][patch-options] fields. A `client.PatchOption` is created by using one of the provided implementations: [`DryRunAll`][dry-run-all], [`ForceOwnership`][force-ownership]. Generally these options are not needed. @@ -271,20 +285,20 @@ Example: ```Go import ( "context" + "k8s.io/api/apps/v1" - "sigs.k8s.io/controller-runtime/pkg/client" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" ) -func (r *AppReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Result, error) { +func (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { ... dep := &v1.Deployment{} - err := r.Get(context.TODO(), request.NamespacedName, dep) + err := r.Get(ctx, request.NamespacedName, dep) ... - ctx := context.TODO() // A merge patch will preserve other fields modified at runtime. patch := client.MergeFrom(dep.DeepCopy()) dep.Spec.Selector.MatchLabels["is_running"] = "true" @@ -316,14 +330,15 @@ Example: ```Go import ( "context" - cachev1alpha1 "github.com/example/memcached-operator/pkg/apis/cache/v1alpha1" + ctrl "sigs.k8s.io/controller-runtime" + + cachev1alpha1 "github.com/example/memcached-operator/api/v1alpha1" ) -func (r *AppReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Result, error) { +func (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { ... - ctx := context.TODO() mem := &cachev1alpha1.Memcached{} err := r.Get(ctx, request.NamespacedName, mem) @@ -350,7 +365,7 @@ func (r *AppReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Resul ```Go // Delete deletes the given obj from Kubernetes cluster. -func (c Client) Delete(ctx context.Context, obj runtime.Object, opts ...client.DeleteOption) error +func (c Client) Delete(ctx context.Context, obj client.Object, opts ...client.DeleteOption) error ``` A `client.DeleteOption` is an interface that sets [`client.DeleteOptions`][delete-opts] fields. A `client.DeleteOption` is created by using one of the provided implementations: [`GracePeriodSeconds`][grace-period-seconds], [`Preconditions`][preconditions], [`PropagationPolicy`][propagation-policy]. @@ -360,20 +375,20 @@ Example: ```Go import ( "context" + "k8s.io/api/core/v1" - "sigs.k8s.io/controller-runtime/pkg/client" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" ) -func (r *AppReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Result, error) { +func (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { ... pod := &v1.Pod{} - err := r.Get(context.TODO(), request.NamespacedName, pod) + err := r.Get(ctx, request.NamespacedName, pod) ... - ctx := context.TODO() if pod.Status.Phase == v1.PodUnknown { // Delete the pod after 5 seconds. err := r.Delete(ctx, pod, client.GracePeriodSeconds(5)) @@ -393,7 +408,7 @@ func (r *AppReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Resul ```Go // DeleteAllOf deletes all objects of the given type matching the given options. -func (c Client) DeleteAllOf(ctx context.Context, obj runtime.Object, opts ...client.DeleteAllOfOption) error +func (c Client) DeleteAllOf(ctx context.Context, obj client.Object, opts ...client.DeleteAllOfOption) error ``` A `client.DeleteAllOfOption` is an interface that sets [`client.DeleteAllOfOptions`][deleteallof-opts] fields. A `client.DeleteAllOfOption` wraps a [`client.ListOption`](#list) and [`client.DeleteOption`](#delete). @@ -404,24 +419,24 @@ Example: import ( "context" "fmt" + "k8s.io/api/core/v1" - "sigs.k8s.io/controller-runtime/pkg/client" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" ) -func (r *AppReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Result, error) { +func (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { ... - // Delete all pods in the request namespace with a label of `app=` + // Delete all pods in the request namespace with a label of `instance=` // and phase `Failed`. pod := &v1.Pod{} opts := []client.DeleteAllOfOption{ client.InNamespace(request.NamespacedName.Namespace), - client.MatchingLabels{"app", request.NamespacedName.Name}, + client.MatchingLabels{"instance", request.NamespacedName.Name}, client.MatchingFields{"status.phase": "Failed"}, client.GracePeriodSeconds(5), } - ctx := context.TODO() err := r.DeleteAllOf(ctx, pod, opts...) ... @@ -437,8 +452,6 @@ import ( "context" "reflect" - appv1alpha1 "github.com/example-org/app-operator/api/v1alpha1" - appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" @@ -446,22 +459,24 @@ import ( "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" + ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - ctrl "sigs.k8s.io/controller-runtime" + + cachev1alpha1 "github.com/example/memcached-operator/api/v1alpha1" ) -type AppReconciler struct { +type MemcachedReconciler struct { client.Client Log logr.Logger Scheme *runtime.Scheme } -func (r *AppReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Result, error) { +func (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - // Fetch the App instance. - app := &appv1alpha1.App{} - err := r.Get(context.TODO(), request.NamespacedName, app) + // Fetch the Memcached instance. + memcached := &cachev1alpha1.Memcached{} + err := r.Get(ctx, request.NamespacedName, memcached) if err != nil { if errors.IsNotFound(err) { return ctrl.Result{}, nil @@ -471,12 +486,12 @@ func (r *AppReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Resul // Check if the deployment already exists, if not create a new deployment. found := &appsv1.Deployment{} - err = r.Get(context.TODO(), types.NamespacedName{Name: app.Name, Namespace: app.Namespace}, found) + err = r.Get(ctx, types.NamespacedName{Name: memcached.Name, Namespace: memcached.Namespace}, found) if err != nil { if errors.IsNotFound(err) { // Define and create a new deployment. - dep := r.deploymentForApp(app) - if err = r.Create(context.TODO(), dep); err != nil { + dep := r.deploymentForMemcached(memcached) + if err = r.Create(ctx, dep); err != nil { return ctrl.Result{}, err } return ctrl.Result{Requeue: true}, nil @@ -486,31 +501,31 @@ func (r *AppReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Resul } // Ensure the deployment size is the same as the spec. - size := app.Spec.Size + size := memcached.Spec.Size if *found.Spec.Replicas != size { found.Spec.Replicas = &size - if err = r.Update(context.TODO(), found); err != nil { + if err = r.Update(ctx, found); err != nil { return ctrl.Result{}, err } return ctrl.Result{Requeue: true}, nil } - // Update the App status with the pod names. - // List the pods for this app's deployment. + // Update the Memcached status with the pod names. + // List the pods for this CR's deployment. podList := &corev1.PodList{} listOpts := []client.ListOption{ - client.InNamespace(app.Namespace), - client.MatchingLabels(labelsForApp(app.Name)), + client.InNamespace(memcached.Namespace), + client.MatchingLabels(labelsForApp(memcached.Name)), } - if err = r.List(context.TODO(), podList, listOpts...); err != nil { + if err = r.List(ctx, podList, listOpts...); err != nil { return ctrl.Result{}, err } // Update status.Nodes if needed. podNames := getPodNames(podList.Items) - if !reflect.DeepEqual(podNames, app.Status.Nodes) { - app.Status.Nodes = podNames - if err := r.Status().Update(context.TODO(), app); err != nil { + if !reflect.DeepEqual(podNames, memcached.Status.Nodes) { + memcached.Status.Nodes = podNames + if err := r.Status().Update(ctx, memcached); err != nil { return ctrl.Result{}, err } } @@ -518,8 +533,8 @@ func (r *AppReconciler) Reconcile(context.Context, req ctrl.Request) (ctrl.Resul return ctrl.Request{}, nil } -// deploymentForApp returns a app Deployment object. -func (r *KindReconciler) deploymentForApp(m *appv1alpha1.App) *appsv1.Deployment { +// deploymentForMemcached returns a Deployment object for data from m. +func (r *MemcachedReconciler) deploymentForMemcached(m *cachev1alpha1.Memcached) *appsv1.Deployment { lbls := labelsForApp(m.Name) replicas := m.Spec.Size @@ -539,12 +554,12 @@ func (r *KindReconciler) deploymentForApp(m *appv1alpha1.App) *appsv1.Deployment }, Spec: corev1.PodSpec{ Containers: []corev1.Container{{ - Image: "app:alpine", - Name: "app", - Command: []string{"app", "-a=64", "-b"}, + Image: "memcached:alpine", + Name: "memcached", + Command: []string{"memcached", "-a=64", "-b"}, Ports: []corev1.ContainerPort{{ ContainerPort: 10000, - Name: "app", + Name: "memcached", }}, }}, }, @@ -552,21 +567,22 @@ func (r *KindReconciler) deploymentForApp(m *appv1alpha1.App) *appsv1.Deployment }, } - // Set App instance as the owner and controller. + // Set Memcached instance as the owner and controller.memcac // NOTE: calling SetControllerReference, and setting owner references in // general, is important as it allows deleted objects to be garbage collected. controllerutil.SetControllerReference(m, dep, r.scheme) return dep } -// labelsForApp creates a simple set of labels for App. +// labelsForApp creates a simple set of labels for Memcached. func labelsForApp(name string) map[string]string { - return map[string]string{"app_name": "app", "app_cr": name} + return map[string]string{"cr_name": name} } ``` +[memcached-testdata]:https://github.com/operator-framework/operator-sdk/tree/master/testdata/go/v3/memcached-operator [repo-controller-runtime]:https://github.com/kubernetes-sigs/controller-runtime -[doc-client-client]:https://godoc.org/github.com/kubernetes-sigs/controller-runtime/pkg/client#Client +[doc-client]:https://godoc.org/github.com/kubernetes-sigs/controller-runtime/pkg/client#Client [doc-split-client]:https://godoc.org/github.com/kubernetes-sigs/controller-runtime/pkg/client#DelegatingClient [doc-client-constr]:https://godoc.org/github.com/kubernetes-sigs/controller-runtime/pkg/client#New [code-scheme-default]:https://github.com/kubernetes-sigs/controller-runtime/blob/master/pkg/client/client.go#L51 diff --git a/website/content/en/docs/building-operators/golang/references/event-filtering.md b/website/content/en/docs/building-operators/golang/references/event-filtering.md index 3e46d122f1b..74efc9ebf56 100644 --- a/website/content/en/docs/building-operators/golang/references/event-filtering.md +++ b/website/content/en/docs/building-operators/golang/references/event-filtering.md @@ -66,7 +66,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/predicate" - cachev1alpha1 "github.com/example/app-operator/apis/cache/v1alpha1" + cachev1alpha1 "github.com/example/app-operator/api/v1alpha1" ) ... diff --git a/website/content/en/docs/building-operators/golang/tutorial.md b/website/content/en/docs/building-operators/golang/tutorial.md index 05786196115..f16fe9ba210 100644 --- a/website/content/en/docs/building-operators/golang/tutorial.md +++ b/website/content/en/docs/building-operators/golang/tutorial.md @@ -79,7 +79,7 @@ This will scaffold the Memcached resource API at `api/v1alpha1/memcached_types.g For an in-depth explanation of Kubernetes APIs and the group-version-kind model, check out these [kubebuilder docs][kb-doc-gkvs]. -In general, it's recommended to have one controller responsible for manage each API created for the project to +In general, it's recommended to have one controller responsible for manage each API created for the project to properly follow the design goals set by [controller-runtime][controller-runtime]. ### Define the API @@ -433,7 +433,7 @@ Next, try adding the following to your project: 1. Validating and mutating [admission webhooks][create_a_webhook]. 2. Operator packaging and distribution with [OLM][olm-integration]. -Also see the [advanced topics][advanced_topics] doc for more use cases and under the hood details. +Also see the [advanced topics][advanced_topics] doc for more use cases and under the hood details. [legacy-quickstart-doc]:https://v0-19-x.sdk.operatorframework.io/docs/golang/legacy/quickstart/ [migration-guide]:/docs/building-operators/golang/migration @@ -480,4 +480,4 @@ Also see the [advanced topics][advanced_topics] doc for more use cases and under [olm-integration]: /docs/olm-integration [openapi-validation]: /docs/building-operators/golang/references/openapi-validation [controller-runtime]: https://github.com/kubernetes-sigs/controller-runtime -[kb-doc-gkvs]: https://book.kubebuilder.io/cronjob-tutorial/gvks.html \ No newline at end of file +[kb-doc-gkvs]: https://book.kubebuilder.io/cronjob-tutorial/gvks.html From e3804a61b1f6675aa2b5eead7b8b990761175c8c Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Thu, 4 Feb 2021 02:08:54 +0100 Subject: [PATCH 303/376] upgrade Python to v 3.8 (#4413) * upgrade Python to v 3.8 * add change notes * add python to installation guide Signed-off-by: reinvantveer Signed-off-by: reinvantveer --- .../fragments/upgrade-python-on-ansible-operator.yaml | 11 +++++++++++ images/ansible-operator/Dockerfile | 4 ++-- .../docs/building-operators/ansible/installation.md | 3 ++- 3 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 changelog/fragments/upgrade-python-on-ansible-operator.yaml diff --git a/changelog/fragments/upgrade-python-on-ansible-operator.yaml b/changelog/fragments/upgrade-python-on-ansible-operator.yaml new file mode 100644 index 00000000000..bee48527ddc --- /dev/null +++ b/changelog/fragments/upgrade-python-on-ansible-operator.yaml @@ -0,0 +1,11 @@ +entries: + - description: > + For Ansible-based operators, the Python version has been updated + to a newer version, from 3.6 to 3.8 to take advantage of performance + improvements, language additions, security updates and generally + better availability for local development. + + kind: change + + # Is this a breaking change? + breaking: false diff --git a/images/ansible-operator/Dockerfile b/images/ansible-operator/Dockerfile index 8b0768dcb65..38731ca6679 100644 --- a/images/ansible-operator/Dockerfile +++ b/images/ansible-operator/Dockerfile @@ -15,7 +15,7 @@ ENV HOME=/opt/ansible \ # yum clean all && rm -rf /var/yum/cache/* first RUN yum clean all && rm -rf /var/cache/yum/* \ && yum -y update \ - && yum install -y libffi-devel openssl-devel python36-devel gcc python3-pip python3-setuptools \ + && yum install -y libffi-devel openssl-devel python38-devel gcc python38-pip python38-setuptools \ && pip3 install --no-cache-dir \ ansible-runner==1.3.4 \ ansible-runner-http==1.0.0 \ @@ -24,7 +24,7 @@ RUN yum clean all && rm -rf /var/cache/yum/* \ openshift==0.10.3 \ ansible==2.9.15 \ jmespath==0.10.0 \ - && yum remove -y gcc libffi-devel openssl-devel python36-devel \ + && yum remove -y gcc libffi-devel openssl-devel python38-devel \ && yum clean all \ && rm -rf /var/cache/yum diff --git a/website/content/en/docs/building-operators/ansible/installation.md b/website/content/en/docs/building-operators/ansible/installation.md index fdc5f5cdaed..5b3141b329a 100644 --- a/website/content/en/docs/building-operators/ansible/installation.md +++ b/website/content/en/docs/building-operators/ansible/installation.md @@ -9,7 +9,7 @@ weight: 1 Follow the steps in the [installation guide][install-guide] to learn how to install the `operator-sdk` CLI tool. ## Additional Prerequisites - +- [python][python] version 3.8.6+ - [ansible][ansible] version v2.9.0+ - [ansible-runner][ansible-runner] version v1.1.0+ - [ansible-runner-http][ansible-runner-http-plugin] version v1.0.0+ @@ -17,6 +17,7 @@ Follow the steps in the [installation guide][install-guide] to learn how to inst [install-guide]:/docs/installation/ +[python]:https://www.python.org/downloads/ [ansible]:https://docs.ansible.com/ansible/latest/index.html [ansible-runner]:https://ansible-runner.readthedocs.io/en/latest/install.html [ansible-runner-http-plugin]:https://github.com/ansible/ansible-runner-http From 2426b409cde8832c41836b1b907de77da83bb936 Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Wed, 3 Feb 2021 17:10:06 -0800 Subject: [PATCH 304/376] *: format finalizers correctly This commit modifies the suggested format for finalizers from . to /, which is the recommended format in k8s docs. This change is not breaking because technically any name format is allowed Signed-off-by: Eric Stroczynski Signed-off-by: reinvantveer --- .../fragments/change-finalizer-format.yaml | 12 +++++ .../samples/internal/ansible/constants.go | 2 +- internal/ansible/controller/reconcile.go | 49 ++++++------------- internal/ansible/controller/reconcile_test.go | 10 ++-- internal/ansible/runner/runner_test.go | 8 +-- .../watches/testdata/duplicate_gvk.yaml | 4 +- .../ansible/watches/testdata/invalid.yaml | 2 +- .../testdata/invalid_finalizer_no_vars.yaml | 2 +- .../invalid_finalizer_playbook_path.yaml | 2 +- .../testdata/invalid_finalizer_role_path.yaml | 2 +- .../testdata/invalid_playbook_path.yaml | 2 +- .../watches/testdata/invalid_role_path.yaml | 2 +- .../ansible/watches/testdata/valid.yaml.tmpl | 6 +-- internal/ansible/watches/watches_test.go | 6 +-- internal/helm/controller/reconcile.go | 33 ++++++------- test/e2e-ansible/e2e_ansible_suite_test.go | 2 +- .../ansible/reference/finalizers.md | 25 +++++----- .../ansible/reference/watches.md | 4 +- .../golang/advanced-topics.md | 2 +- 19 files changed, 84 insertions(+), 91 deletions(-) create mode 100644 changelog/fragments/change-finalizer-format.yaml diff --git a/changelog/fragments/change-finalizer-format.yaml b/changelog/fragments/change-finalizer-format.yaml new file mode 100644 index 00000000000..b2ea01b590f --- /dev/null +++ b/changelog/fragments/change-finalizer-format.yaml @@ -0,0 +1,12 @@ +entries: + - description: > + Changed the suggested finalizer format to `/` + kind: change + migration: + header: Change your operator's finalizer names + body: > + The finalizer name format suggested by [Kubernetes docs](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#finalizers) + is `/`, while the format previously documented by Operator SDK docs was + `.`. If your operator uses any finalizers with names matching the incorrect format, + change them to match the official format. + For example, `finalizer.cache.example.com` should be changed to `cache.example.com/finalizer`. diff --git a/hack/generate/samples/internal/ansible/constants.go b/hack/generate/samples/internal/ansible/constants.go index 0391156e332..6bdc7100c07 100644 --- a/hack/generate/samples/internal/ansible/constants.go +++ b/hack/generate/samples/internal/ansible/constants.go @@ -355,7 +355,7 @@ const taskToDeleteConfigMap = `- name: delete configmap for test const memcachedWatchCustomizations = `playbook: playbooks/memcached.yml finalizer: - name: finalizer.cache.example.com + name: cache.example.com/finalizer role: memfin blacklist: - group: "" diff --git a/internal/ansible/controller/reconcile.go b/internal/ansible/controller/reconcile.go index 9ba4488313b..4d87741ad79 100644 --- a/internal/ansible/controller/reconcile.go +++ b/internal/ansible/controller/reconcile.go @@ -32,6 +32,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/reconcile" @@ -100,22 +101,21 @@ func (r *AnsibleOperatorReconciler) Reconcile(ctx context.Context, request recon deleted := u.GetDeletionTimestamp() != nil finalizer, finalizerExists := r.Runner.GetFinalizer() - pendingFinalizers := u.GetFinalizers() - // If the resource is being deleted we don't want to add the finalizer again - if finalizerExists && !deleted && !contains(pendingFinalizers, finalizer) { - logger.V(1).Info("Adding finalizer to resource", "Finalizer", finalizer) - finalizers := append(pendingFinalizers, finalizer) - u.SetFinalizers(finalizers) - err := r.Client.Update(ctx, u) - if err != nil { - logger.Error(err, "Unable to update cr with finalizer") - return reconcileResult, err + if !controllerutil.ContainsFinalizer(u, finalizer) { + if deleted { + // If the resource is being deleted we don't want to add the finalizer again + logger.Info("Resource is terminated, skipping reconciliation") + return reconcile.Result{}, nil + } else if finalizerExists { + logger.V(1).Info("Adding finalizer to resource", "Finalizer", finalizer) + controllerutil.AddFinalizer(u, finalizer) + err := r.Client.Update(ctx, u) + if err != nil { + logger.Error(err, "Unable to update cr with finalizer") + return reconcileResult, err + } } } - if !contains(pendingFinalizers, finalizer) && deleted { - logger.Info("Resource is terminated, skipping reconciliation") - return reconcile.Result{}, nil - } spec := u.Object["spec"] _, ok := spec.(map[string]interface{}) @@ -240,22 +240,14 @@ func (r *AnsibleOperatorReconciler) Reconcile(ctx context.Context, request recon return reconcile.Result{}, err } - // try to get the updated finalizers - pendingFinalizers = u.GetFinalizers() - // We only want to update the CustomResource once, so we'll track changes // and do it at the end runSuccessful := len(failureMessages) == 0 // The finalizer has run successfully, time to remove it + deleted = u.GetDeletionTimestamp() != nil if deleted && finalizerExists && runSuccessful { - finalizers := []string{} - for _, pendingFinalizer := range pendingFinalizers { - if pendingFinalizer != finalizer { - finalizers = append(finalizers, pendingFinalizer) - } - } - u.SetFinalizers(finalizers) + controllerutil.RemoveFinalizer(u, finalizer) err := r.Client.Update(ctx, u) if err != nil { logger.Error(err, "Failed to remove finalizer") @@ -419,15 +411,6 @@ func (r *AnsibleOperatorReconciler) markDone(ctx context.Context, nn types.Names return r.Client.Status().Update(ctx, u) } -func contains(l []string, s string) bool { - for _, elem := range l { - if elem == s { - return true - } - } - return false -} - // getStatus returns u's "status" block as a status.Status. func getStatus(u *unstructured.Unstructured) ansiblestatus.Status { statusInterface := u.Object["status"] diff --git a/internal/ansible/controller/reconcile_test.go b/internal/ansible/controller/reconcile_test.go index e60a40bc5fb..9a5f8905f8a 100644 --- a/internal/ansible/controller/reconcile_test.go +++ b/internal/ansible/controller/reconcile_test.go @@ -258,7 +258,7 @@ func TestReconcile(t *testing.T) { Created: eventapi.EventTime{Time: eventTime}, }, }, - Finalizer: "testing.io", + Finalizer: "testing.io/finalizer", }, Client: fakeclient.NewClientBuilder().WithObjects(&unstructured.Unstructured{ Object: map[string]interface{}{ @@ -292,7 +292,7 @@ func TestReconcile(t *testing.T) { controller.ReconcilePeriodAnnotation: "3s", }, "finalizers": []interface{}{ - "testing.io", + "testing.io/finalizer", }, }, "apiVersion": "operator-sdk/v1beta1", @@ -329,7 +329,7 @@ func TestReconcile(t *testing.T) { Created: eventapi.EventTime{Time: eventTime}, }, }, - Finalizer: "testing.io", + Finalizer: "testing.io/finalizer", }, Client: fakeclient.NewClientBuilder().WithObjects(&unstructured.Unstructured{ Object: map[string]interface{}{ @@ -366,7 +366,7 @@ func TestReconcile(t *testing.T) { Created: eventapi.EventTime{Time: eventTime}, }, }, - Finalizer: "testing.io", + Finalizer: "testing.io/finalizer", }, Client: fakeclient.NewClientBuilder().WithObjects(&unstructured.Unstructured{ Object: map[string]interface{}{ @@ -374,7 +374,7 @@ func TestReconcile(t *testing.T) { "name": "reconcile", "namespace": "default", "finalizers": []interface{}{ - "testing.io", + "testing.io/finalizer", }, "deletionTimestamp": eventTime.Format(time.RFC3339), }, diff --git a/internal/ansible/runner/runner_test.go b/internal/ansible/runner/runner_test.go index 4133c1a8357..fa41031c5c4 100644 --- a/internal/ansible/runner/runner_test.go +++ b/internal/ansible/runner/runner_test.go @@ -93,7 +93,7 @@ func TestNew(t *testing.T) { }, playbook: validPlaybook, finalizer: &watches.Finalizer{ - Name: "example.finalizer.com", + Name: "operator.example.com/finalizer", Playbook: validPlaybook, }, }, @@ -106,7 +106,7 @@ func TestNew(t *testing.T) { }, role: validRole, finalizer: &watches.Finalizer{ - Name: "example.finalizer.com", + Name: "operator.example.com/finalizer", Role: validRole, }, }, @@ -119,7 +119,7 @@ func TestNew(t *testing.T) { }, playbook: validPlaybook, finalizer: &watches.Finalizer{ - Name: "example.finalizer.com", + Name: "operator.example.com/finalizer", Vars: map[string]interface{}{ "state": "absent", }, @@ -137,7 +137,7 @@ func TestNew(t *testing.T) { "type": "this", }, finalizer: &watches.Finalizer{ - Name: "example.finalizer.com", + Name: "operator.example.com/finalizer", Vars: map[string]interface{}{ "state": "absent", }, diff --git a/internal/ansible/watches/testdata/duplicate_gvk.yaml b/internal/ansible/watches/testdata/duplicate_gvk.yaml index 234883afcec..ce345bf6dcb 100644 --- a/internal/ansible/watches/testdata/duplicate_gvk.yaml +++ b/internal/ansible/watches/testdata/duplicate_gvk.yaml @@ -4,7 +4,7 @@ kind: Database playbook: playbook.yaml finalizer: - name: finalizer.app.example.com + name: app.example.com/finalizer vars: sentinel: finalizer_running - version: v1alpha1 @@ -12,6 +12,6 @@ kind: Database playbook: playbook.yaml finalizer: - name: finalizer.app.example.com + name: app.example.com/finalizer vars: sentinel: finalizer_running diff --git a/internal/ansible/watches/testdata/invalid.yaml b/internal/ansible/watches/testdata/invalid.yaml index 512c1514e2d..110371c4fa1 100644 --- a/internal/ansible/watches/testdata/invalid.yaml +++ b/internal/ansible/watches/testdata/invalid.yaml @@ -4,6 +4,6 @@ version: v1alpha1 kind: Database playbook: playbook.yaml finalizer: - name: finalizer.app.example.com + name: app.example.com/finalizer vars: sentinel: finalizer_running diff --git a/internal/ansible/watches/testdata/invalid_finalizer_no_vars.yaml b/internal/ansible/watches/testdata/invalid_finalizer_no_vars.yaml index 678203ea25a..bade2a38ed9 100644 --- a/internal/ansible/watches/testdata/invalid_finalizer_no_vars.yaml +++ b/internal/ansible/watches/testdata/invalid_finalizer_no_vars.yaml @@ -4,4 +4,4 @@ kind: Database playbook: playbook.yaml finalizer: - name: foo.app.example.com + name: foo.app.example.com/finalizer diff --git a/internal/ansible/watches/testdata/invalid_finalizer_playbook_path.yaml b/internal/ansible/watches/testdata/invalid_finalizer_playbook_path.yaml index 1c39ae92083..66d877570fa 100644 --- a/internal/ansible/watches/testdata/invalid_finalizer_playbook_path.yaml +++ b/internal/ansible/watches/testdata/invalid_finalizer_playbook_path.yaml @@ -4,7 +4,7 @@ kind: Database playbook: playbook.yaml finalizer: - name: finalizer.app.example.com + name: app.example.com/finalizer playbook: playbook.yaml vars: sentinel: finalizer_running diff --git a/internal/ansible/watches/testdata/invalid_finalizer_role_path.yaml b/internal/ansible/watches/testdata/invalid_finalizer_role_path.yaml index 653e523f9a9..a060604a588 100644 --- a/internal/ansible/watches/testdata/invalid_finalizer_role_path.yaml +++ b/internal/ansible/watches/testdata/invalid_finalizer_role_path.yaml @@ -4,7 +4,7 @@ kind: Database playbook: playbook.yaml finalizer: - name: finalizer.app.example.com + name: app.example.com/finalizer role: ansible/role vars: sentinel: finalizer_running diff --git a/internal/ansible/watches/testdata/invalid_playbook_path.yaml b/internal/ansible/watches/testdata/invalid_playbook_path.yaml index 12055fc97b6..9966a3ab8c2 100644 --- a/internal/ansible/watches/testdata/invalid_playbook_path.yaml +++ b/internal/ansible/watches/testdata/invalid_playbook_path.yaml @@ -4,6 +4,6 @@ kind: Database playbook: invalid/playbook.yaml finalizer: - name: finalizer.app.example.com + name: app.example.com/finalizer vars: sentinel: finalizer_running diff --git a/internal/ansible/watches/testdata/invalid_role_path.yaml b/internal/ansible/watches/testdata/invalid_role_path.yaml index 414f20d0513..8fb5d345596 100644 --- a/internal/ansible/watches/testdata/invalid_role_path.yaml +++ b/internal/ansible/watches/testdata/invalid_role_path.yaml @@ -4,6 +4,6 @@ kind: Database role: opt/ansible/playbook.yaml finalizer: - name: finalizer.app.example.com + name: app.example.com/finalizer vars: sentinel: finalizer_running diff --git a/internal/ansible/watches/testdata/valid.yaml.tmpl b/internal/ansible/watches/testdata/valid.yaml.tmpl index e3bcfc3a94a..4dd0a0ef90d 100644 --- a/internal/ansible/watches/testdata/valid.yaml.tmpl +++ b/internal/ansible/watches/testdata/valid.yaml.tmpl @@ -9,7 +9,7 @@ kind: Playbook playbook: {{ .ValidPlaybook }} finalizer: - name: finalizer.app.example.com + name: app.example.com/finalizer role: {{ .ValidRole }} vars: sentinel: finalizer_running @@ -43,7 +43,7 @@ kind: Role role: {{ .ValidRole }} finalizer: - name: finalizer.app.example.com + name: app.example.com/finalizer playbook: {{ .ValidPlaybook }} vars: sentinel: finalizer_running @@ -52,7 +52,7 @@ kind: FinalizerRole role: {{ .ValidRole }} finalizer: - name: finalizer.app.example.com + name: app.example.com/finalizer vars: sentinel: finalizer_running - version: v1alpha1 diff --git a/internal/ansible/watches/watches_test.go b/internal/ansible/watches/watches_test.go index f8fd47b05df..509eef9ae2c 100644 --- a/internal/ansible/watches/watches_test.go +++ b/internal/ansible/watches/watches_test.go @@ -160,7 +160,7 @@ func TestLoad(t *testing.T) { //nolint:gocyclo SnakeCaseParameters: false, WatchClusterScopedResources: false, Finalizer: &Finalizer{ - Name: "finalizer.app.example.com", + Name: "app.example.com/finalizer", Role: validTemplate.ValidRole, Vars: map[string]interface{}{"sentinel": "finalizer_running"}, }, @@ -223,7 +223,7 @@ func TestLoad(t *testing.T) { //nolint:gocyclo Role: validTemplate.ValidRole, ManageStatus: true, Finalizer: &Finalizer{ - Name: "finalizer.app.example.com", + Name: "app.example.com/finalizer", Playbook: validTemplate.ValidPlaybook, Vars: map[string]interface{}{"sentinel": "finalizer_running"}, }, @@ -237,7 +237,7 @@ func TestLoad(t *testing.T) { //nolint:gocyclo Role: validTemplate.ValidRole, ManageStatus: true, Finalizer: &Finalizer{ - Name: "finalizer.app.example.com", + Name: "app.example.com/finalizer", Vars: map[string]interface{}{"sentinel": "finalizer_running"}, }, }, diff --git a/internal/helm/controller/reconcile.go b/internal/helm/controller/reconcile.go index 0b731321b66..644b6f89e54 100644 --- a/internal/helm/controller/reconcile.go +++ b/internal/helm/controller/reconcile.go @@ -56,7 +56,10 @@ type HelmOperatorReconciler struct { } const ( - finalizer = "uninstall-helm-release" + // uninstallFinalizer is added to CRs so they are cleaned up after uninstalling a release. + uninstallFinalizer = "helm.sdk.operatorframework.io/uninstall-release" + // Deprecated: use uninstallFinalizer. This will be removed in operator-sdk v2.0.0. + uninstallFinalizerLegacy = "uninstall-helm-release" ) // Reconcile reconciles the requested resource by installing, updating, or @@ -96,7 +99,9 @@ func (r HelmOperatorReconciler) Reconcile(ctx context.Context, request reconcile log = log.WithValues("release", manager.ReleaseName()) if o.GetDeletionTimestamp() != nil { - if !contains(o.GetFinalizers(), finalizer) { + if !(controllerutil.ContainsFinalizer(o, uninstallFinalizer) || + controllerutil.ContainsFinalizer(o, uninstallFinalizerLegacy)) { + log.Info("Resource is terminated, skipping reconciliation") return reconcile.Result{}, nil } @@ -136,7 +141,8 @@ func (r HelmOperatorReconciler) Reconcile(ctx context.Context, request reconcile return reconcile.Result{}, err } - controllerutil.RemoveFinalizer(o, finalizer) + controllerutil.RemoveFinalizer(o, uninstallFinalizer) + controllerutil.RemoveFinalizer(o, uninstallFinalizerLegacy) if err := r.updateResource(ctx, o); err != nil { log.Info("Failed to remove CR uninstall finalizer") return reconcile.Result{}, err @@ -195,8 +201,8 @@ func (r HelmOperatorReconciler) Reconcile(ctx context.Context, request reconcile } status.RemoveCondition(types.ConditionReleaseFailed) - log.V(1).Info("Adding finalizer", "finalizer", finalizer) - controllerutil.AddFinalizer(o, finalizer) + log.V(1).Info("Adding finalizer", "finalizer", uninstallFinalizer) + controllerutil.AddFinalizer(o, uninstallFinalizer) if err := r.updateResource(ctx, o); err != nil { log.Info("Failed to add CR uninstall finalizer") return reconcile.Result{}, err @@ -232,9 +238,11 @@ func (r HelmOperatorReconciler) Reconcile(ctx context.Context, request reconcile return reconcile.Result{RequeueAfter: r.ReconcilePeriod}, err } - if !contains(o.GetFinalizers(), finalizer) { - log.V(1).Info("Adding finalizer", "finalizer", finalizer) - controllerutil.AddFinalizer(o, finalizer) + if !(controllerutil.ContainsFinalizer(o, uninstallFinalizer) || + controllerutil.ContainsFinalizer(o, uninstallFinalizerLegacy)) { + + log.V(1).Info("Adding finalizer", "finalizer", uninstallFinalizer) + controllerutil.AddFinalizer(o, uninstallFinalizer) if err := r.updateResource(ctx, o); err != nil { log.Info("Failed to add CR uninstall finalizer") return reconcile.Result{}, err @@ -394,12 +402,3 @@ func (r HelmOperatorReconciler) waitForDeletion(ctx context.Context, o client.Ob return false, nil }, tctx.Done()) } - -func contains(l []string, s string) bool { - for _, elem := range l { - if elem == s { - return true - } - } - return false -} diff --git a/test/e2e-ansible/e2e_ansible_suite_test.go b/test/e2e-ansible/e2e_ansible_suite_test.go index 6f008e158d9..894d1f8fbc5 100644 --- a/test/e2e-ansible/e2e_ansible_suite_test.go +++ b/test/e2e-ansible/e2e_ansible_suite_test.go @@ -190,7 +190,7 @@ const taskToDeleteConfigMap = `- name: delete configmap for test const memcachedWatchCustomizations = `playbook: playbooks/memcached.yml finalizer: - name: finalizer.cache.example.com + name: cache.example.com/finalizer role: memfin blacklist: - group: "" diff --git a/website/content/en/docs/building-operators/ansible/reference/finalizers.md b/website/content/en/docs/building-operators/ansible/reference/finalizers.md index f86a8d368c7..c424b6372b6 100644 --- a/website/content/en/docs/building-operators/ansible/reference/finalizers.md +++ b/website/content/en/docs/building-operators/ansible/reference/finalizers.md @@ -9,7 +9,7 @@ created during reconciliation when a managed resource is marked for deletion. Th behavior is usually sufficient for applications that exist only in Kubernetes, but sometimes it is necessary to perform more complex operations (for example, when your action performed against a third party API needs to be undone). These more -complex cases can still be handled by Ansible Operator, through the use of a finalizer. +complex cases can still be handled by Ansible Operator, through the use of a [finalizer][doc-crd-finalizers]. Finalizers allow controllers (such as an Ansible Operator) to implement asynchronous pre-delete hooks. This allows custom logic to run after a resource has been marked for deletion, but @@ -20,18 +20,19 @@ define the mapping from your finalizer to a playbook or role by simply setting t your top-level playbook or role with different variables set. The `watches.yaml` finalizer configuration accepts the following options: -See [Ansible watches documentation][ansible-watches] for more -information. +See [Ansible watches documentation][ansible-watches] for more information. #### name + `name` is required. This is the name of the finalizer. This is basically an arbitrary string, the existence of any finalizer string on a resource will prevent that resource from being deleted until the finalizer is removed. Ansible Operator will remove this string from the list of finalizers on successful execution of the specified role or playbook. A typical finalizer -will be `finalizer.`, where `` is the group of the resource being managed. +will be `/finalizer`, where `` is the fully qualified group +of the resource being managed. #### playbook @@ -71,7 +72,7 @@ Here are a few examples of `watches.yaml` files that specify a finalizer: kind: Database playbook: /opt/ansible/playbook.yml finalizer: - name: finalizer.app.example.com + name: app.example.com/finalizer vars: state: absent ``` @@ -87,7 +88,7 @@ the author can check this value and perform whatever cleanup is necessary. kind: Database role: database finalizer: - name: finalizer.app.example.com + name: app.example.com/finalizer vars: state: absent ``` @@ -103,7 +104,7 @@ role, rather than a playbook, with the `state` variable set to `absent`. kind: Database playbook: playbook.yml finalizer: - name: finalizer.app.example.com + name: app.example.com/finalizer role: teardown_database ``` @@ -116,7 +117,7 @@ This example will run the `/opt/ansible/roles/teardown_database` role when the C kind: Database playbook: playbook.yml finalizer: - name: finalizer.app.example.com + name: app.example.com/finalizer playbook: destroy.yml ``` @@ -129,7 +130,7 @@ This example will run the `/opt/ansible/destroy.yml` playbook when the Custom Re kind: Database playbook: playbook.yml finalizer: - name: finalizer.app.example.com + name: app.example.com/finalizer role: myNamespace.myCollection.myRole ``` @@ -150,7 +151,7 @@ interaction, with a different variable set. kind: Database playbook: playbook.yml finalizer: - name: finalizer.app.example.com + name: app.example.com/finalizer role: manage_credentials vars: state: revoked @@ -165,7 +166,5 @@ causes the role to invalidate our credentials. For everything else in our applic automatic deletion of dependent resources will be sufficient, so we can exit successfully and let the operator remove our finalizer and allow the resource to be deleted. -## Further reading -• [Kubernetes finalizers](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#finalizers) - +[doc-crd-finalizers]:https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#finalizers [ansible-watches]:/docs/building-operators/ansible/reference/watches/ diff --git a/website/content/en/docs/building-operators/ansible/reference/watches.md b/website/content/en/docs/building-operators/ansible/reference/watches.md index e98f4f36fb0..4e89081ef75 100644 --- a/website/content/en/docs/building-operators/ansible/reference/watches.md +++ b/website/content/en/docs/building-operators/ansible/reference/watches.md @@ -121,7 +121,7 @@ Some features can be overridden per resource via an annotation on that CR. The o watchDependentResources: False snakeCaseParameters: False finalizer: - name: finalizer.app.example.com + name: app.example.com/finalizer vars: state: absent ``` @@ -141,7 +141,7 @@ Some features can be overridden per resource via an annotation on that CR. The o manageStatus: False watchDependentResources: False finalizer: - name: finalizer.app.example.com + name: app.example.com/finalizer vars: state: absent diff --git a/website/content/en/docs/building-operators/golang/advanced-topics.md b/website/content/en/docs/building-operators/golang/advanced-topics.md index 8567aee1a35..306b5857537 100644 --- a/website/content/en/docs/building-operators/golang/advanced-topics.md +++ b/website/content/en/docs/building-operators/golang/advanced-topics.md @@ -135,7 +135,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" ) -const memcachedFinalizer = "finalizer.cache.example.com" +const memcachedFinalizer = "cache.example.com/finalizer" func (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { reqLogger := r.log.WithValues("memcached", req.NamespacedName) From eacef4193d46b410ff030adc3b45dc113f01151a Mon Sep 17 00:00:00 2001 From: Jesus Rodriguez Date: Wed, 3 Feb 2021 20:40:51 -0500 Subject: [PATCH 305/376] Fixed invalid object names generated for long package names (#4471) * Fixed invalid object names generated for long package names * TrimDNS1123Label would trim strings but end up creating invalid DNS1123 strings. * FormatOperatorNameDNS1123 would return strings that were invalid if they begin or end with non-alphanumeric or hyphens. * Handle capitals and use more efficient trim mechanism * React to new expectation. Fixes #4470 Signed-off-by: jesus m. rodriguez Signed-off-by: reinvantveer --- .../fix-trim-format-dns1123-functions.yaml | 8 ++ .../registry/configmap/deployment_test.go | 6 +- internal/util/k8sutil/k8sutil.go | 8 +- internal/util/k8sutil/k8sutil_test.go | 92 +++++++++++++++++++ 4 files changed, 109 insertions(+), 5 deletions(-) create mode 100644 changelog/fragments/fix-trim-format-dns1123-functions.yaml diff --git a/changelog/fragments/fix-trim-format-dns1123-functions.yaml b/changelog/fragments/fix-trim-format-dns1123-functions.yaml new file mode 100644 index 00000000000..2c2896ea2a4 --- /dev/null +++ b/changelog/fragments/fix-trim-format-dns1123-functions.yaml @@ -0,0 +1,8 @@ +entries: + - description: > + Fixed invalid object names generated for long package names passed + to `run packagemanifests` & `run bundle`. + + kind: "bugfix" + + breaking: false diff --git a/internal/olm/operator/registry/configmap/deployment_test.go b/internal/olm/operator/registry/configmap/deployment_test.go index 5b73cdf9760..a97e1a47428 100644 --- a/internal/olm/operator/registry/configmap/deployment_test.go +++ b/internal/olm/operator/registry/configmap/deployment_test.go @@ -28,9 +28,9 @@ var _ = Describe("Deployment", func() { Describe("getRegistryServerName", func() { It("should return the formatted servername", func() { - Expect(getRegistryServerName("pkgName")).Should(Equal("pkgName-registry-server")) + Expect(getRegistryServerName("pkgName")).Should(Equal("pkgname-registry-server")) // This checks if all the special characters are handled correctly - Expect(getRegistryServerName("$abc.foo$@(&#(&!*)@&#")).Should(Equal("-abc-foo--registry-server")) + Expect(getRegistryServerName("$abc.foo$@(&#(&!*)@&#")).Should(Equal("abc-foo-registry-server")) }) }) @@ -39,7 +39,7 @@ var _ = Describe("Deployment", func() { labels := map[string]string{ "owner": "operator-sdk", "package-name": "$abc.foo$@(&#(&!*)@&#", - "server-name": "-abc-foo--registry-server", + "server-name": "abc-foo-registry-server", } Expect(getRegistryDeploymentLabels("$abc.foo$@(&#(&!*)@&#")).Should(Equal(labels)) diff --git a/internal/util/k8sutil/k8sutil.go b/internal/util/k8sutil/k8sutil.go index 9fe23a6c865..297fffa80a2 100644 --- a/internal/util/k8sutil/k8sutil.go +++ b/internal/util/k8sutil/k8sutil.go @@ -93,7 +93,11 @@ var dns1123LabelRegexp = regexp.MustCompile("[^a-zA-Z0-9]+") // replacing all non-compliant UTF-8 characters with "-". func FormatOperatorNameDNS1123(name string) string { if len(validation.IsDNS1123Label(name)) != 0 { - return dns1123LabelRegexp.ReplaceAllString(name, "-") + // Use - for any of the non-matching characters + n := dns1123LabelRegexp.ReplaceAllString(name, "-") + + // Now let's remove any leading or trailing - + return strings.ToLower(strings.Trim(n, "-")) } return name } @@ -102,7 +106,7 @@ func FormatOperatorNameDNS1123(name string) string { // by removing characters from the beginning of label such that len(label) <= 63. func TrimDNS1123Label(label string) string { if len(label) > validation.DNS1123LabelMaxLength { - return label[len(label)-validation.DNS1123LabelMaxLength:] + return strings.Trim(label[len(label)-validation.DNS1123LabelMaxLength:], "-") } return label } diff --git a/internal/util/k8sutil/k8sutil_test.go b/internal/util/k8sutil/k8sutil_test.go index 9fcdcbaadc6..21b6690885d 100644 --- a/internal/util/k8sutil/k8sutil_test.go +++ b/internal/util/k8sutil/k8sutil_test.go @@ -240,3 +240,95 @@ func TestSupportsOwnerReference(t *testing.T) { }) } } + +func TestTrimDNS1123Label(t *testing.T) { + type testcase struct { + name string + label string + expected string + } + testcases := []testcase{ + { + name: "return valid truncated values", + label: "quay-io-raffaelespazzoli-proactive-node-scaling-operator-bundle-latest", + expected: "raffaelespazzoli-proactive-node-scaling-operator-bundle-latest", + }, + { + name: "valid labels with proper length are noops", + label: "raffaelespazzoli-proactive-node-scaling-operator-bundle-latest", + expected: "raffaelespazzoli-proactive-node-scaling-operator-bundle-latest", + }, + { + name: "short invalid labels are left alone", + label: "-$*@*#fixed-invalid(__$)@+==-name-#$($", + expected: "-$*@*#fixed-invalid(__$)@+==-name-#$($", + }, + } + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + result := TrimDNS1123Label(tc.label) + assert.Equal(t, tc.expected, result) + }) + } +} + +func TestFormatOperatorNameDNS1123(t *testing.T) { + type testcase struct { + name string + label string + expected string + } + testcases := []testcase{ + { + name: "should not start with -", + label: "-doesnot-start-with-hyphen", + expected: "doesnot-start-with-hyphen", + }, + { + name: "should not start with non-alphanumeric", + label: "$@*#(@does-notstart-garbage", + expected: "does-notstart-garbage", + }, + { + name: "should not have non-alphanumeric", + label: "sample-1234$@*#(@does-notstart-garbage", + expected: "sample-1234-does-notstart-garbage", + }, + { + name: "should not end with non-alphanumeric", + label: "sample-1234-does-notstart-garbage#$*@#*($_!-_@(", + expected: "sample-1234-does-notstart-garbage", + }, + { + name: "should not start or end with hyphen", + label: "-does-not-start-or-end-with-hyphen---", + expected: "does-not-start-or-end-with-hyphen", + }, + { + name: "empty string is a noop", + label: "", + expected: "", + }, + { + name: "string of invalid characters results in empty string", + label: "@#@#)$*!!_$#*$*!@", + expected: "", + }, + { + name: "valid long names are not trimmed", + label: "quay-io-raffaelespazzoli-proactive-node-scaling-operator-bundle-latest", + expected: "quay-io-raffaelespazzoli-proactive-node-scaling-operator-bundle-latest", + }, + { + name: "should not contain capital letters", + label: "QUAY-IO-gobble-gobBLE", + expected: "quay-io-gobble-gobble", + }, + } + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + result := FormatOperatorNameDNS1123(tc.label) + assert.Equal(t, tc.expected, result) + }) + } +} From 9d4e3104e119dd06216f9bbf4a027f3cd08afc20 Mon Sep 17 00:00:00 2001 From: Jesus Rodriguez Date: Thu, 4 Feb 2021 07:32:12 -0500 Subject: [PATCH 306/376] *: Replace 'docker build . -t ${IMG}' with '-t ${IMG} .' (#4466) Because folks may have 'docker' aliased to 'podman', and Podman prefers options before positional arguments: $ podman build --help | grep CONTEXT-DIRECTORY podman build [command options] CONTEXT-DIRECTORY | URL We can't change the v2 sample since it still uses the old format. Co-authored-by: W. Trevor King Signed-off-by: jesus m. rodriguez Co-authored-by: W. Trevor King Signed-off-by: reinvantveer --- changelog/fragments/reorder-docker-args.yaml | 28 +++++++++++++++++++ .../scaffolds/internal/templates/makefile.go | 2 +- .../scaffolds/internal/templates/makefile.go | 2 +- testdata/ansible/memcached-operator/Makefile | 2 +- testdata/helm/memcached-operator/Makefile | 2 +- 5 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 changelog/fragments/reorder-docker-args.yaml diff --git a/changelog/fragments/reorder-docker-args.yaml b/changelog/fragments/reorder-docker-args.yaml new file mode 100644 index 00000000000..aacf029b7f7 --- /dev/null +++ b/changelog/fragments/reorder-docker-args.yaml @@ -0,0 +1,28 @@ +# entries is a list of entries to include in +# release notes and/or the migration guide +entries: + - description: > + (ansible/v1, helm/v1) Post-fixed positional directory argument `.` in `docker-build` make target to align with `podman` + kind: "change" + breaking: false + + # Migration can be defined to automatically add a section to + # the migration guide. This is required for breaking changes. + migration: + header: Move positional directory argument `.` in `docker-build` make target + body: > + The directory argument `.` in the `docker-build` make target was moved to the + last positional argument to align with `podman`'s expectations, making substitution + cleaner. In your `Makefile`, change: + + docker build . -t ${IMG} + + to + docker build -t ${IMG} . + + Alternatively, you could replace it programmatically + + ```sh + sed -i 's/docker build . -t ${IMG}/docker build -t ${IMG} ./' $(git grep -l 'docker.*build \. ') + ``` + diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/makefile.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/makefile.go index fcf32617f41..f5a4c6c2b37 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/makefile.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/makefile.go @@ -93,7 +93,7 @@ undeploy: kustomize # Build the docker image docker-build: - docker build . -t ${IMG} + docker build -t ${IMG} . # Push the docker image docker-push: diff --git a/internal/plugins/helm/v1/scaffolds/internal/templates/makefile.go b/internal/plugins/helm/v1/scaffolds/internal/templates/makefile.go index c530b16970d..7fa3fa3a75e 100644 --- a/internal/plugins/helm/v1/scaffolds/internal/templates/makefile.go +++ b/internal/plugins/helm/v1/scaffolds/internal/templates/makefile.go @@ -93,7 +93,7 @@ undeploy: kustomize # Build the docker image docker-build: - docker build . -t ${IMG} + docker build -t ${IMG} . # Push the docker image docker-push: diff --git a/testdata/ansible/memcached-operator/Makefile b/testdata/ansible/memcached-operator/Makefile index f667456f0f1..8a74f8d6f47 100644 --- a/testdata/ansible/memcached-operator/Makefile +++ b/testdata/ansible/memcached-operator/Makefile @@ -56,7 +56,7 @@ undeploy: kustomize # Build the docker image docker-build: - docker build . -t ${IMG} + docker build -t ${IMG} . # Push the docker image docker-push: diff --git a/testdata/helm/memcached-operator/Makefile b/testdata/helm/memcached-operator/Makefile index a23f8fca9e6..4d3c17c7ec4 100644 --- a/testdata/helm/memcached-operator/Makefile +++ b/testdata/helm/memcached-operator/Makefile @@ -56,7 +56,7 @@ undeploy: kustomize # Build the docker image docker-build: - docker build . -t ${IMG} + docker build -t ${IMG} . # Push the docker image docker-push: From 8ff8780b8b0479fa78d64f605aec88e21f2733bc Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Thu, 4 Feb 2021 12:09:23 -0800 Subject: [PATCH 307/376] update IMAGE_VERSION to v1.4.0 (#4484) Signed-off-by: Eric Stroczynski Signed-off-by: reinvantveer --- Makefile | 2 +- testdata/ansible/memcached-operator/Dockerfile | 2 +- testdata/ansible/memcached-operator/Makefile | 2 +- .../bundle/tests/scorecard/config.yaml | 12 ++++++------ .../config/scorecard/patches/basic.config.yaml | 2 +- .../config/scorecard/patches/olm.config.yaml | 10 +++++----- .../bundle/tests/scorecard/config.yaml | 12 ++++++------ .../config/scorecard/patches/basic.config.yaml | 2 +- .../config/scorecard/patches/olm.config.yaml | 10 +++++----- .../bundle/tests/scorecard/config.yaml | 12 ++++++------ .../config/scorecard/patches/basic.config.yaml | 2 +- .../config/scorecard/patches/olm.config.yaml | 10 +++++----- testdata/helm/memcached-operator/Dockerfile | 2 +- testdata/helm/memcached-operator/Makefile | 2 +- .../bundle/tests/scorecard/config.yaml | 12 ++++++------ .../config/scorecard/patches/basic.config.yaml | 2 +- .../config/scorecard/patches/olm.config.yaml | 10 +++++----- 17 files changed, 53 insertions(+), 53 deletions(-) diff --git a/Makefile b/Makefile index 1a23bf53681..814e457fc09 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ SHELL = /bin/bash # This value must be updated to the release tag of the most recent release, a change that must # occur in the release commit. IMAGE_VERSION will be removed once each subproject that uses this # version is moved to a separate repo and release process. -export IMAGE_VERSION = v1.3.0 +export IMAGE_VERSION = v1.4.0 # Build-time variables to inject into binaries export SIMPLE_VERSION = $(shell (test "$(shell git describe)" = "$(shell git describe --abbrev=0)" && echo $(shell git describe)) || echo $(shell git describe --abbrev=0)+git) export GIT_VERSION = $(shell git describe --dirty --tags --always) diff --git a/testdata/ansible/memcached-operator/Dockerfile b/testdata/ansible/memcached-operator/Dockerfile index 96a41837c53..572eebf86d9 100644 --- a/testdata/ansible/memcached-operator/Dockerfile +++ b/testdata/ansible/memcached-operator/Dockerfile @@ -1,4 +1,4 @@ -FROM quay.io/operator-framework/ansible-operator:v1.3.0 +FROM quay.io/operator-framework/ansible-operator:v1.4.0 COPY requirements.yml ${HOME}/requirements.yml RUN ansible-galaxy collection install -r ${HOME}/requirements.yml \ diff --git a/testdata/ansible/memcached-operator/Makefile b/testdata/ansible/memcached-operator/Makefile index 8a74f8d6f47..e9f22276580 100644 --- a/testdata/ansible/memcached-operator/Makefile +++ b/testdata/ansible/memcached-operator/Makefile @@ -93,7 +93,7 @@ ifeq (,$(shell which ansible-operator 2>/dev/null)) @{ \ set -e ;\ mkdir -p $(dir $(ANSIBLE_OPERATOR)) ;\ - curl -sSLo $(ANSIBLE_OPERATOR) https://github.com/operator-framework/operator-sdk/releases/download/v1.3.0/ansible-operator_$(OS)_$(ARCH) ;\ + curl -sSLo $(ANSIBLE_OPERATOR) https://github.com/operator-framework/operator-sdk/releases/download/v1.4.0/ansible-operator_$(OS)_$(ARCH) ;\ chmod +x $(ANSIBLE_OPERATOR) ;\ } else diff --git a/testdata/ansible/memcached-operator/bundle/tests/scorecard/config.yaml b/testdata/ansible/memcached-operator/bundle/tests/scorecard/config.yaml index 11a06ffe7fe..96b1dbba325 100644 --- a/testdata/ansible/memcached-operator/bundle/tests/scorecard/config.yaml +++ b/testdata/ansible/memcached-operator/bundle/tests/scorecard/config.yaml @@ -8,42 +8,42 @@ stages: - entrypoint: - scorecard-test - basic-check-spec - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: basic test: basic-check-spec-test - entrypoint: - scorecard-test - olm-bundle-validation - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-bundle-validation-test - entrypoint: - scorecard-test - olm-crds-have-validation - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-crds-have-validation-test - entrypoint: - scorecard-test - olm-crds-have-resources - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-crds-have-resources-test - entrypoint: - scorecard-test - olm-spec-descriptors - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-spec-descriptors-test - entrypoint: - scorecard-test - olm-status-descriptors - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-status-descriptors-test diff --git a/testdata/ansible/memcached-operator/config/scorecard/patches/basic.config.yaml b/testdata/ansible/memcached-operator/config/scorecard/patches/basic.config.yaml index d4347861781..4581edc9b02 100644 --- a/testdata/ansible/memcached-operator/config/scorecard/patches/basic.config.yaml +++ b/testdata/ansible/memcached-operator/config/scorecard/patches/basic.config.yaml @@ -4,7 +4,7 @@ entrypoint: - scorecard-test - basic-check-spec - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: basic test: basic-check-spec-test diff --git a/testdata/ansible/memcached-operator/config/scorecard/patches/olm.config.yaml b/testdata/ansible/memcached-operator/config/scorecard/patches/olm.config.yaml index 890bf0572a3..94226814303 100644 --- a/testdata/ansible/memcached-operator/config/scorecard/patches/olm.config.yaml +++ b/testdata/ansible/memcached-operator/config/scorecard/patches/olm.config.yaml @@ -4,7 +4,7 @@ entrypoint: - scorecard-test - olm-bundle-validation - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-bundle-validation-test @@ -14,7 +14,7 @@ entrypoint: - scorecard-test - olm-crds-have-validation - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-crds-have-validation-test @@ -24,7 +24,7 @@ entrypoint: - scorecard-test - olm-crds-have-resources - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-crds-have-resources-test @@ -34,7 +34,7 @@ entrypoint: - scorecard-test - olm-spec-descriptors - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-spec-descriptors-test @@ -44,7 +44,7 @@ entrypoint: - scorecard-test - olm-status-descriptors - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-status-descriptors-test diff --git a/testdata/go/v2/memcached-operator/bundle/tests/scorecard/config.yaml b/testdata/go/v2/memcached-operator/bundle/tests/scorecard/config.yaml index 11a06ffe7fe..96b1dbba325 100644 --- a/testdata/go/v2/memcached-operator/bundle/tests/scorecard/config.yaml +++ b/testdata/go/v2/memcached-operator/bundle/tests/scorecard/config.yaml @@ -8,42 +8,42 @@ stages: - entrypoint: - scorecard-test - basic-check-spec - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: basic test: basic-check-spec-test - entrypoint: - scorecard-test - olm-bundle-validation - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-bundle-validation-test - entrypoint: - scorecard-test - olm-crds-have-validation - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-crds-have-validation-test - entrypoint: - scorecard-test - olm-crds-have-resources - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-crds-have-resources-test - entrypoint: - scorecard-test - olm-spec-descriptors - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-spec-descriptors-test - entrypoint: - scorecard-test - olm-status-descriptors - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-status-descriptors-test diff --git a/testdata/go/v2/memcached-operator/config/scorecard/patches/basic.config.yaml b/testdata/go/v2/memcached-operator/config/scorecard/patches/basic.config.yaml index d4347861781..4581edc9b02 100644 --- a/testdata/go/v2/memcached-operator/config/scorecard/patches/basic.config.yaml +++ b/testdata/go/v2/memcached-operator/config/scorecard/patches/basic.config.yaml @@ -4,7 +4,7 @@ entrypoint: - scorecard-test - basic-check-spec - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: basic test: basic-check-spec-test diff --git a/testdata/go/v2/memcached-operator/config/scorecard/patches/olm.config.yaml b/testdata/go/v2/memcached-operator/config/scorecard/patches/olm.config.yaml index 890bf0572a3..94226814303 100644 --- a/testdata/go/v2/memcached-operator/config/scorecard/patches/olm.config.yaml +++ b/testdata/go/v2/memcached-operator/config/scorecard/patches/olm.config.yaml @@ -4,7 +4,7 @@ entrypoint: - scorecard-test - olm-bundle-validation - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-bundle-validation-test @@ -14,7 +14,7 @@ entrypoint: - scorecard-test - olm-crds-have-validation - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-crds-have-validation-test @@ -24,7 +24,7 @@ entrypoint: - scorecard-test - olm-crds-have-resources - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-crds-have-resources-test @@ -34,7 +34,7 @@ entrypoint: - scorecard-test - olm-spec-descriptors - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-spec-descriptors-test @@ -44,7 +44,7 @@ entrypoint: - scorecard-test - olm-status-descriptors - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-status-descriptors-test diff --git a/testdata/go/v3/memcached-operator/bundle/tests/scorecard/config.yaml b/testdata/go/v3/memcached-operator/bundle/tests/scorecard/config.yaml index 11a06ffe7fe..96b1dbba325 100644 --- a/testdata/go/v3/memcached-operator/bundle/tests/scorecard/config.yaml +++ b/testdata/go/v3/memcached-operator/bundle/tests/scorecard/config.yaml @@ -8,42 +8,42 @@ stages: - entrypoint: - scorecard-test - basic-check-spec - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: basic test: basic-check-spec-test - entrypoint: - scorecard-test - olm-bundle-validation - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-bundle-validation-test - entrypoint: - scorecard-test - olm-crds-have-validation - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-crds-have-validation-test - entrypoint: - scorecard-test - olm-crds-have-resources - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-crds-have-resources-test - entrypoint: - scorecard-test - olm-spec-descriptors - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-spec-descriptors-test - entrypoint: - scorecard-test - olm-status-descriptors - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-status-descriptors-test diff --git a/testdata/go/v3/memcached-operator/config/scorecard/patches/basic.config.yaml b/testdata/go/v3/memcached-operator/config/scorecard/patches/basic.config.yaml index d4347861781..4581edc9b02 100644 --- a/testdata/go/v3/memcached-operator/config/scorecard/patches/basic.config.yaml +++ b/testdata/go/v3/memcached-operator/config/scorecard/patches/basic.config.yaml @@ -4,7 +4,7 @@ entrypoint: - scorecard-test - basic-check-spec - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: basic test: basic-check-spec-test diff --git a/testdata/go/v3/memcached-operator/config/scorecard/patches/olm.config.yaml b/testdata/go/v3/memcached-operator/config/scorecard/patches/olm.config.yaml index 890bf0572a3..94226814303 100644 --- a/testdata/go/v3/memcached-operator/config/scorecard/patches/olm.config.yaml +++ b/testdata/go/v3/memcached-operator/config/scorecard/patches/olm.config.yaml @@ -4,7 +4,7 @@ entrypoint: - scorecard-test - olm-bundle-validation - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-bundle-validation-test @@ -14,7 +14,7 @@ entrypoint: - scorecard-test - olm-crds-have-validation - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-crds-have-validation-test @@ -24,7 +24,7 @@ entrypoint: - scorecard-test - olm-crds-have-resources - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-crds-have-resources-test @@ -34,7 +34,7 @@ entrypoint: - scorecard-test - olm-spec-descriptors - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-spec-descriptors-test @@ -44,7 +44,7 @@ entrypoint: - scorecard-test - olm-status-descriptors - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-status-descriptors-test diff --git a/testdata/helm/memcached-operator/Dockerfile b/testdata/helm/memcached-operator/Dockerfile index 2bc9187976d..8de2979dceb 100644 --- a/testdata/helm/memcached-operator/Dockerfile +++ b/testdata/helm/memcached-operator/Dockerfile @@ -1,5 +1,5 @@ # Build the manager binary -FROM quay.io/operator-framework/helm-operator:v1.3.0 +FROM quay.io/operator-framework/helm-operator:v1.4.0 ENV HOME=/opt/helm COPY watches.yaml ${HOME}/watches.yaml diff --git a/testdata/helm/memcached-operator/Makefile b/testdata/helm/memcached-operator/Makefile index 4d3c17c7ec4..b9dbb0eb202 100644 --- a/testdata/helm/memcached-operator/Makefile +++ b/testdata/helm/memcached-operator/Makefile @@ -93,7 +93,7 @@ ifeq (,$(shell which helm-operator 2>/dev/null)) @{ \ set -e ;\ mkdir -p $(dir $(HELM_OPERATOR)) ;\ - curl -sSLo $(HELM_OPERATOR) https://github.com/operator-framework/operator-sdk/releases/download/v1.3.0/helm-operator_$(OS)_$(ARCH) ;\ + curl -sSLo $(HELM_OPERATOR) https://github.com/operator-framework/operator-sdk/releases/download/v1.4.0/helm-operator_$(OS)_$(ARCH) ;\ chmod +x $(HELM_OPERATOR) ;\ } else diff --git a/testdata/helm/memcached-operator/bundle/tests/scorecard/config.yaml b/testdata/helm/memcached-operator/bundle/tests/scorecard/config.yaml index 11a06ffe7fe..96b1dbba325 100644 --- a/testdata/helm/memcached-operator/bundle/tests/scorecard/config.yaml +++ b/testdata/helm/memcached-operator/bundle/tests/scorecard/config.yaml @@ -8,42 +8,42 @@ stages: - entrypoint: - scorecard-test - basic-check-spec - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: basic test: basic-check-spec-test - entrypoint: - scorecard-test - olm-bundle-validation - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-bundle-validation-test - entrypoint: - scorecard-test - olm-crds-have-validation - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-crds-have-validation-test - entrypoint: - scorecard-test - olm-crds-have-resources - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-crds-have-resources-test - entrypoint: - scorecard-test - olm-spec-descriptors - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-spec-descriptors-test - entrypoint: - scorecard-test - olm-status-descriptors - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-status-descriptors-test diff --git a/testdata/helm/memcached-operator/config/scorecard/patches/basic.config.yaml b/testdata/helm/memcached-operator/config/scorecard/patches/basic.config.yaml index d4347861781..4581edc9b02 100644 --- a/testdata/helm/memcached-operator/config/scorecard/patches/basic.config.yaml +++ b/testdata/helm/memcached-operator/config/scorecard/patches/basic.config.yaml @@ -4,7 +4,7 @@ entrypoint: - scorecard-test - basic-check-spec - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: basic test: basic-check-spec-test diff --git a/testdata/helm/memcached-operator/config/scorecard/patches/olm.config.yaml b/testdata/helm/memcached-operator/config/scorecard/patches/olm.config.yaml index 890bf0572a3..94226814303 100644 --- a/testdata/helm/memcached-operator/config/scorecard/patches/olm.config.yaml +++ b/testdata/helm/memcached-operator/config/scorecard/patches/olm.config.yaml @@ -4,7 +4,7 @@ entrypoint: - scorecard-test - olm-bundle-validation - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-bundle-validation-test @@ -14,7 +14,7 @@ entrypoint: - scorecard-test - olm-crds-have-validation - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-crds-have-validation-test @@ -24,7 +24,7 @@ entrypoint: - scorecard-test - olm-crds-have-resources - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-crds-have-resources-test @@ -34,7 +34,7 @@ entrypoint: - scorecard-test - olm-spec-descriptors - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-spec-descriptors-test @@ -44,7 +44,7 @@ entrypoint: - scorecard-test - olm-status-descriptors - image: quay.io/operator-framework/scorecard-test:v1.3.0 + image: quay.io/operator-framework/scorecard-test:v1.4.0 labels: suite: olm test: olm-status-descriptors-test From 99f45757a3c3720873f86662647d00f6929dbb6d Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Thu, 4 Feb 2021 12:55:36 -0800 Subject: [PATCH 308/376] Release v1.4.0 (#4486) Signed-off-by: Eric Stroczynski Signed-off-by: reinvantveer --- .../bugfix-generate-no-project-name.yaml | 4 - .../fragments/bugfix-run-bundle-upgrade.yaml | 4 - .../fragments/bugfix-validate-add-mode.yaml | 5 - .../fragments/change-finalizer-format.yaml | 12 -- .../fragments/csv-gen-package-aware.yaml | 6 - ...x-bundle-validate-failure-on-warnings.yaml | 6 - .../fragments/fix-bundle-validate-panic.yaml | 4 - changelog/fragments/fix-mac-m1.yaml | 3 - .../fix-trim-format-dns1123-functions.yaml | 8 -- .../helm-ansible-download-makefile.yaml | 18 --- changelog/fragments/helm-uninstall-fix.yaml | 4 - ...erator_fix_helm_keep_annotated_delete.yaml | 5 - changelog/fragments/kuttl-v0.8.0.yaml | 4 - ...liveness_readiness_probe_for_operator.yaml | 91 ------------ changelog/fragments/phase-2-plugin-keys.yaml | 48 ------- .../fragments/pin-docker-base-images.yaml | 12 -- changelog/fragments/reorder-docker-args.yaml | 28 ---- .../upgrade-python-on-ansible-operator.yaml | 11 -- changelog/generated/v1.4.0.md | 36 +++++ website/config.toml | 4 + .../en/docs/upgrading-sdk-version/v1.4.0.md | 129 ++++++++++++++++++ 21 files changed, 169 insertions(+), 273 deletions(-) delete mode 100644 changelog/fragments/bugfix-generate-no-project-name.yaml delete mode 100644 changelog/fragments/bugfix-run-bundle-upgrade.yaml delete mode 100644 changelog/fragments/bugfix-validate-add-mode.yaml delete mode 100644 changelog/fragments/change-finalizer-format.yaml delete mode 100644 changelog/fragments/csv-gen-package-aware.yaml delete mode 100644 changelog/fragments/fix-bundle-validate-failure-on-warnings.yaml delete mode 100644 changelog/fragments/fix-bundle-validate-panic.yaml delete mode 100644 changelog/fragments/fix-mac-m1.yaml delete mode 100644 changelog/fragments/fix-trim-format-dns1123-functions.yaml delete mode 100644 changelog/fragments/helm-ansible-download-makefile.yaml delete mode 100644 changelog/fragments/helm-uninstall-fix.yaml delete mode 100644 changelog/fragments/helm_operator_fix_helm_keep_annotated_delete.yaml delete mode 100644 changelog/fragments/kuttl-v0.8.0.yaml delete mode 100644 changelog/fragments/liveness_readiness_probe_for_operator.yaml delete mode 100644 changelog/fragments/phase-2-plugin-keys.yaml delete mode 100644 changelog/fragments/pin-docker-base-images.yaml delete mode 100644 changelog/fragments/reorder-docker-args.yaml delete mode 100644 changelog/fragments/upgrade-python-on-ansible-operator.yaml create mode 100644 changelog/generated/v1.4.0.md create mode 100644 website/content/en/docs/upgrading-sdk-version/v1.4.0.md diff --git a/changelog/fragments/bugfix-generate-no-project-name.yaml b/changelog/fragments/bugfix-generate-no-project-name.yaml deleted file mode 100644 index 41032f33e86..00000000000 --- a/changelog/fragments/bugfix-generate-no-project-name.yaml +++ /dev/null @@ -1,4 +0,0 @@ -entries: - - description: > - Project version now determines how package name is retrieved for a project - kind: bugfix diff --git a/changelog/fragments/bugfix-run-bundle-upgrade.yaml b/changelog/fragments/bugfix-run-bundle-upgrade.yaml deleted file mode 100644 index af0a6ccf6e9..00000000000 --- a/changelog/fragments/bugfix-run-bundle-upgrade.yaml +++ /dev/null @@ -1,4 +0,0 @@ -entries: - - description: > - `run bundle-upgrade` handles error gracefully when a previous operator version doesn't exist - kind: bugfix diff --git a/changelog/fragments/bugfix-validate-add-mode.yaml b/changelog/fragments/bugfix-validate-add-mode.yaml deleted file mode 100644 index dc5578c3bff..00000000000 --- a/changelog/fragments/bugfix-validate-add-mode.yaml +++ /dev/null @@ -1,5 +0,0 @@ -entries: - - description: > - `run bundle` and `run bundle-upgrade` now validate the value passed to the hidden flag `--mode` before - running a bundle. - kind: bugfix diff --git a/changelog/fragments/change-finalizer-format.yaml b/changelog/fragments/change-finalizer-format.yaml deleted file mode 100644 index b2ea01b590f..00000000000 --- a/changelog/fragments/change-finalizer-format.yaml +++ /dev/null @@ -1,12 +0,0 @@ -entries: - - description: > - Changed the suggested finalizer format to `/` - kind: change - migration: - header: Change your operator's finalizer names - body: > - The finalizer name format suggested by [Kubernetes docs](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#finalizers) - is `/`, while the format previously documented by Operator SDK docs was - `.`. If your operator uses any finalizers with names matching the incorrect format, - change them to match the official format. - For example, `finalizer.cache.example.com` should be changed to `cache.example.com/finalizer`. diff --git a/changelog/fragments/csv-gen-package-aware.yaml b/changelog/fragments/csv-gen-package-aware.yaml deleted file mode 100644 index 85715ed46a9..00000000000 --- a/changelog/fragments/csv-gen-package-aware.yaml +++ /dev/null @@ -1,6 +0,0 @@ -entries: - - description: > - For Go-based projects, `generate ` subcommands now consider package and type names - when parsing Go API types files to generate a CSV's `owned.customresourcedefinitions`, such that types in - different packages and files will not overwrite each other. - kind: bugfix diff --git a/changelog/fragments/fix-bundle-validate-failure-on-warnings.yaml b/changelog/fragments/fix-bundle-validate-failure-on-warnings.yaml deleted file mode 100644 index a48643e8f46..00000000000 --- a/changelog/fragments/fix-bundle-validate-failure-on-warnings.yaml +++ /dev/null @@ -1,6 +0,0 @@ -entries: - - description: > - Bump operator-framework/api to fix "operator-sdk bundle validate" failure when bundle has warnings. - When a warning is detected during validation it should be logged to the CLI but the validation should still pass. - kind: bugfix - breaking: false diff --git a/changelog/fragments/fix-bundle-validate-panic.yaml b/changelog/fragments/fix-bundle-validate-panic.yaml deleted file mode 100644 index 9164ad2d352..00000000000 --- a/changelog/fragments/fix-bundle-validate-panic.yaml +++ /dev/null @@ -1,4 +0,0 @@ -entries: - - description: Fix panic when "operator-sdk bundle validate" fails - kind: bugfix - breaking: false diff --git a/changelog/fragments/fix-mac-m1.yaml b/changelog/fragments/fix-mac-m1.yaml deleted file mode 100644 index 7b61dcf5b59..00000000000 --- a/changelog/fragments/fix-mac-m1.yaml +++ /dev/null @@ -1,3 +0,0 @@ -entries: - - description: Update containerd dependency to correctly handle running the Operator SDK CLI on Apple Silicon. - kind: bugfix diff --git a/changelog/fragments/fix-trim-format-dns1123-functions.yaml b/changelog/fragments/fix-trim-format-dns1123-functions.yaml deleted file mode 100644 index 2c2896ea2a4..00000000000 --- a/changelog/fragments/fix-trim-format-dns1123-functions.yaml +++ /dev/null @@ -1,8 +0,0 @@ -entries: - - description: > - Fixed invalid object names generated for long package names passed - to `run packagemanifests` & `run bundle`. - - kind: "bugfix" - - breaking: false diff --git a/changelog/fragments/helm-ansible-download-makefile.yaml b/changelog/fragments/helm-ansible-download-makefile.yaml deleted file mode 100644 index 7de2f2cb411..00000000000 --- a/changelog/fragments/helm-ansible-download-makefile.yaml +++ /dev/null @@ -1,18 +0,0 @@ -entries: - - description: > - Corrected the download URL for helm-operator and ansible-operator in their respective project types. - kind: bugfix - migration: - header: For Helm and Ansible projects, fix the helm-operator and ansible-operator URLs in the Makefile - body: > - Helm projects: `https://github.com/operator-framework/operator-sdk/releases/download/v1.3.0/helm-operator-v1.3.0-$(ARCHOPER)-$(OSOPER)` - -> `https://github.com/operator-framework/operator-sdk/releases/download/v1.3.0/helm-operator_$(OS)_$(ARCH)` - Ansible projects: `https://github.com/operator-framework/operator-sdk/releases/download/v1.3.0/ansible-operator-v1.3.0-$(ARCHOPER)-$(OSOPER)` - -> `https://github.com/operator-framework/operator-sdk/releases/download/v1.3.0/ansible-operator_$(OS)_$(ARCH)` - - description: > - Fixed the order of helm-operator, ansible-operator, and kustomize binary checks in the Makefile. - kind: bugfix - migration: - header: For Helm and Ansible projects, fix the helm-operator, ansible-operator, and kustomize Makefile rules - body: > - See the diff in [this PR](https://github.com/operator-framework/operator-sdk/pull/4407) for details. diff --git a/changelog/fragments/helm-uninstall-fix.yaml b/changelog/fragments/helm-uninstall-fix.yaml deleted file mode 100644 index e8b6ce88518..00000000000 --- a/changelog/fragments/helm-uninstall-fix.yaml +++ /dev/null @@ -1,4 +0,0 @@ -entries: - - description: Fixed a bug that caused the Helm operator to remove the finalizer without doing a helm uninstall. - kind: "bugfix" - breaking: false \ No newline at end of file diff --git a/changelog/fragments/helm_operator_fix_helm_keep_annotated_delete.yaml b/changelog/fragments/helm_operator_fix_helm_keep_annotated_delete.yaml deleted file mode 100644 index 203f7341939..00000000000 --- a/changelog/fragments/helm_operator_fix_helm_keep_annotated_delete.yaml +++ /dev/null @@ -1,5 +0,0 @@ -entries: - - description: > - For Helm-based operators, do not add owner references to resources that contain the Helm annotation: 'helm.sh/resource-policy: keep'. - kind: bugfix - breaking: false \ No newline at end of file diff --git a/changelog/fragments/kuttl-v0.8.0.yaml b/changelog/fragments/kuttl-v0.8.0.yaml deleted file mode 100644 index 07421adb0d7..00000000000 --- a/changelog/fragments/kuttl-v0.8.0.yaml +++ /dev/null @@ -1,4 +0,0 @@ -entries: - - description: > - Upgraded the `kudobuilder/kuttl` base image version in the `scorecard-test-kuttl` image to v0.8.0 - kind: change diff --git a/changelog/fragments/liveness_readiness_probe_for_operator.yaml b/changelog/fragments/liveness_readiness_probe_for_operator.yaml deleted file mode 100644 index dfe7df56210..00000000000 --- a/changelog/fragments/liveness_readiness_probe_for_operator.yaml +++ /dev/null @@ -1,91 +0,0 @@ -# entries is a list of entries to include in -# release notes and/or the migration guide -entries: - - description: > - For Helm-based operators, added Liveness and Readiness probe by default using [`healthz.Ping`](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/healthz#CheckHandler). - - # kind is one of: - # - addition - # - change - # - deprecation - # - removal - # - bugfix - kind: "addition" - - # Is this a breaking change? - breaking: false - - # Migration can be defined to automatically add a section to - # the migration guide. This is required for breaking changes. - migration: - header: (Optional) For Helm-based operators, add Liveness and Readiness probe - body: > - New projects built with the tool will have the probes configured by default. The endpoints `/healthz` and - `/readyz` are available now in the image based provided. - - You can update your pre-existing project to use them. For that update the Dockerfile to use the latest - release base image, then add the following to the `manager` container in - `config/default/manager/manager.yaml`: - - ```yaml - livenessProbe: - httpGet: - path: /healthz - port: 8081 - initialDelaySeconds: 15 - periodSeconds: 20 - readinessProbe: - httpGet: - path: /readyz - port: 8081 - initialDelaySeconds: 5 - periodSeconds: 10 - ``` - - description: > - For Ansible-based operators, added Liveness and Readiness probe by default using [`healthz.Ping`](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/healthz#CheckHandler). - - # kind is one of: - # - addition - # - change - # - deprecation - # - removal - # - bugfix - kind: "addition" - - # Is this a breaking change? - breaking: false - - # Migration can be defined to automatically add a section to - # the migration guide. This is required for breaking changes. - migration: - header: (Optional) For Ansible-based operators, add Liveness and Readiness probe - body: > - New projects built with the tool will have the probes configured by default. The endpoints `/healthz` and - `/readyz` are available now in the image based provided. - - You can update your pre-existing project to use them. For that update the Dockerfile to use the latest - release base image, then add the following to the `manager` container in - `config/default/manager/manager.yaml`: - - ```yaml - livenessProbe: - httpGet: - path: /healthz - port: 6789 - initialDelaySeconds: 15 - periodSeconds: 20 - readinessProbe: - httpGet: - path: /readyz - port: 6789 - initialDelaySeconds: 5 - periodSeconds: 10 - ``` - - description: > - For Ansible-based operators, the `/ping` endpoint is deprecated. Use `/healthz` instead. - kind: "deprecation" - breaking: false - - - description: > - For Ansible/Helm-based operators, added new flag `--health-probe-bind-address` to set the health probe address. - kind: "addition" diff --git a/changelog/fragments/phase-2-plugin-keys.yaml b/changelog/fragments/phase-2-plugin-keys.yaml deleted file mode 100644 index c13517a1a2d..00000000000 --- a/changelog/fragments/phase-2-plugin-keys.yaml +++ /dev/null @@ -1,48 +0,0 @@ -entries: - - description: > - (go/v2) Changed `go` PROJECT plugin object to `manifests` and `scorecard` objects (`.sdk.operatorframework.io` suffix) - kind: change - breaking: false - migration: - header: (go/v2) Change `go` PROJECT plugin object to `manifests` and `scorecard` objects - body: > - The `manifests` and `scorecard` plugins that create OLM and scorecard manifests, respectively, - now have plugin objects that direct `create` subcommands to create related files. - While the old `go` plugin configuration object is still supported, these new objects will be useful - in the future as configuration options are added to their respective plugins: - - Old: - ```yaml - version: 3-alpha - ... - plugins: - go.sdk.operatorframework.io/v2-alpha: {} - ``` - - New: - ```yaml - version: 3-alpha - ... - plugins: - manifests.sdk.operatorframework.io/v2: {} - scorecard.sdk.operatorframework.io/v2: {} - ``` - - - description: > - (ansible/v1, helm/v1) Added plugin objects for the `manifests` and `scorecard` phase 2 plugins - kind: addition - migration: - header: (ansible/v1, helm/v1) Add `manifests` and `scorecard` plugin objects to your PROJECT - body: > - The `manifests` and `scorecard` plugins that create OLM and scorecard manifests, respectively, - now have plugin objects that direct `create` subcommands to create related files. While not necessary - to add, these new plugin configuration objects in the PROJECT file will be useful in the future - as configuration options are added to their respective plugins: - - ```yaml - version: 3-alpha - ... - plugins: - manifests.sdk.operatorframework.io/v2: {} - scorecard.sdk.operatorframework.io/v2: {} - ``` diff --git a/changelog/fragments/pin-docker-base-images.yaml b/changelog/fragments/pin-docker-base-images.yaml deleted file mode 100644 index 3ed740c7529..00000000000 --- a/changelog/fragments/pin-docker-base-images.yaml +++ /dev/null @@ -1,12 +0,0 @@ -# entries is a list of entries to include in -# release notes and/or the migration guide -entries: - - description: > - For Ansible-based and Helm-based operators, as well as for the - Operator SDK and the (custom) scorecard tests, the Docker base images - are pinned to improve the reproducibility of builds using Docker. - - kind: addition - - # Is this a breaking change? - breaking: false diff --git a/changelog/fragments/reorder-docker-args.yaml b/changelog/fragments/reorder-docker-args.yaml deleted file mode 100644 index aacf029b7f7..00000000000 --- a/changelog/fragments/reorder-docker-args.yaml +++ /dev/null @@ -1,28 +0,0 @@ -# entries is a list of entries to include in -# release notes and/or the migration guide -entries: - - description: > - (ansible/v1, helm/v1) Post-fixed positional directory argument `.` in `docker-build` make target to align with `podman` - kind: "change" - breaking: false - - # Migration can be defined to automatically add a section to - # the migration guide. This is required for breaking changes. - migration: - header: Move positional directory argument `.` in `docker-build` make target - body: > - The directory argument `.` in the `docker-build` make target was moved to the - last positional argument to align with `podman`'s expectations, making substitution - cleaner. In your `Makefile`, change: - - docker build . -t ${IMG} - - to - docker build -t ${IMG} . - - Alternatively, you could replace it programmatically - - ```sh - sed -i 's/docker build . -t ${IMG}/docker build -t ${IMG} ./' $(git grep -l 'docker.*build \. ') - ``` - diff --git a/changelog/fragments/upgrade-python-on-ansible-operator.yaml b/changelog/fragments/upgrade-python-on-ansible-operator.yaml deleted file mode 100644 index bee48527ddc..00000000000 --- a/changelog/fragments/upgrade-python-on-ansible-operator.yaml +++ /dev/null @@ -1,11 +0,0 @@ -entries: - - description: > - For Ansible-based operators, the Python version has been updated - to a newer version, from 3.6 to 3.8 to take advantage of performance - improvements, language additions, security updates and generally - better availability for local development. - - kind: change - - # Is this a breaking change? - breaking: false diff --git a/changelog/generated/v1.4.0.md b/changelog/generated/v1.4.0.md new file mode 100644 index 00000000000..7479040517b --- /dev/null +++ b/changelog/generated/v1.4.0.md @@ -0,0 +1,36 @@ +## v1.4.0 + +### Additions + +- For Helm-based operators, added Liveness and Readiness probe by default using [`healthz.Ping`](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/healthz#CheckHandler). ([#4326](https://github.com/operator-framework/operator-sdk/pull/4326)) +- For Ansible-based operators, added Liveness and Readiness probe by default using [`healthz.Ping`](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/healthz#CheckHandler). ([#4326](https://github.com/operator-framework/operator-sdk/pull/4326)) +- For Ansible/Helm-based operators, added new flag `--health-probe-bind-address` to set the health probe address. ([#4326](https://github.com/operator-framework/operator-sdk/pull/4326)) +- (ansible/v1, helm/v1) Added plugin objects for the `manifests` and `scorecard` phase 2 plugins. ([#4419](https://github.com/operator-framework/operator-sdk/pull/4419)) +- For Ansible-based and Helm-based operators, as well as for the Operator SDK and the (custom) scorecard tests, the Docker base images are pinned to improve the reproducibility of builds using Docker. ([#4417](https://github.com/operator-framework/operator-sdk/pull/4417)) + +### Changes + +- Changed the suggested finalizer format to `/`. ([#4472](https://github.com/operator-framework/operator-sdk/pull/4472)) +- Upgraded the `kudobuilder/kuttl` base image version in the `scorecard-test-kuttl` image to v0.8.0. ([#4391](https://github.com/operator-framework/operator-sdk/pull/4391)) +- (go/v2) Changed `go` PROJECT plugin object to `manifests` and `scorecard` objects (`.sdk.operatorframework.io` suffix). ([#4419](https://github.com/operator-framework/operator-sdk/pull/4419)) +- (ansible/v1, helm/v1) Post-fixed positional directory argument `.` in `docker-build` make target to align with `podman`. ([#4466](https://github.com/operator-framework/operator-sdk/pull/4466)) +- For Ansible-based operators, the Python version has been updated to a newer version, from 3.6 to 3.8 to take advantage of performance improvements, language additions, security updates and generally better availability for local development. ([#4413](https://github.com/operator-framework/operator-sdk/pull/4413)) + +### Deprecations + +- For Ansible-based operators, the `/ping` endpoint is deprecated. Use `/healthz` instead. ([#4326](https://github.com/operator-framework/operator-sdk/pull/4326)) + +### Bug Fixes + +- Project version now determines how package name is retrieved for a project. ([#4431](https://github.com/operator-framework/operator-sdk/pull/4431)) +- `run bundle-upgrade` now handles error gracefully when a previous operator version doesn't exist. ([#4451](https://github.com/operator-framework/operator-sdk/pull/4451)) +- `run bundle` and `run bundle-upgrade` now validate the value passed to the hidden flag `--mode` before running a bundle. ([#4462](https://github.com/operator-framework/operator-sdk/pull/4462)) +- For Go-based projects, `generate ` subcommands now consider package and type names when parsing Go API types files to generate a CSV's `owned.customresourcedefinitions`, such that types in different packages and files will not overwrite each other. ([#4445](https://github.com/operator-framework/operator-sdk/pull/4445)) +- Bumped operator-framework/api to prevent `operator-sdk bundle validate` from exiting non-0 when validation emits only warnings. ([#4458](https://github.com/operator-framework/operator-sdk/pull/4458)) +- Fixed panic when "operator-sdk bundle validate" fails. ([#4386](https://github.com/operator-framework/operator-sdk/pull/4386)) +- Update containerd dependency to correctly handle running the Operator SDK CLI on Apple Silicon. ([#4359](https://github.com/operator-framework/operator-sdk/pull/4359)) +- Fixed invalid object names generated for long package names passed to `run packagemanifests` & `run bundle`. ([#4471](https://github.com/operator-framework/operator-sdk/pull/4471)) +- Corrected the download URL for helm-operator and ansible-operator in their respective project types. ([#4407](https://github.com/operator-framework/operator-sdk/pull/4407)) +- Fixed the order of helm-operator, ansible-operator, and kustomize binary checks in the Makefile. ([#4407](https://github.com/operator-framework/operator-sdk/pull/4407)) +- Fixed a bug that caused the Helm operator to remove the finalizer without doing a helm uninstall. ([#3431](https://github.com/operator-framework/operator-sdk/pull/3431)) +- For Helm-based operators, do not add owner references to resources that contain the Helm annotation: 'helm.sh/resource-policy: keep'. ([#4389](https://github.com/operator-framework/operator-sdk/pull/4389)) diff --git a/website/config.toml b/website/config.toml index 751512ab200..35cbcf6981a 100644 --- a/website/config.toml +++ b/website/config.toml @@ -96,6 +96,10 @@ algolia_docsearch = false ##RELEASE_ADDME## +[[params.versions]] + version = "v1.4" + url = "https://v1-4-x.sdk.operatorframework.io" + [[params.versions]] version = "v1.3" url = "https://v1-3-x.sdk.operatorframework.io" diff --git a/website/content/en/docs/upgrading-sdk-version/v1.4.0.md b/website/content/en/docs/upgrading-sdk-version/v1.4.0.md new file mode 100644 index 00000000000..75c8cc9a5fc --- /dev/null +++ b/website/content/en/docs/upgrading-sdk-version/v1.4.0.md @@ -0,0 +1,129 @@ +--- +title: v1.4.0 +weight: 998996000 +--- + +## Change your operator's finalizer names + +The finalizer name format suggested by [Kubernetes docs](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#finalizers) is `/`, while the format previously documented by Operator SDK docs was `.`. If your operator uses any finalizers with names matching the incorrect format, change them to match the official format. For example, `finalizer.cache.example.com` should be changed to `cache.example.com/finalizer`. + +_See [#4472](https://github.com/operator-framework/operator-sdk/pull/4472) for more details._ + +## For Helm and Ansible projects, fix the helm-operator and ansible-operator URLs in the Makefile + +- Helm projects: + Old: `https://github.com/operator-framework/operator-sdk/releases/download/v1.3.0/helm-operator-v1.3.0-$(ARCHOPER)-$(OSOPER)` + New: `https://github.com/operator-framework/operator-sdk/releases/download/v1.3.1/helm-operator_$(OS)_$(ARCH)` +- Ansible projects: + Old: `https://github.com/operator-framework/operator-sdk/releases/download/v1.3.0/ansible-operator-v1.3.0-$(ARCHOPER)-$(OSOPER)` + New: `https://github.com/operator-framework/operator-sdk/releases/download/v1.3.1/ansible-operator_$(OS)_$(ARCH)` + +_See [#4407](https://github.com/operator-framework/operator-sdk/pull/4407) for more details._ + +## For Helm and Ansible projects, fix the `helm-operator`, `ansible-operator`, and `kustomize` Makefile rules + +These rules will download a local binary but not use it if a global binary is present. +See the diff in [this PR](https://github.com/operator-framework/operator-sdk/pull/4407) for how to fix this. + +_See [#4412](https://github.com/operator-framework/operator-sdk/pull/4407) for more details._ + +## For Helm-based operators, add Liveness and Readiness probe + +New projects built with the tool will have the probes configured by default. The endpoints `/healthz` and `/readyz` are available now in the image based provided. +You can update your pre-existing project to use them. For that update the Dockerfile to use the latest release base image, then add the following to the `manager` container in `config/default/manager/manager.yaml`: +```yaml + livenessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 15 + periodSeconds: 20 + readinessProbe: + httpGet: + path: /readyz + port: 8081 + initialDelaySeconds: 5 + periodSeconds: 10 +``` + +_See [#4326](https://github.com/operator-framework/operator-sdk/pull/4326) for more details._ + +## For Ansible-based operators, add Liveness and Readiness probe + +New projects built with the tool will have the probes configured by default. The endpoints `/healthz` and `/readyz` are available now in the image based provided. +You can update your pre-existing project to use them. For that update the Dockerfile to use the latest release base image, then add the following to the `manager` container in `config/default/manager/manager.yaml`: +```yaml + livenessProbe: + httpGet: + path: /healthz + port: 6789 + initialDelaySeconds: 15 + periodSeconds: 20 + readinessProbe: + httpGet: + path: /readyz + port: 6789 + initialDelaySeconds: 5 + periodSeconds: 10 +``` + +_See [#4326](https://github.com/operator-framework/operator-sdk/pull/4326) for more details._ + +## (go/v2) Change `go` PROJECT plugin object to `manifests` and `scorecard` objects + +The `manifests` and `scorecard` plugins that create OLM and scorecard manifests, respectively, now have plugin objects that direct `create` subcommands to create related files. While the old `go` plugin configuration object is still supported, these new objects will be useful in the future as configuration options are added to their respective plugins: + +Old: +```yaml +version: 3-alpha +... +plugins: + go.sdk.operatorframework.io/v2-alpha: {} +``` + +New: +```yaml +version: 3-alpha +... +plugins: + manifests.sdk.operatorframework.io/v2: {} + scorecard.sdk.operatorframework.io/v2: {} +``` + +_See [#4419](https://github.com/operator-framework/operator-sdk/pull/4419) for more details._ + +## (ansible/v1, helm/v1) Add `manifests` and `scorecard` plugin objects to your PROJECT + +The `manifests` and `scorecard` plugins that create OLM and scorecard manifests, respectively, now have plugin objects that direct `create` subcommands to create related files. While not necessary to add, these new plugin configuration objects in the PROJECT file will be useful in the future as configuration options are added to their respective plugins: +```yaml +version: 3-alpha +... +plugins: + manifests.sdk.operatorframework.io/v2: {} + scorecard.sdk.operatorframework.io/v2: {} +``` + +_See [#4419](https://github.com/operator-framework/operator-sdk/pull/4419) for more details._ + +## Move positional directory argument `.` in `docker-build` make target + +The directory argument `.` in the `docker-build` make target was moved to the last positional argument to align with `podman`'s expectations, making substitution cleaner. + +Old: +```make +docker-build: + docker build . -t ${IMG} +``` + +New: +```make +docker-build: + docker build -t ${IMG} . +``` + +Alternatively, you could replace it programmatically +```sh +sed -i 's/docker build . -t ${IMG}/docker build -t ${IMG} ./' $(git grep -l 'docker.*build \. ') +``` + +_See [#4466](https://github.com/operator-framework/operator-sdk/pull/4466) for more details._ From 13101b428b38d426b545f5cb2831bed469429797 Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Wed, 20 Jan 2021 11:20:07 -0800 Subject: [PATCH 309/376] (helm/v1,ansible/v1) fix download URLs and order of binary checks (#4407) Signed-off-by: Eric Stroczynski Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- .../helm-ansible-download-makefile.yaml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 changelog/fragments/helm-ansible-download-makefile.yaml diff --git a/changelog/fragments/helm-ansible-download-makefile.yaml b/changelog/fragments/helm-ansible-download-makefile.yaml new file mode 100644 index 00000000000..7de2f2cb411 --- /dev/null +++ b/changelog/fragments/helm-ansible-download-makefile.yaml @@ -0,0 +1,18 @@ +entries: + - description: > + Corrected the download URL for helm-operator and ansible-operator in their respective project types. + kind: bugfix + migration: + header: For Helm and Ansible projects, fix the helm-operator and ansible-operator URLs in the Makefile + body: > + Helm projects: `https://github.com/operator-framework/operator-sdk/releases/download/v1.3.0/helm-operator-v1.3.0-$(ARCHOPER)-$(OSOPER)` + -> `https://github.com/operator-framework/operator-sdk/releases/download/v1.3.0/helm-operator_$(OS)_$(ARCH)` + Ansible projects: `https://github.com/operator-framework/operator-sdk/releases/download/v1.3.0/ansible-operator-v1.3.0-$(ARCHOPER)-$(OSOPER)` + -> `https://github.com/operator-framework/operator-sdk/releases/download/v1.3.0/ansible-operator_$(OS)_$(ARCH)` + - description: > + Fixed the order of helm-operator, ansible-operator, and kustomize binary checks in the Makefile. + kind: bugfix + migration: + header: For Helm and Ansible projects, fix the helm-operator, ansible-operator, and kustomize Makefile rules + body: > + See the diff in [this PR](https://github.com/operator-framework/operator-sdk/pull/4407) for details. From a818447757bbb77af168eb4d0816a0f3fefb5045 Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Wed, 27 Jan 2021 08:31:00 -0800 Subject: [PATCH 310/376] generate: respect project version when getting package name (#4431) Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- changelog/fragments/bugfix-generate-no-project-name.yaml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 changelog/fragments/bugfix-generate-no-project-name.yaml diff --git a/changelog/fragments/bugfix-generate-no-project-name.yaml b/changelog/fragments/bugfix-generate-no-project-name.yaml new file mode 100644 index 00000000000..41032f33e86 --- /dev/null +++ b/changelog/fragments/bugfix-generate-no-project-name.yaml @@ -0,0 +1,4 @@ +entries: + - description: > + Project version now determines how package name is retrieved for a project + kind: bugfix From fc48bf6250c0880017aafe75bec6a568f95dae85 Mon Sep 17 00:00:00 2001 From: Rashmi Gottipati Date: Thu, 28 Jan 2021 17:36:56 -0500 Subject: [PATCH 311/376] Bug 1921458: `run bundle-upgrade` should handle error gracefully when a previous operator version doesn't exist (#4448) * `run bundle-upgrade` should handle error gracefully when a previous operator version doesn't exist Signed-off-by: rashmigottipati Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- changelog/fragments/bugfix-run-bundle-upgrade.yaml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 changelog/fragments/bugfix-run-bundle-upgrade.yaml diff --git a/changelog/fragments/bugfix-run-bundle-upgrade.yaml b/changelog/fragments/bugfix-run-bundle-upgrade.yaml new file mode 100644 index 00000000000..af0a6ccf6e9 --- /dev/null +++ b/changelog/fragments/bugfix-run-bundle-upgrade.yaml @@ -0,0 +1,4 @@ +entries: + - description: > + `run bundle-upgrade` handles error gracefully when a previous operator version doesn't exist + kind: bugfix From e5dec087dbefc26af4788dcf109393e0ffd83db3 Mon Sep 17 00:00:00 2001 From: Jesus Rodriguez Date: Fri, 29 Jan 2021 09:51:11 -0500 Subject: [PATCH 312/376] Bug 1921727: Bundle validate should not fail because of warnings. (#4449) Bumped to operator-framework/api. Signed-off-by: jesus m. rodriguez Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- .../fragments/fix-bundle-validate-failure-on-warnings.yaml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 changelog/fragments/fix-bundle-validate-failure-on-warnings.yaml diff --git a/changelog/fragments/fix-bundle-validate-failure-on-warnings.yaml b/changelog/fragments/fix-bundle-validate-failure-on-warnings.yaml new file mode 100644 index 00000000000..a48643e8f46 --- /dev/null +++ b/changelog/fragments/fix-bundle-validate-failure-on-warnings.yaml @@ -0,0 +1,6 @@ +entries: + - description: > + Bump operator-framework/api to fix "operator-sdk bundle validate" failure when bundle has warnings. + When a warning is detected during validation it should be logged to the CLI but the validation should still pass. + kind: bugfix + breaking: false From 3055981a8cea68001659b89728fef265701fa2ae Mon Sep 17 00:00:00 2001 From: Mike Ng Date: Mon, 1 Feb 2021 13:16:05 -0500 Subject: [PATCH 313/376] Bug fix: helm operator uninstall is not properly checking for existing release (#3431) Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- changelog/fragments/helm-uninstall-fix.yaml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 changelog/fragments/helm-uninstall-fix.yaml diff --git a/changelog/fragments/helm-uninstall-fix.yaml b/changelog/fragments/helm-uninstall-fix.yaml new file mode 100644 index 00000000000..e8b6ce88518 --- /dev/null +++ b/changelog/fragments/helm-uninstall-fix.yaml @@ -0,0 +1,4 @@ +entries: + - description: Fixed a bug that caused the Helm operator to remove the finalizer without doing a helm uninstall. + kind: "bugfix" + breaking: false \ No newline at end of file From 69c4d6ce860a784cf1c27270d32593d2a7eefdc3 Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Tue, 2 Feb 2021 00:30:35 +0100 Subject: [PATCH 314/376] Pin docker base images (#4417) Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- changelog/fragments/pin-docker-base-images.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 changelog/fragments/pin-docker-base-images.yaml diff --git a/changelog/fragments/pin-docker-base-images.yaml b/changelog/fragments/pin-docker-base-images.yaml new file mode 100644 index 00000000000..3ed740c7529 --- /dev/null +++ b/changelog/fragments/pin-docker-base-images.yaml @@ -0,0 +1,12 @@ +# entries is a list of entries to include in +# release notes and/or the migration guide +entries: + - description: > + For Ansible-based and Helm-based operators, as well as for the + Operator SDK and the (custom) scorecard tests, the Docker base images + are pinned to improve the reproducibility of builds using Docker. + + kind: addition + + # Is this a breaking change? + breaking: false From c96edc756bc134961f1a986250df25bc663e873e Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Tue, 2 Feb 2021 10:35:26 -0800 Subject: [PATCH 315/376] `run bundle{-upgrade}`: validate `--mode` before running a bundle (#4462) Signed-off-by: Eric Stroczynski Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- changelog/fragments/bugfix-validate-add-mode.yaml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 changelog/fragments/bugfix-validate-add-mode.yaml diff --git a/changelog/fragments/bugfix-validate-add-mode.yaml b/changelog/fragments/bugfix-validate-add-mode.yaml new file mode 100644 index 00000000000..dc5578c3bff --- /dev/null +++ b/changelog/fragments/bugfix-validate-add-mode.yaml @@ -0,0 +1,5 @@ +entries: + - description: > + `run bundle` and `run bundle-upgrade` now validate the value passed to the hidden flag `--mode` before + running a bundle. + kind: bugfix From e9f04fe565b5085126248ea55b65003cd35e4802 Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Tue, 2 Feb 2021 12:11:04 -0800 Subject: [PATCH 316/376] internal/plugins: add `manifests` and `scorecard` plugin keys to all projects (#4419) Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- changelog/fragments/phase-2-plugin-keys.yaml | 48 ++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 changelog/fragments/phase-2-plugin-keys.yaml diff --git a/changelog/fragments/phase-2-plugin-keys.yaml b/changelog/fragments/phase-2-plugin-keys.yaml new file mode 100644 index 00000000000..c13517a1a2d --- /dev/null +++ b/changelog/fragments/phase-2-plugin-keys.yaml @@ -0,0 +1,48 @@ +entries: + - description: > + (go/v2) Changed `go` PROJECT plugin object to `manifests` and `scorecard` objects (`.sdk.operatorframework.io` suffix) + kind: change + breaking: false + migration: + header: (go/v2) Change `go` PROJECT plugin object to `manifests` and `scorecard` objects + body: > + The `manifests` and `scorecard` plugins that create OLM and scorecard manifests, respectively, + now have plugin objects that direct `create` subcommands to create related files. + While the old `go` plugin configuration object is still supported, these new objects will be useful + in the future as configuration options are added to their respective plugins: + + Old: + ```yaml + version: 3-alpha + ... + plugins: + go.sdk.operatorframework.io/v2-alpha: {} + ``` + + New: + ```yaml + version: 3-alpha + ... + plugins: + manifests.sdk.operatorframework.io/v2: {} + scorecard.sdk.operatorframework.io/v2: {} + ``` + + - description: > + (ansible/v1, helm/v1) Added plugin objects for the `manifests` and `scorecard` phase 2 plugins + kind: addition + migration: + header: (ansible/v1, helm/v1) Add `manifests` and `scorecard` plugin objects to your PROJECT + body: > + The `manifests` and `scorecard` plugins that create OLM and scorecard manifests, respectively, + now have plugin objects that direct `create` subcommands to create related files. While not necessary + to add, these new plugin configuration objects in the PROJECT file will be useful in the future + as configuration options are added to their respective plugins: + + ```yaml + version: 3-alpha + ... + plugins: + manifests.sdk.operatorframework.io/v2: {} + scorecard.sdk.operatorframework.io/v2: {} + ``` From 2c40e5ae268134065c5e3f17853aae1a0676b108 Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Tue, 2 Feb 2021 12:50:30 -0800 Subject: [PATCH 317/376] generate: make CSV generator for Go GVKs package-aware (#4445) internal/generatel/clusterserviceversion/bases/definitions: make the owned CRD generator package- and type-aware so multiple packages containing the same type names can be used. Signed-off-by: Eric Stroczynski Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- changelog/fragments/csv-gen-package-aware.yaml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 changelog/fragments/csv-gen-package-aware.yaml diff --git a/changelog/fragments/csv-gen-package-aware.yaml b/changelog/fragments/csv-gen-package-aware.yaml new file mode 100644 index 00000000000..85715ed46a9 --- /dev/null +++ b/changelog/fragments/csv-gen-package-aware.yaml @@ -0,0 +1,6 @@ +entries: + - description: > + For Go-based projects, `generate ` subcommands now consider package and type names + when parsing Go API types files to generate a CSV's `owned.customresourcedefinitions`, such that types in + different packages and files will not overwrite each other. + kind: bugfix From 5f9b358f06654ac0e07ae934d96297bc4f3da96d Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Thu, 4 Feb 2021 02:08:54 +0100 Subject: [PATCH 318/376] upgrade Python to v 3.8 (#4413) * upgrade Python to v 3.8 * add change notes * add python to installation guide Signed-off-by: reinvantveer Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- .../fragments/upgrade-python-on-ansible-operator.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 changelog/fragments/upgrade-python-on-ansible-operator.yaml diff --git a/changelog/fragments/upgrade-python-on-ansible-operator.yaml b/changelog/fragments/upgrade-python-on-ansible-operator.yaml new file mode 100644 index 00000000000..bee48527ddc --- /dev/null +++ b/changelog/fragments/upgrade-python-on-ansible-operator.yaml @@ -0,0 +1,11 @@ +entries: + - description: > + For Ansible-based operators, the Python version has been updated + to a newer version, from 3.6 to 3.8 to take advantage of performance + improvements, language additions, security updates and generally + better availability for local development. + + kind: change + + # Is this a breaking change? + breaking: false From a3101fde3799550dbf28a538df0ea2bb8d516e6c Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Wed, 3 Feb 2021 17:10:06 -0800 Subject: [PATCH 319/376] *: format finalizers correctly This commit modifies the suggested format for finalizers from . to /, which is the recommended format in k8s docs. This change is not breaking because technically any name format is allowed Signed-off-by: Eric Stroczynski Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- changelog/fragments/change-finalizer-format.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 changelog/fragments/change-finalizer-format.yaml diff --git a/changelog/fragments/change-finalizer-format.yaml b/changelog/fragments/change-finalizer-format.yaml new file mode 100644 index 00000000000..b2ea01b590f --- /dev/null +++ b/changelog/fragments/change-finalizer-format.yaml @@ -0,0 +1,12 @@ +entries: + - description: > + Changed the suggested finalizer format to `/` + kind: change + migration: + header: Change your operator's finalizer names + body: > + The finalizer name format suggested by [Kubernetes docs](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#finalizers) + is `/`, while the format previously documented by Operator SDK docs was + `.`. If your operator uses any finalizers with names matching the incorrect format, + change them to match the official format. + For example, `finalizer.cache.example.com` should be changed to `cache.example.com/finalizer`. From fcb28e7ef62c1ea31277f6ac2630bba3b60222a1 Mon Sep 17 00:00:00 2001 From: Jesus Rodriguez Date: Wed, 3 Feb 2021 20:40:51 -0500 Subject: [PATCH 320/376] Fixed invalid object names generated for long package names (#4471) * Fixed invalid object names generated for long package names * TrimDNS1123Label would trim strings but end up creating invalid DNS1123 strings. * FormatOperatorNameDNS1123 would return strings that were invalid if they begin or end with non-alphanumeric or hyphens. * Handle capitals and use more efficient trim mechanism * React to new expectation. Fixes #4470 Signed-off-by: jesus m. rodriguez Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- .../fragments/fix-trim-format-dns1123-functions.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 changelog/fragments/fix-trim-format-dns1123-functions.yaml diff --git a/changelog/fragments/fix-trim-format-dns1123-functions.yaml b/changelog/fragments/fix-trim-format-dns1123-functions.yaml new file mode 100644 index 00000000000..2c2896ea2a4 --- /dev/null +++ b/changelog/fragments/fix-trim-format-dns1123-functions.yaml @@ -0,0 +1,8 @@ +entries: + - description: > + Fixed invalid object names generated for long package names passed + to `run packagemanifests` & `run bundle`. + + kind: "bugfix" + + breaking: false From 4b4d6374430fbda652b5df1ed5b80a367cb57811 Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Thu, 21 Jan 2021 20:23:49 +0100 Subject: [PATCH 321/376] explain what/why of the change Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- ...er-base-images-for-ansible-and-helm-operators.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml diff --git a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml new file mode 100644 index 00000000000..bdb9f083f3a --- /dev/null +++ b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml @@ -0,0 +1,11 @@ +# entries is a list of entries to include in +# release notes and/or the migration guide +entries: + - description: > + For Ansible-based and Helm-based operators, the Docker base image is + pinned to improve the reproducibility of builds using Docker. + + kind: addition + + # Is this a breaking change? + breaking: false From 11b97fc88156c1a3a7263407c71cfaf395862604 Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Thu, 21 Jan 2021 22:21:37 +0100 Subject: [PATCH 322/376] update to reflect pinning all images, rename change file to fit description Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- ...er-base-images-for-ansible-and-helm-operators.yaml | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml diff --git a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml deleted file mode 100644 index bdb9f083f3a..00000000000 --- a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml +++ /dev/null @@ -1,11 +0,0 @@ -# entries is a list of entries to include in -# release notes and/or the migration guide -entries: - - description: > - For Ansible-based and Helm-based operators, the Docker base image is - pinned to improve the reproducibility of builds using Docker. - - kind: addition - - # Is this a breaking change? - breaking: false From 9be8afc4395584f0a7f50bd23c85b928dbcffc5a Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Fri, 22 Jan 2021 22:30:57 +0100 Subject: [PATCH 323/376] move Python package versions to pipenv dependency management to pin sub-dependencies and resolve potential conflicts Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- images/ansible-operator/Dockerfile | 12 +- images/ansible-operator/Pipfile | 18 + images/ansible-operator/Pipfile.lock | 481 +++++++++++++++++++++++++++ 3 files changed, 503 insertions(+), 8 deletions(-) create mode 100644 images/ansible-operator/Pipfile create mode 100644 images/ansible-operator/Pipfile.lock diff --git a/images/ansible-operator/Dockerfile b/images/ansible-operator/Dockerfile index 38731ca6679..027ac25f236 100644 --- a/images/ansible-operator/Dockerfile +++ b/images/ansible-operator/Dockerfile @@ -13,17 +13,13 @@ ENV HOME=/opt/ansible \ # Install python dependencies # Ensure fresh metadata rather than cached metadata in the base by running # yum clean all && rm -rf /var/yum/cache/* first +COPY Pipfile* . +ENV PIP_NO_CACHE_DIR=1 RUN yum clean all && rm -rf /var/cache/yum/* \ && yum -y update \ && yum install -y libffi-devel openssl-devel python38-devel gcc python38-pip python38-setuptools \ - && pip3 install --no-cache-dir \ - ansible-runner==1.3.4 \ - ansible-runner-http==1.0.0 \ - ipaddress==1.0.23 \ - kubernetes==10.1.0 \ - openshift==0.10.3 \ - ansible==2.9.15 \ - jmespath==0.10.0 \ + && pip3 install pipenv==2020.11.15 \ + && pipenv install --deploy --system \ && yum remove -y gcc libffi-devel openssl-devel python38-devel \ && yum clean all \ && rm -rf /var/cache/yum diff --git a/images/ansible-operator/Pipfile b/images/ansible-operator/Pipfile new file mode 100644 index 00000000000..63ca8a38acd --- /dev/null +++ b/images/ansible-operator/Pipfile @@ -0,0 +1,18 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +ansible-runner = "==1.3.4" +ansible-runner-http = "==1.0.0" +ipaddress = "==1.0.23" +kubernetes = "==10.1.0" +openshift = "==0.10.3" +ansible = "==2.9.15" +jmespath = "==0.10.0" + +[dev-packages] + +[requires] +python_version = "3.8" diff --git a/images/ansible-operator/Pipfile.lock b/images/ansible-operator/Pipfile.lock new file mode 100644 index 00000000000..e3895ec363e --- /dev/null +++ b/images/ansible-operator/Pipfile.lock @@ -0,0 +1,481 @@ +{ + "_meta": { + "hash": { + "sha256": "31860839e6fae28389b2ce653261db07c4d73f12d16e7eb21cebbfd35a09c289" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.8" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "ansible": { + "hashes": [ + "sha256:736a19fa6d608b4df2d6b48d31fec057b3f95abf62b7fda69ffa4a743e2f55b6" + ], + "index": "pypi", + "version": "==2.9.15" + }, + "ansible-runner": { + "hashes": [ + "sha256:60f531f1cb9b2b0cb1e8cf8dc9f81186aecda22d01587f35c61a833d0198f220", + "sha256:dafa8f28193ab253e71b07be3314f80d796672e1b96385f2c46c39b597c1e996" + ], + "index": "pypi", + "version": "==1.3.4" + }, + "ansible-runner-http": { + "hashes": [ + "sha256:97da445b7d5c6663b0cceaf6bd5e9b0b0dff9a4c36eae43c8c916c6208aee915", + "sha256:e2f34880531d4088a5e04967fd5eae602eb400cc4eb541b22c8c6853e342587f" + ], + "index": "pypi", + "version": "==1.0.0" + }, + "cachetools": { + "hashes": [ + "sha256:3796e1de094f0eaca982441c92ce96c68c89cced4cd97721ab297ea4b16db90e", + "sha256:c6b07a6ded8c78bf36730b3dc452dfff7d95f2a12a2fed856b1a0cb13ca78c61" + ], + "markers": "python_version ~= '3.5'", + "version": "==4.2.0" + }, + "certifi": { + "hashes": [ + "sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c", + "sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830" + ], + "version": "==2020.12.5" + }, + "cffi": { + "hashes": [ + "sha256:00a1ba5e2e95684448de9b89888ccd02c98d512064b4cb987d48f4b40aa0421e", + "sha256:00e28066507bfc3fe865a31f325c8391a1ac2916219340f87dfad602c3e48e5d", + "sha256:045d792900a75e8b1e1b0ab6787dd733a8190ffcf80e8c8ceb2fb10a29ff238a", + "sha256:0638c3ae1a0edfb77c6765d487fee624d2b1ee1bdfeffc1f0b58c64d149e7eec", + "sha256:105abaf8a6075dc96c1fe5ae7aae073f4696f2905fde6aeada4c9d2926752362", + "sha256:155136b51fd733fa94e1c2ea5211dcd4c8879869008fc811648f16541bf99668", + "sha256:1a465cbe98a7fd391d47dce4b8f7e5b921e6cd805ef421d04f5f66ba8f06086c", + "sha256:1d2c4994f515e5b485fd6d3a73d05526aa0fcf248eb135996b088d25dfa1865b", + "sha256:2c24d61263f511551f740d1a065eb0212db1dbbbbd241db758f5244281590c06", + "sha256:51a8b381b16ddd370178a65360ebe15fbc1c71cf6f584613a7ea08bfad946698", + "sha256:594234691ac0e9b770aee9fcdb8fa02c22e43e5c619456efd0d6c2bf276f3eb2", + "sha256:5cf4be6c304ad0b6602f5c4e90e2f59b47653ac1ed9c662ed379fe48a8f26b0c", + "sha256:64081b3f8f6f3c3de6191ec89d7dc6c86a8a43911f7ecb422c60e90c70be41c7", + "sha256:6bc25fc545a6b3d57b5f8618e59fc13d3a3a68431e8ca5fd4c13241cd70d0009", + "sha256:798caa2a2384b1cbe8a2a139d80734c9db54f9cc155c99d7cc92441a23871c03", + "sha256:7c6b1dece89874d9541fc974917b631406233ea0440d0bdfbb8e03bf39a49b3b", + "sha256:840793c68105fe031f34d6a086eaea153a0cd5c491cde82a74b420edd0a2b909", + "sha256:8d6603078baf4e11edc4168a514c5ce5b3ba6e3e9c374298cb88437957960a53", + "sha256:9cc46bc107224ff5b6d04369e7c595acb700c3613ad7bcf2e2012f62ece80c35", + "sha256:9f7a31251289b2ab6d4012f6e83e58bc3b96bd151f5b5262467f4bb6b34a7c26", + "sha256:9ffb888f19d54a4d4dfd4b3f29bc2c16aa4972f1c2ab9c4ab09b8ab8685b9c2b", + "sha256:a5ed8c05548b54b998b9498753fb9cadbfd92ee88e884641377d8a8b291bcc01", + "sha256:a7711edca4dcef1a75257b50a2fbfe92a65187c47dab5a0f1b9b332c5919a3fb", + "sha256:af5c59122a011049aad5dd87424b8e65a80e4a6477419c0c1015f73fb5ea0293", + "sha256:b18e0a9ef57d2b41f5c68beefa32317d286c3d6ac0484efd10d6e07491bb95dd", + "sha256:b4e248d1087abf9f4c10f3c398896c87ce82a9856494a7155823eb45a892395d", + "sha256:ba4e9e0ae13fc41c6b23299545e5ef73055213e466bd107953e4a013a5ddd7e3", + "sha256:c6332685306b6417a91b1ff9fae889b3ba65c2292d64bd9245c093b1b284809d", + "sha256:d5ff0621c88ce83a28a10d2ce719b2ee85635e85c515f12bac99a95306da4b2e", + "sha256:d9efd8b7a3ef378dd61a1e77367f1924375befc2eba06168b6ebfa903a5e59ca", + "sha256:df5169c4396adc04f9b0a05f13c074df878b6052430e03f50e68adf3a57aa28d", + "sha256:ebb253464a5d0482b191274f1c8bf00e33f7e0b9c66405fbffc61ed2c839c775", + "sha256:ec80dc47f54e6e9a78181ce05feb71a0353854cc26999db963695f950b5fb375", + "sha256:f032b34669220030f905152045dfa27741ce1a6db3324a5bc0b96b6c7420c87b", + "sha256:f60567825f791c6f8a592f3c6e3bd93dd2934e3f9dac189308426bd76b00ef3b", + "sha256:f803eaa94c2fcda012c047e62bc7a51b0bdabda1cad7a92a522694ea2d76e49f" + ], + "version": "==1.14.4" + }, + "chardet": { + "hashes": [ + "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa", + "sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==4.0.0" + }, + "cryptography": { + "hashes": [ + "sha256:0003a52a123602e1acee177dc90dd201f9bb1e73f24a070db7d36c588e8f5c7d", + "sha256:0e85aaae861d0485eb5a79d33226dd6248d2a9f133b81532c8f5aae37de10ff7", + "sha256:594a1db4511bc4d960571536abe21b4e5c3003e8750ab8365fafce71c5d86901", + "sha256:69e836c9e5ff4373ce6d3ab311c1a2eed274793083858d3cd4c7d12ce20d5f9c", + "sha256:788a3c9942df5e4371c199d10383f44a105d67d401fb4304178020142f020244", + "sha256:7e177e4bea2de937a584b13645cab32f25e3d96fc0bc4a4cf99c27dc77682be6", + "sha256:83d9d2dfec70364a74f4e7c70ad04d3ca2e6a08b703606993407bf46b97868c5", + "sha256:84ef7a0c10c24a7773163f917f1cb6b4444597efd505a8aed0a22e8c4780f27e", + "sha256:9e21301f7a1e7c03dbea73e8602905a4ebba641547a462b26dd03451e5769e7c", + "sha256:9f6b0492d111b43de5f70052e24c1f0951cb9e6022188ebcb1cc3a3d301469b0", + "sha256:a69bd3c68b98298f490e84519b954335154917eaab52cf582fa2c5c7efc6e812", + "sha256:b4890d5fb9b7a23e3bf8abf5a8a7da8e228f1e97dc96b30b95685df840b6914a", + "sha256:c366df0401d1ec4e548bebe8f91d55ebcc0ec3137900d214dd7aac8427ef3030", + "sha256:dc42f645f8f3a489c3dd416730a514e7a91a59510ddaadc09d04224c098d3302" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", + "version": "==3.3.1" + }, + "dictdiffer": { + "hashes": [ + "sha256:1adec0d67cdf6166bda96ae2934ddb5e54433998ceab63c984574d187cc563d2", + "sha256:d79d9a39e459fe33497c858470ca0d2e93cb96621751de06d631856adfd9c390" + ], + "version": "==0.8.1" + }, + "docutils": { + "hashes": [ + "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af", + "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==0.16" + }, + "google-auth": { + "hashes": [ + "sha256:0b0e026b412a0ad096e753907559e4bdb180d9ba9f68dd9036164db4fdc4ad2e", + "sha256:ce752cc51c31f479dbf9928435ef4b07514b20261b021c7383bee4bda646acb8" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", + "version": "==1.24.0" + }, + "idna": { + "hashes": [ + "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6", + "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.10" + }, + "ipaddress": { + "hashes": [ + "sha256:6e0f4a39e66cb5bb9a137b00276a2eff74f93b71dcbdad6f10ff7df9d3557fcc", + "sha256:b7f8e0369580bb4a24d5ba1d7cc29660a4a6987763faf1d8a8046830e020e7e2" + ], + "index": "pypi", + "version": "==1.0.23" + }, + "jinja2": { + "hashes": [ + "sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0", + "sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==2.11.2" + }, + "jmespath": { + "hashes": [ + "sha256:b85d0567b8666149a93172712e68920734333c0ce7e89b78b3e987f71e5ed4f9", + "sha256:cdf6525904cc597730141d61b36f2e4b8ecc257c420fa2f4549bac2c2d0cb72f" + ], + "index": "pypi", + "version": "==0.10.0" + }, + "kubernetes": { + "hashes": [ + "sha256:85a767d04f17d6d317374b6c35e09eb168a6bfd9276f0b3177cc206376bad968", + "sha256:9aa4f34431a442dda856bafc959bcf296cb5802f370361604c440093c702b17c" + ], + "index": "pypi", + "version": "==10.1.0" + }, + "lockfile": { + "hashes": [ + "sha256:6aed02de03cba24efabcd600b30540140634fc06cfa603822d508d5361e9f799", + "sha256:6c3cb24f344923d30b2785d5ad75182c8ea7ac1b6171b08657258ec7429d50fa" + ], + "version": "==0.12.2" + }, + "markupsafe": { + "hashes": [ + "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", + "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", + "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", + "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", + "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42", + "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", + "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", + "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", + "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", + "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", + "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", + "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b", + "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", + "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15", + "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", + "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", + "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", + "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", + "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", + "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", + "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", + "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", + "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", + "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", + "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", + "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", + "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", + "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", + "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", + "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", + "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2", + "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7", + "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.1.1" + }, + "oauthlib": { + "hashes": [ + "sha256:bee41cc35fcca6e988463cacc3bcb8a96224f470ca547e697b604cc697b2f889", + "sha256:df884cd6cbe20e32633f1db1072e9356f53638e4361bef4e8b03c9127c9328ea" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==3.1.0" + }, + "openshift": { + "hashes": [ + "sha256:d8462c4bc3eaaa5a11623d6d67048c3e0b16558fa23675ffd85157d66696ff39" + ], + "index": "pypi", + "version": "==0.10.3" + }, + "pexpect": { + "hashes": [ + "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937", + "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c" + ], + "version": "==4.8.0" + }, + "psutil": { + "hashes": [ + "sha256:0066a82f7b1b37d334e68697faba68e5ad5e858279fd6351c8ca6024e8d6ba64", + "sha256:02b8292609b1f7fcb34173b25e48d0da8667bc85f81d7476584d889c6e0f2131", + "sha256:0ae6f386d8d297177fd288be6e8d1afc05966878704dad9847719650e44fc49c", + "sha256:0c9ccb99ab76025f2f0bbecf341d4656e9c1351db8cc8a03ccd62e318ab4b5c6", + "sha256:0dd4465a039d343925cdc29023bb6960ccf4e74a65ad53e768403746a9207023", + "sha256:12d844996d6c2b1d3881cfa6fa201fd635971869a9da945cf6756105af73d2df", + "sha256:1bff0d07e76114ec24ee32e7f7f8d0c4b0514b3fae93e3d2aaafd65d22502394", + "sha256:245b5509968ac0bd179287d91210cd3f37add77dad385ef238b275bad35fa1c4", + "sha256:28ff7c95293ae74bf1ca1a79e8805fcde005c18a122ca983abf676ea3466362b", + "sha256:36b3b6c9e2a34b7d7fbae330a85bf72c30b1c827a4366a07443fc4b6270449e2", + "sha256:52de075468cd394ac98c66f9ca33b2f54ae1d9bff1ef6b67a212ee8f639ec06d", + "sha256:5da29e394bdedd9144c7331192e20c1f79283fb03b06e6abd3a8ae45ffecee65", + "sha256:61f05864b42fedc0771d6d8e49c35f07efd209ade09a5afe6a5059e7bb7bf83d", + "sha256:6223d07a1ae93f86451d0198a0c361032c4c93ebd4bf6d25e2fb3edfad9571ef", + "sha256:6323d5d845c2785efb20aded4726636546b26d3b577aded22492908f7c1bdda7", + "sha256:6ffe81843131ee0ffa02c317186ed1e759a145267d54fdef1bc4ea5f5931ab60", + "sha256:74f2d0be88db96ada78756cb3a3e1b107ce8ab79f65aa885f76d7664e56928f6", + "sha256:74fb2557d1430fff18ff0d72613c5ca30c45cdbfcddd6a5773e9fc1fe9364be8", + "sha256:90d4091c2d30ddd0a03e0b97e6a33a48628469b99585e2ad6bf21f17423b112b", + "sha256:90f31c34d25b1b3ed6c40cdd34ff122b1887a825297c017e4cbd6796dd8b672d", + "sha256:99de3e8739258b3c3e8669cb9757c9a861b2a25ad0955f8e53ac662d66de61ac", + "sha256:c6a5fd10ce6b6344e616cf01cc5b849fa8103fbb5ba507b6b2dee4c11e84c935", + "sha256:ce8b867423291cb65cfc6d9c4955ee9bfc1e21fe03bb50e177f2b957f1c2469d", + "sha256:d225cd8319aa1d3c85bf195c4e07d17d3cd68636b8fc97e6cf198f782f99af28", + "sha256:ea313bb02e5e25224e518e4352af4bf5e062755160f77e4b1767dd5ccb65f876", + "sha256:ea372bcc129394485824ae3e3ddabe67dc0b118d262c568b4d2602a7070afdb0", + "sha256:f4634b033faf0d968bb9220dd1c793b897ab7f1189956e1aa9eae752527127d3", + "sha256:fcc01e900c1d7bee2a37e5d6e4f9194760a93597c97fee89c4ae51701de03563" + ], + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==5.8.0" + }, + "ptyprocess": { + "hashes": [ + "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", + "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220" + ], + "version": "==0.7.0" + }, + "pyasn1": { + "hashes": [ + "sha256:014c0e9976956a08139dc0712ae195324a75e142284d5f87f1a87ee1b068a359", + "sha256:03840c999ba71680a131cfaee6fab142e1ed9bbd9c693e285cc6aca0d555e576", + "sha256:0458773cfe65b153891ac249bcf1b5f8f320b7c2ce462151f8fa74de8934becf", + "sha256:08c3c53b75eaa48d71cf8c710312316392ed40899cb34710d092e96745a358b7", + "sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d", + "sha256:5c9414dcfede6e441f7e8f81b43b34e834731003427e5b09e4e00e3172a10f00", + "sha256:6e7545f1a61025a4e58bb336952c5061697da694db1cae97b116e9c46abcf7c8", + "sha256:78fa6da68ed2727915c4767bb386ab32cdba863caa7dbe473eaae45f9959da86", + "sha256:7ab8a544af125fb704feadb008c99a88805126fb525280b2270bb25cc1d78a12", + "sha256:99fcc3c8d804d1bc6d9a099921e39d827026409a58f2a720dcdb89374ea0c776", + "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba", + "sha256:e89bf84b5437b532b0803ba5c9a5e054d21fec423a89952a74f87fa2c9b7bce2", + "sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3" + ], + "version": "==0.4.8" + }, + "pyasn1-modules": { + "hashes": [ + "sha256:0845a5582f6a02bb3e1bde9ecfc4bfcae6ec3210dd270522fee602365430c3f8", + "sha256:0fe1b68d1e486a1ed5473f1302bd991c1611d319bba158e98b106ff86e1d7199", + "sha256:15b7c67fabc7fc240d87fb9aabf999cf82311a6d6fb2c70d00d3d0604878c811", + "sha256:426edb7a5e8879f1ec54a1864f16b882c2837bfd06eee62f2c982315ee2473ed", + "sha256:65cebbaffc913f4fe9e4808735c95ea22d7a7775646ab690518c056784bc21b4", + "sha256:905f84c712230b2c592c19470d3ca8d552de726050d1d1716282a1f6146be65e", + "sha256:a50b808ffeb97cb3601dd25981f6b016cbb3d31fbf57a8b8a87428e6158d0c74", + "sha256:a99324196732f53093a84c4369c996713eb8c89d360a496b599fb1a9c47fc3eb", + "sha256:b80486a6c77252ea3a3e9b1e360bc9cf28eaac41263d173c032581ad2f20fe45", + "sha256:c29a5e5cc7a3f05926aff34e097e84f8589cd790ce0ed41b67aed6857b26aafd", + "sha256:cbac4bc38d117f2a49aeedec4407d23e8866ea4ac27ff2cf7fb3e5b570df19e0", + "sha256:f39edd8c4ecaa4556e989147ebf219227e2cd2e8a43c7e7fcb1f1c18c5fd6a3d", + "sha256:fe0644d9ab041506b62782e92b06b8c68cca799e1a9636ec398675459e031405" + ], + "version": "==0.2.8" + }, + "pycparser": { + "hashes": [ + "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0", + "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.20" + }, + "python-daemon": { + "hashes": [ + "sha256:57c84f50a04d7825515e4dbf3a31c70cc44414394a71608dee6cfde469e81766", + "sha256:a0d5dc0b435a02c7e0b401e177a7c17c3f4c7b4e22e2d06271122c8fec5f8946" + ], + "version": "==2.2.4" + }, + "python-dateutil": { + "hashes": [ + "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c", + "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "version": "==2.8.1" + }, + "python-string-utils": { + "hashes": [ + "sha256:dcf9060b03f07647c0a603408dc8b03f807f3b54a05c6e19eb14460256fac0cb", + "sha256:f1a88700baf99db1a9b6953f44181ad9ca56623c81e257e6009707e2e7851fa4" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.0" + }, + "pyyaml": { + "hashes": [ + "sha256:3d7da3009c0f3e783b2c873687652d83b1bbfd5c88e9813fb7e5b03c0dd3108b", + "sha256:3ef3092145e9b70e3ddd2c7ad59bdd0252a94dfe3949721633e41344de00a6bf", + "sha256:40c71b8e076d0550b2e6380bada1f1cd1017b882f7e16f09a65be98e017f211a", + "sha256:558dd60b890ba8fd982e05941927a3911dc409a63dcb8b634feaa0cda69330d3", + "sha256:a7c28b45d9f99102fa092bb213aa12e0aaf9a6a1f5e395d36166639c1f96c3a1", + "sha256:aa7dd4a6a427aed7df6fb7f08a580d68d9b118d90310374716ae90b710280af1", + "sha256:bc558586e6045763782014934bfaf39d48b8ae85a2713117d16c39864085c613", + "sha256:d46d7982b62e0729ad0175a9bc7e10a566fc07b224d2c79fafb5e032727eaa04", + "sha256:d5eef459e30b09f5a098b9cea68bebfeb268697f78d647bd255a085371ac7f3f", + "sha256:e01d3203230e1786cd91ccfdc8f8454c8069c91bee3962ad93b87a4b2860f537", + "sha256:e170a9e6fcfd19021dd29845af83bb79236068bf5fd4df3327c1be18182b2531" + ], + "version": "==3.13" + }, + "requests": { + "hashes": [ + "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804", + "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==2.25.1" + }, + "requests-oauthlib": { + "hashes": [ + "sha256:7f71572defaecd16372f9006f33c2ec8c077c3cfa6f5911a9a90202beb513f3d", + "sha256:b4261601a71fd721a8bd6d7aa1cc1d6a8a93b4a9f5e96626f8e4d91e8beeaa6a", + "sha256:fa6c47b933f01060936d87ae9327fead68768b69c6c9ea2109c48be30f2d4dbc" + ], + "version": "==1.3.0" + }, + "requests-unixsocket": { + "hashes": [ + "sha256:014d07bfb66dc805a011a8b4b306cf4ec96d2eddb589f6b2b5765e626f0dc0cc", + "sha256:9e5c1a20afc3cf786197ae59c79bcdb0e7565f218f27df5f891307ee8817c1ea" + ], + "version": "==0.2.0" + }, + "rsa": { + "hashes": [ + "sha256:69805d6b69f56eb05b62daea3a7dbd7aa44324ad1306445e05da8060232d00f4", + "sha256:a8774e55b59fd9fc893b0d05e9bfc6f47081f46ff5b46f39ccf24631b7be356b" + ], + "markers": "python_version >= '3.6'", + "version": "==4.7" + }, + "ruamel.yaml": { + "hashes": [ + "sha256:012b9470a0ea06e4e44e99e7920277edf6b46eee0232a04487ea73a7386340a5", + "sha256:076cc0bc34f1966d920a49f18b52b6ad559fbe656a0748e3535cf7b3f29ebf9e" + ], + "version": "==0.16.12" + }, + "ruamel.yaml.clib": { + "hashes": [ + "sha256:058a1cc3df2a8aecc12f983a48bda99315cebf55a3b3a5463e37bb599b05727b", + "sha256:1236df55e0f73cd138c0eca074ee086136c3f16a97c2ac719032c050f7e0622f", + "sha256:1f8c0a4577c0e6c99d208de5c4d3fd8aceed9574bb154d7a2b21c16bb924154c", + "sha256:2602e91bd5c1b874d6f93d3086f9830f3e907c543c7672cf293a97c3fabdcd91", + "sha256:28116f204103cb3a108dfd37668f20abe6e3cafd0d3fd40dba126c732457b3cc", + "sha256:2d24bd98af676f4990c4d715bcdc2a60b19c56a3fb3a763164d2d8ca0e806ba7", + "sha256:2fd336a5c6415c82e2deb40d08c222087febe0aebe520f4d21910629018ab0f3", + "sha256:30dca9bbcbb1cc858717438218d11eafb78666759e5094dd767468c0d577a7e7", + "sha256:44c7b0498c39f27795224438f1a6be6c5352f82cb887bc33d962c3a3acc00df6", + "sha256:464e66a04e740d754170be5e740657a3b3b6d2bcc567f0c3437879a6e6087ff6", + "sha256:46d6d20815064e8bb023ea8628cfb7402c0f0e83de2c2227a88097e239a7dffd", + "sha256:4df5019e7783d14b79217ad9c56edf1ba7485d614ad5a385d1b3c768635c81c0", + "sha256:4e52c96ca66de04be42ea2278012a2342d89f5e82b4512fb6fb7134e377e2e62", + "sha256:5254af7d8bdf4d5484c089f929cb7f5bafa59b4f01d4f48adda4be41e6d29f99", + "sha256:52ae5739e4b5d6317b52f5b040b1b6639e8af68a5b8fd606a8b08658fbd0cab5", + "sha256:53b9dd1abd70e257a6e32f934ebc482dac5edb8c93e23deb663eac724c30b026", + "sha256:6c0a5dc52fc74eb87c67374a4e554d4761fd42a4d01390b7e868b30d21f4b8bb", + "sha256:73b3d43e04cc4b228fa6fa5d796409ece6fcb53a6c270eb2048109cbcbc3b9c2", + "sha256:74161d827407f4db9072011adcfb825b5258a5ccb3d2cd518dd6c9edea9e30f1", + "sha256:75f0ee6839532e52a3a53f80ce64925ed4aed697dd3fa890c4c918f3304bd4f4", + "sha256:839dd72545ef7ba78fd2aa1a5dd07b33696adf3e68fae7f31327161c1093001b", + "sha256:8be05be57dc5c7b4a0b24edcaa2f7275866d9c907725226cdde46da09367d923", + "sha256:8e8fd0a22c9d92af3a34f91e8a2594eeb35cba90ab643c5e0e643567dc8be43e", + "sha256:a873e4d4954f865dcb60bdc4914af7eaae48fb56b60ed6daa1d6251c72f5337c", + "sha256:ab845f1f51f7eb750a78937be9f79baea4a42c7960f5a94dde34e69f3cce1988", + "sha256:b1e981fe1aff1fd11627f531524826a4dcc1f26c726235a52fcb62ded27d150f", + "sha256:b4b0d31f2052b3f9f9b5327024dc629a253a83d8649d4734ca7f35b60ec3e9e5", + "sha256:c6ac7e45367b1317e56f1461719c853fd6825226f45b835df7436bb04031fd8a", + "sha256:daf21aa33ee9b351f66deed30a3d450ab55c14242cfdfcd377798e2c0d25c9f1", + "sha256:e9f7d1d8c26a6a12c23421061f9022bb62704e38211fe375c645485f38df34a2", + "sha256:f6061a31880c1ed6b6ce341215336e2f3d0c1deccd84957b6fa8ca474b41e89f" + ], + "markers": "platform_python_implementation == 'CPython' and python_version < '3.9'", + "version": "==0.2.2" + }, + "six": { + "hashes": [ + "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259", + "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "version": "==1.15.0" + }, + "urllib3": { + "hashes": [ + "sha256:19188f96923873c92ccb987120ec4acaa12f0461fa9ce5d3d0772bc965a39e08", + "sha256:d8ff90d979214d7b4f8ce956e80f4028fc6860e4431f731ea4a8c08f23f99473" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'", + "version": "==1.26.2" + }, + "websocket-client": { + "hashes": [ + "sha256:0fc45c961324d79c781bab301359d5a1b00b13ad1b10415a4780229ef71a5549", + "sha256:d735b91d6d1692a6a181f2a8c9e0238e5f6373356f561bb9dc4c7af36f452010" + ], + "version": "==0.57.0" + } + }, + "develop": {} +} From 09dbbb310484a4d3b03101bf9fb18ac4879c5fb5 Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Fri, 22 Jan 2021 23:16:05 +0100 Subject: [PATCH 324/376] WIP: pipenv check stubles over pyyaml Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- images/ansible-operator/Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/images/ansible-operator/Dockerfile b/images/ansible-operator/Dockerfile index 027ac25f236..db2ec34cfff 100644 --- a/images/ansible-operator/Dockerfile +++ b/images/ansible-operator/Dockerfile @@ -24,6 +24,8 @@ RUN yum clean all && rm -rf /var/cache/yum/* \ && yum clean all \ && rm -rf /var/cache/yum +RUN pipenv check --system + # Ensure directory permissions are properly set RUN echo "${USER_NAME}:x:${USER_UID}:0:${USER_NAME} user:${HOME}:/sbin/nologin" >> /etc/passwd \ && mkdir -p ${HOME}/.ansible/tmp \ From b29a413bea86ff392e53ac6451380f8ce01ca0f9 Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Fri, 22 Jan 2021 23:17:11 +0100 Subject: [PATCH 325/376] add change description Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- .../use-pipenv-for-python-package-installation.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 changelog/fragments/use-pipenv-for-python-package-installation.yaml diff --git a/changelog/fragments/use-pipenv-for-python-package-installation.yaml b/changelog/fragments/use-pipenv-for-python-package-installation.yaml new file mode 100644 index 00000000000..4fc72b31610 --- /dev/null +++ b/changelog/fragments/use-pipenv-for-python-package-installation.yaml @@ -0,0 +1,10 @@ +entries: + - description: > + For Ansible-based operators, Python package installation in the Docker + image is delegated to a pipenv managed Pipfile and Pipfile.lock, pinning + both the main installed packages and their subdependencies. This prevents + installing conflicting (sub)dependencies + + kind: change + + breaking: false From ab6f03ca981ce16d5440d2762048173bab070cf5 Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Fri, 22 Jan 2021 23:32:25 +0100 Subject: [PATCH 326/376] use env vars to force pipenv to clear caches; install packages and do vulnerability checks in base site-packages Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- images/ansible-operator/Dockerfile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/images/ansible-operator/Dockerfile b/images/ansible-operator/Dockerfile index db2ec34cfff..e67d0da1508 100644 --- a/images/ansible-operator/Dockerfile +++ b/images/ansible-operator/Dockerfile @@ -14,7 +14,9 @@ ENV HOME=/opt/ansible \ # Ensure fresh metadata rather than cached metadata in the base by running # yum clean all && rm -rf /var/yum/cache/* first COPY Pipfile* . -ENV PIP_NO_CACHE_DIR=1 +ENV PIP_NO_CACHE_DIR=1 \ + PIPENV_SYSTEM=1 \ + PIPENV_CLEAR=1 RUN yum clean all && rm -rf /var/cache/yum/* \ && yum -y update \ && yum install -y libffi-devel openssl-devel python38-devel gcc python38-pip python38-setuptools \ @@ -24,7 +26,7 @@ RUN yum clean all && rm -rf /var/cache/yum/* \ && yum clean all \ && rm -rf /var/cache/yum -RUN pipenv check --system +RUN pipenv check # Ensure directory permissions are properly set RUN echo "${USER_NAME}:x:${USER_UID}:0:${USER_NAME} user:${HOME}:/sbin/nologin" >> /etc/passwd \ From 9892ddbd1108d266fb87661cc6dc385c946ce0a5 Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Sat, 23 Jan 2021 17:20:25 +0100 Subject: [PATCH 327/376] upgrade ansible-runner to latest version 1.4.6, see https://ansible-runner.readthedocs.io/en/1.4.6/install.html#changelog since 1.3.4. No breaking changes according to log. Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- images/ansible-operator/Pipfile | 2 +- images/ansible-operator/Pipfile.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/images/ansible-operator/Pipfile b/images/ansible-operator/Pipfile index 63ca8a38acd..10f011f51e9 100644 --- a/images/ansible-operator/Pipfile +++ b/images/ansible-operator/Pipfile @@ -4,7 +4,7 @@ verify_ssl = true name = "pypi" [packages] -ansible-runner = "==1.3.4" +ansible-runner = "==1.4.6" ansible-runner-http = "==1.0.0" ipaddress = "==1.0.23" kubernetes = "==10.1.0" diff --git a/images/ansible-operator/Pipfile.lock b/images/ansible-operator/Pipfile.lock index e3895ec363e..dc6d3ebbdce 100644 --- a/images/ansible-operator/Pipfile.lock +++ b/images/ansible-operator/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "31860839e6fae28389b2ce653261db07c4d73f12d16e7eb21cebbfd35a09c289" + "sha256": "b2bc483f47c283416570727cef63c5501ec07bb83cebbea7e5c4d1ad231ac062" }, "pipfile-spec": 6, "requires": { @@ -25,11 +25,11 @@ }, "ansible-runner": { "hashes": [ - "sha256:60f531f1cb9b2b0cb1e8cf8dc9f81186aecda22d01587f35c61a833d0198f220", - "sha256:dafa8f28193ab253e71b07be3314f80d796672e1b96385f2c46c39b597c1e996" + "sha256:0744642cff32d23310b3a5f5aae23d07bea1051724e66b27f9bbccefec8427dd", + "sha256:53605de32f7d3d3442a6deb8937bf1d9c1f91c785e3f71003d22c3e63f85c71d" ], "index": "pypi", - "version": "==1.3.4" + "version": "==1.4.6" }, "ansible-runner-http": { "hashes": [ @@ -351,7 +351,7 @@ "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c", "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.8.1" }, "python-string-utils": { @@ -450,7 +450,7 @@ "sha256:e9f7d1d8c26a6a12c23421061f9022bb62704e38211fe375c645485f38df34a2", "sha256:f6061a31880c1ed6b6ce341215336e2f3d0c1deccd84957b6fa8ca474b41e89f" ], - "markers": "platform_python_implementation == 'CPython' and python_version < '3.9'", + "markers": "python_version < '3.9' and platform_python_implementation == 'CPython'", "version": "==0.2.2" }, "six": { @@ -458,7 +458,7 @@ "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259", "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.15.0" }, "urllib3": { From e0c63ac732fa31beaf9d7c70f58071fcda748a84 Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Sat, 23 Jan 2021 19:18:05 +0100 Subject: [PATCH 328/376] upgrade openshift lib, remove kubernetes: it is already installed as a pinned-version dependency of openshift. Fixes dependency on vulnerable pyyamml version Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- images/ansible-operator/Pipfile | 3 +- images/ansible-operator/Pipfile.lock | 57 +++++++++++++++------------- 2 files changed, 31 insertions(+), 29 deletions(-) diff --git a/images/ansible-operator/Pipfile b/images/ansible-operator/Pipfile index 10f011f51e9..2cf3af1362c 100644 --- a/images/ansible-operator/Pipfile +++ b/images/ansible-operator/Pipfile @@ -7,8 +7,7 @@ name = "pypi" ansible-runner = "==1.4.6" ansible-runner-http = "==1.0.0" ipaddress = "==1.0.23" -kubernetes = "==10.1.0" -openshift = "==0.10.3" +openshift = "==0.11.2" ansible = "==2.9.15" jmespath = "==0.10.0" diff --git a/images/ansible-operator/Pipfile.lock b/images/ansible-operator/Pipfile.lock index dc6d3ebbdce..088a45beb13 100644 --- a/images/ansible-operator/Pipfile.lock +++ b/images/ansible-operator/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "b2bc483f47c283416570727cef63c5501ec07bb83cebbea7e5c4d1ad231ac062" + "sha256": "85039a7202a9c714cc0626c67bb854174b8c48f4d66907aae6981774f7836f7f" }, "pipfile-spec": 6, "requires": { @@ -123,13 +123,6 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", "version": "==3.3.1" }, - "dictdiffer": { - "hashes": [ - "sha256:1adec0d67cdf6166bda96ae2934ddb5e54433998ceab63c984574d187cc563d2", - "sha256:d79d9a39e459fe33497c858470ca0d2e93cb96621751de06d631856adfd9c390" - ], - "version": "==0.8.1" - }, "docutils": { "hashes": [ "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af", @@ -180,11 +173,10 @@ }, "kubernetes": { "hashes": [ - "sha256:85a767d04f17d6d317374b6c35e09eb168a6bfd9276f0b3177cc206376bad968", - "sha256:9aa4f34431a442dda856bafc959bcf296cb5802f370361604c440093c702b17c" + "sha256:1a2472f8b01bc6aa87e3a34781f859bded5a5c8ff791a53d889a8bd6cc550430", + "sha256:4af81201520977139a143f96123fb789fa351879df37f122916b9b6ed050bbaf" ], - "index": "pypi", - "version": "==10.1.0" + "version": "==11.0.0" }, "lockfile": { "hashes": [ @@ -242,10 +234,10 @@ }, "openshift": { "hashes": [ - "sha256:d8462c4bc3eaaa5a11623d6d67048c3e0b16558fa23675ffd85157d66696ff39" + "sha256:110b0d3c84a83500f0fd150ab26dee29615157e6659bf72808788aa79fc17afc" ], "index": "pypi", - "version": "==0.10.3" + "version": "==0.11.2" }, "pexpect": { "hashes": [ @@ -364,19 +356,30 @@ }, "pyyaml": { "hashes": [ - "sha256:3d7da3009c0f3e783b2c873687652d83b1bbfd5c88e9813fb7e5b03c0dd3108b", - "sha256:3ef3092145e9b70e3ddd2c7ad59bdd0252a94dfe3949721633e41344de00a6bf", - "sha256:40c71b8e076d0550b2e6380bada1f1cd1017b882f7e16f09a65be98e017f211a", - "sha256:558dd60b890ba8fd982e05941927a3911dc409a63dcb8b634feaa0cda69330d3", - "sha256:a7c28b45d9f99102fa092bb213aa12e0aaf9a6a1f5e395d36166639c1f96c3a1", - "sha256:aa7dd4a6a427aed7df6fb7f08a580d68d9b118d90310374716ae90b710280af1", - "sha256:bc558586e6045763782014934bfaf39d48b8ae85a2713117d16c39864085c613", - "sha256:d46d7982b62e0729ad0175a9bc7e10a566fc07b224d2c79fafb5e032727eaa04", - "sha256:d5eef459e30b09f5a098b9cea68bebfeb268697f78d647bd255a085371ac7f3f", - "sha256:e01d3203230e1786cd91ccfdc8f8454c8069c91bee3962ad93b87a4b2860f537", - "sha256:e170a9e6fcfd19021dd29845af83bb79236068bf5fd4df3327c1be18182b2531" - ], - "version": "==3.13" + "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf", + "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696", + "sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393", + "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77", + "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922", + "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5", + "sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8", + "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10", + "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc", + "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018", + "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e", + "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253", + "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183", + "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb", + "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185", + "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db", + "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46", + "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b", + "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63", + "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df", + "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", + "version": "==5.4.1" }, "requests": { "hashes": [ From 03c374ad7e5a12d48507dd092988fc8af563b564 Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Thu, 21 Jan 2021 20:23:49 +0100 Subject: [PATCH 329/376] explain what/why of the change Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- ...er-base-images-for-ansible-and-helm-operators.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml diff --git a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml new file mode 100644 index 00000000000..bdb9f083f3a --- /dev/null +++ b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml @@ -0,0 +1,11 @@ +# entries is a list of entries to include in +# release notes and/or the migration guide +entries: + - description: > + For Ansible-based and Helm-based operators, the Docker base image is + pinned to improve the reproducibility of builds using Docker. + + kind: addition + + # Is this a breaking change? + breaking: false From 71f4634b844220eea9e488d311be08eff1b5c726 Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Thu, 21 Jan 2021 22:21:37 +0100 Subject: [PATCH 330/376] update to reflect pinning all images, rename change file to fit description Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- ...er-base-images-for-ansible-and-helm-operators.yaml | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml diff --git a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml deleted file mode 100644 index bdb9f083f3a..00000000000 --- a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml +++ /dev/null @@ -1,11 +0,0 @@ -# entries is a list of entries to include in -# release notes and/or the migration guide -entries: - - description: > - For Ansible-based and Helm-based operators, the Docker base image is - pinned to improve the reproducibility of builds using Docker. - - kind: addition - - # Is this a breaking change? - breaking: false From 1be76c497eabde60c8a32fe180a08064ee2c8e15 Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Fri, 22 Jan 2021 23:16:05 +0100 Subject: [PATCH 331/376] WIP: pipenv check stubles over pyyaml Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- images/ansible-operator/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/images/ansible-operator/Dockerfile b/images/ansible-operator/Dockerfile index e67d0da1508..fcb08fa0687 100644 --- a/images/ansible-operator/Dockerfile +++ b/images/ansible-operator/Dockerfile @@ -26,7 +26,7 @@ RUN yum clean all && rm -rf /var/cache/yum/* \ && yum clean all \ && rm -rf /var/cache/yum -RUN pipenv check +RUN pipenv check --system # Ensure directory permissions are properly set RUN echo "${USER_NAME}:x:${USER_UID}:0:${USER_NAME} user:${HOME}:/sbin/nologin" >> /etc/passwd \ From c7307db413f4a9bbee179b5ef7049cbb10d93cee Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Fri, 22 Jan 2021 23:32:25 +0100 Subject: [PATCH 332/376] use env vars to force pipenv to clear caches; install packages and do vulnerability checks in base site-packages Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- images/ansible-operator/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/images/ansible-operator/Dockerfile b/images/ansible-operator/Dockerfile index fcb08fa0687..e67d0da1508 100644 --- a/images/ansible-operator/Dockerfile +++ b/images/ansible-operator/Dockerfile @@ -26,7 +26,7 @@ RUN yum clean all && rm -rf /var/cache/yum/* \ && yum clean all \ && rm -rf /var/cache/yum -RUN pipenv check --system +RUN pipenv check # Ensure directory permissions are properly set RUN echo "${USER_NAME}:x:${USER_UID}:0:${USER_NAME} user:${HOME}:/sbin/nologin" >> /etc/passwd \ From ef04854ad6a7a1db483111c182a98db879d7827c Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Sat, 23 Jan 2021 17:20:25 +0100 Subject: [PATCH 333/376] upgrade ansible-runner to latest version 1.4.6, see https://ansible-runner.readthedocs.io/en/1.4.6/install.html#changelog since 1.3.4. No breaking changes according to log. Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- images/ansible-operator/Pipfile.lock | 485 +-------------------------- 1 file changed, 1 insertion(+), 484 deletions(-) diff --git a/images/ansible-operator/Pipfile.lock b/images/ansible-operator/Pipfile.lock index 088a45beb13..ddc6a164d27 100644 --- a/images/ansible-operator/Pipfile.lock +++ b/images/ansible-operator/Pipfile.lock @@ -1,484 +1 @@ -{ - "_meta": { - "hash": { - "sha256": "85039a7202a9c714cc0626c67bb854174b8c48f4d66907aae6981774f7836f7f" - }, - "pipfile-spec": 6, - "requires": { - "python_version": "3.8" - }, - "sources": [ - { - "name": "pypi", - "url": "https://pypi.org/simple", - "verify_ssl": true - } - ] - }, - "default": { - "ansible": { - "hashes": [ - "sha256:736a19fa6d608b4df2d6b48d31fec057b3f95abf62b7fda69ffa4a743e2f55b6" - ], - "index": "pypi", - "version": "==2.9.15" - }, - "ansible-runner": { - "hashes": [ - "sha256:0744642cff32d23310b3a5f5aae23d07bea1051724e66b27f9bbccefec8427dd", - "sha256:53605de32f7d3d3442a6deb8937bf1d9c1f91c785e3f71003d22c3e63f85c71d" - ], - "index": "pypi", - "version": "==1.4.6" - }, - "ansible-runner-http": { - "hashes": [ - "sha256:97da445b7d5c6663b0cceaf6bd5e9b0b0dff9a4c36eae43c8c916c6208aee915", - "sha256:e2f34880531d4088a5e04967fd5eae602eb400cc4eb541b22c8c6853e342587f" - ], - "index": "pypi", - "version": "==1.0.0" - }, - "cachetools": { - "hashes": [ - "sha256:3796e1de094f0eaca982441c92ce96c68c89cced4cd97721ab297ea4b16db90e", - "sha256:c6b07a6ded8c78bf36730b3dc452dfff7d95f2a12a2fed856b1a0cb13ca78c61" - ], - "markers": "python_version ~= '3.5'", - "version": "==4.2.0" - }, - "certifi": { - "hashes": [ - "sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c", - "sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830" - ], - "version": "==2020.12.5" - }, - "cffi": { - "hashes": [ - "sha256:00a1ba5e2e95684448de9b89888ccd02c98d512064b4cb987d48f4b40aa0421e", - "sha256:00e28066507bfc3fe865a31f325c8391a1ac2916219340f87dfad602c3e48e5d", - "sha256:045d792900a75e8b1e1b0ab6787dd733a8190ffcf80e8c8ceb2fb10a29ff238a", - "sha256:0638c3ae1a0edfb77c6765d487fee624d2b1ee1bdfeffc1f0b58c64d149e7eec", - "sha256:105abaf8a6075dc96c1fe5ae7aae073f4696f2905fde6aeada4c9d2926752362", - "sha256:155136b51fd733fa94e1c2ea5211dcd4c8879869008fc811648f16541bf99668", - "sha256:1a465cbe98a7fd391d47dce4b8f7e5b921e6cd805ef421d04f5f66ba8f06086c", - "sha256:1d2c4994f515e5b485fd6d3a73d05526aa0fcf248eb135996b088d25dfa1865b", - "sha256:2c24d61263f511551f740d1a065eb0212db1dbbbbd241db758f5244281590c06", - "sha256:51a8b381b16ddd370178a65360ebe15fbc1c71cf6f584613a7ea08bfad946698", - "sha256:594234691ac0e9b770aee9fcdb8fa02c22e43e5c619456efd0d6c2bf276f3eb2", - "sha256:5cf4be6c304ad0b6602f5c4e90e2f59b47653ac1ed9c662ed379fe48a8f26b0c", - "sha256:64081b3f8f6f3c3de6191ec89d7dc6c86a8a43911f7ecb422c60e90c70be41c7", - "sha256:6bc25fc545a6b3d57b5f8618e59fc13d3a3a68431e8ca5fd4c13241cd70d0009", - "sha256:798caa2a2384b1cbe8a2a139d80734c9db54f9cc155c99d7cc92441a23871c03", - "sha256:7c6b1dece89874d9541fc974917b631406233ea0440d0bdfbb8e03bf39a49b3b", - "sha256:840793c68105fe031f34d6a086eaea153a0cd5c491cde82a74b420edd0a2b909", - "sha256:8d6603078baf4e11edc4168a514c5ce5b3ba6e3e9c374298cb88437957960a53", - "sha256:9cc46bc107224ff5b6d04369e7c595acb700c3613ad7bcf2e2012f62ece80c35", - "sha256:9f7a31251289b2ab6d4012f6e83e58bc3b96bd151f5b5262467f4bb6b34a7c26", - "sha256:9ffb888f19d54a4d4dfd4b3f29bc2c16aa4972f1c2ab9c4ab09b8ab8685b9c2b", - "sha256:a5ed8c05548b54b998b9498753fb9cadbfd92ee88e884641377d8a8b291bcc01", - "sha256:a7711edca4dcef1a75257b50a2fbfe92a65187c47dab5a0f1b9b332c5919a3fb", - "sha256:af5c59122a011049aad5dd87424b8e65a80e4a6477419c0c1015f73fb5ea0293", - "sha256:b18e0a9ef57d2b41f5c68beefa32317d286c3d6ac0484efd10d6e07491bb95dd", - "sha256:b4e248d1087abf9f4c10f3c398896c87ce82a9856494a7155823eb45a892395d", - "sha256:ba4e9e0ae13fc41c6b23299545e5ef73055213e466bd107953e4a013a5ddd7e3", - "sha256:c6332685306b6417a91b1ff9fae889b3ba65c2292d64bd9245c093b1b284809d", - "sha256:d5ff0621c88ce83a28a10d2ce719b2ee85635e85c515f12bac99a95306da4b2e", - "sha256:d9efd8b7a3ef378dd61a1e77367f1924375befc2eba06168b6ebfa903a5e59ca", - "sha256:df5169c4396adc04f9b0a05f13c074df878b6052430e03f50e68adf3a57aa28d", - "sha256:ebb253464a5d0482b191274f1c8bf00e33f7e0b9c66405fbffc61ed2c839c775", - "sha256:ec80dc47f54e6e9a78181ce05feb71a0353854cc26999db963695f950b5fb375", - "sha256:f032b34669220030f905152045dfa27741ce1a6db3324a5bc0b96b6c7420c87b", - "sha256:f60567825f791c6f8a592f3c6e3bd93dd2934e3f9dac189308426bd76b00ef3b", - "sha256:f803eaa94c2fcda012c047e62bc7a51b0bdabda1cad7a92a522694ea2d76e49f" - ], - "version": "==1.14.4" - }, - "chardet": { - "hashes": [ - "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa", - "sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==4.0.0" - }, - "cryptography": { - "hashes": [ - "sha256:0003a52a123602e1acee177dc90dd201f9bb1e73f24a070db7d36c588e8f5c7d", - "sha256:0e85aaae861d0485eb5a79d33226dd6248d2a9f133b81532c8f5aae37de10ff7", - "sha256:594a1db4511bc4d960571536abe21b4e5c3003e8750ab8365fafce71c5d86901", - "sha256:69e836c9e5ff4373ce6d3ab311c1a2eed274793083858d3cd4c7d12ce20d5f9c", - "sha256:788a3c9942df5e4371c199d10383f44a105d67d401fb4304178020142f020244", - "sha256:7e177e4bea2de937a584b13645cab32f25e3d96fc0bc4a4cf99c27dc77682be6", - "sha256:83d9d2dfec70364a74f4e7c70ad04d3ca2e6a08b703606993407bf46b97868c5", - "sha256:84ef7a0c10c24a7773163f917f1cb6b4444597efd505a8aed0a22e8c4780f27e", - "sha256:9e21301f7a1e7c03dbea73e8602905a4ebba641547a462b26dd03451e5769e7c", - "sha256:9f6b0492d111b43de5f70052e24c1f0951cb9e6022188ebcb1cc3a3d301469b0", - "sha256:a69bd3c68b98298f490e84519b954335154917eaab52cf582fa2c5c7efc6e812", - "sha256:b4890d5fb9b7a23e3bf8abf5a8a7da8e228f1e97dc96b30b95685df840b6914a", - "sha256:c366df0401d1ec4e548bebe8f91d55ebcc0ec3137900d214dd7aac8427ef3030", - "sha256:dc42f645f8f3a489c3dd416730a514e7a91a59510ddaadc09d04224c098d3302" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", - "version": "==3.3.1" - }, - "docutils": { - "hashes": [ - "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af", - "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==0.16" - }, - "google-auth": { - "hashes": [ - "sha256:0b0e026b412a0ad096e753907559e4bdb180d9ba9f68dd9036164db4fdc4ad2e", - "sha256:ce752cc51c31f479dbf9928435ef4b07514b20261b021c7383bee4bda646acb8" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", - "version": "==1.24.0" - }, - "idna": { - "hashes": [ - "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6", - "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==2.10" - }, - "ipaddress": { - "hashes": [ - "sha256:6e0f4a39e66cb5bb9a137b00276a2eff74f93b71dcbdad6f10ff7df9d3557fcc", - "sha256:b7f8e0369580bb4a24d5ba1d7cc29660a4a6987763faf1d8a8046830e020e7e2" - ], - "index": "pypi", - "version": "==1.0.23" - }, - "jinja2": { - "hashes": [ - "sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0", - "sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==2.11.2" - }, - "jmespath": { - "hashes": [ - "sha256:b85d0567b8666149a93172712e68920734333c0ce7e89b78b3e987f71e5ed4f9", - "sha256:cdf6525904cc597730141d61b36f2e4b8ecc257c420fa2f4549bac2c2d0cb72f" - ], - "index": "pypi", - "version": "==0.10.0" - }, - "kubernetes": { - "hashes": [ - "sha256:1a2472f8b01bc6aa87e3a34781f859bded5a5c8ff791a53d889a8bd6cc550430", - "sha256:4af81201520977139a143f96123fb789fa351879df37f122916b9b6ed050bbaf" - ], - "version": "==11.0.0" - }, - "lockfile": { - "hashes": [ - "sha256:6aed02de03cba24efabcd600b30540140634fc06cfa603822d508d5361e9f799", - "sha256:6c3cb24f344923d30b2785d5ad75182c8ea7ac1b6171b08657258ec7429d50fa" - ], - "version": "==0.12.2" - }, - "markupsafe": { - "hashes": [ - "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", - "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", - "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", - "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", - "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42", - "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", - "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", - "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", - "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", - "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", - "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", - "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b", - "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", - "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15", - "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", - "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", - "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", - "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", - "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", - "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", - "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", - "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", - "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", - "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", - "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", - "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", - "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", - "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", - "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", - "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", - "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2", - "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7", - "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.1.1" - }, - "oauthlib": { - "hashes": [ - "sha256:bee41cc35fcca6e988463cacc3bcb8a96224f470ca547e697b604cc697b2f889", - "sha256:df884cd6cbe20e32633f1db1072e9356f53638e4361bef4e8b03c9127c9328ea" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==3.1.0" - }, - "openshift": { - "hashes": [ - "sha256:110b0d3c84a83500f0fd150ab26dee29615157e6659bf72808788aa79fc17afc" - ], - "index": "pypi", - "version": "==0.11.2" - }, - "pexpect": { - "hashes": [ - "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937", - "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c" - ], - "version": "==4.8.0" - }, - "psutil": { - "hashes": [ - "sha256:0066a82f7b1b37d334e68697faba68e5ad5e858279fd6351c8ca6024e8d6ba64", - "sha256:02b8292609b1f7fcb34173b25e48d0da8667bc85f81d7476584d889c6e0f2131", - "sha256:0ae6f386d8d297177fd288be6e8d1afc05966878704dad9847719650e44fc49c", - "sha256:0c9ccb99ab76025f2f0bbecf341d4656e9c1351db8cc8a03ccd62e318ab4b5c6", - "sha256:0dd4465a039d343925cdc29023bb6960ccf4e74a65ad53e768403746a9207023", - "sha256:12d844996d6c2b1d3881cfa6fa201fd635971869a9da945cf6756105af73d2df", - "sha256:1bff0d07e76114ec24ee32e7f7f8d0c4b0514b3fae93e3d2aaafd65d22502394", - "sha256:245b5509968ac0bd179287d91210cd3f37add77dad385ef238b275bad35fa1c4", - "sha256:28ff7c95293ae74bf1ca1a79e8805fcde005c18a122ca983abf676ea3466362b", - "sha256:36b3b6c9e2a34b7d7fbae330a85bf72c30b1c827a4366a07443fc4b6270449e2", - "sha256:52de075468cd394ac98c66f9ca33b2f54ae1d9bff1ef6b67a212ee8f639ec06d", - "sha256:5da29e394bdedd9144c7331192e20c1f79283fb03b06e6abd3a8ae45ffecee65", - "sha256:61f05864b42fedc0771d6d8e49c35f07efd209ade09a5afe6a5059e7bb7bf83d", - "sha256:6223d07a1ae93f86451d0198a0c361032c4c93ebd4bf6d25e2fb3edfad9571ef", - "sha256:6323d5d845c2785efb20aded4726636546b26d3b577aded22492908f7c1bdda7", - "sha256:6ffe81843131ee0ffa02c317186ed1e759a145267d54fdef1bc4ea5f5931ab60", - "sha256:74f2d0be88db96ada78756cb3a3e1b107ce8ab79f65aa885f76d7664e56928f6", - "sha256:74fb2557d1430fff18ff0d72613c5ca30c45cdbfcddd6a5773e9fc1fe9364be8", - "sha256:90d4091c2d30ddd0a03e0b97e6a33a48628469b99585e2ad6bf21f17423b112b", - "sha256:90f31c34d25b1b3ed6c40cdd34ff122b1887a825297c017e4cbd6796dd8b672d", - "sha256:99de3e8739258b3c3e8669cb9757c9a861b2a25ad0955f8e53ac662d66de61ac", - "sha256:c6a5fd10ce6b6344e616cf01cc5b849fa8103fbb5ba507b6b2dee4c11e84c935", - "sha256:ce8b867423291cb65cfc6d9c4955ee9bfc1e21fe03bb50e177f2b957f1c2469d", - "sha256:d225cd8319aa1d3c85bf195c4e07d17d3cd68636b8fc97e6cf198f782f99af28", - "sha256:ea313bb02e5e25224e518e4352af4bf5e062755160f77e4b1767dd5ccb65f876", - "sha256:ea372bcc129394485824ae3e3ddabe67dc0b118d262c568b4d2602a7070afdb0", - "sha256:f4634b033faf0d968bb9220dd1c793b897ab7f1189956e1aa9eae752527127d3", - "sha256:fcc01e900c1d7bee2a37e5d6e4f9194760a93597c97fee89c4ae51701de03563" - ], - "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==5.8.0" - }, - "ptyprocess": { - "hashes": [ - "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", - "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220" - ], - "version": "==0.7.0" - }, - "pyasn1": { - "hashes": [ - "sha256:014c0e9976956a08139dc0712ae195324a75e142284d5f87f1a87ee1b068a359", - "sha256:03840c999ba71680a131cfaee6fab142e1ed9bbd9c693e285cc6aca0d555e576", - "sha256:0458773cfe65b153891ac249bcf1b5f8f320b7c2ce462151f8fa74de8934becf", - "sha256:08c3c53b75eaa48d71cf8c710312316392ed40899cb34710d092e96745a358b7", - "sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d", - "sha256:5c9414dcfede6e441f7e8f81b43b34e834731003427e5b09e4e00e3172a10f00", - "sha256:6e7545f1a61025a4e58bb336952c5061697da694db1cae97b116e9c46abcf7c8", - "sha256:78fa6da68ed2727915c4767bb386ab32cdba863caa7dbe473eaae45f9959da86", - "sha256:7ab8a544af125fb704feadb008c99a88805126fb525280b2270bb25cc1d78a12", - "sha256:99fcc3c8d804d1bc6d9a099921e39d827026409a58f2a720dcdb89374ea0c776", - "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba", - "sha256:e89bf84b5437b532b0803ba5c9a5e054d21fec423a89952a74f87fa2c9b7bce2", - "sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3" - ], - "version": "==0.4.8" - }, - "pyasn1-modules": { - "hashes": [ - "sha256:0845a5582f6a02bb3e1bde9ecfc4bfcae6ec3210dd270522fee602365430c3f8", - "sha256:0fe1b68d1e486a1ed5473f1302bd991c1611d319bba158e98b106ff86e1d7199", - "sha256:15b7c67fabc7fc240d87fb9aabf999cf82311a6d6fb2c70d00d3d0604878c811", - "sha256:426edb7a5e8879f1ec54a1864f16b882c2837bfd06eee62f2c982315ee2473ed", - "sha256:65cebbaffc913f4fe9e4808735c95ea22d7a7775646ab690518c056784bc21b4", - "sha256:905f84c712230b2c592c19470d3ca8d552de726050d1d1716282a1f6146be65e", - "sha256:a50b808ffeb97cb3601dd25981f6b016cbb3d31fbf57a8b8a87428e6158d0c74", - "sha256:a99324196732f53093a84c4369c996713eb8c89d360a496b599fb1a9c47fc3eb", - "sha256:b80486a6c77252ea3a3e9b1e360bc9cf28eaac41263d173c032581ad2f20fe45", - "sha256:c29a5e5cc7a3f05926aff34e097e84f8589cd790ce0ed41b67aed6857b26aafd", - "sha256:cbac4bc38d117f2a49aeedec4407d23e8866ea4ac27ff2cf7fb3e5b570df19e0", - "sha256:f39edd8c4ecaa4556e989147ebf219227e2cd2e8a43c7e7fcb1f1c18c5fd6a3d", - "sha256:fe0644d9ab041506b62782e92b06b8c68cca799e1a9636ec398675459e031405" - ], - "version": "==0.2.8" - }, - "pycparser": { - "hashes": [ - "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0", - "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==2.20" - }, - "python-daemon": { - "hashes": [ - "sha256:57c84f50a04d7825515e4dbf3a31c70cc44414394a71608dee6cfde469e81766", - "sha256:a0d5dc0b435a02c7e0b401e177a7c17c3f4c7b4e22e2d06271122c8fec5f8946" - ], - "version": "==2.2.4" - }, - "python-dateutil": { - "hashes": [ - "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c", - "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==2.8.1" - }, - "python-string-utils": { - "hashes": [ - "sha256:dcf9060b03f07647c0a603408dc8b03f807f3b54a05c6e19eb14460256fac0cb", - "sha256:f1a88700baf99db1a9b6953f44181ad9ca56623c81e257e6009707e2e7851fa4" - ], - "markers": "python_version >= '3.5'", - "version": "==1.0.0" - }, - "pyyaml": { - "hashes": [ - "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf", - "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696", - "sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393", - "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77", - "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922", - "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5", - "sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8", - "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10", - "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc", - "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018", - "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e", - "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253", - "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183", - "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb", - "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185", - "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db", - "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46", - "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b", - "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63", - "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df", - "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", - "version": "==5.4.1" - }, - "requests": { - "hashes": [ - "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804", - "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==2.25.1" - }, - "requests-oauthlib": { - "hashes": [ - "sha256:7f71572defaecd16372f9006f33c2ec8c077c3cfa6f5911a9a90202beb513f3d", - "sha256:b4261601a71fd721a8bd6d7aa1cc1d6a8a93b4a9f5e96626f8e4d91e8beeaa6a", - "sha256:fa6c47b933f01060936d87ae9327fead68768b69c6c9ea2109c48be30f2d4dbc" - ], - "version": "==1.3.0" - }, - "requests-unixsocket": { - "hashes": [ - "sha256:014d07bfb66dc805a011a8b4b306cf4ec96d2eddb589f6b2b5765e626f0dc0cc", - "sha256:9e5c1a20afc3cf786197ae59c79bcdb0e7565f218f27df5f891307ee8817c1ea" - ], - "version": "==0.2.0" - }, - "rsa": { - "hashes": [ - "sha256:69805d6b69f56eb05b62daea3a7dbd7aa44324ad1306445e05da8060232d00f4", - "sha256:a8774e55b59fd9fc893b0d05e9bfc6f47081f46ff5b46f39ccf24631b7be356b" - ], - "markers": "python_version >= '3.6'", - "version": "==4.7" - }, - "ruamel.yaml": { - "hashes": [ - "sha256:012b9470a0ea06e4e44e99e7920277edf6b46eee0232a04487ea73a7386340a5", - "sha256:076cc0bc34f1966d920a49f18b52b6ad559fbe656a0748e3535cf7b3f29ebf9e" - ], - "version": "==0.16.12" - }, - "ruamel.yaml.clib": { - "hashes": [ - "sha256:058a1cc3df2a8aecc12f983a48bda99315cebf55a3b3a5463e37bb599b05727b", - "sha256:1236df55e0f73cd138c0eca074ee086136c3f16a97c2ac719032c050f7e0622f", - "sha256:1f8c0a4577c0e6c99d208de5c4d3fd8aceed9574bb154d7a2b21c16bb924154c", - "sha256:2602e91bd5c1b874d6f93d3086f9830f3e907c543c7672cf293a97c3fabdcd91", - "sha256:28116f204103cb3a108dfd37668f20abe6e3cafd0d3fd40dba126c732457b3cc", - "sha256:2d24bd98af676f4990c4d715bcdc2a60b19c56a3fb3a763164d2d8ca0e806ba7", - "sha256:2fd336a5c6415c82e2deb40d08c222087febe0aebe520f4d21910629018ab0f3", - "sha256:30dca9bbcbb1cc858717438218d11eafb78666759e5094dd767468c0d577a7e7", - "sha256:44c7b0498c39f27795224438f1a6be6c5352f82cb887bc33d962c3a3acc00df6", - "sha256:464e66a04e740d754170be5e740657a3b3b6d2bcc567f0c3437879a6e6087ff6", - "sha256:46d6d20815064e8bb023ea8628cfb7402c0f0e83de2c2227a88097e239a7dffd", - "sha256:4df5019e7783d14b79217ad9c56edf1ba7485d614ad5a385d1b3c768635c81c0", - "sha256:4e52c96ca66de04be42ea2278012a2342d89f5e82b4512fb6fb7134e377e2e62", - "sha256:5254af7d8bdf4d5484c089f929cb7f5bafa59b4f01d4f48adda4be41e6d29f99", - "sha256:52ae5739e4b5d6317b52f5b040b1b6639e8af68a5b8fd606a8b08658fbd0cab5", - "sha256:53b9dd1abd70e257a6e32f934ebc482dac5edb8c93e23deb663eac724c30b026", - "sha256:6c0a5dc52fc74eb87c67374a4e554d4761fd42a4d01390b7e868b30d21f4b8bb", - "sha256:73b3d43e04cc4b228fa6fa5d796409ece6fcb53a6c270eb2048109cbcbc3b9c2", - "sha256:74161d827407f4db9072011adcfb825b5258a5ccb3d2cd518dd6c9edea9e30f1", - "sha256:75f0ee6839532e52a3a53f80ce64925ed4aed697dd3fa890c4c918f3304bd4f4", - "sha256:839dd72545ef7ba78fd2aa1a5dd07b33696adf3e68fae7f31327161c1093001b", - "sha256:8be05be57dc5c7b4a0b24edcaa2f7275866d9c907725226cdde46da09367d923", - "sha256:8e8fd0a22c9d92af3a34f91e8a2594eeb35cba90ab643c5e0e643567dc8be43e", - "sha256:a873e4d4954f865dcb60bdc4914af7eaae48fb56b60ed6daa1d6251c72f5337c", - "sha256:ab845f1f51f7eb750a78937be9f79baea4a42c7960f5a94dde34e69f3cce1988", - "sha256:b1e981fe1aff1fd11627f531524826a4dcc1f26c726235a52fcb62ded27d150f", - "sha256:b4b0d31f2052b3f9f9b5327024dc629a253a83d8649d4734ca7f35b60ec3e9e5", - "sha256:c6ac7e45367b1317e56f1461719c853fd6825226f45b835df7436bb04031fd8a", - "sha256:daf21aa33ee9b351f66deed30a3d450ab55c14242cfdfcd377798e2c0d25c9f1", - "sha256:e9f7d1d8c26a6a12c23421061f9022bb62704e38211fe375c645485f38df34a2", - "sha256:f6061a31880c1ed6b6ce341215336e2f3d0c1deccd84957b6fa8ca474b41e89f" - ], - "markers": "python_version < '3.9' and platform_python_implementation == 'CPython'", - "version": "==0.2.2" - }, - "six": { - "hashes": [ - "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259", - "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.15.0" - }, - "urllib3": { - "hashes": [ - "sha256:19188f96923873c92ccb987120ec4acaa12f0461fa9ce5d3d0772bc965a39e08", - "sha256:d8ff90d979214d7b4f8ce956e80f4028fc6860e4431f731ea4a8c08f23f99473" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'", - "version": "==1.26.2" - }, - "websocket-client": { - "hashes": [ - "sha256:0fc45c961324d79c781bab301359d5a1b00b13ad1b10415a4780229ef71a5549", - "sha256:d735b91d6d1692a6a181f2a8c9e0238e5f6373356f561bb9dc4c7af36f452010" - ], - "version": "==0.57.0" - } - }, - "develop": {} -} +{ "_meta": { "hash": { "sha256": "85039a7202a9c714cc0626c67bb854174b8c48f4d66907aae6981774f7836f7f" }, "pipfile-spec": 6, "requires": { "python_version": "3.8" }, "sources": [ { "name": "pypi", "url": "https://pypi.org/simple", "verify_ssl": true } ] }, "default": { "ansible": { "hashes": [ "sha256:736a19fa6d608b4df2d6b48d31fec057b3f95abf62b7fda69ffa4a743e2f55b6" ], "index": "pypi", "version": "==2.9.15" }, "ansible-runner": { "hashes": [ "sha256:0744642cff32d23310b3a5f5aae23d07bea1051724e66b27f9bbccefec8427dd", "sha256:53605de32f7d3d3442a6deb8937bf1d9c1f91c785e3f71003d22c3e63f85c71d" ], "index": "pypi", "version": "==1.4.6" }, "ansible-runner-http": { "hashes": [ "sha256:97da445b7d5c6663b0cceaf6bd5e9b0b0dff9a4c36eae43c8c916c6208aee915", "sha256:e2f34880531d4088a5e04967fd5eae602eb400cc4eb541b22c8c6853e342587f" ], "index": "pypi", "version": "==1.0.0" }, "cachetools": { "hashes": [ "sha256:3796e1de094f0eaca982441c92ce96c68c89cced4cd97721ab297ea4b16db90e", "sha256:c6b07a6ded8c78bf36730b3dc452dfff7d95f2a12a2fed856b1a0cb13ca78c61" ], "markers": "python_version ~= '3.5'", "version": "==4.2.0" }, "certifi": { "hashes": [ "sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c", "sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830" ], "version": "==2020.12.5" }, "cffi": { "hashes": [ "sha256:00a1ba5e2e95684448de9b89888ccd02c98d512064b4cb987d48f4b40aa0421e", "sha256:00e28066507bfc3fe865a31f325c8391a1ac2916219340f87dfad602c3e48e5d", "sha256:045d792900a75e8b1e1b0ab6787dd733a8190ffcf80e8c8ceb2fb10a29ff238a", "sha256:0638c3ae1a0edfb77c6765d487fee624d2b1ee1bdfeffc1f0b58c64d149e7eec", "sha256:105abaf8a6075dc96c1fe5ae7aae073f4696f2905fde6aeada4c9d2926752362", "sha256:155136b51fd733fa94e1c2ea5211dcd4c8879869008fc811648f16541bf99668", "sha256:1a465cbe98a7fd391d47dce4b8f7e5b921e6cd805ef421d04f5f66ba8f06086c", "sha256:1d2c4994f515e5b485fd6d3a73d05526aa0fcf248eb135996b088d25dfa1865b", "sha256:2c24d61263f511551f740d1a065eb0212db1dbbbbd241db758f5244281590c06", "sha256:51a8b381b16ddd370178a65360ebe15fbc1c71cf6f584613a7ea08bfad946698", "sha256:594234691ac0e9b770aee9fcdb8fa02c22e43e5c619456efd0d6c2bf276f3eb2", "sha256:5cf4be6c304ad0b6602f5c4e90e2f59b47653ac1ed9c662ed379fe48a8f26b0c", "sha256:64081b3f8f6f3c3de6191ec89d7dc6c86a8a43911f7ecb422c60e90c70be41c7", "sha256:6bc25fc545a6b3d57b5f8618e59fc13d3a3a68431e8ca5fd4c13241cd70d0009", "sha256:798caa2a2384b1cbe8a2a139d80734c9db54f9cc155c99d7cc92441a23871c03", "sha256:7c6b1dece89874d9541fc974917b631406233ea0440d0bdfbb8e03bf39a49b3b", "sha256:840793c68105fe031f34d6a086eaea153a0cd5c491cde82a74b420edd0a2b909", "sha256:8d6603078baf4e11edc4168a514c5ce5b3ba6e3e9c374298cb88437957960a53", "sha256:9cc46bc107224ff5b6d04369e7c595acb700c3613ad7bcf2e2012f62ece80c35", "sha256:9f7a31251289b2ab6d4012f6e83e58bc3b96bd151f5b5262467f4bb6b34a7c26", "sha256:9ffb888f19d54a4d4dfd4b3f29bc2c16aa4972f1c2ab9c4ab09b8ab8685b9c2b", "sha256:a5ed8c05548b54b998b9498753fb9cadbfd92ee88e884641377d8a8b291bcc01", "sha256:a7711edca4dcef1a75257b50a2fbfe92a65187c47dab5a0f1b9b332c5919a3fb", "sha256:af5c59122a011049aad5dd87424b8e65a80e4a6477419c0c1015f73fb5ea0293", "sha256:b18e0a9ef57d2b41f5c68beefa32317d286c3d6ac0484efd10d6e07491bb95dd", "sha256:b4e248d1087abf9f4c10f3c398896c87ce82a9856494a7155823eb45a892395d", "sha256:ba4e9e0ae13fc41c6b23299545e5ef73055213e466bd107953e4a013a5ddd7e3", "sha256:c6332685306b6417a91b1ff9fae889b3ba65c2292d64bd9245c093b1b284809d", "sha256:d5ff0621c88ce83a28a10d2ce719b2ee85635e85c515f12bac99a95306da4b2e", "sha256:d9efd8b7a3ef378dd61a1e77367f1924375befc2eba06168b6ebfa903a5e59ca", "sha256:df5169c4396adc04f9b0a05f13c074df878b6052430e03f50e68adf3a57aa28d", "sha256:ebb253464a5d0482b191274f1c8bf00e33f7e0b9c66405fbffc61ed2c839c775", "sha256:ec80dc47f54e6e9a78181ce05feb71a0353854cc26999db963695f950b5fb375", "sha256:f032b34669220030f905152045dfa27741ce1a6db3324a5bc0b96b6c7420c87b", "sha256:f60567825f791c6f8a592f3c6e3bd93dd2934e3f9dac189308426bd76b00ef3b", "sha256:f803eaa94c2fcda012c047e62bc7a51b0bdabda1cad7a92a522694ea2d76e49f" ], "version": "==1.14.4" }, "chardet": { "hashes": [ "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa", "sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "version": "==4.0.0" }, "cryptography": { "hashes": [ "sha256:0003a52a123602e1acee177dc90dd201f9bb1e73f24a070db7d36c588e8f5c7d", "sha256:0e85aaae861d0485eb5a79d33226dd6248d2a9f133b81532c8f5aae37de10ff7", "sha256:594a1db4511bc4d960571536abe21b4e5c3003e8750ab8365fafce71c5d86901", "sha256:69e836c9e5ff4373ce6d3ab311c1a2eed274793083858d3cd4c7d12ce20d5f9c", "sha256:788a3c9942df5e4371c199d10383f44a105d67d401fb4304178020142f020244", "sha256:7e177e4bea2de937a584b13645cab32f25e3d96fc0bc4a4cf99c27dc77682be6", "sha256:83d9d2dfec70364a74f4e7c70ad04d3ca2e6a08b703606993407bf46b97868c5", "sha256:84ef7a0c10c24a7773163f917f1cb6b4444597efd505a8aed0a22e8c4780f27e", "sha256:9e21301f7a1e7c03dbea73e8602905a4ebba641547a462b26dd03451e5769e7c", "sha256:9f6b0492d111b43de5f70052e24c1f0951cb9e6022188ebcb1cc3a3d301469b0", "sha256:a69bd3c68b98298f490e84519b954335154917eaab52cf582fa2c5c7efc6e812", "sha256:b4890d5fb9b7a23e3bf8abf5a8a7da8e228f1e97dc96b30b95685df840b6914a", "sha256:c366df0401d1ec4e548bebe8f91d55ebcc0ec3137900d214dd7aac8427ef3030", "sha256:dc42f645f8f3a489c3dd416730a514e7a91a59510ddaadc09d04224c098d3302" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", "version": "==3.3.1" }, "docutils": { "hashes": [ "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af", "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "version": "==0.16" }, "google-auth": { "hashes": [ "sha256:0b0e026b412a0ad096e753907559e4bdb180d9ba9f68dd9036164db4fdc4ad2e", "sha256:ce752cc51c31f479dbf9928435ef4b07514b20261b021c7383bee4bda646acb8" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", "version": "==1.24.0" }, "idna": { "hashes": [ "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6", "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.10" }, "ipaddress": { "hashes": [ "sha256:6e0f4a39e66cb5bb9a137b00276a2eff74f93b71dcbdad6f10ff7df9d3557fcc", "sha256:b7f8e0369580bb4a24d5ba1d7cc29660a4a6987763faf1d8a8046830e020e7e2" ], "index": "pypi", "version": "==1.0.23" }, "jinja2": { "hashes": [ "sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0", "sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "version": "==2.11.2" }, "jmespath": { "hashes": [ "sha256:b85d0567b8666149a93172712e68920734333c0ce7e89b78b3e987f71e5ed4f9", "sha256:cdf6525904cc597730141d61b36f2e4b8ecc257c420fa2f4549bac2c2d0cb72f" ], "index": "pypi", "version": "==0.10.0" }, "kubernetes": { "hashes": [ "sha256:1a2472f8b01bc6aa87e3a34781f859bded5a5c8ff791a53d889a8bd6cc550430", "sha256:4af81201520977139a143f96123fb789fa351879df37f122916b9b6ed050bbaf" ], "version": "==11.0.0" }, "lockfile": { "hashes": [ "sha256:6aed02de03cba24efabcd600b30540140634fc06cfa603822d508d5361e9f799", "sha256:6c3cb24f344923d30b2785d5ad75182c8ea7ac1b6171b08657258ec7429d50fa" ], "version": "==0.12.2" }, "markupsafe": { "hashes": [ "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42", "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b", "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15", "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2", "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7", "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.1.1" }, "oauthlib": { "hashes": [ "sha256:bee41cc35fcca6e988463cacc3bcb8a96224f470ca547e697b604cc697b2f889", "sha256:df884cd6cbe20e32633f1db1072e9356f53638e4361bef4e8b03c9127c9328ea" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==3.1.0" }, "openshift": { "hashes": [ "sha256:110b0d3c84a83500f0fd150ab26dee29615157e6659bf72808788aa79fc17afc" ], "index": "pypi", "version": "==0.11.2" }, "pexpect": { "hashes": [ "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937", "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c" ], "version": "==4.8.0" }, "psutil": { "hashes": [ "sha256:0066a82f7b1b37d334e68697faba68e5ad5e858279fd6351c8ca6024e8d6ba64", "sha256:02b8292609b1f7fcb34173b25e48d0da8667bc85f81d7476584d889c6e0f2131", "sha256:0ae6f386d8d297177fd288be6e8d1afc05966878704dad9847719650e44fc49c", "sha256:0c9ccb99ab76025f2f0bbecf341d4656e9c1351db8cc8a03ccd62e318ab4b5c6", "sha256:0dd4465a039d343925cdc29023bb6960ccf4e74a65ad53e768403746a9207023", "sha256:12d844996d6c2b1d3881cfa6fa201fd635971869a9da945cf6756105af73d2df", "sha256:1bff0d07e76114ec24ee32e7f7f8d0c4b0514b3fae93e3d2aaafd65d22502394", "sha256:245b5509968ac0bd179287d91210cd3f37add77dad385ef238b275bad35fa1c4", "sha256:28ff7c95293ae74bf1ca1a79e8805fcde005c18a122ca983abf676ea3466362b", "sha256:36b3b6c9e2a34b7d7fbae330a85bf72c30b1c827a4366a07443fc4b6270449e2", "sha256:52de075468cd394ac98c66f9ca33b2f54ae1d9bff1ef6b67a212ee8f639ec06d", "sha256:5da29e394bdedd9144c7331192e20c1f79283fb03b06e6abd3a8ae45ffecee65", "sha256:61f05864b42fedc0771d6d8e49c35f07efd209ade09a5afe6a5059e7bb7bf83d", "sha256:6223d07a1ae93f86451d0198a0c361032c4c93ebd4bf6d25e2fb3edfad9571ef", "sha256:6323d5d845c2785efb20aded4726636546b26d3b577aded22492908f7c1bdda7", "sha256:6ffe81843131ee0ffa02c317186ed1e759a145267d54fdef1bc4ea5f5931ab60", "sha256:74f2d0be88db96ada78756cb3a3e1b107ce8ab79f65aa885f76d7664e56928f6", "sha256:74fb2557d1430fff18ff0d72613c5ca30c45cdbfcddd6a5773e9fc1fe9364be8", "sha256:90d4091c2d30ddd0a03e0b97e6a33a48628469b99585e2ad6bf21f17423b112b", "sha256:90f31c34d25b1b3ed6c40cdd34ff122b1887a825297c017e4cbd6796dd8b672d", "sha256:99de3e8739258b3c3e8669cb9757c9a861b2a25ad0955f8e53ac662d66de61ac", "sha256:c6a5fd10ce6b6344e616cf01cc5b849fa8103fbb5ba507b6b2dee4c11e84c935", "sha256:ce8b867423291cb65cfc6d9c4955ee9bfc1e21fe03bb50e177f2b957f1c2469d", "sha256:d225cd8319aa1d3c85bf195c4e07d17d3cd68636b8fc97e6cf198f782f99af28", "sha256:ea313bb02e5e25224e518e4352af4bf5e062755160f77e4b1767dd5ccb65f876", "sha256:ea372bcc129394485824ae3e3ddabe67dc0b118d262c568b4d2602a7070afdb0", "sha256:f4634b033faf0d968bb9220dd1c793b897ab7f1189956e1aa9eae752527127d3", "sha256:fcc01e900c1d7bee2a37e5d6e4f9194760a93597c97fee89c4ae51701de03563" ], "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==5.8.0" }, "ptyprocess": { "hashes": [ "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220" ], "version": "==0.7.0" }, "pyasn1": { "hashes": [ "sha256:014c0e9976956a08139dc0712ae195324a75e142284d5f87f1a87ee1b068a359", "sha256:03840c999ba71680a131cfaee6fab142e1ed9bbd9c693e285cc6aca0d555e576", "sha256:0458773cfe65b153891ac249bcf1b5f8f320b7c2ce462151f8fa74de8934becf", "sha256:08c3c53b75eaa48d71cf8c710312316392ed40899cb34710d092e96745a358b7", "sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d", "sha256:5c9414dcfede6e441f7e8f81b43b34e834731003427e5b09e4e00e3172a10f00", "sha256:6e7545f1a61025a4e58bb336952c5061697da694db1cae97b116e9c46abcf7c8", "sha256:78fa6da68ed2727915c4767bb386ab32cdba863caa7dbe473eaae45f9959da86", "sha256:7ab8a544af125fb704feadb008c99a88805126fb525280b2270bb25cc1d78a12", "sha256:99fcc3c8d804d1bc6d9a099921e39d827026409a58f2a720dcdb89374ea0c776", "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba", "sha256:e89bf84b5437b532b0803ba5c9a5e054d21fec423a89952a74f87fa2c9b7bce2", "sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3" ], "version": "==0.4.8" }, "pyasn1-modules": { "hashes": [ "sha256:0845a5582f6a02bb3e1bde9ecfc4bfcae6ec3210dd270522fee602365430c3f8", "sha256:0fe1b68d1e486a1ed5473f1302bd991c1611d319bba158e98b106ff86e1d7199", "sha256:15b7c67fabc7fc240d87fb9aabf999cf82311a6d6fb2c70d00d3d0604878c811", "sha256:426edb7a5e8879f1ec54a1864f16b882c2837bfd06eee62f2c982315ee2473ed", "sha256:65cebbaffc913f4fe9e4808735c95ea22d7a7775646ab690518c056784bc21b4", "sha256:905f84c712230b2c592c19470d3ca8d552de726050d1d1716282a1f6146be65e", "sha256:a50b808ffeb97cb3601dd25981f6b016cbb3d31fbf57a8b8a87428e6158d0c74", "sha256:a99324196732f53093a84c4369c996713eb8c89d360a496b599fb1a9c47fc3eb", "sha256:b80486a6c77252ea3a3e9b1e360bc9cf28eaac41263d173c032581ad2f20fe45", "sha256:c29a5e5cc7a3f05926aff34e097e84f8589cd790ce0ed41b67aed6857b26aafd", "sha256:cbac4bc38d117f2a49aeedec4407d23e8866ea4ac27ff2cf7fb3e5b570df19e0", "sha256:f39edd8c4ecaa4556e989147ebf219227e2cd2e8a43c7e7fcb1f1c18c5fd6a3d", "sha256:fe0644d9ab041506b62782e92b06b8c68cca799e1a9636ec398675459e031405" ], "version": "==0.2.8" }, "pycparser": { "hashes": [ "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0", "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.20" }, "python-daemon": { "hashes": [ "sha256:57c84f50a04d7825515e4dbf3a31c70cc44414394a71608dee6cfde469e81766", "sha256:a0d5dc0b435a02c7e0b401e177a7c17c3f4c7b4e22e2d06271122c8fec5f8946" ], "version": "==2.2.4" }, "python-dateutil": { "hashes": [ "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c", "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.8.1" }, "python-string-utils": { "hashes": [ "sha256:dcf9060b03f07647c0a603408dc8b03f807f3b54a05c6e19eb14460256fac0cb", "sha256:f1a88700baf99db1a9b6953f44181ad9ca56623c81e257e6009707e2e7851fa4" ], "markers": "python_version >= '3.5'", "version": "==1.0.0" }, "pyyaml": { "hashes": [ "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf", "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696", "sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393", "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77", "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922", "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5", "sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8", "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10", "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc", "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018", "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e", "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253", "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183", "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb", "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185", "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db", "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46", "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b", "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63", "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df", "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", "version": "==5.4.1" }, "requests": { "hashes": [ "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804", "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "version": "==2.25.1" }, "requests-oauthlib": { "hashes": [ "sha256:7f71572defaecd16372f9006f33c2ec8c077c3cfa6f5911a9a90202beb513f3d", "sha256:b4261601a71fd721a8bd6d7aa1cc1d6a8a93b4a9f5e96626f8e4d91e8beeaa6a", "sha256:fa6c47b933f01060936d87ae9327fead68768b69c6c9ea2109c48be30f2d4dbc" ], "version": "==1.3.0" }, "requests-unixsocket": { "hashes": [ "sha256:014d07bfb66dc805a011a8b4b306cf4ec96d2eddb589f6b2b5765e626f0dc0cc", "sha256:9e5c1a20afc3cf786197ae59c79bcdb0e7565f218f27df5f891307ee8817c1ea" ], "version": "==0.2.0" }, "rsa": { "hashes": [ "sha256:69805d6b69f56eb05b62daea3a7dbd7aa44324ad1306445e05da8060232d00f4", "sha256:a8774e55b59fd9fc893b0d05e9bfc6f47081f46ff5b46f39ccf24631b7be356b" ], "markers": "python_version >= '3.6'", "version": "==4.7" }, "ruamel.yaml": { "hashes": [ "sha256:012b9470a0ea06e4e44e99e7920277edf6b46eee0232a04487ea73a7386340a5", "sha256:076cc0bc34f1966d920a49f18b52b6ad559fbe656a0748e3535cf7b3f29ebf9e" ], "version": "==0.16.12" }, "ruamel.yaml.clib": { "hashes": [ "sha256:058a1cc3df2a8aecc12f983a48bda99315cebf55a3b3a5463e37bb599b05727b", "sha256:1236df55e0f73cd138c0eca074ee086136c3f16a97c2ac719032c050f7e0622f", "sha256:1f8c0a4577c0e6c99d208de5c4d3fd8aceed9574bb154d7a2b21c16bb924154c", "sha256:2602e91bd5c1b874d6f93d3086f9830f3e907c543c7672cf293a97c3fabdcd91", "sha256:28116f204103cb3a108dfd37668f20abe6e3cafd0d3fd40dba126c732457b3cc", "sha256:2d24bd98af676f4990c4d715bcdc2a60b19c56a3fb3a763164d2d8ca0e806ba7", "sha256:2fd336a5c6415c82e2deb40d08c222087febe0aebe520f4d21910629018ab0f3", "sha256:30dca9bbcbb1cc858717438218d11eafb78666759e5094dd767468c0d577a7e7", "sha256:44c7b0498c39f27795224438f1a6be6c5352f82cb887bc33d962c3a3acc00df6", "sha256:464e66a04e740d754170be5e740657a3b3b6d2bcc567f0c3437879a6e6087ff6", "sha256:46d6d20815064e8bb023ea8628cfb7402c0f0e83de2c2227a88097e239a7dffd", "sha256:4df5019e7783d14b79217ad9c56edf1ba7485d614ad5a385d1b3c768635c81c0", "sha256:4e52c96ca66de04be42ea2278012a2342d89f5e82b4512fb6fb7134e377e2e62", "sha256:5254af7d8bdf4d5484c089f929cb7f5bafa59b4f01d4f48adda4be41e6d29f99", "sha256:52ae5739e4b5d6317b52f5b040b1b6639e8af68a5b8fd606a8b08658fbd0cab5", "sha256:53b9dd1abd70e257a6e32f934ebc482dac5edb8c93e23deb663eac724c30b026", "sha256:6c0a5dc52fc74eb87c67374a4e554d4761fd42a4d01390b7e868b30d21f4b8bb", "sha256:73b3d43e04cc4b228fa6fa5d796409ece6fcb53a6c270eb2048109cbcbc3b9c2", "sha256:74161d827407f4db9072011adcfb825b5258a5ccb3d2cd518dd6c9edea9e30f1", "sha256:75f0ee6839532e52a3a53f80ce64925ed4aed697dd3fa890c4c918f3304bd4f4", "sha256:839dd72545ef7ba78fd2aa1a5dd07b33696adf3e68fae7f31327161c1093001b", "sha256:8be05be57dc5c7b4a0b24edcaa2f7275866d9c907725226cdde46da09367d923", "sha256:8e8fd0a22c9d92af3a34f91e8a2594eeb35cba90ab643c5e0e643567dc8be43e", "sha256:a873e4d4954f865dcb60bdc4914af7eaae48fb56b60ed6daa1d6251c72f5337c", "sha256:ab845f1f51f7eb750a78937be9f79baea4a42c7960f5a94dde34e69f3cce1988", "sha256:b1e981fe1aff1fd11627f531524826a4dcc1f26c726235a52fcb62ded27d150f", "sha256:b4b0d31f2052b3f9f9b5327024dc629a253a83d8649d4734ca7f35b60ec3e9e5", "sha256:c6ac7e45367b1317e56f1461719c853fd6825226f45b835df7436bb04031fd8a", "sha256:daf21aa33ee9b351f66deed30a3d450ab55c14242cfdfcd377798e2c0d25c9f1", "sha256:e9f7d1d8c26a6a12c23421061f9022bb62704e38211fe375c645485f38df34a2", "sha256:f6061a31880c1ed6b6ce341215336e2f3d0c1deccd84957b6fa8ca474b41e89f" ], "markers": "python_version < '3.9' and platform_python_implementation == 'CPython'", "version": "==0.2.2" }, "six": { "hashes": [ "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259", "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.15.0" }, "urllib3": { "hashes": [ "sha256:19188f96923873c92ccb987120ec4acaa12f0461fa9ce5d3d0772bc965a39e08", "sha256:d8ff90d979214d7b4f8ce956e80f4028fc6860e4431f731ea4a8c08f23f99473" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'", "version": "==1.26.2" }, "websocket-client": { "hashes": [ "sha256:0fc45c961324d79c781bab301359d5a1b00b13ad1b10415a4780229ef71a5549", "sha256:d735b91d6d1692a6a181f2a8c9e0238e5f6373356f561bb9dc4c7af36f452010" ], "version": "==0.57.0" } }, "develop": {} } \ No newline at end of file From 3ae53906fcc5718b6d6369b7c54cab80d44998f8 Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Sat, 23 Jan 2021 19:18:05 +0100 Subject: [PATCH 334/376] upgrade openshift lib, remove kubernetes: it is already installed as a pinned-version dependency of openshift. Fixes dependency on vulnerable pyyamml version Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- images/ansible-operator/Pipfile.lock | 485 ++++++++++++++++++++++++++- 1 file changed, 484 insertions(+), 1 deletion(-) diff --git a/images/ansible-operator/Pipfile.lock b/images/ansible-operator/Pipfile.lock index ddc6a164d27..088a45beb13 100644 --- a/images/ansible-operator/Pipfile.lock +++ b/images/ansible-operator/Pipfile.lock @@ -1 +1,484 @@ -{ "_meta": { "hash": { "sha256": "85039a7202a9c714cc0626c67bb854174b8c48f4d66907aae6981774f7836f7f" }, "pipfile-spec": 6, "requires": { "python_version": "3.8" }, "sources": [ { "name": "pypi", "url": "https://pypi.org/simple", "verify_ssl": true } ] }, "default": { "ansible": { "hashes": [ "sha256:736a19fa6d608b4df2d6b48d31fec057b3f95abf62b7fda69ffa4a743e2f55b6" ], "index": "pypi", "version": "==2.9.15" }, "ansible-runner": { "hashes": [ "sha256:0744642cff32d23310b3a5f5aae23d07bea1051724e66b27f9bbccefec8427dd", "sha256:53605de32f7d3d3442a6deb8937bf1d9c1f91c785e3f71003d22c3e63f85c71d" ], "index": "pypi", "version": "==1.4.6" }, "ansible-runner-http": { "hashes": [ "sha256:97da445b7d5c6663b0cceaf6bd5e9b0b0dff9a4c36eae43c8c916c6208aee915", "sha256:e2f34880531d4088a5e04967fd5eae602eb400cc4eb541b22c8c6853e342587f" ], "index": "pypi", "version": "==1.0.0" }, "cachetools": { "hashes": [ "sha256:3796e1de094f0eaca982441c92ce96c68c89cced4cd97721ab297ea4b16db90e", "sha256:c6b07a6ded8c78bf36730b3dc452dfff7d95f2a12a2fed856b1a0cb13ca78c61" ], "markers": "python_version ~= '3.5'", "version": "==4.2.0" }, "certifi": { "hashes": [ "sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c", "sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830" ], "version": "==2020.12.5" }, "cffi": { "hashes": [ "sha256:00a1ba5e2e95684448de9b89888ccd02c98d512064b4cb987d48f4b40aa0421e", "sha256:00e28066507bfc3fe865a31f325c8391a1ac2916219340f87dfad602c3e48e5d", "sha256:045d792900a75e8b1e1b0ab6787dd733a8190ffcf80e8c8ceb2fb10a29ff238a", "sha256:0638c3ae1a0edfb77c6765d487fee624d2b1ee1bdfeffc1f0b58c64d149e7eec", "sha256:105abaf8a6075dc96c1fe5ae7aae073f4696f2905fde6aeada4c9d2926752362", "sha256:155136b51fd733fa94e1c2ea5211dcd4c8879869008fc811648f16541bf99668", "sha256:1a465cbe98a7fd391d47dce4b8f7e5b921e6cd805ef421d04f5f66ba8f06086c", "sha256:1d2c4994f515e5b485fd6d3a73d05526aa0fcf248eb135996b088d25dfa1865b", "sha256:2c24d61263f511551f740d1a065eb0212db1dbbbbd241db758f5244281590c06", "sha256:51a8b381b16ddd370178a65360ebe15fbc1c71cf6f584613a7ea08bfad946698", "sha256:594234691ac0e9b770aee9fcdb8fa02c22e43e5c619456efd0d6c2bf276f3eb2", "sha256:5cf4be6c304ad0b6602f5c4e90e2f59b47653ac1ed9c662ed379fe48a8f26b0c", "sha256:64081b3f8f6f3c3de6191ec89d7dc6c86a8a43911f7ecb422c60e90c70be41c7", "sha256:6bc25fc545a6b3d57b5f8618e59fc13d3a3a68431e8ca5fd4c13241cd70d0009", "sha256:798caa2a2384b1cbe8a2a139d80734c9db54f9cc155c99d7cc92441a23871c03", "sha256:7c6b1dece89874d9541fc974917b631406233ea0440d0bdfbb8e03bf39a49b3b", "sha256:840793c68105fe031f34d6a086eaea153a0cd5c491cde82a74b420edd0a2b909", "sha256:8d6603078baf4e11edc4168a514c5ce5b3ba6e3e9c374298cb88437957960a53", "sha256:9cc46bc107224ff5b6d04369e7c595acb700c3613ad7bcf2e2012f62ece80c35", "sha256:9f7a31251289b2ab6d4012f6e83e58bc3b96bd151f5b5262467f4bb6b34a7c26", "sha256:9ffb888f19d54a4d4dfd4b3f29bc2c16aa4972f1c2ab9c4ab09b8ab8685b9c2b", "sha256:a5ed8c05548b54b998b9498753fb9cadbfd92ee88e884641377d8a8b291bcc01", "sha256:a7711edca4dcef1a75257b50a2fbfe92a65187c47dab5a0f1b9b332c5919a3fb", "sha256:af5c59122a011049aad5dd87424b8e65a80e4a6477419c0c1015f73fb5ea0293", "sha256:b18e0a9ef57d2b41f5c68beefa32317d286c3d6ac0484efd10d6e07491bb95dd", "sha256:b4e248d1087abf9f4c10f3c398896c87ce82a9856494a7155823eb45a892395d", "sha256:ba4e9e0ae13fc41c6b23299545e5ef73055213e466bd107953e4a013a5ddd7e3", "sha256:c6332685306b6417a91b1ff9fae889b3ba65c2292d64bd9245c093b1b284809d", "sha256:d5ff0621c88ce83a28a10d2ce719b2ee85635e85c515f12bac99a95306da4b2e", "sha256:d9efd8b7a3ef378dd61a1e77367f1924375befc2eba06168b6ebfa903a5e59ca", "sha256:df5169c4396adc04f9b0a05f13c074df878b6052430e03f50e68adf3a57aa28d", "sha256:ebb253464a5d0482b191274f1c8bf00e33f7e0b9c66405fbffc61ed2c839c775", "sha256:ec80dc47f54e6e9a78181ce05feb71a0353854cc26999db963695f950b5fb375", "sha256:f032b34669220030f905152045dfa27741ce1a6db3324a5bc0b96b6c7420c87b", "sha256:f60567825f791c6f8a592f3c6e3bd93dd2934e3f9dac189308426bd76b00ef3b", "sha256:f803eaa94c2fcda012c047e62bc7a51b0bdabda1cad7a92a522694ea2d76e49f" ], "version": "==1.14.4" }, "chardet": { "hashes": [ "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa", "sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "version": "==4.0.0" }, "cryptography": { "hashes": [ "sha256:0003a52a123602e1acee177dc90dd201f9bb1e73f24a070db7d36c588e8f5c7d", "sha256:0e85aaae861d0485eb5a79d33226dd6248d2a9f133b81532c8f5aae37de10ff7", "sha256:594a1db4511bc4d960571536abe21b4e5c3003e8750ab8365fafce71c5d86901", "sha256:69e836c9e5ff4373ce6d3ab311c1a2eed274793083858d3cd4c7d12ce20d5f9c", "sha256:788a3c9942df5e4371c199d10383f44a105d67d401fb4304178020142f020244", "sha256:7e177e4bea2de937a584b13645cab32f25e3d96fc0bc4a4cf99c27dc77682be6", "sha256:83d9d2dfec70364a74f4e7c70ad04d3ca2e6a08b703606993407bf46b97868c5", "sha256:84ef7a0c10c24a7773163f917f1cb6b4444597efd505a8aed0a22e8c4780f27e", "sha256:9e21301f7a1e7c03dbea73e8602905a4ebba641547a462b26dd03451e5769e7c", "sha256:9f6b0492d111b43de5f70052e24c1f0951cb9e6022188ebcb1cc3a3d301469b0", "sha256:a69bd3c68b98298f490e84519b954335154917eaab52cf582fa2c5c7efc6e812", "sha256:b4890d5fb9b7a23e3bf8abf5a8a7da8e228f1e97dc96b30b95685df840b6914a", "sha256:c366df0401d1ec4e548bebe8f91d55ebcc0ec3137900d214dd7aac8427ef3030", "sha256:dc42f645f8f3a489c3dd416730a514e7a91a59510ddaadc09d04224c098d3302" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", "version": "==3.3.1" }, "docutils": { "hashes": [ "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af", "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "version": "==0.16" }, "google-auth": { "hashes": [ "sha256:0b0e026b412a0ad096e753907559e4bdb180d9ba9f68dd9036164db4fdc4ad2e", "sha256:ce752cc51c31f479dbf9928435ef4b07514b20261b021c7383bee4bda646acb8" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", "version": "==1.24.0" }, "idna": { "hashes": [ "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6", "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.10" }, "ipaddress": { "hashes": [ "sha256:6e0f4a39e66cb5bb9a137b00276a2eff74f93b71dcbdad6f10ff7df9d3557fcc", "sha256:b7f8e0369580bb4a24d5ba1d7cc29660a4a6987763faf1d8a8046830e020e7e2" ], "index": "pypi", "version": "==1.0.23" }, "jinja2": { "hashes": [ "sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0", "sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "version": "==2.11.2" }, "jmespath": { "hashes": [ "sha256:b85d0567b8666149a93172712e68920734333c0ce7e89b78b3e987f71e5ed4f9", "sha256:cdf6525904cc597730141d61b36f2e4b8ecc257c420fa2f4549bac2c2d0cb72f" ], "index": "pypi", "version": "==0.10.0" }, "kubernetes": { "hashes": [ "sha256:1a2472f8b01bc6aa87e3a34781f859bded5a5c8ff791a53d889a8bd6cc550430", "sha256:4af81201520977139a143f96123fb789fa351879df37f122916b9b6ed050bbaf" ], "version": "==11.0.0" }, "lockfile": { "hashes": [ "sha256:6aed02de03cba24efabcd600b30540140634fc06cfa603822d508d5361e9f799", "sha256:6c3cb24f344923d30b2785d5ad75182c8ea7ac1b6171b08657258ec7429d50fa" ], "version": "==0.12.2" }, "markupsafe": { "hashes": [ "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42", "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b", "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15", "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2", "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7", "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.1.1" }, "oauthlib": { "hashes": [ "sha256:bee41cc35fcca6e988463cacc3bcb8a96224f470ca547e697b604cc697b2f889", "sha256:df884cd6cbe20e32633f1db1072e9356f53638e4361bef4e8b03c9127c9328ea" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==3.1.0" }, "openshift": { "hashes": [ "sha256:110b0d3c84a83500f0fd150ab26dee29615157e6659bf72808788aa79fc17afc" ], "index": "pypi", "version": "==0.11.2" }, "pexpect": { "hashes": [ "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937", "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c" ], "version": "==4.8.0" }, "psutil": { "hashes": [ "sha256:0066a82f7b1b37d334e68697faba68e5ad5e858279fd6351c8ca6024e8d6ba64", "sha256:02b8292609b1f7fcb34173b25e48d0da8667bc85f81d7476584d889c6e0f2131", "sha256:0ae6f386d8d297177fd288be6e8d1afc05966878704dad9847719650e44fc49c", "sha256:0c9ccb99ab76025f2f0bbecf341d4656e9c1351db8cc8a03ccd62e318ab4b5c6", "sha256:0dd4465a039d343925cdc29023bb6960ccf4e74a65ad53e768403746a9207023", "sha256:12d844996d6c2b1d3881cfa6fa201fd635971869a9da945cf6756105af73d2df", "sha256:1bff0d07e76114ec24ee32e7f7f8d0c4b0514b3fae93e3d2aaafd65d22502394", "sha256:245b5509968ac0bd179287d91210cd3f37add77dad385ef238b275bad35fa1c4", "sha256:28ff7c95293ae74bf1ca1a79e8805fcde005c18a122ca983abf676ea3466362b", "sha256:36b3b6c9e2a34b7d7fbae330a85bf72c30b1c827a4366a07443fc4b6270449e2", "sha256:52de075468cd394ac98c66f9ca33b2f54ae1d9bff1ef6b67a212ee8f639ec06d", "sha256:5da29e394bdedd9144c7331192e20c1f79283fb03b06e6abd3a8ae45ffecee65", "sha256:61f05864b42fedc0771d6d8e49c35f07efd209ade09a5afe6a5059e7bb7bf83d", "sha256:6223d07a1ae93f86451d0198a0c361032c4c93ebd4bf6d25e2fb3edfad9571ef", "sha256:6323d5d845c2785efb20aded4726636546b26d3b577aded22492908f7c1bdda7", "sha256:6ffe81843131ee0ffa02c317186ed1e759a145267d54fdef1bc4ea5f5931ab60", "sha256:74f2d0be88db96ada78756cb3a3e1b107ce8ab79f65aa885f76d7664e56928f6", "sha256:74fb2557d1430fff18ff0d72613c5ca30c45cdbfcddd6a5773e9fc1fe9364be8", "sha256:90d4091c2d30ddd0a03e0b97e6a33a48628469b99585e2ad6bf21f17423b112b", "sha256:90f31c34d25b1b3ed6c40cdd34ff122b1887a825297c017e4cbd6796dd8b672d", "sha256:99de3e8739258b3c3e8669cb9757c9a861b2a25ad0955f8e53ac662d66de61ac", "sha256:c6a5fd10ce6b6344e616cf01cc5b849fa8103fbb5ba507b6b2dee4c11e84c935", "sha256:ce8b867423291cb65cfc6d9c4955ee9bfc1e21fe03bb50e177f2b957f1c2469d", "sha256:d225cd8319aa1d3c85bf195c4e07d17d3cd68636b8fc97e6cf198f782f99af28", "sha256:ea313bb02e5e25224e518e4352af4bf5e062755160f77e4b1767dd5ccb65f876", "sha256:ea372bcc129394485824ae3e3ddabe67dc0b118d262c568b4d2602a7070afdb0", "sha256:f4634b033faf0d968bb9220dd1c793b897ab7f1189956e1aa9eae752527127d3", "sha256:fcc01e900c1d7bee2a37e5d6e4f9194760a93597c97fee89c4ae51701de03563" ], "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==5.8.0" }, "ptyprocess": { "hashes": [ "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220" ], "version": "==0.7.0" }, "pyasn1": { "hashes": [ "sha256:014c0e9976956a08139dc0712ae195324a75e142284d5f87f1a87ee1b068a359", "sha256:03840c999ba71680a131cfaee6fab142e1ed9bbd9c693e285cc6aca0d555e576", "sha256:0458773cfe65b153891ac249bcf1b5f8f320b7c2ce462151f8fa74de8934becf", "sha256:08c3c53b75eaa48d71cf8c710312316392ed40899cb34710d092e96745a358b7", "sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d", "sha256:5c9414dcfede6e441f7e8f81b43b34e834731003427e5b09e4e00e3172a10f00", "sha256:6e7545f1a61025a4e58bb336952c5061697da694db1cae97b116e9c46abcf7c8", "sha256:78fa6da68ed2727915c4767bb386ab32cdba863caa7dbe473eaae45f9959da86", "sha256:7ab8a544af125fb704feadb008c99a88805126fb525280b2270bb25cc1d78a12", "sha256:99fcc3c8d804d1bc6d9a099921e39d827026409a58f2a720dcdb89374ea0c776", "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba", "sha256:e89bf84b5437b532b0803ba5c9a5e054d21fec423a89952a74f87fa2c9b7bce2", "sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3" ], "version": "==0.4.8" }, "pyasn1-modules": { "hashes": [ "sha256:0845a5582f6a02bb3e1bde9ecfc4bfcae6ec3210dd270522fee602365430c3f8", "sha256:0fe1b68d1e486a1ed5473f1302bd991c1611d319bba158e98b106ff86e1d7199", "sha256:15b7c67fabc7fc240d87fb9aabf999cf82311a6d6fb2c70d00d3d0604878c811", "sha256:426edb7a5e8879f1ec54a1864f16b882c2837bfd06eee62f2c982315ee2473ed", "sha256:65cebbaffc913f4fe9e4808735c95ea22d7a7775646ab690518c056784bc21b4", "sha256:905f84c712230b2c592c19470d3ca8d552de726050d1d1716282a1f6146be65e", "sha256:a50b808ffeb97cb3601dd25981f6b016cbb3d31fbf57a8b8a87428e6158d0c74", "sha256:a99324196732f53093a84c4369c996713eb8c89d360a496b599fb1a9c47fc3eb", "sha256:b80486a6c77252ea3a3e9b1e360bc9cf28eaac41263d173c032581ad2f20fe45", "sha256:c29a5e5cc7a3f05926aff34e097e84f8589cd790ce0ed41b67aed6857b26aafd", "sha256:cbac4bc38d117f2a49aeedec4407d23e8866ea4ac27ff2cf7fb3e5b570df19e0", "sha256:f39edd8c4ecaa4556e989147ebf219227e2cd2e8a43c7e7fcb1f1c18c5fd6a3d", "sha256:fe0644d9ab041506b62782e92b06b8c68cca799e1a9636ec398675459e031405" ], "version": "==0.2.8" }, "pycparser": { "hashes": [ "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0", "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.20" }, "python-daemon": { "hashes": [ "sha256:57c84f50a04d7825515e4dbf3a31c70cc44414394a71608dee6cfde469e81766", "sha256:a0d5dc0b435a02c7e0b401e177a7c17c3f4c7b4e22e2d06271122c8fec5f8946" ], "version": "==2.2.4" }, "python-dateutil": { "hashes": [ "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c", "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.8.1" }, "python-string-utils": { "hashes": [ "sha256:dcf9060b03f07647c0a603408dc8b03f807f3b54a05c6e19eb14460256fac0cb", "sha256:f1a88700baf99db1a9b6953f44181ad9ca56623c81e257e6009707e2e7851fa4" ], "markers": "python_version >= '3.5'", "version": "==1.0.0" }, "pyyaml": { "hashes": [ "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf", "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696", "sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393", "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77", "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922", "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5", "sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8", "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10", "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc", "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018", "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e", "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253", "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183", "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb", "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185", "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db", "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46", "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b", "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63", "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df", "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", "version": "==5.4.1" }, "requests": { "hashes": [ "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804", "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "version": "==2.25.1" }, "requests-oauthlib": { "hashes": [ "sha256:7f71572defaecd16372f9006f33c2ec8c077c3cfa6f5911a9a90202beb513f3d", "sha256:b4261601a71fd721a8bd6d7aa1cc1d6a8a93b4a9f5e96626f8e4d91e8beeaa6a", "sha256:fa6c47b933f01060936d87ae9327fead68768b69c6c9ea2109c48be30f2d4dbc" ], "version": "==1.3.0" }, "requests-unixsocket": { "hashes": [ "sha256:014d07bfb66dc805a011a8b4b306cf4ec96d2eddb589f6b2b5765e626f0dc0cc", "sha256:9e5c1a20afc3cf786197ae59c79bcdb0e7565f218f27df5f891307ee8817c1ea" ], "version": "==0.2.0" }, "rsa": { "hashes": [ "sha256:69805d6b69f56eb05b62daea3a7dbd7aa44324ad1306445e05da8060232d00f4", "sha256:a8774e55b59fd9fc893b0d05e9bfc6f47081f46ff5b46f39ccf24631b7be356b" ], "markers": "python_version >= '3.6'", "version": "==4.7" }, "ruamel.yaml": { "hashes": [ "sha256:012b9470a0ea06e4e44e99e7920277edf6b46eee0232a04487ea73a7386340a5", "sha256:076cc0bc34f1966d920a49f18b52b6ad559fbe656a0748e3535cf7b3f29ebf9e" ], "version": "==0.16.12" }, "ruamel.yaml.clib": { "hashes": [ "sha256:058a1cc3df2a8aecc12f983a48bda99315cebf55a3b3a5463e37bb599b05727b", "sha256:1236df55e0f73cd138c0eca074ee086136c3f16a97c2ac719032c050f7e0622f", "sha256:1f8c0a4577c0e6c99d208de5c4d3fd8aceed9574bb154d7a2b21c16bb924154c", "sha256:2602e91bd5c1b874d6f93d3086f9830f3e907c543c7672cf293a97c3fabdcd91", "sha256:28116f204103cb3a108dfd37668f20abe6e3cafd0d3fd40dba126c732457b3cc", "sha256:2d24bd98af676f4990c4d715bcdc2a60b19c56a3fb3a763164d2d8ca0e806ba7", "sha256:2fd336a5c6415c82e2deb40d08c222087febe0aebe520f4d21910629018ab0f3", "sha256:30dca9bbcbb1cc858717438218d11eafb78666759e5094dd767468c0d577a7e7", "sha256:44c7b0498c39f27795224438f1a6be6c5352f82cb887bc33d962c3a3acc00df6", "sha256:464e66a04e740d754170be5e740657a3b3b6d2bcc567f0c3437879a6e6087ff6", "sha256:46d6d20815064e8bb023ea8628cfb7402c0f0e83de2c2227a88097e239a7dffd", "sha256:4df5019e7783d14b79217ad9c56edf1ba7485d614ad5a385d1b3c768635c81c0", "sha256:4e52c96ca66de04be42ea2278012a2342d89f5e82b4512fb6fb7134e377e2e62", "sha256:5254af7d8bdf4d5484c089f929cb7f5bafa59b4f01d4f48adda4be41e6d29f99", "sha256:52ae5739e4b5d6317b52f5b040b1b6639e8af68a5b8fd606a8b08658fbd0cab5", "sha256:53b9dd1abd70e257a6e32f934ebc482dac5edb8c93e23deb663eac724c30b026", "sha256:6c0a5dc52fc74eb87c67374a4e554d4761fd42a4d01390b7e868b30d21f4b8bb", "sha256:73b3d43e04cc4b228fa6fa5d796409ece6fcb53a6c270eb2048109cbcbc3b9c2", "sha256:74161d827407f4db9072011adcfb825b5258a5ccb3d2cd518dd6c9edea9e30f1", "sha256:75f0ee6839532e52a3a53f80ce64925ed4aed697dd3fa890c4c918f3304bd4f4", "sha256:839dd72545ef7ba78fd2aa1a5dd07b33696adf3e68fae7f31327161c1093001b", "sha256:8be05be57dc5c7b4a0b24edcaa2f7275866d9c907725226cdde46da09367d923", "sha256:8e8fd0a22c9d92af3a34f91e8a2594eeb35cba90ab643c5e0e643567dc8be43e", "sha256:a873e4d4954f865dcb60bdc4914af7eaae48fb56b60ed6daa1d6251c72f5337c", "sha256:ab845f1f51f7eb750a78937be9f79baea4a42c7960f5a94dde34e69f3cce1988", "sha256:b1e981fe1aff1fd11627f531524826a4dcc1f26c726235a52fcb62ded27d150f", "sha256:b4b0d31f2052b3f9f9b5327024dc629a253a83d8649d4734ca7f35b60ec3e9e5", "sha256:c6ac7e45367b1317e56f1461719c853fd6825226f45b835df7436bb04031fd8a", "sha256:daf21aa33ee9b351f66deed30a3d450ab55c14242cfdfcd377798e2c0d25c9f1", "sha256:e9f7d1d8c26a6a12c23421061f9022bb62704e38211fe375c645485f38df34a2", "sha256:f6061a31880c1ed6b6ce341215336e2f3d0c1deccd84957b6fa8ca474b41e89f" ], "markers": "python_version < '3.9' and platform_python_implementation == 'CPython'", "version": "==0.2.2" }, "six": { "hashes": [ "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259", "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.15.0" }, "urllib3": { "hashes": [ "sha256:19188f96923873c92ccb987120ec4acaa12f0461fa9ce5d3d0772bc965a39e08", "sha256:d8ff90d979214d7b4f8ce956e80f4028fc6860e4431f731ea4a8c08f23f99473" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'", "version": "==1.26.2" }, "websocket-client": { "hashes": [ "sha256:0fc45c961324d79c781bab301359d5a1b00b13ad1b10415a4780229ef71a5549", "sha256:d735b91d6d1692a6a181f2a8c9e0238e5f6373356f561bb9dc4c7af36f452010" ], "version": "==0.57.0" } }, "develop": {} } \ No newline at end of file +{ + "_meta": { + "hash": { + "sha256": "85039a7202a9c714cc0626c67bb854174b8c48f4d66907aae6981774f7836f7f" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.8" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "ansible": { + "hashes": [ + "sha256:736a19fa6d608b4df2d6b48d31fec057b3f95abf62b7fda69ffa4a743e2f55b6" + ], + "index": "pypi", + "version": "==2.9.15" + }, + "ansible-runner": { + "hashes": [ + "sha256:0744642cff32d23310b3a5f5aae23d07bea1051724e66b27f9bbccefec8427dd", + "sha256:53605de32f7d3d3442a6deb8937bf1d9c1f91c785e3f71003d22c3e63f85c71d" + ], + "index": "pypi", + "version": "==1.4.6" + }, + "ansible-runner-http": { + "hashes": [ + "sha256:97da445b7d5c6663b0cceaf6bd5e9b0b0dff9a4c36eae43c8c916c6208aee915", + "sha256:e2f34880531d4088a5e04967fd5eae602eb400cc4eb541b22c8c6853e342587f" + ], + "index": "pypi", + "version": "==1.0.0" + }, + "cachetools": { + "hashes": [ + "sha256:3796e1de094f0eaca982441c92ce96c68c89cced4cd97721ab297ea4b16db90e", + "sha256:c6b07a6ded8c78bf36730b3dc452dfff7d95f2a12a2fed856b1a0cb13ca78c61" + ], + "markers": "python_version ~= '3.5'", + "version": "==4.2.0" + }, + "certifi": { + "hashes": [ + "sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c", + "sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830" + ], + "version": "==2020.12.5" + }, + "cffi": { + "hashes": [ + "sha256:00a1ba5e2e95684448de9b89888ccd02c98d512064b4cb987d48f4b40aa0421e", + "sha256:00e28066507bfc3fe865a31f325c8391a1ac2916219340f87dfad602c3e48e5d", + "sha256:045d792900a75e8b1e1b0ab6787dd733a8190ffcf80e8c8ceb2fb10a29ff238a", + "sha256:0638c3ae1a0edfb77c6765d487fee624d2b1ee1bdfeffc1f0b58c64d149e7eec", + "sha256:105abaf8a6075dc96c1fe5ae7aae073f4696f2905fde6aeada4c9d2926752362", + "sha256:155136b51fd733fa94e1c2ea5211dcd4c8879869008fc811648f16541bf99668", + "sha256:1a465cbe98a7fd391d47dce4b8f7e5b921e6cd805ef421d04f5f66ba8f06086c", + "sha256:1d2c4994f515e5b485fd6d3a73d05526aa0fcf248eb135996b088d25dfa1865b", + "sha256:2c24d61263f511551f740d1a065eb0212db1dbbbbd241db758f5244281590c06", + "sha256:51a8b381b16ddd370178a65360ebe15fbc1c71cf6f584613a7ea08bfad946698", + "sha256:594234691ac0e9b770aee9fcdb8fa02c22e43e5c619456efd0d6c2bf276f3eb2", + "sha256:5cf4be6c304ad0b6602f5c4e90e2f59b47653ac1ed9c662ed379fe48a8f26b0c", + "sha256:64081b3f8f6f3c3de6191ec89d7dc6c86a8a43911f7ecb422c60e90c70be41c7", + "sha256:6bc25fc545a6b3d57b5f8618e59fc13d3a3a68431e8ca5fd4c13241cd70d0009", + "sha256:798caa2a2384b1cbe8a2a139d80734c9db54f9cc155c99d7cc92441a23871c03", + "sha256:7c6b1dece89874d9541fc974917b631406233ea0440d0bdfbb8e03bf39a49b3b", + "sha256:840793c68105fe031f34d6a086eaea153a0cd5c491cde82a74b420edd0a2b909", + "sha256:8d6603078baf4e11edc4168a514c5ce5b3ba6e3e9c374298cb88437957960a53", + "sha256:9cc46bc107224ff5b6d04369e7c595acb700c3613ad7bcf2e2012f62ece80c35", + "sha256:9f7a31251289b2ab6d4012f6e83e58bc3b96bd151f5b5262467f4bb6b34a7c26", + "sha256:9ffb888f19d54a4d4dfd4b3f29bc2c16aa4972f1c2ab9c4ab09b8ab8685b9c2b", + "sha256:a5ed8c05548b54b998b9498753fb9cadbfd92ee88e884641377d8a8b291bcc01", + "sha256:a7711edca4dcef1a75257b50a2fbfe92a65187c47dab5a0f1b9b332c5919a3fb", + "sha256:af5c59122a011049aad5dd87424b8e65a80e4a6477419c0c1015f73fb5ea0293", + "sha256:b18e0a9ef57d2b41f5c68beefa32317d286c3d6ac0484efd10d6e07491bb95dd", + "sha256:b4e248d1087abf9f4c10f3c398896c87ce82a9856494a7155823eb45a892395d", + "sha256:ba4e9e0ae13fc41c6b23299545e5ef73055213e466bd107953e4a013a5ddd7e3", + "sha256:c6332685306b6417a91b1ff9fae889b3ba65c2292d64bd9245c093b1b284809d", + "sha256:d5ff0621c88ce83a28a10d2ce719b2ee85635e85c515f12bac99a95306da4b2e", + "sha256:d9efd8b7a3ef378dd61a1e77367f1924375befc2eba06168b6ebfa903a5e59ca", + "sha256:df5169c4396adc04f9b0a05f13c074df878b6052430e03f50e68adf3a57aa28d", + "sha256:ebb253464a5d0482b191274f1c8bf00e33f7e0b9c66405fbffc61ed2c839c775", + "sha256:ec80dc47f54e6e9a78181ce05feb71a0353854cc26999db963695f950b5fb375", + "sha256:f032b34669220030f905152045dfa27741ce1a6db3324a5bc0b96b6c7420c87b", + "sha256:f60567825f791c6f8a592f3c6e3bd93dd2934e3f9dac189308426bd76b00ef3b", + "sha256:f803eaa94c2fcda012c047e62bc7a51b0bdabda1cad7a92a522694ea2d76e49f" + ], + "version": "==1.14.4" + }, + "chardet": { + "hashes": [ + "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa", + "sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==4.0.0" + }, + "cryptography": { + "hashes": [ + "sha256:0003a52a123602e1acee177dc90dd201f9bb1e73f24a070db7d36c588e8f5c7d", + "sha256:0e85aaae861d0485eb5a79d33226dd6248d2a9f133b81532c8f5aae37de10ff7", + "sha256:594a1db4511bc4d960571536abe21b4e5c3003e8750ab8365fafce71c5d86901", + "sha256:69e836c9e5ff4373ce6d3ab311c1a2eed274793083858d3cd4c7d12ce20d5f9c", + "sha256:788a3c9942df5e4371c199d10383f44a105d67d401fb4304178020142f020244", + "sha256:7e177e4bea2de937a584b13645cab32f25e3d96fc0bc4a4cf99c27dc77682be6", + "sha256:83d9d2dfec70364a74f4e7c70ad04d3ca2e6a08b703606993407bf46b97868c5", + "sha256:84ef7a0c10c24a7773163f917f1cb6b4444597efd505a8aed0a22e8c4780f27e", + "sha256:9e21301f7a1e7c03dbea73e8602905a4ebba641547a462b26dd03451e5769e7c", + "sha256:9f6b0492d111b43de5f70052e24c1f0951cb9e6022188ebcb1cc3a3d301469b0", + "sha256:a69bd3c68b98298f490e84519b954335154917eaab52cf582fa2c5c7efc6e812", + "sha256:b4890d5fb9b7a23e3bf8abf5a8a7da8e228f1e97dc96b30b95685df840b6914a", + "sha256:c366df0401d1ec4e548bebe8f91d55ebcc0ec3137900d214dd7aac8427ef3030", + "sha256:dc42f645f8f3a489c3dd416730a514e7a91a59510ddaadc09d04224c098d3302" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", + "version": "==3.3.1" + }, + "docutils": { + "hashes": [ + "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af", + "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==0.16" + }, + "google-auth": { + "hashes": [ + "sha256:0b0e026b412a0ad096e753907559e4bdb180d9ba9f68dd9036164db4fdc4ad2e", + "sha256:ce752cc51c31f479dbf9928435ef4b07514b20261b021c7383bee4bda646acb8" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", + "version": "==1.24.0" + }, + "idna": { + "hashes": [ + "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6", + "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.10" + }, + "ipaddress": { + "hashes": [ + "sha256:6e0f4a39e66cb5bb9a137b00276a2eff74f93b71dcbdad6f10ff7df9d3557fcc", + "sha256:b7f8e0369580bb4a24d5ba1d7cc29660a4a6987763faf1d8a8046830e020e7e2" + ], + "index": "pypi", + "version": "==1.0.23" + }, + "jinja2": { + "hashes": [ + "sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0", + "sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==2.11.2" + }, + "jmespath": { + "hashes": [ + "sha256:b85d0567b8666149a93172712e68920734333c0ce7e89b78b3e987f71e5ed4f9", + "sha256:cdf6525904cc597730141d61b36f2e4b8ecc257c420fa2f4549bac2c2d0cb72f" + ], + "index": "pypi", + "version": "==0.10.0" + }, + "kubernetes": { + "hashes": [ + "sha256:1a2472f8b01bc6aa87e3a34781f859bded5a5c8ff791a53d889a8bd6cc550430", + "sha256:4af81201520977139a143f96123fb789fa351879df37f122916b9b6ed050bbaf" + ], + "version": "==11.0.0" + }, + "lockfile": { + "hashes": [ + "sha256:6aed02de03cba24efabcd600b30540140634fc06cfa603822d508d5361e9f799", + "sha256:6c3cb24f344923d30b2785d5ad75182c8ea7ac1b6171b08657258ec7429d50fa" + ], + "version": "==0.12.2" + }, + "markupsafe": { + "hashes": [ + "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", + "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", + "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", + "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", + "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42", + "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", + "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", + "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", + "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", + "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", + "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", + "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b", + "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", + "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15", + "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", + "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", + "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", + "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", + "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", + "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", + "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", + "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", + "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", + "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", + "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", + "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", + "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", + "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", + "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", + "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", + "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2", + "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7", + "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.1.1" + }, + "oauthlib": { + "hashes": [ + "sha256:bee41cc35fcca6e988463cacc3bcb8a96224f470ca547e697b604cc697b2f889", + "sha256:df884cd6cbe20e32633f1db1072e9356f53638e4361bef4e8b03c9127c9328ea" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==3.1.0" + }, + "openshift": { + "hashes": [ + "sha256:110b0d3c84a83500f0fd150ab26dee29615157e6659bf72808788aa79fc17afc" + ], + "index": "pypi", + "version": "==0.11.2" + }, + "pexpect": { + "hashes": [ + "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937", + "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c" + ], + "version": "==4.8.0" + }, + "psutil": { + "hashes": [ + "sha256:0066a82f7b1b37d334e68697faba68e5ad5e858279fd6351c8ca6024e8d6ba64", + "sha256:02b8292609b1f7fcb34173b25e48d0da8667bc85f81d7476584d889c6e0f2131", + "sha256:0ae6f386d8d297177fd288be6e8d1afc05966878704dad9847719650e44fc49c", + "sha256:0c9ccb99ab76025f2f0bbecf341d4656e9c1351db8cc8a03ccd62e318ab4b5c6", + "sha256:0dd4465a039d343925cdc29023bb6960ccf4e74a65ad53e768403746a9207023", + "sha256:12d844996d6c2b1d3881cfa6fa201fd635971869a9da945cf6756105af73d2df", + "sha256:1bff0d07e76114ec24ee32e7f7f8d0c4b0514b3fae93e3d2aaafd65d22502394", + "sha256:245b5509968ac0bd179287d91210cd3f37add77dad385ef238b275bad35fa1c4", + "sha256:28ff7c95293ae74bf1ca1a79e8805fcde005c18a122ca983abf676ea3466362b", + "sha256:36b3b6c9e2a34b7d7fbae330a85bf72c30b1c827a4366a07443fc4b6270449e2", + "sha256:52de075468cd394ac98c66f9ca33b2f54ae1d9bff1ef6b67a212ee8f639ec06d", + "sha256:5da29e394bdedd9144c7331192e20c1f79283fb03b06e6abd3a8ae45ffecee65", + "sha256:61f05864b42fedc0771d6d8e49c35f07efd209ade09a5afe6a5059e7bb7bf83d", + "sha256:6223d07a1ae93f86451d0198a0c361032c4c93ebd4bf6d25e2fb3edfad9571ef", + "sha256:6323d5d845c2785efb20aded4726636546b26d3b577aded22492908f7c1bdda7", + "sha256:6ffe81843131ee0ffa02c317186ed1e759a145267d54fdef1bc4ea5f5931ab60", + "sha256:74f2d0be88db96ada78756cb3a3e1b107ce8ab79f65aa885f76d7664e56928f6", + "sha256:74fb2557d1430fff18ff0d72613c5ca30c45cdbfcddd6a5773e9fc1fe9364be8", + "sha256:90d4091c2d30ddd0a03e0b97e6a33a48628469b99585e2ad6bf21f17423b112b", + "sha256:90f31c34d25b1b3ed6c40cdd34ff122b1887a825297c017e4cbd6796dd8b672d", + "sha256:99de3e8739258b3c3e8669cb9757c9a861b2a25ad0955f8e53ac662d66de61ac", + "sha256:c6a5fd10ce6b6344e616cf01cc5b849fa8103fbb5ba507b6b2dee4c11e84c935", + "sha256:ce8b867423291cb65cfc6d9c4955ee9bfc1e21fe03bb50e177f2b957f1c2469d", + "sha256:d225cd8319aa1d3c85bf195c4e07d17d3cd68636b8fc97e6cf198f782f99af28", + "sha256:ea313bb02e5e25224e518e4352af4bf5e062755160f77e4b1767dd5ccb65f876", + "sha256:ea372bcc129394485824ae3e3ddabe67dc0b118d262c568b4d2602a7070afdb0", + "sha256:f4634b033faf0d968bb9220dd1c793b897ab7f1189956e1aa9eae752527127d3", + "sha256:fcc01e900c1d7bee2a37e5d6e4f9194760a93597c97fee89c4ae51701de03563" + ], + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==5.8.0" + }, + "ptyprocess": { + "hashes": [ + "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", + "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220" + ], + "version": "==0.7.0" + }, + "pyasn1": { + "hashes": [ + "sha256:014c0e9976956a08139dc0712ae195324a75e142284d5f87f1a87ee1b068a359", + "sha256:03840c999ba71680a131cfaee6fab142e1ed9bbd9c693e285cc6aca0d555e576", + "sha256:0458773cfe65b153891ac249bcf1b5f8f320b7c2ce462151f8fa74de8934becf", + "sha256:08c3c53b75eaa48d71cf8c710312316392ed40899cb34710d092e96745a358b7", + "sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d", + "sha256:5c9414dcfede6e441f7e8f81b43b34e834731003427e5b09e4e00e3172a10f00", + "sha256:6e7545f1a61025a4e58bb336952c5061697da694db1cae97b116e9c46abcf7c8", + "sha256:78fa6da68ed2727915c4767bb386ab32cdba863caa7dbe473eaae45f9959da86", + "sha256:7ab8a544af125fb704feadb008c99a88805126fb525280b2270bb25cc1d78a12", + "sha256:99fcc3c8d804d1bc6d9a099921e39d827026409a58f2a720dcdb89374ea0c776", + "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba", + "sha256:e89bf84b5437b532b0803ba5c9a5e054d21fec423a89952a74f87fa2c9b7bce2", + "sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3" + ], + "version": "==0.4.8" + }, + "pyasn1-modules": { + "hashes": [ + "sha256:0845a5582f6a02bb3e1bde9ecfc4bfcae6ec3210dd270522fee602365430c3f8", + "sha256:0fe1b68d1e486a1ed5473f1302bd991c1611d319bba158e98b106ff86e1d7199", + "sha256:15b7c67fabc7fc240d87fb9aabf999cf82311a6d6fb2c70d00d3d0604878c811", + "sha256:426edb7a5e8879f1ec54a1864f16b882c2837bfd06eee62f2c982315ee2473ed", + "sha256:65cebbaffc913f4fe9e4808735c95ea22d7a7775646ab690518c056784bc21b4", + "sha256:905f84c712230b2c592c19470d3ca8d552de726050d1d1716282a1f6146be65e", + "sha256:a50b808ffeb97cb3601dd25981f6b016cbb3d31fbf57a8b8a87428e6158d0c74", + "sha256:a99324196732f53093a84c4369c996713eb8c89d360a496b599fb1a9c47fc3eb", + "sha256:b80486a6c77252ea3a3e9b1e360bc9cf28eaac41263d173c032581ad2f20fe45", + "sha256:c29a5e5cc7a3f05926aff34e097e84f8589cd790ce0ed41b67aed6857b26aafd", + "sha256:cbac4bc38d117f2a49aeedec4407d23e8866ea4ac27ff2cf7fb3e5b570df19e0", + "sha256:f39edd8c4ecaa4556e989147ebf219227e2cd2e8a43c7e7fcb1f1c18c5fd6a3d", + "sha256:fe0644d9ab041506b62782e92b06b8c68cca799e1a9636ec398675459e031405" + ], + "version": "==0.2.8" + }, + "pycparser": { + "hashes": [ + "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0", + "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.20" + }, + "python-daemon": { + "hashes": [ + "sha256:57c84f50a04d7825515e4dbf3a31c70cc44414394a71608dee6cfde469e81766", + "sha256:a0d5dc0b435a02c7e0b401e177a7c17c3f4c7b4e22e2d06271122c8fec5f8946" + ], + "version": "==2.2.4" + }, + "python-dateutil": { + "hashes": [ + "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c", + "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.8.1" + }, + "python-string-utils": { + "hashes": [ + "sha256:dcf9060b03f07647c0a603408dc8b03f807f3b54a05c6e19eb14460256fac0cb", + "sha256:f1a88700baf99db1a9b6953f44181ad9ca56623c81e257e6009707e2e7851fa4" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.0" + }, + "pyyaml": { + "hashes": [ + "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf", + "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696", + "sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393", + "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77", + "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922", + "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5", + "sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8", + "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10", + "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc", + "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018", + "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e", + "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253", + "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183", + "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb", + "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185", + "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db", + "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46", + "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b", + "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63", + "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df", + "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", + "version": "==5.4.1" + }, + "requests": { + "hashes": [ + "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804", + "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==2.25.1" + }, + "requests-oauthlib": { + "hashes": [ + "sha256:7f71572defaecd16372f9006f33c2ec8c077c3cfa6f5911a9a90202beb513f3d", + "sha256:b4261601a71fd721a8bd6d7aa1cc1d6a8a93b4a9f5e96626f8e4d91e8beeaa6a", + "sha256:fa6c47b933f01060936d87ae9327fead68768b69c6c9ea2109c48be30f2d4dbc" + ], + "version": "==1.3.0" + }, + "requests-unixsocket": { + "hashes": [ + "sha256:014d07bfb66dc805a011a8b4b306cf4ec96d2eddb589f6b2b5765e626f0dc0cc", + "sha256:9e5c1a20afc3cf786197ae59c79bcdb0e7565f218f27df5f891307ee8817c1ea" + ], + "version": "==0.2.0" + }, + "rsa": { + "hashes": [ + "sha256:69805d6b69f56eb05b62daea3a7dbd7aa44324ad1306445e05da8060232d00f4", + "sha256:a8774e55b59fd9fc893b0d05e9bfc6f47081f46ff5b46f39ccf24631b7be356b" + ], + "markers": "python_version >= '3.6'", + "version": "==4.7" + }, + "ruamel.yaml": { + "hashes": [ + "sha256:012b9470a0ea06e4e44e99e7920277edf6b46eee0232a04487ea73a7386340a5", + "sha256:076cc0bc34f1966d920a49f18b52b6ad559fbe656a0748e3535cf7b3f29ebf9e" + ], + "version": "==0.16.12" + }, + "ruamel.yaml.clib": { + "hashes": [ + "sha256:058a1cc3df2a8aecc12f983a48bda99315cebf55a3b3a5463e37bb599b05727b", + "sha256:1236df55e0f73cd138c0eca074ee086136c3f16a97c2ac719032c050f7e0622f", + "sha256:1f8c0a4577c0e6c99d208de5c4d3fd8aceed9574bb154d7a2b21c16bb924154c", + "sha256:2602e91bd5c1b874d6f93d3086f9830f3e907c543c7672cf293a97c3fabdcd91", + "sha256:28116f204103cb3a108dfd37668f20abe6e3cafd0d3fd40dba126c732457b3cc", + "sha256:2d24bd98af676f4990c4d715bcdc2a60b19c56a3fb3a763164d2d8ca0e806ba7", + "sha256:2fd336a5c6415c82e2deb40d08c222087febe0aebe520f4d21910629018ab0f3", + "sha256:30dca9bbcbb1cc858717438218d11eafb78666759e5094dd767468c0d577a7e7", + "sha256:44c7b0498c39f27795224438f1a6be6c5352f82cb887bc33d962c3a3acc00df6", + "sha256:464e66a04e740d754170be5e740657a3b3b6d2bcc567f0c3437879a6e6087ff6", + "sha256:46d6d20815064e8bb023ea8628cfb7402c0f0e83de2c2227a88097e239a7dffd", + "sha256:4df5019e7783d14b79217ad9c56edf1ba7485d614ad5a385d1b3c768635c81c0", + "sha256:4e52c96ca66de04be42ea2278012a2342d89f5e82b4512fb6fb7134e377e2e62", + "sha256:5254af7d8bdf4d5484c089f929cb7f5bafa59b4f01d4f48adda4be41e6d29f99", + "sha256:52ae5739e4b5d6317b52f5b040b1b6639e8af68a5b8fd606a8b08658fbd0cab5", + "sha256:53b9dd1abd70e257a6e32f934ebc482dac5edb8c93e23deb663eac724c30b026", + "sha256:6c0a5dc52fc74eb87c67374a4e554d4761fd42a4d01390b7e868b30d21f4b8bb", + "sha256:73b3d43e04cc4b228fa6fa5d796409ece6fcb53a6c270eb2048109cbcbc3b9c2", + "sha256:74161d827407f4db9072011adcfb825b5258a5ccb3d2cd518dd6c9edea9e30f1", + "sha256:75f0ee6839532e52a3a53f80ce64925ed4aed697dd3fa890c4c918f3304bd4f4", + "sha256:839dd72545ef7ba78fd2aa1a5dd07b33696adf3e68fae7f31327161c1093001b", + "sha256:8be05be57dc5c7b4a0b24edcaa2f7275866d9c907725226cdde46da09367d923", + "sha256:8e8fd0a22c9d92af3a34f91e8a2594eeb35cba90ab643c5e0e643567dc8be43e", + "sha256:a873e4d4954f865dcb60bdc4914af7eaae48fb56b60ed6daa1d6251c72f5337c", + "sha256:ab845f1f51f7eb750a78937be9f79baea4a42c7960f5a94dde34e69f3cce1988", + "sha256:b1e981fe1aff1fd11627f531524826a4dcc1f26c726235a52fcb62ded27d150f", + "sha256:b4b0d31f2052b3f9f9b5327024dc629a253a83d8649d4734ca7f35b60ec3e9e5", + "sha256:c6ac7e45367b1317e56f1461719c853fd6825226f45b835df7436bb04031fd8a", + "sha256:daf21aa33ee9b351f66deed30a3d450ab55c14242cfdfcd377798e2c0d25c9f1", + "sha256:e9f7d1d8c26a6a12c23421061f9022bb62704e38211fe375c645485f38df34a2", + "sha256:f6061a31880c1ed6b6ce341215336e2f3d0c1deccd84957b6fa8ca474b41e89f" + ], + "markers": "python_version < '3.9' and platform_python_implementation == 'CPython'", + "version": "==0.2.2" + }, + "six": { + "hashes": [ + "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259", + "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.15.0" + }, + "urllib3": { + "hashes": [ + "sha256:19188f96923873c92ccb987120ec4acaa12f0461fa9ce5d3d0772bc965a39e08", + "sha256:d8ff90d979214d7b4f8ce956e80f4028fc6860e4431f731ea4a8c08f23f99473" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'", + "version": "==1.26.2" + }, + "websocket-client": { + "hashes": [ + "sha256:0fc45c961324d79c781bab301359d5a1b00b13ad1b10415a4780229ef71a5549", + "sha256:d735b91d6d1692a6a181f2a8c9e0238e5f6373356f561bb9dc4c7af36f452010" + ], + "version": "==0.57.0" + } + }, + "develop": {} +} From e4beaee4a9c3eb951f048861890f450bb42f039a Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Sat, 23 Jan 2021 19:49:43 +0100 Subject: [PATCH 335/376] define install dependencies only once and remove afterwards, remove redundant python38-setuptools which is already a python dep of openshift package, move pipenv check inside command chain Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- images/ansible-operator/Dockerfile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/images/ansible-operator/Dockerfile b/images/ansible-operator/Dockerfile index e67d0da1508..d30295c75df 100644 --- a/images/ansible-operator/Dockerfile +++ b/images/ansible-operator/Dockerfile @@ -17,17 +17,17 @@ COPY Pipfile* . ENV PIP_NO_CACHE_DIR=1 \ PIPENV_SYSTEM=1 \ PIPENV_CLEAR=1 -RUN yum clean all && rm -rf /var/cache/yum/* \ +RUN INSTALL_DEPS="libffi-devel openssl-devel python38-devel gcc" \ + && yum clean all && rm -rf /var/cache/yum/* \ && yum -y update \ - && yum install -y libffi-devel openssl-devel python38-devel gcc python38-pip python38-setuptools \ + && yum install -y ${INSTALL_DEPS} python38-pip \ && pip3 install pipenv==2020.11.15 \ && pipenv install --deploy --system \ - && yum remove -y gcc libffi-devel openssl-devel python38-devel \ + && pipenv check \ + && yum remove -y ${INSTALL_DEPS} \ && yum clean all \ && rm -rf /var/cache/yum -RUN pipenv check - # Ensure directory permissions are properly set RUN echo "${USER_NAME}:x:${USER_UID}:0:${USER_NAME} user:${HOME}:/sbin/nologin" >> /etc/passwd \ && mkdir -p ${HOME}/.ansible/tmp \ From d01cc80a5617d38b9a6cf77b6e00a3427423beac Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Sat, 23 Jan 2021 20:03:54 +0100 Subject: [PATCH 336/376] it appears none of the listed build dependencies are still required Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- images/ansible-operator/Dockerfile | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/images/ansible-operator/Dockerfile b/images/ansible-operator/Dockerfile index d30295c75df..ad521cbcf7f 100644 --- a/images/ansible-operator/Dockerfile +++ b/images/ansible-operator/Dockerfile @@ -17,14 +17,13 @@ COPY Pipfile* . ENV PIP_NO_CACHE_DIR=1 \ PIPENV_SYSTEM=1 \ PIPENV_CLEAR=1 -RUN INSTALL_DEPS="libffi-devel openssl-devel python38-devel gcc" \ - && yum clean all && rm -rf /var/cache/yum/* \ +RUN yum clean all \ + && rm -rf /var/cache/yum/* \ && yum -y update \ - && yum install -y ${INSTALL_DEPS} python38-pip \ + && yum install -y python38-pip \ && pip3 install pipenv==2020.11.15 \ && pipenv install --deploy --system \ && pipenv check \ - && yum remove -y ${INSTALL_DEPS} \ && yum clean all \ && rm -rf /var/cache/yum From 8d20991e3dbdbcba95e9812eb611cf96b199ad21 Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Sat, 23 Jan 2021 20:06:16 +0100 Subject: [PATCH 337/376] prune: cleaning yum caches beforehand has no effect on installation or image size Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- images/ansible-operator/Dockerfile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/images/ansible-operator/Dockerfile b/images/ansible-operator/Dockerfile index ad521cbcf7f..f119848c92e 100644 --- a/images/ansible-operator/Dockerfile +++ b/images/ansible-operator/Dockerfile @@ -17,9 +17,7 @@ COPY Pipfile* . ENV PIP_NO_CACHE_DIR=1 \ PIPENV_SYSTEM=1 \ PIPENV_CLEAR=1 -RUN yum clean all \ - && rm -rf /var/cache/yum/* \ - && yum -y update \ +RUN yum -y update \ && yum install -y python38-pip \ && pip3 install pipenv==2020.11.15 \ && pipenv install --deploy --system \ From 221f9635cb5c7297ab3e7138784cf8e412ed3256 Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Thu, 4 Feb 2021 08:04:52 +0100 Subject: [PATCH 338/376] update dependencies Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- images/ansible-operator/Pipfile.lock | 46 ++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/images/ansible-operator/Pipfile.lock b/images/ansible-operator/Pipfile.lock index 088a45beb13..e37ae0a55a2 100644 --- a/images/ansible-operator/Pipfile.lock +++ b/images/ansible-operator/Pipfile.lock @@ -41,11 +41,11 @@ }, "cachetools": { "hashes": [ - "sha256:3796e1de094f0eaca982441c92ce96c68c89cced4cd97721ab297ea4b16db90e", - "sha256:c6b07a6ded8c78bf36730b3dc452dfff7d95f2a12a2fed856b1a0cb13ca78c61" + "sha256:1d9d5f567be80f7c07d765e21b814326d78c61eb0c3a637dffc0e5d1796cb2e2", + "sha256:f469e29e7aa4cff64d8de4aad95ce76de8ea1125a16c68e0d93f65c3c3dc92e9" ], "markers": "python_version ~= '3.5'", - "version": "==4.2.0" + "version": "==4.2.1" }, "certifi": { "hashes": [ @@ -72,6 +72,7 @@ "sha256:6bc25fc545a6b3d57b5f8618e59fc13d3a3a68431e8ca5fd4c13241cd70d0009", "sha256:798caa2a2384b1cbe8a2a139d80734c9db54f9cc155c99d7cc92441a23871c03", "sha256:7c6b1dece89874d9541fc974917b631406233ea0440d0bdfbb8e03bf39a49b3b", + "sha256:7ef7d4ced6b325e92eb4d3502946c78c5367bc416398d387b39591532536734e", "sha256:840793c68105fe031f34d6a086eaea153a0cd5c491cde82a74b420edd0a2b909", "sha256:8d6603078baf4e11edc4168a514c5ce5b3ba6e3e9c374298cb88437957960a53", "sha256:9cc46bc107224ff5b6d04369e7c595acb700c3613ad7bcf2e2012f62ece80c35", @@ -133,11 +134,11 @@ }, "google-auth": { "hashes": [ - "sha256:0b0e026b412a0ad096e753907559e4bdb180d9ba9f68dd9036164db4fdc4ad2e", - "sha256:ce752cc51c31f479dbf9928435ef4b07514b20261b021c7383bee4bda646acb8" + "sha256:008e23ed080674f69f9d2d7d80db4c2591b9bb307d136cea7b3bc129771d211d", + "sha256:514e39f4190ca972200ba33876da5a8857c5665f2b4ccc36c8b8ee21228aae80" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", - "version": "==1.24.0" + "version": "==1.25.0" }, "idna": { "hashes": [ @@ -157,11 +158,11 @@ }, "jinja2": { "hashes": [ - "sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0", - "sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035" + "sha256:03e47ad063331dd6a3f04a43eddca8a966a26ba0c5b7207a9a9e4e08f1b29419", + "sha256:a6d58433de0ae800347cab1fa3043cebbabe8baa9d29e668f1c768cb87a333c6" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==2.11.2" + "version": "==2.11.3" }, "jmespath": { "hashes": [ @@ -192,8 +193,12 @@ "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42", + "sha256:195d7d2c4fbb0ee8139a6cf67194f3973a6b3042d742ebe0a9ed36d8b6f0c07f", + "sha256:22c178a091fc6630d0d045bdb5992d2dfe14e3259760e713c490da5323866c39", "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", + "sha256:2beec1e0de6924ea551859edb9e7679da6e4870d32cb766240ce17e0a0ba2014", + "sha256:3b8a6499709d29c2e2399569d96719a1b21dcd94410a586a18526b143ec8470f", "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", @@ -202,24 +207,39 @@ "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15", "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", + "sha256:6f1e273a344928347c1290119b493a1f0303c52f5a5eae5f16d74f48c15d4a85", + "sha256:6fffc775d90dcc9aed1b89219549b329a9250d918fd0b8fa8d93d154918422e1", "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", + "sha256:7fed13866cf14bba33e7176717346713881f56d9d2bcebab207f7a036f41b850", + "sha256:84dee80c15f1b560d55bcfe6d47b27d070b4681c699c572af2e3c7cc90a3b8e0", "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", + "sha256:98bae9582248d6cf62321dcb52aaf5d9adf0bad3b40582925ef7c7f0ed85fceb", "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", + "sha256:a6a744282b7718a2a62d2ed9d993cad6f5f585605ad352c11de459f4108df0a1", + "sha256:acf08ac40292838b3cbbb06cfe9b2cb9ec78fce8baca31ddb87aaac2e2dc3bc2", "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", + "sha256:b1dba4527182c95a0db8b6060cc98ac49b9e2f5e64320e2b56e47cb2831978c7", "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", + "sha256:b7d644ddb4dbd407d31ffb699f1d140bc35478da613b441c582aeb7c43838dd8", "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", + "sha256:bf5aa3cbcfdf57fa2ee9cd1822c862ef23037f5c832ad09cfea57fa846dec193", "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", + "sha256:caabedc8323f1e93231b52fc32bdcde6db817623d33e100708d9a68e1f53b26b", "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2", + "sha256:d53bc011414228441014aa71dbec320c66468c1030aae3a6e29778a3382d96e5", + "sha256:d73a845f227b0bfe8a7455ee623525ee656a9e2e749e4742706d80a6065d5e2c", + "sha256:d9be0ba6c527163cbed5e0857c451fcd092ce83947944d6c14bc95441203f032", "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7", - "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be" + "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be", + "sha256:feb7b34d6325451ef96bc0e36e1a6c0c1c64bc1fbec4b854f4529e51887b1621" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.1.1" @@ -466,11 +486,11 @@ }, "urllib3": { "hashes": [ - "sha256:19188f96923873c92ccb987120ec4acaa12f0461fa9ce5d3d0772bc965a39e08", - "sha256:d8ff90d979214d7b4f8ce956e80f4028fc6860e4431f731ea4a8c08f23f99473" + "sha256:1b465e494e3e0d8939b50680403e3aedaa2bc434b7d5af64dfd3c958d7f5ae80", + "sha256:de3eedaad74a2683334e282005cd8d7f22f4d55fa690a2a1020a416cb0a47e73" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'", - "version": "==1.26.2" + "version": "==1.26.3" }, "websocket-client": { "hashes": [ From 148ff4b60868634cf145e3134aedefe3d2546b67 Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Thu, 21 Jan 2021 20:23:49 +0100 Subject: [PATCH 339/376] explain what/why of the change Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- ...er-base-images-for-ansible-and-helm-operators.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml diff --git a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml new file mode 100644 index 00000000000..bdb9f083f3a --- /dev/null +++ b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml @@ -0,0 +1,11 @@ +# entries is a list of entries to include in +# release notes and/or the migration guide +entries: + - description: > + For Ansible-based and Helm-based operators, the Docker base image is + pinned to improve the reproducibility of builds using Docker. + + kind: addition + + # Is this a breaking change? + breaking: false From b84e3d3ee0979001ca04526170b3587853645f39 Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Thu, 21 Jan 2021 22:21:37 +0100 Subject: [PATCH 340/376] update to reflect pinning all images, rename change file to fit description Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- ...er-base-images-for-ansible-and-helm-operators.yaml | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml diff --git a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml deleted file mode 100644 index bdb9f083f3a..00000000000 --- a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml +++ /dev/null @@ -1,11 +0,0 @@ -# entries is a list of entries to include in -# release notes and/or the migration guide -entries: - - description: > - For Ansible-based and Helm-based operators, the Docker base image is - pinned to improve the reproducibility of builds using Docker. - - kind: addition - - # Is this a breaking change? - breaking: false From de897cc2b074a7e5c51bc189654b3655948251cd Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Fri, 22 Jan 2021 23:16:05 +0100 Subject: [PATCH 341/376] WIP: pipenv check stubles over pyyaml Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- images/ansible-operator/Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/images/ansible-operator/Dockerfile b/images/ansible-operator/Dockerfile index f119848c92e..f2639e771f7 100644 --- a/images/ansible-operator/Dockerfile +++ b/images/ansible-operator/Dockerfile @@ -25,6 +25,8 @@ RUN yum -y update \ && yum clean all \ && rm -rf /var/cache/yum +RUN pipenv check --system + # Ensure directory permissions are properly set RUN echo "${USER_NAME}:x:${USER_UID}:0:${USER_NAME} user:${HOME}:/sbin/nologin" >> /etc/passwd \ && mkdir -p ${HOME}/.ansible/tmp \ From a3119c292e8fc80466e1bbaf042c895c4a7668f1 Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Thu, 21 Jan 2021 20:23:49 +0100 Subject: [PATCH 342/376] explain what/why of the change Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- ...er-base-images-for-ansible-and-helm-operators.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml diff --git a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml new file mode 100644 index 00000000000..bdb9f083f3a --- /dev/null +++ b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml @@ -0,0 +1,11 @@ +# entries is a list of entries to include in +# release notes and/or the migration guide +entries: + - description: > + For Ansible-based and Helm-based operators, the Docker base image is + pinned to improve the reproducibility of builds using Docker. + + kind: addition + + # Is this a breaking change? + breaking: false From 730363ea140a81fa38110f8170ba0f2842e02318 Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Thu, 21 Jan 2021 22:21:37 +0100 Subject: [PATCH 343/376] update to reflect pinning all images, rename change file to fit description Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- ...er-base-images-for-ansible-and-helm-operators.yaml | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml diff --git a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml deleted file mode 100644 index bdb9f083f3a..00000000000 --- a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml +++ /dev/null @@ -1,11 +0,0 @@ -# entries is a list of entries to include in -# release notes and/or the migration guide -entries: - - description: > - For Ansible-based and Helm-based operators, the Docker base image is - pinned to improve the reproducibility of builds using Docker. - - kind: addition - - # Is this a breaking change? - breaking: false From 9c5f3e27ef8b1105eac43a763a94e02cd217ebf3 Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Thu, 4 Feb 2021 18:03:09 +0100 Subject: [PATCH 344/376] fix docker copy command to use target folder Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- images/ansible-operator/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/images/ansible-operator/Dockerfile b/images/ansible-operator/Dockerfile index f2639e771f7..dfb70dc09ec 100644 --- a/images/ansible-operator/Dockerfile +++ b/images/ansible-operator/Dockerfile @@ -13,7 +13,7 @@ ENV HOME=/opt/ansible \ # Install python dependencies # Ensure fresh metadata rather than cached metadata in the base by running # yum clean all && rm -rf /var/yum/cache/* first -COPY Pipfile* . +COPY Pipfile* ./ ENV PIP_NO_CACHE_DIR=1 \ PIPENV_SYSTEM=1 \ PIPENV_CLEAR=1 From f428dad77bcb07d2d0f4e2acae31076bd85daec4 Mon Sep 17 00:00:00 2001 From: blaqkube <64150653+blaqkube@users.noreply.github.com> Date: Mon, 11 Jan 2021 19:46:31 +0100 Subject: [PATCH 345/376] Fix panic with "operator-sdk bundle validate" and OCI (#4373) Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- changelog/fragments/fix-bundle-validate-panic.yaml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 changelog/fragments/fix-bundle-validate-panic.yaml diff --git a/changelog/fragments/fix-bundle-validate-panic.yaml b/changelog/fragments/fix-bundle-validate-panic.yaml new file mode 100644 index 00000000000..9164ad2d352 --- /dev/null +++ b/changelog/fragments/fix-bundle-validate-panic.yaml @@ -0,0 +1,4 @@ +entries: + - description: Fix panic when "operator-sdk bundle validate" fails + kind: bugfix + breaking: false From 5b2a8b66e6355531cff63d0c3e5baf9f29c534cd Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Mon, 11 Jan 2021 19:50:13 -0800 Subject: [PATCH 346/376] images/scorecard-test-kuttl: upgrade kuttl to v0.8.0 (#4391) Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- changelog/fragments/kuttl-v0.8.0.yaml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 changelog/fragments/kuttl-v0.8.0.yaml diff --git a/changelog/fragments/kuttl-v0.8.0.yaml b/changelog/fragments/kuttl-v0.8.0.yaml new file mode 100644 index 00000000000..07421adb0d7 --- /dev/null +++ b/changelog/fragments/kuttl-v0.8.0.yaml @@ -0,0 +1,4 @@ +entries: + - description: > + Upgraded the `kudobuilder/kuttl` base image version in the `scorecard-test-kuttl` image to v0.8.0 + kind: change From 9b68f3e75ca835461dac9be4270ff22c7260038d Mon Sep 17 00:00:00 2001 From: Mike Ng <58747157+mikeshng@users.noreply.github.com> Date: Wed, 13 Jan 2021 13:57:54 -0500 Subject: [PATCH 347/376] fix: (helm) - do not add owner references to resources that contain the Helm keep resource-policy annotation (#4389) Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- .../helm_operator_fix_helm_keep_annotated_delete.yaml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 changelog/fragments/helm_operator_fix_helm_keep_annotated_delete.yaml diff --git a/changelog/fragments/helm_operator_fix_helm_keep_annotated_delete.yaml b/changelog/fragments/helm_operator_fix_helm_keep_annotated_delete.yaml new file mode 100644 index 00000000000..203f7341939 --- /dev/null +++ b/changelog/fragments/helm_operator_fix_helm_keep_annotated_delete.yaml @@ -0,0 +1,5 @@ +entries: + - description: > + For Helm-based operators, do not add owner references to resources that contain the Helm annotation: 'helm.sh/resource-policy: keep'. + kind: bugfix + breaking: false \ No newline at end of file From c981780e5df4076e6f567ba4333e6efc517aa03e Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Thu, 21 Jan 2021 20:23:49 +0100 Subject: [PATCH 348/376] explain what/why of the change Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- ...er-base-images-for-ansible-and-helm-operators.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml diff --git a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml new file mode 100644 index 00000000000..bdb9f083f3a --- /dev/null +++ b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml @@ -0,0 +1,11 @@ +# entries is a list of entries to include in +# release notes and/or the migration guide +entries: + - description: > + For Ansible-based and Helm-based operators, the Docker base image is + pinned to improve the reproducibility of builds using Docker. + + kind: addition + + # Is this a breaking change? + breaking: false From 63cc62af452f5283c44002ae9351c9791b65d155 Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Thu, 21 Jan 2021 22:21:37 +0100 Subject: [PATCH 349/376] update to reflect pinning all images, rename change file to fit description Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- ...er-base-images-for-ansible-and-helm-operators.yaml | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml diff --git a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml deleted file mode 100644 index bdb9f083f3a..00000000000 --- a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml +++ /dev/null @@ -1,11 +0,0 @@ -# entries is a list of entries to include in -# release notes and/or the migration guide -entries: - - description: > - For Ansible-based and Helm-based operators, the Docker base image is - pinned to improve the reproducibility of builds using Docker. - - kind: addition - - # Is this a breaking change? - breaking: false From e7c663d3e0619d6340ba3a57fd12447a0024755f Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Thu, 21 Jan 2021 20:23:49 +0100 Subject: [PATCH 350/376] explain what/why of the change Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- ...er-base-images-for-ansible-and-helm-operators.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml diff --git a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml new file mode 100644 index 00000000000..bdb9f083f3a --- /dev/null +++ b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml @@ -0,0 +1,11 @@ +# entries is a list of entries to include in +# release notes and/or the migration guide +entries: + - description: > + For Ansible-based and Helm-based operators, the Docker base image is + pinned to improve the reproducibility of builds using Docker. + + kind: addition + + # Is this a breaking change? + breaking: false From 3718e48ab8bec15858725d6aa753311866aa783f Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Thu, 21 Jan 2021 22:21:37 +0100 Subject: [PATCH 351/376] update to reflect pinning all images, rename change file to fit description Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- ...er-base-images-for-ansible-and-helm-operators.yaml | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml diff --git a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml deleted file mode 100644 index bdb9f083f3a..00000000000 --- a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml +++ /dev/null @@ -1,11 +0,0 @@ -# entries is a list of entries to include in -# release notes and/or the migration guide -entries: - - description: > - For Ansible-based and Helm-based operators, the Docker base image is - pinned to improve the reproducibility of builds using Docker. - - kind: addition - - # Is this a breaking change? - breaking: false From d1f17947c8c483aac2dd5fa3f13955de54925a07 Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Fri, 22 Jan 2021 23:32:25 +0100 Subject: [PATCH 352/376] use env vars to force pipenv to clear caches; install packages and do vulnerability checks in base site-packages Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- images/ansible-operator/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/images/ansible-operator/Dockerfile b/images/ansible-operator/Dockerfile index dfb70dc09ec..bf13876ba2b 100644 --- a/images/ansible-operator/Dockerfile +++ b/images/ansible-operator/Dockerfile @@ -25,7 +25,7 @@ RUN yum -y update \ && yum clean all \ && rm -rf /var/cache/yum -RUN pipenv check --system +RUN pipenv check # Ensure directory permissions are properly set RUN echo "${USER_NAME}:x:${USER_UID}:0:${USER_NAME} user:${HOME}:/sbin/nologin" >> /etc/passwd \ From 28cc5a352189ebce6a1932579e8ff42339807655 Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Thu, 21 Jan 2021 20:23:49 +0100 Subject: [PATCH 353/376] explain what/why of the change Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- ...er-base-images-for-ansible-and-helm-operators.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml diff --git a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml new file mode 100644 index 00000000000..bdb9f083f3a --- /dev/null +++ b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml @@ -0,0 +1,11 @@ +# entries is a list of entries to include in +# release notes and/or the migration guide +entries: + - description: > + For Ansible-based and Helm-based operators, the Docker base image is + pinned to improve the reproducibility of builds using Docker. + + kind: addition + + # Is this a breaking change? + breaking: false From f6c2e515c7f6f863c6d4c4cccc9504ea6dbe3a64 Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Thu, 21 Jan 2021 22:21:37 +0100 Subject: [PATCH 354/376] update to reflect pinning all images, rename change file to fit description Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- ...er-base-images-for-ansible-and-helm-operators.yaml | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml diff --git a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml deleted file mode 100644 index bdb9f083f3a..00000000000 --- a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml +++ /dev/null @@ -1,11 +0,0 @@ -# entries is a list of entries to include in -# release notes and/or the migration guide -entries: - - description: > - For Ansible-based and Helm-based operators, the Docker base image is - pinned to improve the reproducibility of builds using Docker. - - kind: addition - - # Is this a breaking change? - breaking: false From 4d309d2270d05845951d4fc4e9329a387bba970c Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Thu, 21 Jan 2021 20:23:49 +0100 Subject: [PATCH 355/376] explain what/why of the change Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- ...er-base-images-for-ansible-and-helm-operators.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml diff --git a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml new file mode 100644 index 00000000000..bdb9f083f3a --- /dev/null +++ b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml @@ -0,0 +1,11 @@ +# entries is a list of entries to include in +# release notes and/or the migration guide +entries: + - description: > + For Ansible-based and Helm-based operators, the Docker base image is + pinned to improve the reproducibility of builds using Docker. + + kind: addition + + # Is this a breaking change? + breaking: false From fbeb39d909252e184d8e1a060600f75224866cd5 Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Thu, 21 Jan 2021 22:21:37 +0100 Subject: [PATCH 356/376] update to reflect pinning all images, rename change file to fit description Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- ...er-base-images-for-ansible-and-helm-operators.yaml | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml diff --git a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml deleted file mode 100644 index bdb9f083f3a..00000000000 --- a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml +++ /dev/null @@ -1,11 +0,0 @@ -# entries is a list of entries to include in -# release notes and/or the migration guide -entries: - - description: > - For Ansible-based and Helm-based operators, the Docker base image is - pinned to improve the reproducibility of builds using Docker. - - kind: addition - - # Is this a breaking change? - breaking: false From 5deebc0c15a0ba0c3da875d5aa06ad7c94b762f5 Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Thu, 21 Jan 2021 20:23:49 +0100 Subject: [PATCH 357/376] explain what/why of the change Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- ...er-base-images-for-ansible-and-helm-operators.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml diff --git a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml new file mode 100644 index 00000000000..bdb9f083f3a --- /dev/null +++ b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml @@ -0,0 +1,11 @@ +# entries is a list of entries to include in +# release notes and/or the migration guide +entries: + - description: > + For Ansible-based and Helm-based operators, the Docker base image is + pinned to improve the reproducibility of builds using Docker. + + kind: addition + + # Is this a breaking change? + breaking: false From 2f41daf5d46eab50b69af9d2e959ba7973c93ecf Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Thu, 21 Jan 2021 22:21:37 +0100 Subject: [PATCH 358/376] update to reflect pinning all images, rename change file to fit description Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- ...er-base-images-for-ansible-and-helm-operators.yaml | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml diff --git a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml deleted file mode 100644 index bdb9f083f3a..00000000000 --- a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml +++ /dev/null @@ -1,11 +0,0 @@ -# entries is a list of entries to include in -# release notes and/or the migration guide -entries: - - description: > - For Ansible-based and Helm-based operators, the Docker base image is - pinned to improve the reproducibility of builds using Docker. - - kind: addition - - # Is this a breaking change? - breaking: false From d15e9dc6c21a47f6dd3a0a16d02166a2de483243 Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Thu, 21 Jan 2021 20:23:49 +0100 Subject: [PATCH 359/376] explain what/why of the change Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- ...er-base-images-for-ansible-and-helm-operators.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml diff --git a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml new file mode 100644 index 00000000000..bdb9f083f3a --- /dev/null +++ b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml @@ -0,0 +1,11 @@ +# entries is a list of entries to include in +# release notes and/or the migration guide +entries: + - description: > + For Ansible-based and Helm-based operators, the Docker base image is + pinned to improve the reproducibility of builds using Docker. + + kind: addition + + # Is this a breaking change? + breaking: false From d02b2a58b7af7ea8d2ccd87a2035ed6739b4a2fe Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Thu, 21 Jan 2021 22:21:37 +0100 Subject: [PATCH 360/376] update to reflect pinning all images, rename change file to fit description Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- ...er-base-images-for-ansible-and-helm-operators.yaml | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml diff --git a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml deleted file mode 100644 index bdb9f083f3a..00000000000 --- a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml +++ /dev/null @@ -1,11 +0,0 @@ -# entries is a list of entries to include in -# release notes and/or the migration guide -entries: - - description: > - For Ansible-based and Helm-based operators, the Docker base image is - pinned to improve the reproducibility of builds using Docker. - - kind: addition - - # Is this a breaking change? - breaking: false From 24d79515bbad0d91d96d81154231e1c28f89dded Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Fri, 22 Jan 2021 23:16:05 +0100 Subject: [PATCH 361/376] WIP: pipenv check stubles over pyyaml Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- images/ansible-operator/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/images/ansible-operator/Dockerfile b/images/ansible-operator/Dockerfile index bf13876ba2b..dfb70dc09ec 100644 --- a/images/ansible-operator/Dockerfile +++ b/images/ansible-operator/Dockerfile @@ -25,7 +25,7 @@ RUN yum -y update \ && yum clean all \ && rm -rf /var/cache/yum -RUN pipenv check +RUN pipenv check --system # Ensure directory permissions are properly set RUN echo "${USER_NAME}:x:${USER_UID}:0:${USER_NAME} user:${HOME}:/sbin/nologin" >> /etc/passwd \ From 8e73baecfb48d49fad04cf791659cca254c4b5bf Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Fri, 22 Jan 2021 23:32:25 +0100 Subject: [PATCH 362/376] use env vars to force pipenv to clear caches; install packages and do vulnerability checks in base site-packages Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- images/ansible-operator/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/images/ansible-operator/Dockerfile b/images/ansible-operator/Dockerfile index dfb70dc09ec..bf13876ba2b 100644 --- a/images/ansible-operator/Dockerfile +++ b/images/ansible-operator/Dockerfile @@ -25,7 +25,7 @@ RUN yum -y update \ && yum clean all \ && rm -rf /var/cache/yum -RUN pipenv check --system +RUN pipenv check # Ensure directory permissions are properly set RUN echo "${USER_NAME}:x:${USER_UID}:0:${USER_NAME} user:${HOME}:/sbin/nologin" >> /etc/passwd \ From 1c1cc96302e79a61157b7cd4ed6c5ee26ef63baa Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Thu, 21 Jan 2021 20:23:49 +0100 Subject: [PATCH 363/376] explain what/why of the change Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- ...er-base-images-for-ansible-and-helm-operators.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml diff --git a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml new file mode 100644 index 00000000000..bdb9f083f3a --- /dev/null +++ b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml @@ -0,0 +1,11 @@ +# entries is a list of entries to include in +# release notes and/or the migration guide +entries: + - description: > + For Ansible-based and Helm-based operators, the Docker base image is + pinned to improve the reproducibility of builds using Docker. + + kind: addition + + # Is this a breaking change? + breaking: false From cc0369f214d448c9dd5a2575f596b46679067ee4 Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Thu, 21 Jan 2021 22:21:37 +0100 Subject: [PATCH 364/376] update to reflect pinning all images, rename change file to fit description Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- ...er-base-images-for-ansible-and-helm-operators.yaml | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml diff --git a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml deleted file mode 100644 index bdb9f083f3a..00000000000 --- a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml +++ /dev/null @@ -1,11 +0,0 @@ -# entries is a list of entries to include in -# release notes and/or the migration guide -entries: - - description: > - For Ansible-based and Helm-based operators, the Docker base image is - pinned to improve the reproducibility of builds using Docker. - - kind: addition - - # Is this a breaking change? - breaking: false From 919729df3cf143480e4e313fd0f3dc1d84df6814 Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Thu, 21 Jan 2021 20:23:49 +0100 Subject: [PATCH 365/376] explain what/why of the change Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- ...er-base-images-for-ansible-and-helm-operators.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml diff --git a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml new file mode 100644 index 00000000000..bdb9f083f3a --- /dev/null +++ b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml @@ -0,0 +1,11 @@ +# entries is a list of entries to include in +# release notes and/or the migration guide +entries: + - description: > + For Ansible-based and Helm-based operators, the Docker base image is + pinned to improve the reproducibility of builds using Docker. + + kind: addition + + # Is this a breaking change? + breaking: false From fd0e6b236df26519685770f0b1d1e188dce5f992 Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Thu, 21 Jan 2021 22:21:37 +0100 Subject: [PATCH 366/376] update to reflect pinning all images, rename change file to fit description Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- ...er-base-images-for-ansible-and-helm-operators.yaml | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml diff --git a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml deleted file mode 100644 index bdb9f083f3a..00000000000 --- a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml +++ /dev/null @@ -1,11 +0,0 @@ -# entries is a list of entries to include in -# release notes and/or the migration guide -entries: - - description: > - For Ansible-based and Helm-based operators, the Docker base image is - pinned to improve the reproducibility of builds using Docker. - - kind: addition - - # Is this a breaking change? - breaking: false From 42fe116432d38f1c03063ba51fc5b4316e2b72cb Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Thu, 21 Jan 2021 20:23:49 +0100 Subject: [PATCH 367/376] explain what/why of the change Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- ...er-base-images-for-ansible-and-helm-operators.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml diff --git a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml new file mode 100644 index 00000000000..bdb9f083f3a --- /dev/null +++ b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml @@ -0,0 +1,11 @@ +# entries is a list of entries to include in +# release notes and/or the migration guide +entries: + - description: > + For Ansible-based and Helm-based operators, the Docker base image is + pinned to improve the reproducibility of builds using Docker. + + kind: addition + + # Is this a breaking change? + breaking: false From ba370a765f64edb6f1c40cb9aa667312047259f6 Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Thu, 21 Jan 2021 22:21:37 +0100 Subject: [PATCH 368/376] update to reflect pinning all images, rename change file to fit description Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- ...er-base-images-for-ansible-and-helm-operators.yaml | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml diff --git a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml deleted file mode 100644 index bdb9f083f3a..00000000000 --- a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml +++ /dev/null @@ -1,11 +0,0 @@ -# entries is a list of entries to include in -# release notes and/or the migration guide -entries: - - description: > - For Ansible-based and Helm-based operators, the Docker base image is - pinned to improve the reproducibility of builds using Docker. - - kind: addition - - # Is this a breaking change? - breaking: false From 0a059e294a22b0de7d86f75bf7a24e19f950dbba Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Thu, 21 Jan 2021 20:23:49 +0100 Subject: [PATCH 369/376] explain what/why of the change Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- ...er-base-images-for-ansible-and-helm-operators.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml diff --git a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml new file mode 100644 index 00000000000..bdb9f083f3a --- /dev/null +++ b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml @@ -0,0 +1,11 @@ +# entries is a list of entries to include in +# release notes and/or the migration guide +entries: + - description: > + For Ansible-based and Helm-based operators, the Docker base image is + pinned to improve the reproducibility of builds using Docker. + + kind: addition + + # Is this a breaking change? + breaking: false From f9a7e4ce5ed310dfeb99ffc8bd64f19485a25790 Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Thu, 21 Jan 2021 22:21:37 +0100 Subject: [PATCH 370/376] update to reflect pinning all images, rename change file to fit description Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- ...er-base-images-for-ansible-and-helm-operators.yaml | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml diff --git a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml deleted file mode 100644 index bdb9f083f3a..00000000000 --- a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml +++ /dev/null @@ -1,11 +0,0 @@ -# entries is a list of entries to include in -# release notes and/or the migration guide -entries: - - description: > - For Ansible-based and Helm-based operators, the Docker base image is - pinned to improve the reproducibility of builds using Docker. - - kind: addition - - # Is this a breaking change? - breaking: false From d1d57ef4aae8c2997a7a937338866c28df75e5c7 Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Fri, 22 Jan 2021 23:16:05 +0100 Subject: [PATCH 371/376] WIP: pipenv check stubles over pyyaml Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- images/ansible-operator/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/images/ansible-operator/Dockerfile b/images/ansible-operator/Dockerfile index bf13876ba2b..dfb70dc09ec 100644 --- a/images/ansible-operator/Dockerfile +++ b/images/ansible-operator/Dockerfile @@ -25,7 +25,7 @@ RUN yum -y update \ && yum clean all \ && rm -rf /var/cache/yum -RUN pipenv check +RUN pipenv check --system # Ensure directory permissions are properly set RUN echo "${USER_NAME}:x:${USER_UID}:0:${USER_NAME} user:${HOME}:/sbin/nologin" >> /etc/passwd \ From b33a2cd9b1bbf7d6593abb231a5832a5db646be1 Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Fri, 22 Jan 2021 23:32:25 +0100 Subject: [PATCH 372/376] use env vars to force pipenv to clear caches; install packages and do vulnerability checks in base site-packages Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- images/ansible-operator/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/images/ansible-operator/Dockerfile b/images/ansible-operator/Dockerfile index dfb70dc09ec..bf13876ba2b 100644 --- a/images/ansible-operator/Dockerfile +++ b/images/ansible-operator/Dockerfile @@ -25,7 +25,7 @@ RUN yum -y update \ && yum clean all \ && rm -rf /var/cache/yum -RUN pipenv check --system +RUN pipenv check # Ensure directory permissions are properly set RUN echo "${USER_NAME}:x:${USER_UID}:0:${USER_NAME} user:${HOME}:/sbin/nologin" >> /etc/passwd \ From 799f936025dd4da49883ad870586322ddbf9e455 Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Thu, 21 Jan 2021 20:23:49 +0100 Subject: [PATCH 373/376] explain what/why of the change Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- ...er-base-images-for-ansible-and-helm-operators.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml diff --git a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml new file mode 100644 index 00000000000..bdb9f083f3a --- /dev/null +++ b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml @@ -0,0 +1,11 @@ +# entries is a list of entries to include in +# release notes and/or the migration guide +entries: + - description: > + For Ansible-based and Helm-based operators, the Docker base image is + pinned to improve the reproducibility of builds using Docker. + + kind: addition + + # Is this a breaking change? + breaking: false From d1b556ed6ee13104ea9f1434db2edd73b1125c5b Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Thu, 21 Jan 2021 22:21:37 +0100 Subject: [PATCH 374/376] update to reflect pinning all images, rename change file to fit description Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- ...er-base-images-for-ansible-and-helm-operators.yaml | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml diff --git a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml deleted file mode 100644 index bdb9f083f3a..00000000000 --- a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml +++ /dev/null @@ -1,11 +0,0 @@ -# entries is a list of entries to include in -# release notes and/or the migration guide -entries: - - description: > - For Ansible-based and Helm-based operators, the Docker base image is - pinned to improve the reproducibility of builds using Docker. - - kind: addition - - # Is this a breaking change? - breaking: false From d6959ca8ee732609d18a1b1116306dc0b52df84c Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Thu, 21 Jan 2021 20:23:49 +0100 Subject: [PATCH 375/376] explain what/why of the change Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- ...er-base-images-for-ansible-and-helm-operators.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml diff --git a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml new file mode 100644 index 00000000000..bdb9f083f3a --- /dev/null +++ b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml @@ -0,0 +1,11 @@ +# entries is a list of entries to include in +# release notes and/or the migration guide +entries: + - description: > + For Ansible-based and Helm-based operators, the Docker base image is + pinned to improve the reproducibility of builds using Docker. + + kind: addition + + # Is this a breaking change? + breaking: false From 03a435dfb765edde389cae00d5a385f2fb37ff8e Mon Sep 17 00:00:00 2001 From: Rein van 't Veer Date: Thu, 21 Jan 2021 22:21:37 +0100 Subject: [PATCH 376/376] update to reflect pinning all images, rename change file to fit description Signed-off-by: Rein van 't Veer Signed-off-by: reinvantveer --- ...er-base-images-for-ansible-and-helm-operators.yaml | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml diff --git a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml b/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml deleted file mode 100644 index bdb9f083f3a..00000000000 --- a/changelog/fragments/pin-docker-base-images-for-ansible-and-helm-operators.yaml +++ /dev/null @@ -1,11 +0,0 @@ -# entries is a list of entries to include in -# release notes and/or the migration guide -entries: - - description: > - For Ansible-based and Helm-based operators, the Docker base image is - pinned to improve the reproducibility of builds using Docker. - - kind: addition - - # Is this a breaking change? - breaking: false