From 6df5501a06d774ab1354a85448f2efeae78f15ec Mon Sep 17 00:00:00 2001 From: Patrik Egyed Date: Fri, 19 May 2023 20:40:46 +0200 Subject: [PATCH 01/24] test(docs/install): added install e2e test --- Makefile | 6 +- tests/e2e/cert_manager_test.go | 73 +++++++++++++ tests/e2e/go.mod | 2 - tests/e2e/go.sum | 4 - tests/e2e/helm_test.go | 157 +++++++++++++++++++++++++++ tests/e2e/install_test.go | 38 +++++++ tests/e2e/k8s_test.go | 174 ++++++++++++++++++++++++++++++ tests/e2e/koperator_suite_test.go | 2 - tests/e2e/koperator_test.go | 122 +++++++++++++++++++++ tests/e2e/prometheus_test.go | 65 +++++++++++ tests/e2e/zookeeper_test.go | 50 +++++++++ 11 files changed, 680 insertions(+), 13 deletions(-) create mode 100644 tests/e2e/cert_manager_test.go create mode 100644 tests/e2e/helm_test.go create mode 100644 tests/e2e/install_test.go create mode 100644 tests/e2e/k8s_test.go create mode 100644 tests/e2e/koperator_test.go create mode 100644 tests/e2e/prometheus_test.go create mode 100644 tests/e2e/zookeeper_test.go diff --git a/Makefile b/Makefile index 3b613d7ff..52ba33ece 100644 --- a/Makefile +++ b/Makefile @@ -102,11 +102,7 @@ test: generate fmt vet manifests bin/setup-envtest test-e2e: go test github.com/banzaicloud/koperator/tests/e2e \ -v \ - -timeout 15m \ - -tags e2e \ - --ginkgo.show-node-events \ - --ginkgo.trace \ - --ginkgo.v + -timeout 5m # Build manager binary manager: generate fmt vet diff --git a/tests/e2e/cert_manager_test.go b/tests/e2e/cert_manager_test.go new file mode 100644 index 000000000..10b8175ba --- /dev/null +++ b/tests/e2e/cert_manager_test.go @@ -0,0 +1,73 @@ +// Copyright © 2023 Cisco Systems, Inc. and/or its affiliates +// +// 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 ( + "github.com/gruntwork-io/terratest/modules/k8s" + . "github.com/onsi/ginkgo/v2" +) + +// requireApplyingCertManagerCRDs deploys the cert-manager CRDs and checks +// their existence afterwards. +func requireApplyingCertManagerCRDs(kubectlOptions *k8s.KubectlOptions, certManagerVersion string) { + It("Applying cert-manager CRDs", func() { + By("Applying cert-manager CRDs with version " + certManagerVersion) + applyK8sResourceManifest( + kubectlOptions, + "https://github.com/jetstack/cert-manager/releases/download/"+certManagerVersion+"/cert-manager.crds.yaml", + ) + + By("Verifying cert-manager CRDs") + requireExistingCRDs( + kubectlOptions, + "certificaterequests.cert-manager.io", + "certificates.cert-manager.io", + "challenges.acme.cert-manager.io", + "clusterissuers.cert-manager.io", + "issuers.cert-manager.io", + "orders.acme.cert-manager.io", + ) + }) +} + +// requireInstallingCertManager deploys cert-manager CRDs and Helm chart and +// checks the success of those operations. +func requireInstallingCertManager(kubectlOptions *k8s.KubectlOptions, certManagerVersion string) { + When("Installing cert-manager", func() { + requireApplyingCertManagerCRDs(kubectlOptions, certManagerVersion) + requireInstallingCertManagerHelmChartIfDoesNotExist(kubectlOptions, certManagerVersion) + }) +} + +// requireDeployingCertManagerHelmChart checks the existence of the cert-manager +// Helm release and installs it if it's not present. +func requireInstallingCertManagerHelmChartIfDoesNotExist( + kubectlOptions *k8s.KubectlOptions, + certManagerVersion string, +) { + It("Installing cert-manager Helm chart", func() { + installHelmChartIfDoesNotExist( + kubectlOptions, + "https://charts.jetstack.io", + "cert-manager", + certManagerVersion, + "cert-manager", + nil, + ) + + By("Verifying cert-manager pods") + requireRunningPods(kubectlOptions, "app.kubernetes.io/name", "cert-manager", "cainjector", "webhook") + }) +} diff --git a/tests/e2e/go.mod b/tests/e2e/go.mod index 8cb3c9f3d..032baf8d2 100644 --- a/tests/e2e/go.mod +++ b/tests/e2e/go.mod @@ -4,7 +4,6 @@ go 1.20 require ( emperror.dev/errors v0.8.1 - github.com/cisco-open/k8s-objectmatcher v1.9.0 github.com/gruntwork-io/terratest v0.41.24 github.com/onsi/ginkgo/v2 v2.9.5 github.com/onsi/gomega v1.27.6 @@ -19,7 +18,6 @@ require ( github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/emicklei/go-restful/v3 v3.9.0 // indirect - github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/ghodss/yaml v1.0.0 // indirect github.com/go-errors/errors v1.4.2 // indirect github.com/go-logr/logr v1.2.4 // indirect diff --git a/tests/e2e/go.sum b/tests/e2e/go.sum index 029a9c038..d6318451f 100644 --- a/tests/e2e/go.sum +++ b/tests/e2e/go.sum @@ -12,8 +12,6 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA 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/cisco-open/k8s-objectmatcher v1.9.0 h1:/sfuO0BD09fpynZjXsqeZrh28Juc4VEwc2P6Ov/Q6fM= -github.com/cisco-open/k8s-objectmatcher v1.9.0/go.mod h1:CH4E6qAK+q+JwKFJn0DaTNqxrbmWCaDQzGthKLK4nZ0= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= @@ -27,8 +25,6 @@ github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhF github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= 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 v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= -github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= diff --git a/tests/e2e/helm_test.go b/tests/e2e/helm_test.go new file mode 100644 index 000000000..e1dacc259 --- /dev/null +++ b/tests/e2e/helm_test.go @@ -0,0 +1,157 @@ +// Copyright © 2023 Cisco Systems, Inc. and/or its affiliates +// +// 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" + + "github.com/gruntwork-io/terratest/modules/helm" + "github.com/gruntwork-io/terratest/modules/k8s" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "sigs.k8s.io/yaml" +) + +// HelmReleaseStatus describes the possible states of a Helm release. +type HelmReleaseStatus string + +const ( + // HelmReleaseDeployed is the Helm release state where the deployment is + // successfully applied to the cluster. + HelmReleaseDeployed HelmReleaseStatus = "deployed" + + // HelmReleaseFailed is the Helm release state where the deployment + // encountered an error and couldn't be applied successfully to the cluster. + HelmReleaseFailed HelmReleaseStatus = "failed" +) + +// HelmRelease describes a Helm +type HelmRelease struct { + ReleaseName string `json:"name" yaml:"name"` + Namespace string `json:"namespace" yaml:"namespace"` + Revision string `json:"revision" yaml:"revision"` + UpdatedTime string `json:"updated" yaml:"updated"` // Note: not parsable implicitly. + Status HelmReleaseStatus `json:"status" yaml:"status"` + Chart string `json:"chart" yaml:"chart"` + AppVersion string `json:"app_version" yaml:"app_version"` +} + +// installHelmChart deploys a Helm chart to the specified kubectl context and +// namespace using the specified infos, extra arguments can be any of the helm +// CLI install flag arguments, flag keys and values must be provided separately. +func installHelmChart( + kubectlOptions *k8s.KubectlOptions, + helmRepository string, + helmChartName string, + helmChartVersion string, + helmReleaseName string, + setValues map[string]string, +) { + By( + fmt.Sprintf( + "Installing Helm chart %s from %s with version %s by name %s", + helmChartName, helmRepository, helmChartVersion, helmReleaseName, + ), + ) + + fixedArguments := []string{ + "--repo", helmRepository, + "--create-namespace", + "--atomic", + "--debug", + } + + helm.Install( + GinkgoT(), + &helm.Options{ + SetValues: setValues, + KubectlOptions: kubectlOptions, + Version: helmChartVersion, + ExtraArgs: map[string][]string{ + "install": fixedArguments, + }, + }, + helmChartName, + helmReleaseName, + ) +} + +// installHelmChart checks whether the specified named Helm release exists in +// the provided kubectl context and namespace, logs it if it does and returns or +// alternatively deploys the Helm chart to the specified kubectl context and +// namespace using the specified infos, extra arguments can be any of the helm +// CLI install flag arguments, flag keys and values must be provided separately. +func installHelmChartIfDoesNotExist( + kubectlOptions *k8s.KubectlOptions, + helmRepository string, + helmChartName string, + helmChartVersion string, + helmReleaseName string, + setValues map[string]string, +) { + By(fmt.Sprintf("Checking for existing Helm release named %s", helmReleaseName)) + helmRelease, isInstalled := lookUpInstalledHelmReleaseByName(kubectlOptions, helmReleaseName) + + if isInstalled { + By(fmt.Sprintf( + "Skipping the installation of %s, because the Helm release is already present: %+v", + helmReleaseName, helmRelease, + )) + + return + } + + installHelmChart(kubectlOptions, helmRepository, helmChartName, helmChartVersion, helmReleaseName, setValues) +} + +// listHelmReleases returns a slice of Helm releases retrieved from the cluster +// using the specified kubectl context and namespace. +func listHelmReleases(kubectlOptions *k8s.KubectlOptions) []*HelmRelease { + By("Listing Helm releases") + output, err := helm.RunHelmCommandAndGetOutputE( + GinkgoT(), + &helm.Options{ + KubectlOptions: kubectlOptions, + }, + "list", + "--output", "yaml", + ) + + Expect(err).NotTo(HaveOccurred()) + + var releases []*HelmRelease + err = yaml.Unmarshal([]byte(output), &releases) + + Expect(err).NotTo(HaveOccurred()) + + return releases +} + +// lookUpInstalledHelmReleaseByName returns a Helm release and an indicator +// whether the Helm release is installed to the specified kubectl context +// and namespace by the provided Helm release name. +func lookUpInstalledHelmReleaseByName(kubectlOptions *k8s.KubectlOptions, helmReleaseName string) (*HelmRelease, bool) { + releases := listHelmReleases(kubectlOptions) + + for _, release := range releases { + if release.ReleaseName == helmReleaseName { + Expect(release.Status).To(BeEquivalentTo(HelmReleaseDeployed)) + + return release, true + } + } + + return nil, false +} diff --git a/tests/e2e/install_test.go b/tests/e2e/install_test.go new file mode 100644 index 000000000..d93c62e8b --- /dev/null +++ b/tests/e2e/install_test.go @@ -0,0 +1,38 @@ +// Copyright © 2023 Cisco Systems, Inc. and/or its affiliates +// +// 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 ( + "github.com/gruntwork-io/terratest/modules/k8s" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +var _ = When("Installing Koperator", func() { + var kubeconfigPath string + var kubecontextName string + + It("Acquiring K8s config and context", func() { + var err error + kubeconfigPath, kubecontextName, err = currentEnvK8sContext() + + Expect(err).NotTo(HaveOccurred()) + }) + + requireInstallingCertManager(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "cert-manager"), "v1.11.0") + requireInstallingZookeeperOperator(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "zookeeper"), "0.2.14") + requireInstallingPrometheusOperator(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "prometheus"), "42.0.1") + requireInstallingKoperator(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "kafka"), "v0.24.1") +}) diff --git a/tests/e2e/k8s_test.go b/tests/e2e/k8s_test.go new file mode 100644 index 000000000..aecd68cc4 --- /dev/null +++ b/tests/e2e/k8s_test.go @@ -0,0 +1,174 @@ +// Copyright © 2023 Cisco Systems, Inc. and/or its affiliates +// +// 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" + "os" + "path" + "strings" + + "emperror.dev/errors" + "github.com/gruntwork-io/terratest/modules/k8s" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/yaml" +) + +// applyK8sResourceManifests applies the specified manifest to the provided +// kubectl context and namespace. +func applyK8sResourceManifest(kubectlOptions *k8s.KubectlOptions, manifestPath string) { + By(fmt.Sprintf("Applying k8s manifest %s", manifestPath)) + k8s.KubectlApply(GinkgoT(), kubectlOptions, manifestPath) +} + +// createK8sResourcesFromManifest creates Kubernetes resources from the +// specified manifest to the provided kubectl context and namespace. +func createK8sResourcesFromManifest(kubectlOptions *k8s.KubectlOptions, manifestPath string, shouldBeValidated bool) { + By(fmt.Sprintf("Creating k8s resources from manifest %s", manifestPath)) + k8s.RunKubectl( + GinkgoT(), + kubectlOptions, + "create", + fmt.Sprintf("--validate=%t", shouldBeValidated), + "--filename", manifestPath, + ) +} + +// createOrReplaceK8sResourcesFromManifest creates non-existent Kubernetes +// resources or replaces existing ones from the specified manifest to the +// provided kubectl context and namespace. +func createOrReplaceK8sResourcesFromManifest( + kubectlOptions *k8s.KubectlOptions, + resourceKind string, + resourceName string, + resourceManifest string, + shouldBeValidated bool, +) { + By(fmt.Sprintf("Checking the existence of resource %s", resourceName)) + err := k8s.RunKubectlE(GinkgoT(), kubectlOptions, "get", resourceKind, resourceName) + + if err == nil { + replaceK8sResourcesFromManifest(kubectlOptions, resourceManifest, shouldBeValidated) + } else { + createK8sResourcesFromManifest(kubectlOptions, resourceManifest, shouldBeValidated) + } +} + +// currentKubernetesContext returns the currently set Kubernetes context based +// on the the environment variables and the KUBECONFIG file. +func currentEnvK8sContext() (kubeconfigPath string, kubecontextName string, err error) { + kubeconfigPath, isExisting := os.LookupEnv("KUBECONFIG") + if !isExisting { + homePath, err := os.UserHomeDir() + if err != nil { + return "", "", errors.WrapIf(err, "retrieving user home directory failed") + } + + kubeconfigPath = path.Join(homePath, ".kube", "config") + } + + kubeconfigBytes, err := os.ReadFile(kubeconfigPath) + if err != nil { + return "", "", errors.WrapIfWithDetails(err, "reading KUBECONFIG file failed", "path", kubeconfigPath) + } + + structuredKubeconfig := make(map[string]interface{}) + err = yaml.Unmarshal(kubeconfigBytes, &structuredKubeconfig) + if err != nil { + return "", "", errors.WrapIfWithDetails( + err, + "parsing kubeconfig failed", + "kubeconfig", string(kubeconfigBytes), + ) + } + + kubecontext, isOk := structuredKubeconfig["current-context"].(string) + if !isOk { + return "", "", errors.WrapIfWithDetails( + err, + "kubeconfig current-context is not string", + "current-context", structuredKubeconfig["current-context"], + ) + } + + return kubeconfigPath, kubecontext, nil +} + +// listK8sCRDs lists the available CRDs from the specified kubectl context and +// namespace optionally filtering for the specified CRD names. +func listK8sCRDs(kubectlOptions *k8s.KubectlOptions, crdNames ...string) []string { + if len(crdNames) == 0 { + By("Listing CRDs") + } else { + By(fmt.Sprintf("Listing CRDs filtered for CRD names %+v", crdNames)) + } + + args := append([]string{"get", "crd", "-o", "name"}, crdNames...) + output, err := k8s.RunKubectlAndGetOutputE( + GinkgoT(), + kubectlOptions, + args..., + ) + + Expect(err).NotTo(HaveOccurred()) + + return strings.Split(output, "\n") +} + +// replaceK8sResourcesFromManifest replaces existing Kubernetes resources from +// the specified manifest to the provided kubectl context and namespace. +func replaceK8sResourcesFromManifest(kubectlOptions *k8s.KubectlOptions, manifestPath string, shouldBeValidated bool) { + By(fmt.Sprintf("Replacing k8s resources from manifest %s", manifestPath)) + k8s.RunKubectl( + GinkgoT(), + kubectlOptions, + "replace", + fmt.Sprintf("--validate=%t", shouldBeValidated), + "--filename", manifestPath, + ) +} + +// requireExistingCRDs checks whether the specified CRDs are existing on +// the provided kubectl context. +func requireExistingCRDs(kubectlOptions *k8s.KubectlOptions, crdNames ...string) { + crds := listK8sCRDs(kubectlOptions, crdNames...) + + crdFullNames := make([]string, 0, len(crds)) + for _, crdName := range crdNames { + crdFullNames = append(crdFullNames, "customresourcedefinition.apiextensions.k8s.io/"+crdName) + } + + Expect(crds).To(ContainElements(crdFullNames)) +} + +// requireRunningPods checks whether the specified pod names are existing in the +// namespace and have a running status. +func requireRunningPods(kubectlOptions *k8s.KubectlOptions, matchingLabelKey string, podNames ...string) { + By(fmt.Sprintf("Verifying running pods for pod names %+v", podNames)) + pods := k8s.ListPods(GinkgoT(), kubectlOptions, v1.ListOptions{}) + + podNamesAsInterfaces := make([]interface{}, 0, len(podNames)) + for _, podName := range podNames { + podNamesAsInterfaces = append(podNamesAsInterfaces, podName) + } + + Expect(pods).To(HaveLen(len(podNames))) + for _, pod := range pods { + Expect(pod.GetLabels()[matchingLabelKey]).To(BeElementOf(podNamesAsInterfaces...)) + Expect(pod.Status.Phase).To(BeEquivalentTo("Running")) + } +} diff --git a/tests/e2e/koperator_suite_test.go b/tests/e2e/koperator_suite_test.go index 5be005541..dcc89263c 100644 --- a/tests/e2e/koperator_suite_test.go +++ b/tests/e2e/koperator_suite_test.go @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build e2e - package e2e import ( diff --git a/tests/e2e/koperator_test.go b/tests/e2e/koperator_test.go new file mode 100644 index 000000000..de7bd4fa5 --- /dev/null +++ b/tests/e2e/koperator_test.go @@ -0,0 +1,122 @@ +// Copyright © 2023 Cisco Systems, Inc. and/or its affiliates +// +// 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 ( + "bytes" + "fmt" + "io" + "net/http" + "os" + "path" + "time" + + "github.com/gruntwork-io/terratest/modules/k8s" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + "sigs.k8s.io/yaml" +) + +// requireApplyingKoperatorCRDs deploys the koperator CRDs and checks their +// existence afterwards. +func requireApplyingKoperatorCRDs(kubectlOptions *k8s.KubectlOptions, koperatorVersion string) { + It("Applying koperator CRDs", func() { + By(fmt.Sprintf("Retrieving Koperator CRDs (to work around too long CRD) with version %s ", koperatorVersion)) + // Note: had to go lower because none of apply, create, replace works + // properly with the KafkaCluster CRD due to the size (apply cannot + // handle the size, create is not idempotent, replace is only idempotent + // if the resources are existing already). Tried dropping the + // descriptions in the CRDs, but still too large + httpClient := new(http.Client) + httpClient.Timeout = 5 * time.Second + + response, err := httpClient.Get("https://github.com/banzaicloud/koperator/releases/download/" + koperatorVersion + "/kafka-operator.crds.yaml") + if response != nil { + defer func() { _ = response.Body.Close() }() + } + + Expect(err).NotTo(HaveOccurred()) + + rawKoperatorCRDsManifest, err := io.ReadAll(response.Body) + + Expect(err).NotTo(HaveOccurred()) + + rawKoperatorCRDs := bytes.Split(rawKoperatorCRDsManifest, []byte("\n---\n")) + for rawKoperatorCRDIndex, rawKoperatorCRD := range rawKoperatorCRDs { + rawKoperatorCRDs[rawKoperatorCRDIndex] = bytes.Trim(rawKoperatorCRD, "\n-") + } + + allowedCRDByteCount := 262144 + tempDir := os.TempDir() + tempFile := path.Join(tempDir, "manifest.yaml") + for _, rawKoperatorCRD := range rawKoperatorCRDs { + err = os.WriteFile(tempFile, rawKoperatorCRD, 0o777) + + Expect(err).NotTo(HaveOccurred()) + + if len(rawKoperatorCRD) > allowedCRDByteCount { // Note: too long CRDs cannot be applied, only created or replaced. + var koperatorCRD apiextensionsv1.CustomResourceDefinition + err := yaml.Unmarshal(rawKoperatorCRD, &koperatorCRD) + + Expect(err).NotTo(HaveOccurred()) + + createOrReplaceK8sResourcesFromManifest(kubectlOptions, "crd", koperatorCRD.GetName(), tempFile, false) + } else { + By("Applying cert-manager CRDs with version " + koperatorVersion) + applyK8sResourceManifest(kubectlOptions, tempFile) + } + } + + By("Verifying koperator CRDs") + requireExistingCRDs( + kubectlOptions, + "cruisecontroloperations.kafka.banzaicloud.io", + "kafkaclusters.kafka.banzaicloud.io", + "kafkatopics.kafka.banzaicloud.io", + "kafkausers.kafka.banzaicloud.io", + ) + }) +} + +// requireInstallingKoperator deploys koperator CRDs and Helm chart and checks +// the success of those operations. +func requireInstallingKoperator(kubectlOptions *k8s.KubectlOptions, koperatorVersion string) { + When("Installing koperator", func() { + requireApplyingKoperatorCRDs(kubectlOptions, koperatorVersion) + requireInstallingKoperatorHelmChartIfDoesNotExist(kubectlOptions, koperatorVersion) + }) +} + +// requireDeployingKoperatorHelmChart checks the existence of the koperator Helm +// release and installs it if it's not present. +func requireInstallingKoperatorHelmChartIfDoesNotExist( + kubectlOptions *k8s.KubectlOptions, + koperatorVersion string, +) { + It("Installing koperator Helm chart", func() { + installHelmChartIfDoesNotExist( + kubectlOptions, + "https://kubernetes-charts.banzaicloud.com", + "kafka-operator", + koperatorVersion, + "kafka-operator", + nil, + ) + + By("Verifying koperator pods") + requireRunningPods(kubectlOptions, "app.kubernetes.io/name", "kafka-operator") + }) +} diff --git a/tests/e2e/prometheus_test.go b/tests/e2e/prometheus_test.go new file mode 100644 index 000000000..6df14c606 --- /dev/null +++ b/tests/e2e/prometheus_test.go @@ -0,0 +1,65 @@ +// Copyright © 2023 Cisco Systems, Inc. and/or its affiliates +// +// 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 ( + "github.com/gruntwork-io/terratest/modules/k8s" + + . "github.com/onsi/ginkgo/v2" +) + +// requireInstallingPrometheusOperator deploys prometheus-operator Helm chart +// and checks the success of that operation. +func requireInstallingPrometheusOperator(kubectlOptions *k8s.KubectlOptions, certManagerVersion string) { + When("Installing prometheus-operator", func() { + requireInstallingPrometheusOperatorHelmChartIfDoesNotExist(kubectlOptions, certManagerVersion) + }) +} + +// requireDeployingCertManagerHelmChart checks the existence of the cert-manager +// Helm release and installs it if it's not present. +func requireInstallingPrometheusOperatorHelmChartIfDoesNotExist( + kubectlOptions *k8s.KubectlOptions, + prometheusOperatorVersion string, +) { + It("Installing prometheus-operator Helm chart", func() { + installHelmChartIfDoesNotExist( + kubectlOptions, + "https://prometheus-community.github.io/helm-charts", + "kube-prometheus-stack", + prometheusOperatorVersion, + "prometheus-operator", + map[string]string{ + "prometheusOperator.createCustomResource": "true", + "defaultRules.enabled": "false", + "alertmanager.enabled": "false", + "grafana.enabled": "false", + "kubeApiServer.enabled": "false", + "kubelet.enabled": "false", + "kubeControllerManager.enabled": "false", + "coreDNS.enabled": "false", + "kubeEtcd.enabled": "false", + "kubeScheduler.enabled": "false", + "kubeProxy.enabled": "false", + "kubeStateMetrics.enabled": "false", + "nodeExporter.enabled": "false", + "prometheus.enabled": "false", + }, + ) + + By("Verifying prometheus-operator pods") + requireRunningPods(kubectlOptions, "app", "kube-prometheus-stack-operator") + }) +} diff --git a/tests/e2e/zookeeper_test.go b/tests/e2e/zookeeper_test.go new file mode 100644 index 000000000..573f2a6b5 --- /dev/null +++ b/tests/e2e/zookeeper_test.go @@ -0,0 +1,50 @@ +// Copyright © 2023 Cisco Systems, Inc. and/or its affiliates +// +// 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 ( + "github.com/gruntwork-io/terratest/modules/k8s" + + . "github.com/onsi/ginkgo/v2" +) + +// requireInstallingZookeeperOperator deploys zookeeper-operator Helm chart and +// checks the success of that operation. +func requireInstallingZookeeperOperator(kubectlOptions *k8s.KubectlOptions, certManagerVersion string) { + When("Installing zookeeper-operator", func() { + requireInstallingZookeeperOperatorHelmChartIfDoesNotExist(kubectlOptions, certManagerVersion) + }) +} + +// requireDeployingCertManagerHelmChart checks the existence of the cert-manager +// Helm release and installs it if it's not present. +func requireInstallingZookeeperOperatorHelmChartIfDoesNotExist( + kubectlOptions *k8s.KubectlOptions, + zookeeperOperatorVersion string, +) { + It("Installing zookeeper-operator Helm chart", func() { + installHelmChartIfDoesNotExist( + kubectlOptions, + "https://charts.pravega.io", + "zookeeper-operator", + zookeeperOperatorVersion, + "zookeeper-operator", + nil, + ) + + By("Verifying zookeeper-operator pods") + requireRunningPods(kubectlOptions, "name", "zookeeper-operator") + }) +} From bd41f3b6a07d5b6a270aa4a5987485b6da15c96e Mon Sep 17 00:00:00 2001 From: Patrik Egyed Date: Mon, 22 May 2023 01:15:11 +0200 Subject: [PATCH 02/24] test(docs/install): added localversion 4 Koperator --- tests/e2e/cert_manager_test.go | 4 +- tests/e2e/helm_test.go | 22 ++++++++--- tests/e2e/install_test.go | 2 +- tests/e2e/koperator_test.go | 68 +++++++++++++++++++++++----------- tests/e2e/prometheus_test.go | 6 +-- tests/e2e/version_test.go | 22 +++++++++++ 6 files changed, 90 insertions(+), 34 deletions(-) create mode 100644 tests/e2e/version_test.go diff --git a/tests/e2e/cert_manager_test.go b/tests/e2e/cert_manager_test.go index 10b8175ba..be80e343a 100644 --- a/tests/e2e/cert_manager_test.go +++ b/tests/e2e/cert_manager_test.go @@ -21,7 +21,7 @@ import ( // requireApplyingCertManagerCRDs deploys the cert-manager CRDs and checks // their existence afterwards. -func requireApplyingCertManagerCRDs(kubectlOptions *k8s.KubectlOptions, certManagerVersion string) { +func requireApplyingCertManagerCRDs(kubectlOptions *k8s.KubectlOptions, certManagerVersion Version) { It("Applying cert-manager CRDs", func() { By("Applying cert-manager CRDs with version " + certManagerVersion) applyK8sResourceManifest( @@ -44,7 +44,7 @@ func requireApplyingCertManagerCRDs(kubectlOptions *k8s.KubectlOptions, certMana // requireInstallingCertManager deploys cert-manager CRDs and Helm chart and // checks the success of those operations. -func requireInstallingCertManager(kubectlOptions *k8s.KubectlOptions, certManagerVersion string) { +func requireInstallingCertManager(kubectlOptions *k8s.KubectlOptions, certManagerVersion Version) { When("Installing cert-manager", func() { requireApplyingCertManagerCRDs(kubectlOptions, certManagerVersion) requireInstallingCertManagerHelmChartIfDoesNotExist(kubectlOptions, certManagerVersion) diff --git a/tests/e2e/helm_test.go b/tests/e2e/helm_test.go index e1dacc259..e0e179b67 100644 --- a/tests/e2e/helm_test.go +++ b/tests/e2e/helm_test.go @@ -54,7 +54,7 @@ type HelmRelease struct { func installHelmChart( kubectlOptions *k8s.KubectlOptions, helmRepository string, - helmChartName string, + helmChartNameOrLocalPath string, helmChartVersion string, helmReleaseName string, setValues map[string]string, @@ -62,17 +62,20 @@ func installHelmChart( By( fmt.Sprintf( "Installing Helm chart %s from %s with version %s by name %s", - helmChartName, helmRepository, helmChartVersion, helmReleaseName, + helmChartNameOrLocalPath, helmRepository, helmChartVersion, helmReleaseName, ), ) fixedArguments := []string{ - "--repo", helmRepository, "--create-namespace", "--atomic", "--debug", } + if helmRepository != "" { + fixedArguments = append([]string{"--repo", helmRepository}, fixedArguments...) + } + helm.Install( GinkgoT(), &helm.Options{ @@ -83,7 +86,7 @@ func installHelmChart( "install": fixedArguments, }, }, - helmChartName, + helmChartNameOrLocalPath, helmReleaseName, ) } @@ -96,7 +99,7 @@ func installHelmChart( func installHelmChartIfDoesNotExist( kubectlOptions *k8s.KubectlOptions, helmRepository string, - helmChartName string, + helmChartNameOrLocalPath string, helmChartVersion string, helmReleaseName string, setValues map[string]string, @@ -113,7 +116,14 @@ func installHelmChartIfDoesNotExist( return } - installHelmChart(kubectlOptions, helmRepository, helmChartName, helmChartVersion, helmReleaseName, setValues) + installHelmChart( + kubectlOptions, + helmRepository, + helmChartNameOrLocalPath, + helmChartVersion, + helmReleaseName, + setValues, + ) } // listHelmReleases returns a slice of Helm releases retrieved from the cluster diff --git a/tests/e2e/install_test.go b/tests/e2e/install_test.go index d93c62e8b..18769fc45 100644 --- a/tests/e2e/install_test.go +++ b/tests/e2e/install_test.go @@ -34,5 +34,5 @@ var _ = When("Installing Koperator", func() { requireInstallingCertManager(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "cert-manager"), "v1.11.0") requireInstallingZookeeperOperator(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "zookeeper"), "0.2.14") requireInstallingPrometheusOperator(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "prometheus"), "42.0.1") - requireInstallingKoperator(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "kafka"), "v0.24.1") + requireInstallingKoperator(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "kafka"), LocalVersion) }) diff --git a/tests/e2e/koperator_test.go b/tests/e2e/koperator_test.go index de7bd4fa5..7fa563204 100644 --- a/tests/e2e/koperator_test.go +++ b/tests/e2e/koperator_test.go @@ -23,6 +23,7 @@ import ( "path" "time" + "github.com/gruntwork-io/terratest/modules/helm" "github.com/gruntwork-io/terratest/modules/k8s" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -32,7 +33,7 @@ import ( // requireApplyingKoperatorCRDs deploys the koperator CRDs and checks their // existence afterwards. -func requireApplyingKoperatorCRDs(kubectlOptions *k8s.KubectlOptions, koperatorVersion string) { +func requireApplyingKoperatorCRDs(kubectlOptions *k8s.KubectlOptions, koperatorVersion Version) { It("Applying koperator CRDs", func() { By(fmt.Sprintf("Retrieving Koperator CRDs (to work around too long CRD) with version %s ", koperatorVersion)) // Note: had to go lower because none of apply, create, replace works @@ -40,19 +41,37 @@ func requireApplyingKoperatorCRDs(kubectlOptions *k8s.KubectlOptions, koperatorV // handle the size, create is not idempotent, replace is only idempotent // if the resources are existing already). Tried dropping the // descriptions in the CRDs, but still too large - httpClient := new(http.Client) - httpClient.Timeout = 5 * time.Second - - response, err := httpClient.Get("https://github.com/banzaicloud/koperator/releases/download/" + koperatorVersion + "/kafka-operator.crds.yaml") - if response != nil { - defer func() { _ = response.Body.Close() }() - } + var rawKoperatorCRDsManifest []byte + var err error + + switch koperatorVersion { + case LocalVersion: + rawKoperatorCRDsManifest = []byte(helm.RenderTemplate( + GinkgoT(), + &helm.Options{ + SetValues: map[string]string{ + "crd.enabled": "true", + }, + }, + "../../charts/kafka-operator", + "dummy", + []string{"templates/crds.yaml"}, + )) + default: + httpClient := new(http.Client) + httpClient.Timeout = 5 * time.Second + + response, err := httpClient.Get("https://github.com/banzaicloud/koperator/releases/download/" + koperatorVersion + "/kafka-operator.crds.yaml") + if response != nil { + defer func() { _ = response.Body.Close() }() + } - Expect(err).NotTo(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) - rawKoperatorCRDsManifest, err := io.ReadAll(response.Body) + rawKoperatorCRDsManifest, err = io.ReadAll(response.Body) - Expect(err).NotTo(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) + } rawKoperatorCRDs := bytes.Split(rawKoperatorCRDsManifest, []byte("\n---\n")) for rawKoperatorCRDIndex, rawKoperatorCRD := range rawKoperatorCRDs { @@ -75,7 +94,7 @@ func requireApplyingKoperatorCRDs(kubectlOptions *k8s.KubectlOptions, koperatorV createOrReplaceK8sResourcesFromManifest(kubectlOptions, "crd", koperatorCRD.GetName(), tempFile, false) } else { - By("Applying cert-manager CRDs with version " + koperatorVersion) + By("Applying koperator CRDs with version " + koperatorVersion) applyK8sResourceManifest(kubectlOptions, tempFile) } } @@ -93,7 +112,7 @@ func requireApplyingKoperatorCRDs(kubectlOptions *k8s.KubectlOptions, koperatorV // requireInstallingKoperator deploys koperator CRDs and Helm chart and checks // the success of those operations. -func requireInstallingKoperator(kubectlOptions *k8s.KubectlOptions, koperatorVersion string) { +func requireInstallingKoperator(kubectlOptions *k8s.KubectlOptions, koperatorVersion Version) { When("Installing koperator", func() { requireApplyingKoperatorCRDs(kubectlOptions, koperatorVersion) requireInstallingKoperatorHelmChartIfDoesNotExist(kubectlOptions, koperatorVersion) @@ -104,17 +123,22 @@ func requireInstallingKoperator(kubectlOptions *k8s.KubectlOptions, koperatorVer // release and installs it if it's not present. func requireInstallingKoperatorHelmChartIfDoesNotExist( kubectlOptions *k8s.KubectlOptions, - koperatorVersion string, + koperatorVersion Version, ) { It("Installing koperator Helm chart", func() { - installHelmChartIfDoesNotExist( - kubectlOptions, - "https://kubernetes-charts.banzaicloud.com", - "kafka-operator", - koperatorVersion, - "kafka-operator", - nil, - ) + switch koperatorVersion { + case LocalVersion: + installHelmChartIfDoesNotExist(kubectlOptions, "", "../../charts/kafka-operator", "", "kafka-operator", nil) + default: + installHelmChartIfDoesNotExist( + kubectlOptions, + "https://kubernetes-charts.banzaicloud.com", + "kafka-operator", + koperatorVersion, + "kafka-operator", + nil, + ) + } By("Verifying koperator pods") requireRunningPods(kubectlOptions, "app.kubernetes.io/name", "kafka-operator") diff --git a/tests/e2e/prometheus_test.go b/tests/e2e/prometheus_test.go index 6df14c606..0f9f784f3 100644 --- a/tests/e2e/prometheus_test.go +++ b/tests/e2e/prometheus_test.go @@ -22,9 +22,9 @@ import ( // requireInstallingPrometheusOperator deploys prometheus-operator Helm chart // and checks the success of that operation. -func requireInstallingPrometheusOperator(kubectlOptions *k8s.KubectlOptions, certManagerVersion string) { +func requireInstallingPrometheusOperator(kubectlOptions *k8s.KubectlOptions, prometheusOperatorVersion Version) { When("Installing prometheus-operator", func() { - requireInstallingPrometheusOperatorHelmChartIfDoesNotExist(kubectlOptions, certManagerVersion) + requireInstallingPrometheusOperatorHelmChartIfDoesNotExist(kubectlOptions, prometheusOperatorVersion) }) } @@ -32,7 +32,7 @@ func requireInstallingPrometheusOperator(kubectlOptions *k8s.KubectlOptions, cer // Helm release and installs it if it's not present. func requireInstallingPrometheusOperatorHelmChartIfDoesNotExist( kubectlOptions *k8s.KubectlOptions, - prometheusOperatorVersion string, + prometheusOperatorVersion Version, ) { It("Installing prometheus-operator Helm chart", func() { installHelmChartIfDoesNotExist( diff --git a/tests/e2e/version_test.go b/tests/e2e/version_test.go new file mode 100644 index 000000000..983916b6c --- /dev/null +++ b/tests/e2e/version_test.go @@ -0,0 +1,22 @@ +// Copyright © 2023 Cisco Systems, Inc. and/or its affiliates +// +// 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 + +type Version = string + +const ( + // LocalVersion means using the files in the local repository snapshot. + LocalVersion Version = "local" +) From bdce6491f7ddd7232fdb4b681c6d244fb1b30dfe Mon Sep 17 00:00:00 2001 From: marbarta Date: Sun, 28 May 2023 16:09:36 +0200 Subject: [PATCH 03/24] feat(e2e): added uninstall koperator and dep --- Makefile | 6 +- tests/e2e/cert_manager_test.go | 44 ++++++- tests/e2e/const.go | 107 ++++++++++++++++ tests/e2e/go.mod | 33 +++-- tests/e2e/go.sum | 147 +++++++++++++++++++--- tests/e2e/helm_test.go | 68 +++++++++- tests/e2e/install_test.go | 24 +++- tests/e2e/k8s_test.go | 184 ++++++++++++++++++++++++++++ tests/e2e/kafka_prod_consum_test.go | 148 ++++++++++++++++++++++ tests/e2e/koperator_test.go | 122 +++++++++++++++++- tests/e2e/prometheus_test.go | 41 +++++++ tests/e2e/templates/kcat.yaml.tmpl | 13 ++ tests/e2e/templates/topic.yaml.tmpl | 15 +++ tests/e2e/utils.go | 80 ++++++++++++ tests/e2e/version_test.go | 22 ---- tests/e2e/zookeeper_test.go | 67 ++++++++++ 16 files changed, 1062 insertions(+), 59 deletions(-) create mode 100644 tests/e2e/kafka_prod_consum_test.go create mode 100644 tests/e2e/templates/kcat.yaml.tmpl create mode 100644 tests/e2e/templates/topic.yaml.tmpl create mode 100644 tests/e2e/utils.go delete mode 100644 tests/e2e/version_test.go diff --git a/Makefile b/Makefile index 52ba33ece..9a588bc61 100644 --- a/Makefile +++ b/Makefile @@ -102,7 +102,11 @@ test: generate fmt vet manifests bin/setup-envtest test-e2e: go test github.com/banzaicloud/koperator/tests/e2e \ -v \ - -timeout 5m + -timeout 15m \ + --ginkgo.fail-fast \ + --ginkgo.show-node-events \ + --ginkgo.trace \ + --ginkgo.v # Build manager binary manager: generate fmt vet diff --git a/tests/e2e/cert_manager_test.go b/tests/e2e/cert_manager_test.go index be80e343a..c483d16aa 100644 --- a/tests/e2e/cert_manager_test.go +++ b/tests/e2e/cert_manager_test.go @@ -15,8 +15,11 @@ package e2e import ( + "fmt" + "github.com/gruntwork-io/terratest/modules/k8s" . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" ) // requireApplyingCertManagerCRDs deploys the cert-manager CRDs and checks @@ -51,7 +54,7 @@ func requireInstallingCertManager(kubectlOptions *k8s.KubectlOptions, certManage }) } -// requireDeployingCertManagerHelmChart checks the existence of the cert-manager +// requireInstallingCertManagerHelmChartIfDoesNotExist checks the existence of the cert-manager // Helm release and installs it if it's not present. func requireInstallingCertManagerHelmChartIfDoesNotExist( kubectlOptions *k8s.KubectlOptions, @@ -71,3 +74,42 @@ func requireInstallingCertManagerHelmChartIfDoesNotExist( requireRunningPods(kubectlOptions, "app.kubernetes.io/name", "cert-manager", "cainjector", "webhook") }) } + +// requireUninstallingCertManager uninstall Cert-manager Helm chart and +// remove CRDs. +func requireUninstallingCertManager(kubectlOptions *k8s.KubectlOptions) { + When("Uninstalling zookeeper-operator", func() { + requireUninstallingCertManagerHelmChart(kubectlOptions) + requireRemoveCertManagerCRDs(kubectlOptions) + }) +} + +// requireUninstallingCertManagerHelmChart uninstalls cert-manager helm chart +// and checks the success of that operation. +func requireUninstallingCertManagerHelmChart(kubectlOptions *k8s.KubectlOptions) { + It("Uninstalling Cert-manager Helm chart", func() { + uninstallHelmChartIfExists(kubectlOptions, "cert-manager", true) + By("Verifying Cert-manager helm chart resources cleanup") + + certManagerK8sResources := basicK8sCRDs() + certManagerK8sResources = append(certManagerK8sResources, certManagerCRDs()...) + + remainedResources := getK8sResources(kubectlOptions, + certManagerK8sResources, + fmt.Sprintf(managedByHelmLabelTemplate, "cert-manager"), + "", + kubectlArgGoTemplateKindNameNamespace, + "--all-namespaces") + Expect(remainedResources).Should(BeEmpty()) + }) + +} + +// requireRemoveKoperatorCRDs deletes the cert-manager CRDs +func requireRemoveCertManagerCRDs(kubectlOptions *k8s.KubectlOptions) { + It("Removing cert-manager CRDs", func() { + for _, crd := range certManagerCRDs() { + deleteK8sResourceGlobalNoErrNotFound(kubectlOptions, defaultDeletionTimeout, "crds", crd) + } + }) +} diff --git a/tests/e2e/const.go b/tests/e2e/const.go index 1b1b86d56..5f9c529dd 100644 --- a/tests/e2e/const.go +++ b/tests/e2e/const.go @@ -14,6 +14,8 @@ package e2e +import "time" + // HelmDescriptors. var ( // certManagerHelmDescriptor describes the cert-manager Helm component. @@ -103,6 +105,111 @@ var ( type Version = string const ( + // LocalVersion means using the files in the local repository snapshot. LocalVersion Version = "local" + + kubectlNotFoundErrorMsg = "NotFound" + + kubectlArgGoTemplateName = `-o=go-template='{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}'` + kubectlArgGoTemplateKindNameNamespace = `-o=go-template='{{range .items}}{{.kind}}{{"/"}}{{.metadata.name}}{{if .metadata.namespace}}{{"."}}{{.metadata.namespace}}{{end}}{{"\n"}}{{end}}'` + kubectlArgGoTemplateInternalListenersName = `-o=go-template='{{range $key,$value := .status.listenerStatuses.internalListeners}}{{$key}}{{"\n"}}{{end}}` + kubectlArgGoTemplateInternalListenerAddressesTemplate = `-o=go-template='{{range .status.listenerStatuses.internalListeners.%s}}{{.address}}{{"\n"}}{{end}}` + // kubectlArgGoTemplateExternalListenersName = `-o=go-template='{{range $key,$value := .status.listenerStatuses.externallListeners}}{{$key}}{{"\n"}}{{end}}` + // kubectlArgGoTemplateExternalListenerAddressesTemplate = `-o=go-template='{{range .status.listenerStatuses.externalListeners.%s}}{{.address}}{{"\n"}}{{end}}` + + kafkaKind = "kafkaclusters.kafka.banzaicloud.io" + kafkaClusterName = "kafka" + testTopicName = "topic-icp" + kcatPodName = "kcat" + zookeeperKind = "zookeeperclusters.zookeeper.pravega.io" + zookeeperClusterName = "zookeeper-server" + managedByHelmLabelTemplate = "app.kubernetes.io/managed-by=Helm,app.kubernetes.io/instance=%s" + + defaultDeletionTimeout = 20 * time.Second + defaultPodReadinessWaitTime = 10 * time.Second + defaultTopicCreationWaitTime = 10 * time.Second + kafkaClusterResourceCleanupTimeout = 30 * time.Second + zookeeperClusterResourceCleanupTimeout = 60 * time.Second + externalConsumerTimeout = 5 * time.Second + externalProducerTimeout = 5 * time.Second + + kcatPodTemplate = "templates/kcat.yaml.tmpl" + kafkaTopicTemplate = "templates/topic.yaml.tmpl" ) + +func basicK8sCRDs() []string { + return []string{ + "pods", + "services", + "deployments.apps", + "daemonset.apps", + "replicasets.apps", + "statefulsets.apps", + "secrets", + "serviceaccounts", + "configmaps", + "mutatingwebhookconfigurations.admissionregistration.k8s.io", + "validatingwebhookconfigurations.admissionregistration.k8s.io", + "jobs.batch", + "cronjobs.batch", + "poddisruptionbudgets.policy", + "podsecuritypolicies.policy", + "persistentvolumeclaims", + "persistentvolumes", + } +} + +func certManagerCRDs() []string { + return []string{ + "certificaterequests.cert-manager.io", + "certificates.cert-manager.io", + "challenges.acme.cert-manager.io", + "clusterissuers.cert-manager.io", + "issuers.cert-manager.io", + "orders.acme.cert-manager.io", + } +} + +func prometheusCRDs() []string { + return []string{ + "alertmanagerconfigs.monitoring.coreos.com", + "alertmanagers.monitoring.coreos.com", + "probes.monitoring.coreos.com", + "prometheuses.monitoring.coreos.com", + "prometheusrules.monitoring.coreos.com", + "servicemonitors.monitoring.coreos.com", + "thanosrulers.monitoring.coreos.com", + "podmonitors.monitoring.coreos.com", + } +} + +func zookeeperCRDs() []string { + return []string{ + "zookeeperclusters.zookeeper.pravega.io", + } +} + +func koperatorCRDs() []string { + return []string{ + "kafkatopics.kafka.banzaicloud.io", + "kafkaclusters.kafka.banzaicloud.io", + "kafkausers.kafka.banzaicloud.io", + "cruisecontroloperations.kafka.banzaicloud.io", + } +} + +func getKoperatorRelatedResourceKinds() []string { + return []string{ + "nodepoollabelsets.labels.banzaicloud.io", + "kafkatopics.kafka.banzaicloud.io", + "kafkaclusters.kafka.banzaicloud.io", + "kafkausers.kafka.banzaicloud.io", + "cruisecontroloperations.kafka.banzaicloud.io", + "istiomeshgateways.servicemesh.cisco.com", + "virtualservices.networking.istio.io", + "gateways.networking.istio.io", + "clusterissuers.cert-manager.io", + "servicemonitors.monitoring.coreos.com", + } +} diff --git a/tests/e2e/go.mod b/tests/e2e/go.mod index 032baf8d2..52753ef6b 100644 --- a/tests/e2e/go.mod +++ b/tests/e2e/go.mod @@ -4,6 +4,8 @@ go 1.20 require ( emperror.dev/errors v0.8.1 + github.com/Masterminds/sprig/v3 v3.2.3 + github.com/banzaicloud/koperator/api v0.28.0 github.com/gruntwork-io/terratest v0.41.24 github.com/onsi/ginkgo/v2 v2.9.5 github.com/onsi/gomega v1.27.6 @@ -13,9 +15,19 @@ require ( ) require ( + github.com/klauspost/compress v1.16.3 // indirect + github.com/pierrec/lz4/v4 v4.1.17 // indirect + github.com/twmb/franz-go/pkg/kmsg v1.4.0 // indirect +) + +require ( + github.com/Masterminds/goutils v1.1.1 // indirect + github.com/Masterminds/semver/v3 v3.2.0 // indirect github.com/aws/aws-sdk-go v1.44.122 // indirect + github.com/banzaicloud/istio-client-go v0.0.17 // indirect github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect + github.com/cert-manager/cert-manager v1.9.1 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/emicklei/go-restful/v3 v3.9.0 // indirect github.com/ghodss/yaml v1.0.0 // indirect @@ -28,21 +40,24 @@ require ( github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/google/gnostic v0.5.7-v3refs // indirect + github.com/google/gnostic v0.6.9 // indirect github.com/google/go-cmp v0.5.9 // indirect - github.com/google/gofuzz v1.1.0 // indirect + github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect github.com/google/uuid v1.3.0 // indirect github.com/gruntwork-io/go-commons v0.8.0 // indirect - github.com/hashicorp/errwrap v1.0.0 // indirect - github.com/hashicorp/go-multierror v1.1.0 // indirect - github.com/imdario/mergo v0.3.11 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/huandu/xstrings v1.3.3 // indirect + github.com/imdario/mergo v0.3.13 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/moby/spdystream v0.2.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect @@ -51,12 +66,15 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pquerna/otp v1.2.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/shopspring/decimal v1.2.0 // indirect + github.com/spf13/cast v1.4.1 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/testify v1.8.1 // indirect + github.com/twmb/franz-go v1.13.4 github.com/urfave/cli v1.22.2 // indirect go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect - golang.org/x/crypto v0.1.0 // indirect + golang.org/x/crypto v0.7.0 // indirect golang.org/x/net v0.10.0 // indirect golang.org/x/oauth2 v0.1.0 // indirect golang.org/x/sys v0.8.0 // indirect @@ -74,6 +92,7 @@ require ( k8s.io/klog/v2 v2.90.1 // indirect k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f // indirect k8s.io/utils v0.0.0-20230209194617-a36077c30491 // indirect + sigs.k8s.io/controller-runtime v0.13.0 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect ) diff --git a/tests/e2e/go.sum b/tests/e2e/go.sum index d6318451f..c1e6fa1c7 100644 --- a/tests/e2e/go.sum +++ b/tests/e2e/go.sum @@ -1,21 +1,41 @@ 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= emperror.dev/errors v0.8.1 h1:UavXZ5cSX/4u9iyvH6aDcuGkVjeexUGJ7Ij7G4VfQT0= emperror.dev/errors v0.8.1/go.mod h1:YcRvLPh626Ubn2xqtoprejnA5nFha+TJ+2vew48kWuE= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= +github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= +github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= +github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/aws/aws-sdk-go v1.44.122 h1:p6mw01WBaNpbdP2xrisz5tIkcNwzj/HysobNoaAHjgo= github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= +github.com/banzaicloud/istio-client-go v0.0.17 h1:wiplbM7FDiIHopujInAnin3zuovtVcphtKy9En39q5I= +github.com/banzaicloud/istio-client-go v0.0.17/go.mod h1:rpnEYYGHzisx8nARl2d30Oq38EeCX0/PPaxMaREfE9I= +github.com/banzaicloud/koperator/api v0.28.0 h1:JV7J28PWNGb9JSsimqAQLsZVacPWh5DkF0oalygi6eU= +github.com/banzaicloud/koperator/api v0.28.0/go.mod h1:qvpewvjdELAnfO70vg9397CXZ4K4uHxpiWtf5fhKSrQ= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI= github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= +github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cert-manager/cert-manager v1.9.1 h1:bNIsQyfWdIMSEwxgO4sVUEyAn6xuSgNwdt9m92OBACc= +github.com/cert-manager/cert-manager v1.9.1/go.mod h1:Bs3WsNX1LPKTs3boh//p7jLOn6ZRGEPz99ITeZU0g3c= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= 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/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU= +github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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= @@ -23,14 +43,21 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 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/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -44,6 +71,7 @@ github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZp github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -51,55 +79,71 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb 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/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54= -github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= +github.com/google/gnostic v0.6.9 h1:ZK/5VhkoX835RikCHpSUJV9a+S3e1zLh59YnyWeBW+0= +github.com/google/gnostic v0.6.9/go.mod h1:Nm8234We1lq6iB9OmlgNv3nH91XLLVZHCDayfA3xq+E= 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.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 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/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/gruntwork-io/go-commons v0.8.0 h1:k/yypwrPqSeYHevLlEDmvmgQzcyTwrlZGRaxEM6G0ro= github.com/gruntwork-io/go-commons v0.8.0/go.mod h1:gtp0yTtIBExIZp7vyIV9I0XQkVwiQZze678hvDXof78= github.com/gruntwork-io/terratest v0.41.24 h1:j6T6qe4deVvynTG2UmnjGwZy83he6xKgTaYWiSdFv/w= github.com/gruntwork-io/terratest v0.41.24/go.mod h1:O6gajNBjO1wvc7Wl9WtbO+ORcdnhAV2GQiBE71ycwIk= -github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI= -github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4= +github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= +github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY= +github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= @@ -115,21 +159,33 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA github.com/mattn/go-zglob v0.0.1/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326 h1:ofNAzWCcyTALn2Zv40+8XitdzCgXY6e9qvXwN9W0YXg= github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= +github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= 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 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q= github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k= github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE= github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg= +github.com/pierrec/lz4 v2.5.2+incompatible h1:WCjObylUIOlKy/+7Abdn34TLIkXiA4UWUMhxq9m9ZXI= +github.com/pierrec/lz4/v4 v4.1.17 h1:kV4Ip+/hUBC+8T6+2EgburRtkE9ef4nbY3f4dFhGjMc= +github.com/pierrec/lz4/v4 v4.1.17/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= 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= @@ -137,12 +193,20 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/pquerna/otp v1.2.0 h1:/A3+Jn+cagqayeR3iHs/L62m5ue7710D35zl1zJ1kok= github.com/pquerna/otp v1.2.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= +github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA= +github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +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/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= @@ -159,10 +223,19 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/twmb/franz-go v1.13.4 h1:xu+lTAJChFqDh6u+Edr1IR2sq81nS+XGtk6OETTxFbc= +github.com/twmb/franz-go v1.13.4/go.mod h1:jm/FtYxmhxDTN0gNSb26XaJY0irdSVcsckLiR5tQNMk= +github.com/twmb/franz-go/pkg/kmsg v1.4.0 h1:tbp9hxU6m8qZhQTlpGiaIJOm4BXix5lsuEZ7K00dF0s= +github.com/twmb/franz-go/pkg/kmsg v1.4.0/go.mod h1:SxG/xJKhgPu25SamAq0rrucfp7lbzCpEXOC+vH/ELrY= github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= @@ -170,35 +243,49 @@ go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9i golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= -golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 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-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= 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-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-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/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-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.1.0 h1:isLCZuhj4v+tYv7eskaN4v/TM+A1begWWgyVJDdl1+Y= golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= 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-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/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -206,23 +293,37 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/text v0.3.0/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/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/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-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -230,6 +331,7 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -242,57 +344,74 @@ google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6 google.golang.org/appengine v1.6.7/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-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= 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/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 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/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/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/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= k8s.io/api v0.27.2 h1:+H17AJpUMvl+clT+BPnKf0E3ksMAzoBBg7CntpSuADo= k8s.io/api v0.27.2/go.mod h1:ENmbocXfBT2ADujUXcBhHV55RIT31IIEvkntP6vZKS4= k8s.io/apiextensions-apiserver v0.27.2 h1:iwhyoeS4xj9Y7v8YExhUwbVuBhMr3Q4bd/laClBV6Bo= k8s.io/apiextensions-apiserver v0.27.2/go.mod h1:Oz9UdvGguL3ULgRdY9QMUzL2RZImotgxvGjdWRq6ZXQ= +k8s.io/apimachinery v0.0.0-20190704094733-8f6ac2502e51/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= k8s.io/apimachinery v0.27.2 h1:vBjGaKKieaIreI+oQwELalVG4d8f3YAMNpWLzDXkxeg= k8s.io/apimachinery v0.27.2/go.mod h1:XNfZ6xklnMCOGGFNqXG7bUrQCoR04dh/E7FprV6pb+E= k8s.io/client-go v0.27.2 h1:vDLSeuYvCHKeoQRhCXjxXO45nHVv2Ip4Fe0MfioMrhE= k8s.io/client-go v0.27.2/go.mod h1:tY0gVmUsHrAmjzHX9zs7eCjxcBsf8IiNe7KQ52biTcQ= +k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog/v2 v2.90.1 h1:m4bYOKall2MmOiRaR1J+We67Do7vm9KiQVlT96lnHUw= k8s.io/klog/v2 v2.90.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f h1:2kWPakN3i/k81b0gvD5C5FJ2kxm1WrQFanWchyKuqGg= k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f/go.mod h1:byini6yhqGC14c3ebc/QwanvYwhuMWF6yz2F8uwW8eg= k8s.io/utils v0.0.0-20230209194617-a36077c30491 h1:r0BAOLElQnnFhE/ApUsg3iHdVYYPBjNSSOMowRZxxsY= k8s.io/utils v0.0.0-20230209194617-a36077c30491/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/controller-runtime v0.13.0 h1:iqa5RNciy7ADWnIc8QxCbOX5FEKVR3uxVxKHRMc2WIQ= +sigs.k8s.io/controller-runtime v0.13.0/go.mod h1:Zbz+el8Yg31jubvAEyglRZGdLAjplZl+PgtYNI6WNTI= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/tests/e2e/helm_test.go b/tests/e2e/helm_test.go index e0e179b67..bb8e3c67d 100644 --- a/tests/e2e/helm_test.go +++ b/tests/e2e/helm_test.go @@ -15,13 +15,13 @@ package e2e import ( + "encoding/json" "fmt" "github.com/gruntwork-io/terratest/modules/helm" "github.com/gruntwork-io/terratest/modules/k8s" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - "sigs.k8s.io/yaml" ) // HelmReleaseStatus describes the possible states of a Helm release. @@ -136,13 +136,13 @@ func listHelmReleases(kubectlOptions *k8s.KubectlOptions) []*HelmRelease { KubectlOptions: kubectlOptions, }, "list", - "--output", "yaml", + "--output", "json", ) Expect(err).NotTo(HaveOccurred()) var releases []*HelmRelease - err = yaml.Unmarshal([]byte(output), &releases) + err = json.Unmarshal([]byte(output), &releases) Expect(err).NotTo(HaveOccurred()) @@ -165,3 +165,65 @@ func lookUpInstalledHelmReleaseByName(kubectlOptions *k8s.KubectlOptions, helmRe return nil, false } + +// uninstallHelmChart uninstall Helm chart from the specified kubectl context and +// namespace using the specified helm release name. When purge is true, it removes records +// and make that name free to be reused for another installation. +// Extra arguments can be any of the helm CLI uninstall flag arguments. +func uninstallHelmChart( + kubectlOptions *k8s.KubectlOptions, + helmReleaseName string, + purge bool, + extraArgs ...string, +) { + By( + fmt.Sprintf( + "uninstalling Helm chart by name %s", + helmReleaseName, + ), + ) + + fixedArguments := []string{ + "--debug", + } + + extraArgs = append(extraArgs, fixedArguments...) + + helm.Delete( + GinkgoT(), + &helm.Options{ + KubectlOptions: kubectlOptions, + ExtraArgs: map[string][]string{ + "delete": extraArgs, + }, + }, + helmReleaseName, + purge, + ) +} + +// uninstallHelmChartIfExists checks whether the specified named Helm release exists in +// the provided kubectl context and namespace, logs it if it does and returns or +// alternatively uninstall the Helm chart from the specified kubectl context and +// namespace using the release name, extra arguments can be any of the helm +// CLI install flag arguments. +func uninstallHelmChartIfExists( + kubectlOptions *k8s.KubectlOptions, + helmReleaseName string, + purge bool, + extraArgs ...string, +) { + By(fmt.Sprintf("Checking for existing Helm release names %s", helmReleaseName)) + _, isInstalled := lookUpInstalledHelmReleaseByName(kubectlOptions, helmReleaseName) + + if !isInstalled { + By(fmt.Sprintf( + "skipping the uninstallation of %s, because the Helm release is not present.", + helmReleaseName, + )) + + return + } + + uninstallHelmChart(kubectlOptions, helmReleaseName, purge, extraArgs...) +} diff --git a/tests/e2e/install_test.go b/tests/e2e/install_test.go index 18769fc45..cdf6b8903 100644 --- a/tests/e2e/install_test.go +++ b/tests/e2e/install_test.go @@ -20,7 +20,7 @@ import ( . "github.com/onsi/gomega" ) -var _ = When("Installing Koperator", func() { +var _ = When("Installing Koperator", Ordered, func() { var kubeconfigPath string var kubecontextName string @@ -31,8 +31,22 @@ var _ = When("Installing Koperator", func() { Expect(err).NotTo(HaveOccurred()) }) - requireInstallingCertManager(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "cert-manager"), "v1.11.0") - requireInstallingZookeeperOperator(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "zookeeper"), "0.2.14") - requireInstallingPrometheusOperator(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "prometheus"), "42.0.1") - requireInstallingKoperator(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "kafka"), LocalVersion) + // requireInstallingCertManager(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "cert-manager"), "v1.11.0") + // requireInstallingZookeeperOperator(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "zookeeper"), "0.2.14") + // requireInstallingPrometheusOperator(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "prometheus"), "42.0.1") + // requireInstallingKoperator(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "kafka"), LocalVersion) + // ----------------------------------------------------------------------------------------------------------- + // requireCreatingZookeeperCluster(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "zookeeper"), "../../config/samples/zookeeper_sample.yaml") + // requireCreatingKafkaCluster(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "kafka"), "local", "simplekafkacluster_ssl.yaml") + // // ----------------------------------------------------------------------------------------------------------- + requireInternalProducerConsumer(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "kafka")) + // // ----------------------------------------------------------------------------------------------------------- + // requireUninstallKafkaCluster(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "kafka"), "kafka") + // requireUninstallZookeeperCluster(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "zookeeper"), "zookeeper-server") + // // ----------------------------------------------------------------------------------------------------------- + // requireUninstallingKoperator(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "kafka")) + // requireUninstallingPrometheusOperator(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "prometheus")) + // requireUninstallingZookeeperOperator(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "zookeeper")) + // requireUninstallingCertManager(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "cert-manager")) + //requireExternalProducerConsumer(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "kafka")) }) diff --git a/tests/e2e/k8s_test.go b/tests/e2e/k8s_test.go index aecd68cc4..d707228d5 100644 --- a/tests/e2e/k8s_test.go +++ b/tests/e2e/k8s_test.go @@ -15,12 +15,16 @@ package e2e import ( + "bytes" "fmt" "os" "path" "strings" + "text/template" + "time" "emperror.dev/errors" + "github.com/Masterminds/sprig/v3" "github.com/gruntwork-io/terratest/modules/k8s" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -28,6 +32,81 @@ import ( "sigs.k8s.io/yaml" ) +// deleteK8sResourceOpts deletes K8s resources based on the kind and name or kind and selector. +// When noErrNotFound is true then the deletion is passed in case when the resource is not found. +// timeout parameter specifies the timeout for the deletion. +// globalResource parameter indicates that the resource is global, +// extraArgs can be any of the kubectl arguments. +func deleteK8sResourceOpts( + kubectlOptions *k8s.KubectlOptions, + globalResource, + noErrNotFound bool, + timeout time.Duration, + kind string, + selector string, + name string, + extraArgs ...string) { + + args := []string{"delete", kind} + + args = append(args, fmt.Sprintf("--timeout=%s", timeout)) + kubectlNamespace := kubectlOptions.Namespace + + if globalResource { + kubectlOptions.Namespace = "" + } + + logMsg := fmt.Sprintf("Deleting k8s resource: kind: '%s' ", kind) + logMsg, args = _kubectlArgExtender(args, logMsg, selector, name, kubectlOptions.Namespace, extraArgs) + By(logMsg) + + args = append(args, extraArgs...) + + _, err := k8s.RunKubectlAndGetOutputE( + GinkgoT(), + kubectlOptions, + args..., + ) + + kubectlOptions.Namespace = kubectlNamespace + + if _isNotFoundError(err) && noErrNotFound { + By("Resource not found") + } else { + Expect(err).NotTo(HaveOccurred()) + } +} + +// deleteK8sResourceGlobalNoErrNotFound deletes K8s global resources based on the kind and name or kind and selector. +// Deletion is passed in case the resource is not found. +// timeout parameter specifies the timeout for the deletion. +// extraArgs can be any of the kubectl arguments. +func deleteK8sResourceGlobalNoErrNotFound(kubectlOptions *k8s.KubectlOptions, timeout time.Duration, kind string, name string, extraArgs ...string) { + deleteK8sResourceOpts(kubectlOptions, true, true, timeout, kind, "", name, extraArgs...) +} + +// deleteK8sResourceGlobal deletes K8s resources based on the kind and name or kind and selector. +// timeout parameter specifies the timeout for the deletion. +// extraArgs can be any of the kubectl arguments. +func deleteK8sResourceGlobal(kubectlOptions *k8s.KubectlOptions, timeout time.Duration, kind string, name string, extraArgs ...string) { + deleteK8sResourceOpts(kubectlOptions, true, false, timeout, kind, "", name, extraArgs...) +} + +// deleteK8sResource deletes K8s resources based on the kind and name or kind and selector. +// timeout parameter specifies the timeout for the deletion. +// extraArgs can be any of the kubectl arguments. +func deleteK8sResource(kubectlOptions *k8s.KubectlOptions, timeout time.Duration, kind string, name string, extraArgs ...string) { + deleteK8sResourceOpts(kubectlOptions, false, false, timeout, kind, "", name, extraArgs...) +} + +// deleteK8sResourceNoErrNotFound deletes K8s resources based on the kind and name or kind and selector. +// Deletion is passed in case the resource is not found. +// timeout parameter specifies the timeout for the deletion. +// extraArgs can be any of the kubectl arguments. +func deleteK8sResourceNoErrNotFound(kubectlOptions *k8s.KubectlOptions, timeout time.Duration, kind string, name string, extraArgs ...string) { + deleteK8sResourceOpts(kubectlOptions, false, true, timeout, kind, "", name, extraArgs...) +} + // applyK8sResourceManifests applies the specified manifest to the provided // kubectl context and namespace. func applyK8sResourceManifest(kubectlOptions *k8s.KubectlOptions, manifestPath string) { @@ -35,6 +114,37 @@ func applyK8sResourceManifest(kubectlOptions *k8s.KubectlOptions, manifestPath s k8s.KubectlApply(GinkgoT(), kubectlOptions, manifestPath) } +// applyK8sResourceManifestFromString applies the specified manifest in string format to the provided +// kubectl context and namespace. +func applyK8sResourceManifestFromString(kubectlOptions *k8s.KubectlOptions, manifest string) { + By(fmt.Sprintf("Applying k8s manifest\n%s", manifest)) + k8s.KubectlApplyFromString(GinkgoT(), kubectlOptions, manifest) +} + +// applyK8sResourceFromTemplate generates manifest from the specified go-template based on values +// and applies the specified manifest to the provided kubectl context and namespace. +func applyK8sResourceFromTemplate(kubectlOptions *k8s.KubectlOptions, templateFile string, values map[string]interface{}) { + By(fmt.Sprintf("Generating K8s manifest from template %s", templateFile)) + var manifest bytes.Buffer + rawTemplate, err := os.ReadFile(templateFile) + Expect(err).NotTo(HaveOccurred()) + t := template.Must(template.New("template").Funcs(sprig.TxtFuncMap()).Parse(string(rawTemplate))) + err = t.Execute(&manifest, values) + Expect(err).NotTo(HaveOccurred()) + applyK8sResourceManifestFromString(kubectlOptions, manifest.String()) +} + +// checkExistenceOfK8sResource queries a Resource by it's kind, namespace and name and +// returns the output of stderr +func checkExistenceOfK8sResource( + kubectlOptions *k8s.KubectlOptions, + resourceKind string, + resourceName string, +) error { + By(fmt.Sprintf("Checking the existence of resource %s", resourceName)) + return k8s.RunKubectlE(GinkgoT(), kubectlOptions, "get", resourceKind, resourceName) +} + // createK8sResourcesFromManifest creates Kubernetes resources from the // specified manifest to the provided kubectl context and namespace. func createK8sResourcesFromManifest(kubectlOptions *k8s.KubectlOptions, manifestPath string, shouldBeValidated bool) { @@ -129,6 +239,22 @@ func listK8sCRDs(kubectlOptions *k8s.KubectlOptions, crdNames ...string) []strin return strings.Split(output, "\n") } +// listK8sAllResourceType lists all of the available resource type on the K8s cluster +func listK8sAllResourceType(kubectlOptions *k8s.KubectlOptions) []string { + By("Listing available K8s resource types") + + args := []string{"api-resources", "--verbs=list", "-o", "name"} + output, err := k8s.RunKubectlAndGetOutputE( + GinkgoT(), + kubectlOptions, + args..., + ) + + Expect(err).NotTo(HaveOccurred()) + + return strings.Split(output, "\n") +} + // replaceK8sResourcesFromManifest replaces existing Kubernetes resources from // the specified manifest to the provided kubectl context and namespace. func replaceK8sResourcesFromManifest(kubectlOptions *k8s.KubectlOptions, manifestPath string, shouldBeValidated bool) { @@ -172,3 +298,61 @@ func requireRunningPods(kubectlOptions *k8s.KubectlOptions, matchingLabelKey str Expect(pod.Status.Phase).To(BeEquivalentTo("Running")) } } + +// getK8sResources gets the specified K8S resources from the specified kubectl context and +// namespace optionally. Extra arguments can be any of the kubectl get flag arguments. +// Returns a slice of the returned elements. Separator between elements must be newline. +func getK8sResources(kubectlOptions *k8s.KubectlOptions, resourceKind []string, selector string, names string, extraArgs ...string) []string { + logMsg := fmt.Sprintf("Get K8S resources: '%s'", resourceKind) + + args := []string{"get", strings.Join(resourceKind, ",")} + logMsg, args = _kubectlArgExtender(args, logMsg, selector, names, kubectlOptions.Namespace, extraArgs) + + By(logMsg) + + args = append(args, extraArgs...) + + output, err := k8s.RunKubectlAndGetOutputE( + GinkgoT(), + kubectlOptions, + args..., + ) + + Expect(err).NotTo(HaveOccurred()) + + output = strings.Trim(output, "'") + if output == "" { + return nil + } + + output = strings.TrimRight(output, "\n") + outputSlice := strings.Split(output, "\n") + + // Remove warning message pollution from the output + + return _kubectlRemoveWarnings(outputSlice) +} + +// waitK8sResourceCondition waits until the condition is met or the timeout is elapsed for the selected K8s resource(s) +// extraArgs can be any of the kubectl arguments +func waitK8sResourceCondition(kubectlOptions *k8s.KubectlOptions, resourceKind, waitFor string, timeout time.Duration, selector string, names string, extraArgs ...string) { + logMsg := fmt.Sprintf("Waiting K8s resource(s)' condition: '%s' to fulfil", waitFor) + + args := []string{ + "wait", + resourceKind, + fmt.Sprintf("--for=%s", waitFor), + fmt.Sprintf("--timeout=%s", timeout), + } + + logMsg, args = _kubectlArgExtender(args, logMsg, selector, names, kubectlOptions.Namespace, extraArgs) + By(logMsg) + + _, err := k8s.RunKubectlAndGetOutputE( + GinkgoT(), + kubectlOptions, + args..., + ) + + Expect(err).NotTo(HaveOccurred()) +} diff --git a/tests/e2e/kafka_prod_consum_test.go b/tests/e2e/kafka_prod_consum_test.go new file mode 100644 index 000000000..16b10b676 --- /dev/null +++ b/tests/e2e/kafka_prod_consum_test.go @@ -0,0 +1,148 @@ +// Copyright © 2023 Cisco Systems, Inc. and/or its affiliates +// +// 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" + "time" + + "github.com/gruntwork-io/terratest/modules/k8s" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +// requireInternalProducerConsumer deploys a kcat pod and a kafkaTopic into the K8s cluster +// and produces, consumes messages and makes comparisons between them. +// After deletes the kafkaTopic and kcat pod. +func requireInternalProducerConsumer(kubectlOptions *k8s.KubectlOptions) { + When("Internally produce and consume message to Kafka cluster", func() { + requireDeployingKcatPod(kubectlOptions, kcatPodName) + requireDeployingKafkaTopic(kubectlOptions, testTopicName) + requireInternalProducingConsumingMessage(kubectlOptions, "", kcatPodName, testTopicName) + requireDeleteKafkaTopic(kubectlOptions, testTopicName) + requireDeleteKcatPod(kubectlOptions, kcatPodName) + }) +} + +// requireDeployingKcatPod deploys kcat pod form a template and checks the pod readiness +func requireDeployingKcatPod(kubectlOptions *k8s.KubectlOptions, podName string) { + It("Deploying Kcat Pod", func() { + applyK8sResourceFromTemplate(kubectlOptions, + kcatPodTemplate, + map[string]interface{}{ + "Name": kcatPodName, + "Namespace": kubectlOptions.Namespace, + }, + ) + waitK8sResourceCondition(kubectlOptions, "pods", "condition=Ready", defaultPodReadinessWaitTime, "", kcatPodName) + }) + +} + +// requireDeployingKafkaTopic deploys a kafkaTopic resource from a template +func requireDeployingKafkaTopic(kubectlOptions *k8s.KubectlOptions, topicName string) { + It("Deploying KafkaTopic CR", func() { + applyK8sResourceFromTemplate(kubectlOptions, + kafkaTopicTemplate, + map[string]interface{}{ + "Name": topicName, + "TopicName": topicName, + "Namespace": kubectlOptions.Namespace, + }, + ) + waitK8sResourceCondition(kubectlOptions, "kafkatopic", "jsonpath={.status.state}=created", defaultTopicCreationWaitTime, "", topicName) + }) + +} + +// requireDeleteKafkaTopic deletes kafkaTopic resource. +func requireDeleteKafkaTopic(kubectlOptions *k8s.KubectlOptions, topicName string) { + It("Deleting KafkaTopic CR", func() { + deleteK8sResource(kubectlOptions, defaultDeletionTimeout, "kafkatopic", topicName) + }) +} + +// requireDeleteKcatPod deletes kcat pod. +func requireDeleteKcatPod(kubectlOptions *k8s.KubectlOptions, podName string) { + It("Deleting Kcat pod", func() { + deleteK8sResource(kubectlOptions, defaultDeletionTimeout, "pods", podName) + }) +} + +// requireInternalProducingConsumingMessage produces and consumes messages internally through a kcat pod +// and makes comparisons between the produced and consumed messages. +// When internalAddress parameter is empty, it gets the internal address from the kafkaCluster CR status +func requireInternalProducingConsumingMessage(kubectlOptions *k8s.KubectlOptions, internalAddress, kcatPodName, topicName string) { + It(fmt.Sprintf("Producing and consuming messages to/from topicName: '%s", topicName), func() { + if internalAddress == "" { + By("Getting Kafka cluster internal addresses") + internalListenerNames := getK8sResources(kubectlOptions, + []string{"kafkacluster"}, + "", + kafkaClusterName, + kubectlArgGoTemplateInternalListenersName, + ) + Expect(internalListenerNames).ShouldNot(BeEmpty()) + + internalListenerAddresses := getK8sResources(kubectlOptions, + []string{"kafkacluster"}, + "", + kafkaClusterName, + fmt.Sprintf(kubectlArgGoTemplateInternalListenerAddressesTemplate, internalListenerNames[0]), + ) + Expect(internalListenerAddresses).ShouldNot(BeEmpty()) + + internalAddress = internalListenerAddresses[0] + } + + By("Producing message") + // When kubectl exec command is used the namespace flag cannot be at the beginning + // thus we need to specify by hand + currentTime := time.Now() + _, err := k8s.RunKubectlAndGetOutputE(GinkgoT(), + k8s.NewKubectlOptions(kubectlOptions.ContextName, kubectlOptions.ConfigPath, ""), + "exec", + "kcat", + "-n", + kubectlOptions.Namespace, + "--", + "/bin/sh", + "-c", + fmt.Sprintf("echo %s | kcat -L -b %s -t %s -P", currentTime.String(), internalAddress, topicName), + ) + Expect(err).NotTo(HaveOccurred()) + + By("Consuming message") + consumedMessage, err := k8s.RunKubectlAndGetOutputE(GinkgoT(), + k8s.NewKubectlOptions(kubectlOptions.ContextName, kubectlOptions.ConfigPath, ""), + "exec", + "kcat", + "-n", + kubectlOptions.Namespace, + "--", + "/usr/bin/kcat", + "-L", + "-b", + internalAddress, + "-t", + topicName, + "-e", + "-C", + ) + + Expect(err).NotTo(HaveOccurred()) + Expect(consumedMessage).Should(ContainSubstring(currentTime.String())) + }) +} diff --git a/tests/e2e/koperator_test.go b/tests/e2e/koperator_test.go index 7fa563204..0723d17d8 100644 --- a/tests/e2e/koperator_test.go +++ b/tests/e2e/koperator_test.go @@ -16,21 +16,79 @@ package e2e import ( "bytes" + "context" "fmt" "io" "net/http" "os" "path" + "strings" "time" + koperator_v1beta1 "github.com/banzaicloud/koperator/api/v1beta1" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + "github.com/gruntwork-io/terratest/modules/helm" "github.com/gruntwork-io/terratest/modules/k8s" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "sigs.k8s.io/yaml" ) +// requireApplyingKoperatorSampleResource deploys the specified sample resource (config/samples). +// The full path of the manifest also can be specified. +// It supports different versions that can be specified with the koperatorVersion parameter. +func requireApplyingKoperatorSampleResource(kubectlOptions *k8s.KubectlOptions, koperatorVersion Version, sampleFile string) { + It("Applying Koperator sample resource", func() { + By(fmt.Sprintf("Retrieving Koperator sample resource: '%s' with version: '%s' ", sampleFile, koperatorVersion)) + + sampleFileSplit := strings.Split(sampleFile, "/") + Expect(sampleFileSplit).ShouldNot(BeEmpty()) + + var err error + var rawKoperatorSampleResource []byte + + switch koperatorVersion { + case LocalVersion: + if len(sampleFileSplit) == 1 { + sampleFile = fmt.Sprintf("../../config/samples/%s", sampleFile) + } + + rawKoperatorSampleResource, err = os.ReadFile(sampleFile) + Expect(err).NotTo(HaveOccurred()) + default: + httpClient := new(http.Client) + httpClient.Timeout = 5 * time.Second + + Expect(sampleFileSplit).Should(HaveLen(1)) + + response, err := httpClient.Get("https://raw.githubusercontent.com/banzaicloud/koperator/" + koperatorVersion + "/config/samples/" + sampleFile) + if response != nil { + defer func() { _ = response.Body.Close() }() + } + + Expect(err).NotTo(HaveOccurred()) + + rawKoperatorSampleResource, err = io.ReadAll(response.Body) + + Expect(err).NotTo(HaveOccurred()) + } + + By(fmt.Sprintf("Applying K8s manifest %s", sampleFile)) + k8s.KubectlApplyFromString(GinkgoT(), kubectlOptions, string(rawKoperatorSampleResource)) + + }) +} + +// requireRemoveKoperatorCRDs deletes the koperator CRDs +func requireRemoveKoperatorCRDs(kubectlOptions *k8s.KubectlOptions) { + It("Removing koperator CRDs", func() { + for _, crd := range koperatorCRDs() { + deleteK8sResourceGlobalNoErrNotFound(kubectlOptions, defaultDeletionTimeout, "crds", crd) + } + }) +} + // requireApplyingKoperatorCRDs deploys the koperator CRDs and checks their // existence afterwards. func requireApplyingKoperatorCRDs(kubectlOptions *k8s.KubectlOptions, koperatorVersion Version) { @@ -102,10 +160,7 @@ func requireApplyingKoperatorCRDs(kubectlOptions *k8s.KubectlOptions, koperatorV By("Verifying koperator CRDs") requireExistingCRDs( kubectlOptions, - "cruisecontroloperations.kafka.banzaicloud.io", - "kafkaclusters.kafka.banzaicloud.io", - "kafkatopics.kafka.banzaicloud.io", - "kafkausers.kafka.banzaicloud.io", + koperatorCRDs()..., ) }) } @@ -141,6 +196,61 @@ func requireInstallingKoperatorHelmChartIfDoesNotExist( } By("Verifying koperator pods") - requireRunningPods(kubectlOptions, "app.kubernetes.io/name", "kafka-operator") + //requireRunningPods(kubectlOptions, "app.kubernetes.io/name", "kafka-operator") + }) +} + +// requireUninstallingKoperator uninstall koperator Helm chart and removes Koperator's CRDs. +func requireUninstallingKoperator(kubectlOptions *k8s.KubectlOptions) { + When("Uninstalling Koperator", func() { + requireUninstallingKoperatorHelmChart(kubectlOptions) + requireRemoveKoperatorCRDs(kubectlOptions) + }) +} + +// requireUninstallingKoperatorHelmChart uninstall Koperator Helm chart +// and checks the success of that operation. +func requireUninstallingKoperatorHelmChart(kubectlOptions *k8s.KubectlOptions) { + It("Uninstalling Koperator Helm chart", func() { + uninstallHelmChartIfExists(kubectlOptions, "kafka-operator", true) + By("Verifying Koperator helm chart resources cleanup") + k8sCRDs := listK8sAllResourceType(kubectlOptions) + remainedResources := getK8sResources(kubectlOptions, + k8sCRDs, + fmt.Sprintf(managedByHelmLabelTemplate, "kafka-operator"), + "", + kubectlArgGoTemplateKindNameNamespace, + "--all-namespaces") + Expect(remainedResources).Should(BeEmpty()) + }) +} + +// requireUninstallKafkaCluster uninstall the Kafka cluster +func requireUninstallKafkaCluster(kubectlOptions *k8s.KubectlOptions, name string) { + When("Uninstalling Kafka cluster", func() { + requireDeleteKafkaCluster(kubectlOptions, name) + + }) +} + +// requireDeleteKafkaCluster deletes KafkaCluster resource and +// checks the removal of the Kafka cluster related resources +func requireDeleteKafkaCluster(kubectlOptions *k8s.KubectlOptions, name string) { + It("Delete KafkaCluster custom resource", func() { + deleteK8sResourceGlobalNoErrNotFound(kubectlOptions, defaultDeletionTimeout, "kafkacluster", "kafka") + Eventually(context.Background(), func() []string { + By("Verifying the Kafka cluster resource cleanup") + + // Check only those Koperator related resource types we have in K8s (istio usecase) + k8sCRDs := listK8sAllResourceType(kubectlOptions) + koperatorCRDsSelected := _stringSlicesUnion(getKoperatorRelatedResourceKinds(), k8sCRDs) + koperatorCRDsSelected = append(koperatorCRDsSelected, basicK8sCRDs()...) + + return getK8sResources(kubectlOptions, + koperatorCRDsSelected, + fmt.Sprintf("%s=%s", koperator_v1beta1.KafkaCRLabelKey, name), + "", + "--all-namespaces", kubectlArgGoTemplateKindNameNamespace) + }, kafkaClusterResourceCleanupTimeout, 3*time.Millisecond).Should(BeEmpty()) }) } diff --git a/tests/e2e/prometheus_test.go b/tests/e2e/prometheus_test.go index 0f9f784f3..584ad97a2 100644 --- a/tests/e2e/prometheus_test.go +++ b/tests/e2e/prometheus_test.go @@ -15,9 +15,12 @@ package e2e import ( + "fmt" + "github.com/gruntwork-io/terratest/modules/k8s" . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" ) // requireInstallingPrometheusOperator deploys prometheus-operator Helm chart @@ -63,3 +66,41 @@ func requireInstallingPrometheusOperatorHelmChartIfDoesNotExist( requireRunningPods(kubectlOptions, "app", "kube-prometheus-stack-operator") }) } + +// requireUninstallingPrometheusOperator uninstall prometheus-operator Helm chart and +// remove CRDs. +func requireUninstallingPrometheusOperator(kubectlOptions *k8s.KubectlOptions) { + When("Uninstalling prometheus-operator", func() { + requireUninstallingPrometheusOperatorHelmChart(kubectlOptions) + requireRemovePrometheusOperatorCRDs(kubectlOptions) + }) +} + +// requireUninstallingPrometheusOperatorHelmChart uninstall prometheus-operator Helm chart +// and checks the success of that operation. +func requireUninstallingPrometheusOperatorHelmChart(kubectlOptions *k8s.KubectlOptions) { + It("Uninstalling Prometheus-operator Helm chart", func() { + uninstallHelmChartIfExists(kubectlOptions, "prometheus-operator", true) + By("Verifying Prometheus-operator helm chart resources cleanup") + + prometheusK8sResources := basicK8sCRDs() + prometheusK8sResources = append(prometheusK8sResources, prometheusCRDs()...) + + remainedResources := getK8sResources(kubectlOptions, + prometheusK8sResources, + fmt.Sprintf(managedByHelmLabelTemplate, "prometheus-operator"), + "", + kubectlArgGoTemplateKindNameNamespace, + "--all-namespaces") + Expect(remainedResources).Should(BeEmpty()) + }) +} + +// requireRemovePrometheusOperatorCRDs deletes the Prometheus-operator CRDs +func requireRemovePrometheusOperatorCRDs(kubectlOptions *k8s.KubectlOptions) { + It("Removing prometheus-operator CRDs", func() { + for _, crd := range prometheusCRDs() { + deleteK8sResourceGlobalNoErrNotFound(kubectlOptions, defaultDeletionTimeout, "crds", crd) + } + }) +} diff --git a/tests/e2e/templates/kcat.yaml.tmpl b/tests/e2e/templates/kcat.yaml.tmpl new file mode 100644 index 000000000..47e783070 --- /dev/null +++ b/tests/e2e/templates/kcat.yaml.tmpl @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Pod +metadata: + name: {{or .Name "kcat"}} + namespace: {{or .Namespace "kafka" }} +spec: + serviceAccount: {{or .ServiceAccount "default"}} + containers: + - name: kafka-client + image: edenhill/kcat:1.7.0 + # Just spin & wait forever + command: [ "/bin/sh", "-c", "--" ] + args: [ "while true; do sleep 3000; done;" ] diff --git a/tests/e2e/templates/topic.yaml.tmpl b/tests/e2e/templates/topic.yaml.tmpl new file mode 100644 index 000000000..991baffe8 --- /dev/null +++ b/tests/e2e/templates/topic.yaml.tmpl @@ -0,0 +1,15 @@ +apiVersion: kafka.banzaicloud.io/v1alpha1 +kind: KafkaTopic +metadata: + name: {{ .Name }} + namespace: {{or .Namespace "kafka"}} +spec: + clusterRef: + name: kafka + namespace: kafka + name: {{ .TopicName }} + partitions: {{or .Partition 2}} + replicationFactor: {{or .ReplicationFactor 2}} + config: + "retention.ms": "604800000" + "cleanup.policy": "delete" diff --git a/tests/e2e/utils.go b/tests/e2e/utils.go new file mode 100644 index 000000000..7440b4b2d --- /dev/null +++ b/tests/e2e/utils.go @@ -0,0 +1,80 @@ +// Copyright © 2023 Cisco Systems, Inc. and/or its affiliates +// +// 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" + "sort" + "strings" +) + +// Returns the union of the slices from argument. +func _stringSlicesUnion(sliceA, sliceB []string) []string { + if len(sliceA) == 0 || len(sliceB) == 0 { + return nil + } + + sort.Slice(sliceA, func(i int, j int) bool { + return sliceA[i] < sliceA[j] + }) + sort.Slice(sliceB, func(i int, j int) bool { + return sliceB[i] < sliceB[j] + }) + + var union []string + for i := range sliceB { + for j := range sliceA { + if sliceB[i] < sliceA[j] { + break + } else if sliceB[i] == sliceA[j] { + union = append(union, sliceB[i]) + } + } + } + return union +} + +func _kubectlArgExtender(args []string, logMsg, selector, names, namespace string, extraArgs []string) (string, []string) { + if selector != "" { + logMsg = fmt.Sprintf("%s selector: '%s'", logMsg, selector) + args = append(args, fmt.Sprintf("--selector=%s", selector)) + } else if names != "" { + logMsg = fmt.Sprintf("%s name(s): '%s'", logMsg, names) + args = append(args, names) + } + if namespace != "" { + logMsg = fmt.Sprintf("%s namespace: '%s'", logMsg, namespace) + } + if len(extraArgs) != 0 { + logMsg = fmt.Sprintf("%s extraArgs: '%s'", logMsg, extraArgs) + } + return logMsg, args +} + +// _kubectlRemoveWarning removes those elements from the outputSlice parameter which contains kubectl warning message. +func _kubectlRemoveWarnings(outputSlice []string) []string { + // Remove warning message pollution from the output + result := make([]string, 0, len(outputSlice)) + for i := range outputSlice { + if !strings.Contains(outputSlice[i], "Warning:") { + result = append(result, outputSlice[i]) + } + } + return result +} + +func _isNotFoundError(err error) bool { + return err != nil && strings.Contains(err.Error(), kubectlNotFoundErrorMsg) +} diff --git a/tests/e2e/version_test.go b/tests/e2e/version_test.go deleted file mode 100644 index 983916b6c..000000000 --- a/tests/e2e/version_test.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright © 2023 Cisco Systems, Inc. and/or its affiliates -// -// 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 - -type Version = string - -const ( - // LocalVersion means using the files in the local repository snapshot. - LocalVersion Version = "local" -) diff --git a/tests/e2e/zookeeper_test.go b/tests/e2e/zookeeper_test.go index 573f2a6b5..94bc2ba02 100644 --- a/tests/e2e/zookeeper_test.go +++ b/tests/e2e/zookeeper_test.go @@ -15,9 +15,14 @@ package e2e import ( + "context" + "fmt" + "time" + "github.com/gruntwork-io/terratest/modules/k8s" . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" ) // requireInstallingZookeeperOperator deploys zookeeper-operator Helm chart and @@ -48,3 +53,65 @@ func requireInstallingZookeeperOperatorHelmChartIfDoesNotExist( requireRunningPods(kubectlOptions, "name", "zookeeper-operator") }) } + +// requireUninstallingZookeeperOperator uninstall Zookeeper-operator Helm chart +// and remove CRDs. +func requireUninstallingZookeeperOperator(kubectlOptions *k8s.KubectlOptions) { + When("Uninstalling zookeeper-operator", func() { + requireUninstallingZookeeperOperatorHelmChart(kubectlOptions) + requireRemoveZookeeperOperatorCRDs(kubectlOptions) + }) +} + +// requireUninstallingZookeeperOperatorHelmChart uninstall Zookeeper-operator Helm chart +// and checks the success of that operation. +func requireUninstallingZookeeperOperatorHelmChart(kubectlOptions *k8s.KubectlOptions) { + It("Uninstalling zookeeper-operator Helm chart", func() { + uninstallHelmChartIfExists(kubectlOptions, "zookeeper-operator", true) + By("Verifying Zookeeper-operator helm chart resources cleanup") + k8sCRDs := listK8sAllResourceType(kubectlOptions) + remainedResources := getK8sResources(kubectlOptions, + k8sCRDs, + fmt.Sprintf(managedByHelmLabelTemplate, "zookeeper-operator"), + "", + kubectlArgGoTemplateKindNameNamespace, + "--all-namespaces") + Expect(remainedResources).Should(BeEmpty()) + }) +} + +// requireRemoveZookeeperOperatorCRDs deletes the zookeeper-operator CRDs +func requireRemoveZookeeperOperatorCRDs(kubectlOptions *k8s.KubectlOptions) { + It("Removing zookeeper-operator CRDs", func() { + for _, crd := range zookeeperCRDs() { + deleteK8sResourceGlobalNoErrNotFound(kubectlOptions, defaultDeletionTimeout, "crds", crd) + } + }) +} + +// requireUninstallZookeeperCluster uninstall the Zookeeper cluster +func requireUninstallZookeeperCluster(kubectlOptions *k8s.KubectlOptions, name string) { + When("Uninstalling Zookeeper cluster", func() { + requireDeleteZookeeperCluster(kubectlOptions, name) + + }) +} + +// requireDeleteZookeeperCluster deletes the ZookeeperCluster CR and verify the corresponding resources cleanup +func requireDeleteZookeeperCluster(kubectlOptions *k8s.KubectlOptions, name string) { + It("Delete ZookeeperCluster custom resource", func() { + deleteK8sResourceGlobalNoErrNotFound(kubectlOptions, defaultDeletionTimeout, zookeeperKind, name) + Eventually(context.Background(), func() []string { + By("Verifying the Zookeeper cluster resource cleanup") + + zookeeperK8sResources := basicK8sCRDs() + zookeeperK8sResources = append(zookeeperK8sResources, zookeeperCRDs()...) + + return getK8sResources(kubectlOptions, + zookeeperK8sResources, + fmt.Sprintf("app=%s", name), + "", + "--all-namespaces", kubectlArgGoTemplateKindNameNamespace) + }, zookeeperClusterResourceCleanupTimeout, 3*time.Millisecond).Should(BeEmpty()) + }) +} From d9331f289ac629cecf7141aed9d36b45a0bd9649 Mon Sep 17 00:00:00 2001 From: marbarta Date: Wed, 14 Jun 2023 17:21:03 +0200 Subject: [PATCH 04/24] Refactor after Pregnor PR merge --- tests/e2e/cert_manager_test.go | 115 ------ tests/e2e/const.go | 8 +- tests/e2e/go.mod | 35 +- tests/e2e/go.sum | 151 ++------ tests/e2e/helm.go | 65 ++++ tests/e2e/helm_test.go | 229 ----------- tests/e2e/install_test.go | 52 --- tests/e2e/k8s.go | 155 ++++++++ tests/e2e/k8s_test.go | 358 ------------------ tests/e2e/koperator_test.go | 256 ------------- ...prod_consum_test.go => produce_consume.go} | 41 +- tests/e2e/produce_consume_test.go | 27 ++ tests/e2e/prometheus_test.go | 106 ------ tests/e2e/test_install.go | 4 +- tests/e2e/test_test.go | 27 ++ tests/e2e/test_uninstall.go | 55 +++ tests/e2e/uninstall.go | 194 ++++++++++ tests/e2e/uninstall_cluster.go | 77 ++++ tests/e2e/uninstall_cluster_test.go | 52 +++ tests/e2e/utils.go | 5 + tests/e2e/zookeeper_test.go | 117 ------ 21 files changed, 714 insertions(+), 1415 deletions(-) delete mode 100644 tests/e2e/cert_manager_test.go delete mode 100644 tests/e2e/helm_test.go delete mode 100644 tests/e2e/install_test.go delete mode 100644 tests/e2e/k8s_test.go delete mode 100644 tests/e2e/koperator_test.go rename tests/e2e/{kafka_prod_consum_test.go => produce_consume.go} (69%) create mode 100644 tests/e2e/produce_consume_test.go delete mode 100644 tests/e2e/prometheus_test.go create mode 100644 tests/e2e/test_test.go create mode 100644 tests/e2e/test_uninstall.go create mode 100644 tests/e2e/uninstall.go create mode 100644 tests/e2e/uninstall_cluster.go create mode 100644 tests/e2e/uninstall_cluster_test.go delete mode 100644 tests/e2e/zookeeper_test.go diff --git a/tests/e2e/cert_manager_test.go b/tests/e2e/cert_manager_test.go deleted file mode 100644 index c483d16aa..000000000 --- a/tests/e2e/cert_manager_test.go +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright © 2023 Cisco Systems, Inc. and/or its affiliates -// -// 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" - - "github.com/gruntwork-io/terratest/modules/k8s" - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" -) - -// requireApplyingCertManagerCRDs deploys the cert-manager CRDs and checks -// their existence afterwards. -func requireApplyingCertManagerCRDs(kubectlOptions *k8s.KubectlOptions, certManagerVersion Version) { - It("Applying cert-manager CRDs", func() { - By("Applying cert-manager CRDs with version " + certManagerVersion) - applyK8sResourceManifest( - kubectlOptions, - "https://github.com/jetstack/cert-manager/releases/download/"+certManagerVersion+"/cert-manager.crds.yaml", - ) - - By("Verifying cert-manager CRDs") - requireExistingCRDs( - kubectlOptions, - "certificaterequests.cert-manager.io", - "certificates.cert-manager.io", - "challenges.acme.cert-manager.io", - "clusterissuers.cert-manager.io", - "issuers.cert-manager.io", - "orders.acme.cert-manager.io", - ) - }) -} - -// requireInstallingCertManager deploys cert-manager CRDs and Helm chart and -// checks the success of those operations. -func requireInstallingCertManager(kubectlOptions *k8s.KubectlOptions, certManagerVersion Version) { - When("Installing cert-manager", func() { - requireApplyingCertManagerCRDs(kubectlOptions, certManagerVersion) - requireInstallingCertManagerHelmChartIfDoesNotExist(kubectlOptions, certManagerVersion) - }) -} - -// requireInstallingCertManagerHelmChartIfDoesNotExist checks the existence of the cert-manager -// Helm release and installs it if it's not present. -func requireInstallingCertManagerHelmChartIfDoesNotExist( - kubectlOptions *k8s.KubectlOptions, - certManagerVersion string, -) { - It("Installing cert-manager Helm chart", func() { - installHelmChartIfDoesNotExist( - kubectlOptions, - "https://charts.jetstack.io", - "cert-manager", - certManagerVersion, - "cert-manager", - nil, - ) - - By("Verifying cert-manager pods") - requireRunningPods(kubectlOptions, "app.kubernetes.io/name", "cert-manager", "cainjector", "webhook") - }) -} - -// requireUninstallingCertManager uninstall Cert-manager Helm chart and -// remove CRDs. -func requireUninstallingCertManager(kubectlOptions *k8s.KubectlOptions) { - When("Uninstalling zookeeper-operator", func() { - requireUninstallingCertManagerHelmChart(kubectlOptions) - requireRemoveCertManagerCRDs(kubectlOptions) - }) -} - -// requireUninstallingCertManagerHelmChart uninstalls cert-manager helm chart -// and checks the success of that operation. -func requireUninstallingCertManagerHelmChart(kubectlOptions *k8s.KubectlOptions) { - It("Uninstalling Cert-manager Helm chart", func() { - uninstallHelmChartIfExists(kubectlOptions, "cert-manager", true) - By("Verifying Cert-manager helm chart resources cleanup") - - certManagerK8sResources := basicK8sCRDs() - certManagerK8sResources = append(certManagerK8sResources, certManagerCRDs()...) - - remainedResources := getK8sResources(kubectlOptions, - certManagerK8sResources, - fmt.Sprintf(managedByHelmLabelTemplate, "cert-manager"), - "", - kubectlArgGoTemplateKindNameNamespace, - "--all-namespaces") - Expect(remainedResources).Should(BeEmpty()) - }) - -} - -// requireRemoveKoperatorCRDs deletes the cert-manager CRDs -func requireRemoveCertManagerCRDs(kubectlOptions *k8s.KubectlOptions) { - It("Removing cert-manager CRDs", func() { - for _, crd := range certManagerCRDs() { - deleteK8sResourceGlobalNoErrNotFound(kubectlOptions, defaultDeletionTimeout, "crds", crd) - } - }) -} diff --git a/tests/e2e/const.go b/tests/e2e/const.go index 5f9c529dd..79d570f06 100644 --- a/tests/e2e/const.go +++ b/tests/e2e/const.go @@ -109,8 +109,6 @@ const ( // LocalVersion means using the files in the local repository snapshot. LocalVersion Version = "local" - kubectlNotFoundErrorMsg = "NotFound" - kubectlArgGoTemplateName = `-o=go-template='{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}'` kubectlArgGoTemplateKindNameNamespace = `-o=go-template='{{range .items}}{{.kind}}{{"/"}}{{.metadata.name}}{{if .metadata.namespace}}{{"."}}{{.metadata.namespace}}{{end}}{{"\n"}}{{end}}'` kubectlArgGoTemplateInternalListenersName = `-o=go-template='{{range $key,$value := .status.listenerStatuses.internalListeners}}{{$key}}{{"\n"}}{{end}}` @@ -118,9 +116,11 @@ const ( // kubectlArgGoTemplateExternalListenersName = `-o=go-template='{{range $key,$value := .status.listenerStatuses.externallListeners}}{{$key}}{{"\n"}}{{end}}` // kubectlArgGoTemplateExternalListenerAddressesTemplate = `-o=go-template='{{range .status.listenerStatuses.externalListeners.%s}}{{.address}}{{"\n"}}{{end}}` + crdKind = "customresourcedefinitions.apiextensions.k8s.io" kafkaKind = "kafkaclusters.kafka.banzaicloud.io" + kafkaTopicKind = "kafkatopics.kafka.banzaicloud.io" kafkaClusterName = "kafka" - testTopicName = "topic-icp" + testTopicName = "topic-test" kcatPodName = "kcat" zookeeperKind = "zookeeperclusters.zookeeper.pravega.io" zookeeperClusterName = "zookeeper-server" @@ -138,7 +138,7 @@ const ( kafkaTopicTemplate = "templates/topic.yaml.tmpl" ) -func basicK8sCRDs() []string { +func basicK8sResourceKinds() []string { return []string{ "pods", "services", diff --git a/tests/e2e/go.mod b/tests/e2e/go.mod index 52753ef6b..00dd8e12d 100644 --- a/tests/e2e/go.mod +++ b/tests/e2e/go.mod @@ -4,8 +4,7 @@ go 1.20 require ( emperror.dev/errors v0.8.1 - github.com/Masterminds/sprig/v3 v3.2.3 - github.com/banzaicloud/koperator/api v0.28.0 + github.com/cisco-open/k8s-objectmatcher v1.9.0 github.com/gruntwork-io/terratest v0.41.24 github.com/onsi/ginkgo/v2 v2.9.5 github.com/onsi/gomega v1.27.6 @@ -14,22 +13,16 @@ require ( sigs.k8s.io/yaml v1.3.0 ) -require ( - github.com/klauspost/compress v1.16.3 // indirect - github.com/pierrec/lz4/v4 v4.1.17 // indirect - github.com/twmb/franz-go/pkg/kmsg v1.4.0 // indirect -) - require ( github.com/Masterminds/goutils v1.1.1 // indirect - github.com/Masterminds/semver/v3 v3.2.0 // indirect + github.com/Masterminds/semver v1.5.0 // indirect + github.com/Masterminds/sprig v2.22.0+incompatible // indirect github.com/aws/aws-sdk-go v1.44.122 // indirect - github.com/banzaicloud/istio-client-go v0.0.17 // indirect github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect - github.com/cert-manager/cert-manager v1.9.1 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/emicklei/go-restful/v3 v3.9.0 // indirect + github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/ghodss/yaml v1.0.0 // indirect github.com/go-errors/errors v1.4.2 // indirect github.com/go-logr/logr v1.2.4 // indirect @@ -40,16 +33,16 @@ require ( github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/google/gnostic v0.6.9 // indirect + github.com/google/gnostic v0.5.7-v3refs // indirect github.com/google/go-cmp v0.5.9 // indirect - github.com/google/gofuzz v1.2.0 // indirect + github.com/google/gofuzz v1.1.0 // indirect github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect github.com/google/uuid v1.3.0 // indirect github.com/gruntwork-io/go-commons v0.8.0 // indirect - github.com/hashicorp/errwrap v1.1.0 // indirect - github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/huandu/xstrings v1.3.3 // indirect - github.com/imdario/mergo v0.3.13 // indirect + github.com/hashicorp/errwrap v1.0.0 // indirect + github.com/hashicorp/go-multierror v1.1.0 // indirect + github.com/huandu/xstrings v1.4.0 // indirect + github.com/imdario/mergo v0.3.11 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -66,15 +59,12 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pquerna/otp v1.2.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/shopspring/decimal v1.2.0 // indirect - github.com/spf13/cast v1.4.1 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/testify v1.8.1 // indirect - github.com/twmb/franz-go v1.13.4 github.com/urfave/cli v1.22.2 // indirect go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect - golang.org/x/crypto v0.7.0 // indirect + golang.org/x/crypto v0.1.0 // indirect golang.org/x/net v0.10.0 // indirect golang.org/x/oauth2 v0.1.0 // indirect golang.org/x/sys v0.8.0 // indirect @@ -92,7 +82,6 @@ require ( k8s.io/klog/v2 v2.90.1 // indirect k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f // indirect k8s.io/utils v0.0.0-20230209194617-a36077c30491 // indirect - sigs.k8s.io/controller-runtime v0.13.0 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect ) diff --git a/tests/e2e/go.sum b/tests/e2e/go.sum index c1e6fa1c7..8db5daf55 100644 --- a/tests/e2e/go.sum +++ b/tests/e2e/go.sum @@ -1,41 +1,29 @@ 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= emperror.dev/errors v0.8.1 h1:UavXZ5cSX/4u9iyvH6aDcuGkVjeexUGJ7Ij7G4VfQT0= emperror.dev/errors v0.8.1/go.mod h1:YcRvLPh626Ubn2xqtoprejnA5nFha+TJ+2vew48kWuE= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= -github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= -github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= -github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= -github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= +github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60= +github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/aws/aws-sdk-go v1.44.122 h1:p6mw01WBaNpbdP2xrisz5tIkcNwzj/HysobNoaAHjgo= github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= -github.com/banzaicloud/istio-client-go v0.0.17 h1:wiplbM7FDiIHopujInAnin3zuovtVcphtKy9En39q5I= -github.com/banzaicloud/istio-client-go v0.0.17/go.mod h1:rpnEYYGHzisx8nARl2d30Oq38EeCX0/PPaxMaREfE9I= -github.com/banzaicloud/koperator/api v0.28.0 h1:JV7J28PWNGb9JSsimqAQLsZVacPWh5DkF0oalygi6eU= -github.com/banzaicloud/koperator/api v0.28.0/go.mod h1:qvpewvjdELAnfO70vg9397CXZ4K4uHxpiWtf5fhKSrQ= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI= github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= -github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cert-manager/cert-manager v1.9.1 h1:bNIsQyfWdIMSEwxgO4sVUEyAn6xuSgNwdt9m92OBACc= -github.com/cert-manager/cert-manager v1.9.1/go.mod h1:Bs3WsNX1LPKTs3boh//p7jLOn6ZRGEPz99ITeZU0g3c= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= 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/cisco-open/k8s-objectmatcher v1.9.0 h1:/sfuO0BD09fpynZjXsqeZrh28Juc4VEwc2P6Ov/Q6fM= +github.com/cisco-open/k8s-objectmatcher v1.9.0/go.mod h1:CH4E6qAK+q+JwKFJn0DaTNqxrbmWCaDQzGthKLK4nZ0= 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= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU= -github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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= @@ -43,21 +31,16 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 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/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= +github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= -github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= -github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -71,7 +54,6 @@ github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZp github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= -github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -79,71 +61,57 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb 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/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/gnostic v0.6.9 h1:ZK/5VhkoX835RikCHpSUJV9a+S3e1zLh59YnyWeBW+0= -github.com/google/gnostic v0.6.9/go.mod h1:Nm8234We1lq6iB9OmlgNv3nH91XLLVZHCDayfA3xq+E= +github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54= +github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= 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.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= -github.com/google/gofuzz v1.2.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/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/gruntwork-io/go-commons v0.8.0 h1:k/yypwrPqSeYHevLlEDmvmgQzcyTwrlZGRaxEM6G0ro= github.com/gruntwork-io/go-commons v0.8.0/go.mod h1:gtp0yTtIBExIZp7vyIV9I0XQkVwiQZze678hvDXof78= github.com/gruntwork-io/terratest v0.41.24 h1:j6T6qe4deVvynTG2UmnjGwZy83he6xKgTaYWiSdFv/w= github.com/gruntwork-io/terratest v0.41.24/go.mod h1:O6gajNBjO1wvc7Wl9WtbO+ORcdnhAV2GQiBE71ycwIk= +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= -github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= -github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4= -github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI= +github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= +github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU= +github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= -github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY= -github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= @@ -159,12 +127,10 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA github.com/mattn/go-zglob v0.0.1/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326 h1:ofNAzWCcyTALn2Zv40+8XitdzCgXY6e9qvXwN9W0YXg= github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= -github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= @@ -172,20 +138,14 @@ github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0Gq 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 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= -github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q= github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k= github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE= github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg= -github.com/pierrec/lz4 v2.5.2+incompatible h1:WCjObylUIOlKy/+7Abdn34TLIkXiA4UWUMhxq9m9ZXI= -github.com/pierrec/lz4/v4 v4.1.17 h1:kV4Ip+/hUBC+8T6+2EgburRtkE9ef4nbY3f4dFhGjMc= -github.com/pierrec/lz4/v4 v4.1.17/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= 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= @@ -193,20 +153,12 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/pquerna/otp v1.2.0 h1:/A3+Jn+cagqayeR3iHs/L62m5ue7710D35zl1zJ1kok= github.com/pquerna/otp v1.2.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= -github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA= -github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -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/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= @@ -223,19 +175,10 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/twmb/franz-go v1.13.4 h1:xu+lTAJChFqDh6u+Edr1IR2sq81nS+XGtk6OETTxFbc= -github.com/twmb/franz-go v1.13.4/go.mod h1:jm/FtYxmhxDTN0gNSb26XaJY0irdSVcsckLiR5tQNMk= -github.com/twmb/franz-go/pkg/kmsg v1.4.0 h1:tbp9hxU6m8qZhQTlpGiaIJOm4BXix5lsuEZ7K00dF0s= -github.com/twmb/franz-go/pkg/kmsg v1.4.0/go.mod h1:SxG/xJKhgPu25SamAq0rrucfp7lbzCpEXOC+vH/ELrY= github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= -github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= @@ -243,49 +186,35 @@ go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9i golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= -golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= -golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 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-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= 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-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-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/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-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.1.0 h1:isLCZuhj4v+tYv7eskaN4v/TM+A1begWWgyVJDdl1+Y= golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= 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-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/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -293,37 +222,23 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/text v0.3.0/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/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/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-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -331,7 +246,6 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -344,74 +258,57 @@ google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6 google.golang.org/appengine v1.6.7/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-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= 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.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 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/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/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/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= k8s.io/api v0.27.2 h1:+H17AJpUMvl+clT+BPnKf0E3ksMAzoBBg7CntpSuADo= k8s.io/api v0.27.2/go.mod h1:ENmbocXfBT2ADujUXcBhHV55RIT31IIEvkntP6vZKS4= k8s.io/apiextensions-apiserver v0.27.2 h1:iwhyoeS4xj9Y7v8YExhUwbVuBhMr3Q4bd/laClBV6Bo= k8s.io/apiextensions-apiserver v0.27.2/go.mod h1:Oz9UdvGguL3ULgRdY9QMUzL2RZImotgxvGjdWRq6ZXQ= -k8s.io/apimachinery v0.0.0-20190704094733-8f6ac2502e51/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= k8s.io/apimachinery v0.27.2 h1:vBjGaKKieaIreI+oQwELalVG4d8f3YAMNpWLzDXkxeg= k8s.io/apimachinery v0.27.2/go.mod h1:XNfZ6xklnMCOGGFNqXG7bUrQCoR04dh/E7FprV6pb+E= k8s.io/client-go v0.27.2 h1:vDLSeuYvCHKeoQRhCXjxXO45nHVv2Ip4Fe0MfioMrhE= k8s.io/client-go v0.27.2/go.mod h1:tY0gVmUsHrAmjzHX9zs7eCjxcBsf8IiNe7KQ52biTcQ= -k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog/v2 v2.90.1 h1:m4bYOKall2MmOiRaR1J+We67Do7vm9KiQVlT96lnHUw= k8s.io/klog/v2 v2.90.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f h1:2kWPakN3i/k81b0gvD5C5FJ2kxm1WrQFanWchyKuqGg= k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f/go.mod h1:byini6yhqGC14c3ebc/QwanvYwhuMWF6yz2F8uwW8eg= k8s.io/utils v0.0.0-20230209194617-a36077c30491 h1:r0BAOLElQnnFhE/ApUsg3iHdVYYPBjNSSOMowRZxxsY= k8s.io/utils v0.0.0-20230209194617-a36077c30491/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/controller-runtime v0.13.0 h1:iqa5RNciy7ADWnIc8QxCbOX5FEKVR3uxVxKHRMc2WIQ= -sigs.k8s.io/controller-runtime v0.13.0/go.mod h1:Zbz+el8Yg31jubvAEyglRZGdLAjplZl+PgtYNI6WNTI= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= -sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/tests/e2e/helm.go b/tests/e2e/helm.go index 8a39173e0..f97c0c4f7 100644 --- a/tests/e2e/helm.go +++ b/tests/e2e/helm.go @@ -292,3 +292,68 @@ func lookUpInstalledHelmReleaseByName( return nil, false, nil } + +// uninstallHelmChart uninstall Helm chart from the specified kubectl context and +// namespace using the specified helm release name. When purge is true, it removes records +// and make that name free to be reused for another installation. +// Extra arguments can be any of the helm CLI uninstall flag arguments. +func uninstallHelmChart( + kubectlOptions k8s.KubectlOptions, + helmReleaseName string, + purge bool, + extraArgs ...string, +) error { + By( + fmt.Sprintf( + "uninstalling Helm chart by name %s", + helmReleaseName, + ), + ) + + fixedArguments := []string{ + "--debug", + } + + extraArgs = append(extraArgs, fixedArguments...) + + return helm.DeleteE( + GinkgoT(), + &helm.Options{ + KubectlOptions: &kubectlOptions, + ExtraArgs: map[string][]string{ + "delete": extraArgs, + }, + }, + helmReleaseName, + purge, + ) +} + +// uninstallHelmChartIfExists checks whether the specified named Helm release exists in +// the provided kubectl context and namespace, logs it if it does and returns or +// alternatively uninstall the Helm chart from the specified kubectl context and +// namespace using the release name, extra arguments can be any of the helm +// CLI install flag arguments. +func uninstallHelmChartIfExists( + kubectlOptions k8s.KubectlOptions, + helmReleaseName string, + purge bool, + extraArgs ...string, +) error { + By(fmt.Sprintf("Checking for existing Helm release names %s", helmReleaseName)) + _, isInstalled, err := lookUpInstalledHelmReleaseByName(kubectlOptions, helmReleaseName) + if err != nil { + return err + } + + if !isInstalled { + By(fmt.Sprintf( + "skipping the uninstallation of %s, because the Helm release is not present.", + helmReleaseName, + )) + + return nil + } + + return uninstallHelmChart(kubectlOptions, helmReleaseName, purge, extraArgs...) +} diff --git a/tests/e2e/helm_test.go b/tests/e2e/helm_test.go deleted file mode 100644 index bb8e3c67d..000000000 --- a/tests/e2e/helm_test.go +++ /dev/null @@ -1,229 +0,0 @@ -// Copyright © 2023 Cisco Systems, Inc. and/or its affiliates -// -// 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 ( - "encoding/json" - "fmt" - - "github.com/gruntwork-io/terratest/modules/helm" - "github.com/gruntwork-io/terratest/modules/k8s" - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" -) - -// HelmReleaseStatus describes the possible states of a Helm release. -type HelmReleaseStatus string - -const ( - // HelmReleaseDeployed is the Helm release state where the deployment is - // successfully applied to the cluster. - HelmReleaseDeployed HelmReleaseStatus = "deployed" - - // HelmReleaseFailed is the Helm release state where the deployment - // encountered an error and couldn't be applied successfully to the cluster. - HelmReleaseFailed HelmReleaseStatus = "failed" -) - -// HelmRelease describes a Helm -type HelmRelease struct { - ReleaseName string `json:"name" yaml:"name"` - Namespace string `json:"namespace" yaml:"namespace"` - Revision string `json:"revision" yaml:"revision"` - UpdatedTime string `json:"updated" yaml:"updated"` // Note: not parsable implicitly. - Status HelmReleaseStatus `json:"status" yaml:"status"` - Chart string `json:"chart" yaml:"chart"` - AppVersion string `json:"app_version" yaml:"app_version"` -} - -// installHelmChart deploys a Helm chart to the specified kubectl context and -// namespace using the specified infos, extra arguments can be any of the helm -// CLI install flag arguments, flag keys and values must be provided separately. -func installHelmChart( - kubectlOptions *k8s.KubectlOptions, - helmRepository string, - helmChartNameOrLocalPath string, - helmChartVersion string, - helmReleaseName string, - setValues map[string]string, -) { - By( - fmt.Sprintf( - "Installing Helm chart %s from %s with version %s by name %s", - helmChartNameOrLocalPath, helmRepository, helmChartVersion, helmReleaseName, - ), - ) - - fixedArguments := []string{ - "--create-namespace", - "--atomic", - "--debug", - } - - if helmRepository != "" { - fixedArguments = append([]string{"--repo", helmRepository}, fixedArguments...) - } - - helm.Install( - GinkgoT(), - &helm.Options{ - SetValues: setValues, - KubectlOptions: kubectlOptions, - Version: helmChartVersion, - ExtraArgs: map[string][]string{ - "install": fixedArguments, - }, - }, - helmChartNameOrLocalPath, - helmReleaseName, - ) -} - -// installHelmChart checks whether the specified named Helm release exists in -// the provided kubectl context and namespace, logs it if it does and returns or -// alternatively deploys the Helm chart to the specified kubectl context and -// namespace using the specified infos, extra arguments can be any of the helm -// CLI install flag arguments, flag keys and values must be provided separately. -func installHelmChartIfDoesNotExist( - kubectlOptions *k8s.KubectlOptions, - helmRepository string, - helmChartNameOrLocalPath string, - helmChartVersion string, - helmReleaseName string, - setValues map[string]string, -) { - By(fmt.Sprintf("Checking for existing Helm release named %s", helmReleaseName)) - helmRelease, isInstalled := lookUpInstalledHelmReleaseByName(kubectlOptions, helmReleaseName) - - if isInstalled { - By(fmt.Sprintf( - "Skipping the installation of %s, because the Helm release is already present: %+v", - helmReleaseName, helmRelease, - )) - - return - } - - installHelmChart( - kubectlOptions, - helmRepository, - helmChartNameOrLocalPath, - helmChartVersion, - helmReleaseName, - setValues, - ) -} - -// listHelmReleases returns a slice of Helm releases retrieved from the cluster -// using the specified kubectl context and namespace. -func listHelmReleases(kubectlOptions *k8s.KubectlOptions) []*HelmRelease { - By("Listing Helm releases") - output, err := helm.RunHelmCommandAndGetOutputE( - GinkgoT(), - &helm.Options{ - KubectlOptions: kubectlOptions, - }, - "list", - "--output", "json", - ) - - Expect(err).NotTo(HaveOccurred()) - - var releases []*HelmRelease - err = json.Unmarshal([]byte(output), &releases) - - Expect(err).NotTo(HaveOccurred()) - - return releases -} - -// lookUpInstalledHelmReleaseByName returns a Helm release and an indicator -// whether the Helm release is installed to the specified kubectl context -// and namespace by the provided Helm release name. -func lookUpInstalledHelmReleaseByName(kubectlOptions *k8s.KubectlOptions, helmReleaseName string) (*HelmRelease, bool) { - releases := listHelmReleases(kubectlOptions) - - for _, release := range releases { - if release.ReleaseName == helmReleaseName { - Expect(release.Status).To(BeEquivalentTo(HelmReleaseDeployed)) - - return release, true - } - } - - return nil, false -} - -// uninstallHelmChart uninstall Helm chart from the specified kubectl context and -// namespace using the specified helm release name. When purge is true, it removes records -// and make that name free to be reused for another installation. -// Extra arguments can be any of the helm CLI uninstall flag arguments. -func uninstallHelmChart( - kubectlOptions *k8s.KubectlOptions, - helmReleaseName string, - purge bool, - extraArgs ...string, -) { - By( - fmt.Sprintf( - "uninstalling Helm chart by name %s", - helmReleaseName, - ), - ) - - fixedArguments := []string{ - "--debug", - } - - extraArgs = append(extraArgs, fixedArguments...) - - helm.Delete( - GinkgoT(), - &helm.Options{ - KubectlOptions: kubectlOptions, - ExtraArgs: map[string][]string{ - "delete": extraArgs, - }, - }, - helmReleaseName, - purge, - ) -} - -// uninstallHelmChartIfExists checks whether the specified named Helm release exists in -// the provided kubectl context and namespace, logs it if it does and returns or -// alternatively uninstall the Helm chart from the specified kubectl context and -// namespace using the release name, extra arguments can be any of the helm -// CLI install flag arguments. -func uninstallHelmChartIfExists( - kubectlOptions *k8s.KubectlOptions, - helmReleaseName string, - purge bool, - extraArgs ...string, -) { - By(fmt.Sprintf("Checking for existing Helm release names %s", helmReleaseName)) - _, isInstalled := lookUpInstalledHelmReleaseByName(kubectlOptions, helmReleaseName) - - if !isInstalled { - By(fmt.Sprintf( - "skipping the uninstallation of %s, because the Helm release is not present.", - helmReleaseName, - )) - - return - } - - uninstallHelmChart(kubectlOptions, helmReleaseName, purge, extraArgs...) -} diff --git a/tests/e2e/install_test.go b/tests/e2e/install_test.go deleted file mode 100644 index cdf6b8903..000000000 --- a/tests/e2e/install_test.go +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright © 2023 Cisco Systems, Inc. and/or its affiliates -// -// 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 ( - "github.com/gruntwork-io/terratest/modules/k8s" - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" -) - -var _ = When("Installing Koperator", Ordered, func() { - var kubeconfigPath string - var kubecontextName string - - It("Acquiring K8s config and context", func() { - var err error - kubeconfigPath, kubecontextName, err = currentEnvK8sContext() - - Expect(err).NotTo(HaveOccurred()) - }) - - // requireInstallingCertManager(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "cert-manager"), "v1.11.0") - // requireInstallingZookeeperOperator(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "zookeeper"), "0.2.14") - // requireInstallingPrometheusOperator(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "prometheus"), "42.0.1") - // requireInstallingKoperator(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "kafka"), LocalVersion) - // ----------------------------------------------------------------------------------------------------------- - // requireCreatingZookeeperCluster(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "zookeeper"), "../../config/samples/zookeeper_sample.yaml") - // requireCreatingKafkaCluster(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "kafka"), "local", "simplekafkacluster_ssl.yaml") - // // ----------------------------------------------------------------------------------------------------------- - requireInternalProducerConsumer(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "kafka")) - // // ----------------------------------------------------------------------------------------------------------- - // requireUninstallKafkaCluster(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "kafka"), "kafka") - // requireUninstallZookeeperCluster(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "zookeeper"), "zookeeper-server") - // // ----------------------------------------------------------------------------------------------------------- - // requireUninstallingKoperator(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "kafka")) - // requireUninstallingPrometheusOperator(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "prometheus")) - // requireUninstallingZookeeperOperator(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "zookeeper")) - // requireUninstallingCertManager(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "cert-manager")) - //requireExternalProducerConsumer(k8s.NewKubectlOptions(kubecontextName, kubeconfigPath, "kafka")) -}) diff --git a/tests/e2e/k8s.go b/tests/e2e/k8s.go index 2b2f807a9..4dd00febc 100644 --- a/tests/e2e/k8s.go +++ b/tests/e2e/k8s.go @@ -22,9 +22,11 @@ import ( "os" "path" "strings" + "text/template" "time" "emperror.dev/errors" + "github.com/Masterminds/sprig" "github.com/cisco-open/k8s-objectmatcher/patch" "github.com/gruntwork-io/terratest/modules/k8s" . "github.com/onsi/ginkgo/v2" @@ -392,3 +394,156 @@ func listK8sCRDs(kubectlOptions k8s.KubectlOptions, crdNames ...string) ([]strin return strings.Split(output, "\n"), nil } + +// deleteK8sResourceOpts deletes K8s resources based on the kind and name or kind and selector. +// When noErrNotFound is true then the deletion is passed in case when the resource is not found. +// timeout parameter specifies the timeout for the deletion. +// extraArgs can be any of the kubectl arguments. +func deleteK8sResource( + kubectlOptions k8s.KubectlOptions, + timeout time.Duration, + kind string, + selector string, + name string, + extraArgs ...string) error { + + args := []string{"delete", kind} + + args = append(args, fmt.Sprintf("--timeout=%s", timeout)) + + logMsg := fmt.Sprintf("Deleting k8s resource: kind: '%s' ", kind) + logMsg, args = _kubectlArgExtender(args, logMsg, selector, name, kubectlOptions.Namespace, extraArgs) + By(logMsg) + + _, err := k8s.RunKubectlAndGetOutputE( + GinkgoT(), + &kubectlOptions, + args..., + ) + + return err +} + +// deleteK8sResourceNoErrNotFound deletes K8s resources based on the kind and name or kind and selector. +// Deletion is passed in case the resource is not found. +// timeout parameter specifies the timeout for the deletion. +// extraArgs can be any of the kubectl arguments. +func deleteK8sResourceNoErrNotFound(kubectlOptions k8s.KubectlOptions, timeout time.Duration, kind string, name string, extraArgs ...string) error { + err := deleteK8sResource(kubectlOptions, timeout, kind, "", name, extraArgs...) + if _isNotFoundError(err) { + By("Resource not found") + return nil + } + return err +} + +// applyK8sResourceManifestFromString applies the specified manifest in string format to the provided +// kubectl context and namespace. +func applyK8sResourceManifestFromString(kubectlOptions k8s.KubectlOptions, manifest string) error { + By(fmt.Sprintf("Applying k8s manifest\n%s", manifest)) + return k8s.KubectlApplyFromStringE(GinkgoT(), &kubectlOptions, manifest) +} + +// applyK8sResourceFromTemplate generates manifest from the specified go-template based on values +// and applies the specified manifest to the provided kubectl context and namespace. +func applyK8sResourceFromTemplate(kubectlOptions k8s.KubectlOptions, templateFile string, values map[string]interface{}) error { + By(fmt.Sprintf("Generating K8s manifest from template %s", templateFile)) + var manifest bytes.Buffer + rawTemplate, err := os.ReadFile(templateFile) + if err != nil { + return err + } + t := template.Must(template.New("template").Funcs(sprig.TxtFuncMap()).Parse(string(rawTemplate))) + err = t.Execute(&manifest, values) + if err != nil { + return err + } + return applyK8sResourceManifestFromString(kubectlOptions, manifest.String()) +} + +// checkExistenceOfK8sResource queries a Resource by it's kind, namespace and name and +// returns the output of stderr +func checkExistenceOfK8sResource( + kubectlOptions *k8s.KubectlOptions, + resourceKind string, + resourceName string, +) error { + By(fmt.Sprintf("Checking the existence of resource %s", resourceName)) + return k8s.RunKubectlE(GinkgoT(), kubectlOptions, "get", resourceKind, resourceName) +} + +// listK8sAllResourceKind lists all of the available resource type on the K8s cluster +func listK8sAllResourceKind(kubectlOptions k8s.KubectlOptions) ([]string, error) { + By("Listing available K8s resource kind") + + args := []string{"api-resources", "--verbs=list", "-o", "name"} + output, err := k8s.RunKubectlAndGetOutputE( + GinkgoT(), + &kubectlOptions, + args..., + ) + + if err != nil { + return nil, err + } + + return _kubectlRemoveWarnings(strings.Split(output, "\n")), nil +} + +// getK8sResources gets the specified K8S resources from the specified kubectl context and +// namespace optionally. Extra arguments can be any of the kubectl get flag arguments. +// Returns a slice of the returned elements. Separator between elements must be newline. +func getK8sResources(kubectlOptions k8s.KubectlOptions, resourceKind []string, selector string, names string, extraArgs ...string) ([]string, error) { + logMsg := fmt.Sprintf("Get K8S resources: '%s'", resourceKind) + + args := []string{"get", strings.Join(resourceKind, ",")} + logMsg, args = _kubectlArgExtender(args, logMsg, selector, names, kubectlOptions.Namespace, extraArgs) + By(logMsg) + + output, err := k8s.RunKubectlAndGetOutputE( + GinkgoT(), + &kubectlOptions, + args..., + ) + + if err != nil { + return nil, err + } + + output = strings.Trim(output, "'") + // Empty output + if output == "" { + return nil, nil + } + + output = strings.TrimRight(output, "\n") + outputSlice := strings.Split(output, "\n") + + // Remove warning message pollution from the output + + return _kubectlRemoveWarnings(outputSlice), nil +} + +// waitK8sResourceCondition waits until the condition is met or the timeout is elapsed for the selected K8s resource(s) +// extraArgs can be any of the kubectl arguments +func waitK8sResourceCondition(kubectlOptions k8s.KubectlOptions, resourceKind, waitFor string, timeout time.Duration, selector string, names string, extraArgs ...string) error { + logMsg := fmt.Sprintf("Waiting K8s resource(s)' condition: '%s' to fulfil", waitFor) + + args := []string{ + "wait", + resourceKind, + fmt.Sprintf("--for=%s", waitFor), + fmt.Sprintf("--timeout=%s", timeout), + } + + logMsg, args = _kubectlArgExtender(args, logMsg, selector, names, kubectlOptions.Namespace, extraArgs) + By(logMsg) + + _, err := k8s.RunKubectlAndGetOutputE( + GinkgoT(), + &kubectlOptions, + args..., + ) + + return err +} diff --git a/tests/e2e/k8s_test.go b/tests/e2e/k8s_test.go deleted file mode 100644 index d707228d5..000000000 --- a/tests/e2e/k8s_test.go +++ /dev/null @@ -1,358 +0,0 @@ -// Copyright © 2023 Cisco Systems, Inc. and/or its affiliates -// -// 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 ( - "bytes" - "fmt" - "os" - "path" - "strings" - "text/template" - "time" - - "emperror.dev/errors" - "github.com/Masterminds/sprig/v3" - "github.com/gruntwork-io/terratest/modules/k8s" - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "sigs.k8s.io/yaml" -) - -// deleteK8sResourceOpts deletes K8s resources based on the kind and name or kind and selector. -// When noErrNotFound is true then the deletion is passed in case when the resource is not found. -// timeout parameter specifies the timeout for the deletion. -// globalResource parameter indicates that the resource is global, -// extraArgs can be any of the kubectl arguments. -func deleteK8sResourceOpts( - kubectlOptions *k8s.KubectlOptions, - globalResource, - noErrNotFound bool, - timeout time.Duration, - kind string, - selector string, - name string, - extraArgs ...string) { - - args := []string{"delete", kind} - - args = append(args, fmt.Sprintf("--timeout=%s", timeout)) - kubectlNamespace := kubectlOptions.Namespace - - if globalResource { - kubectlOptions.Namespace = "" - } - - logMsg := fmt.Sprintf("Deleting k8s resource: kind: '%s' ", kind) - logMsg, args = _kubectlArgExtender(args, logMsg, selector, name, kubectlOptions.Namespace, extraArgs) - By(logMsg) - - args = append(args, extraArgs...) - - _, err := k8s.RunKubectlAndGetOutputE( - GinkgoT(), - kubectlOptions, - args..., - ) - - kubectlOptions.Namespace = kubectlNamespace - - if _isNotFoundError(err) && noErrNotFound { - By("Resource not found") - } else { - Expect(err).NotTo(HaveOccurred()) - } -} - -// deleteK8sResourceGlobalNoErrNotFound deletes K8s global resources based on the kind and name or kind and selector. -// Deletion is passed in case the resource is not found. -// timeout parameter specifies the timeout for the deletion. -// extraArgs can be any of the kubectl arguments. -func deleteK8sResourceGlobalNoErrNotFound(kubectlOptions *k8s.KubectlOptions, timeout time.Duration, kind string, name string, extraArgs ...string) { - deleteK8sResourceOpts(kubectlOptions, true, true, timeout, kind, "", name, extraArgs...) -} - -// deleteK8sResourceGlobal deletes K8s resources based on the kind and name or kind and selector. -// timeout parameter specifies the timeout for the deletion. -// extraArgs can be any of the kubectl arguments. -func deleteK8sResourceGlobal(kubectlOptions *k8s.KubectlOptions, timeout time.Duration, kind string, name string, extraArgs ...string) { - deleteK8sResourceOpts(kubectlOptions, true, false, timeout, kind, "", name, extraArgs...) -} - -// deleteK8sResource deletes K8s resources based on the kind and name or kind and selector. -// timeout parameter specifies the timeout for the deletion. -// extraArgs can be any of the kubectl arguments. -func deleteK8sResource(kubectlOptions *k8s.KubectlOptions, timeout time.Duration, kind string, name string, extraArgs ...string) { - deleteK8sResourceOpts(kubectlOptions, false, false, timeout, kind, "", name, extraArgs...) -} - -// deleteK8sResourceNoErrNotFound deletes K8s resources based on the kind and name or kind and selector. -// Deletion is passed in case the resource is not found. -// timeout parameter specifies the timeout for the deletion. -// extraArgs can be any of the kubectl arguments. -func deleteK8sResourceNoErrNotFound(kubectlOptions *k8s.KubectlOptions, timeout time.Duration, kind string, name string, extraArgs ...string) { - deleteK8sResourceOpts(kubectlOptions, false, true, timeout, kind, "", name, extraArgs...) -} - -// applyK8sResourceManifests applies the specified manifest to the provided -// kubectl context and namespace. -func applyK8sResourceManifest(kubectlOptions *k8s.KubectlOptions, manifestPath string) { - By(fmt.Sprintf("Applying k8s manifest %s", manifestPath)) - k8s.KubectlApply(GinkgoT(), kubectlOptions, manifestPath) -} - -// applyK8sResourceManifestFromString applies the specified manifest in string format to the provided -// kubectl context and namespace. -func applyK8sResourceManifestFromString(kubectlOptions *k8s.KubectlOptions, manifest string) { - By(fmt.Sprintf("Applying k8s manifest\n%s", manifest)) - k8s.KubectlApplyFromString(GinkgoT(), kubectlOptions, manifest) -} - -// applyK8sResourceFromTemplate generates manifest from the specified go-template based on values -// and applies the specified manifest to the provided kubectl context and namespace. -func applyK8sResourceFromTemplate(kubectlOptions *k8s.KubectlOptions, templateFile string, values map[string]interface{}) { - By(fmt.Sprintf("Generating K8s manifest from template %s", templateFile)) - var manifest bytes.Buffer - rawTemplate, err := os.ReadFile(templateFile) - Expect(err).NotTo(HaveOccurred()) - t := template.Must(template.New("template").Funcs(sprig.TxtFuncMap()).Parse(string(rawTemplate))) - err = t.Execute(&manifest, values) - Expect(err).NotTo(HaveOccurred()) - applyK8sResourceManifestFromString(kubectlOptions, manifest.String()) -} - -// checkExistenceOfK8sResource queries a Resource by it's kind, namespace and name and -// returns the output of stderr -func checkExistenceOfK8sResource( - kubectlOptions *k8s.KubectlOptions, - resourceKind string, - resourceName string, -) error { - By(fmt.Sprintf("Checking the existence of resource %s", resourceName)) - return k8s.RunKubectlE(GinkgoT(), kubectlOptions, "get", resourceKind, resourceName) -} - -// createK8sResourcesFromManifest creates Kubernetes resources from the -// specified manifest to the provided kubectl context and namespace. -func createK8sResourcesFromManifest(kubectlOptions *k8s.KubectlOptions, manifestPath string, shouldBeValidated bool) { - By(fmt.Sprintf("Creating k8s resources from manifest %s", manifestPath)) - k8s.RunKubectl( - GinkgoT(), - kubectlOptions, - "create", - fmt.Sprintf("--validate=%t", shouldBeValidated), - "--filename", manifestPath, - ) -} - -// createOrReplaceK8sResourcesFromManifest creates non-existent Kubernetes -// resources or replaces existing ones from the specified manifest to the -// provided kubectl context and namespace. -func createOrReplaceK8sResourcesFromManifest( - kubectlOptions *k8s.KubectlOptions, - resourceKind string, - resourceName string, - resourceManifest string, - shouldBeValidated bool, -) { - By(fmt.Sprintf("Checking the existence of resource %s", resourceName)) - err := k8s.RunKubectlE(GinkgoT(), kubectlOptions, "get", resourceKind, resourceName) - - if err == nil { - replaceK8sResourcesFromManifest(kubectlOptions, resourceManifest, shouldBeValidated) - } else { - createK8sResourcesFromManifest(kubectlOptions, resourceManifest, shouldBeValidated) - } -} - -// currentKubernetesContext returns the currently set Kubernetes context based -// on the the environment variables and the KUBECONFIG file. -func currentEnvK8sContext() (kubeconfigPath string, kubecontextName string, err error) { - kubeconfigPath, isExisting := os.LookupEnv("KUBECONFIG") - if !isExisting { - homePath, err := os.UserHomeDir() - if err != nil { - return "", "", errors.WrapIf(err, "retrieving user home directory failed") - } - - kubeconfigPath = path.Join(homePath, ".kube", "config") - } - - kubeconfigBytes, err := os.ReadFile(kubeconfigPath) - if err != nil { - return "", "", errors.WrapIfWithDetails(err, "reading KUBECONFIG file failed", "path", kubeconfigPath) - } - - structuredKubeconfig := make(map[string]interface{}) - err = yaml.Unmarshal(kubeconfigBytes, &structuredKubeconfig) - if err != nil { - return "", "", errors.WrapIfWithDetails( - err, - "parsing kubeconfig failed", - "kubeconfig", string(kubeconfigBytes), - ) - } - - kubecontext, isOk := structuredKubeconfig["current-context"].(string) - if !isOk { - return "", "", errors.WrapIfWithDetails( - err, - "kubeconfig current-context is not string", - "current-context", structuredKubeconfig["current-context"], - ) - } - - return kubeconfigPath, kubecontext, nil -} - -// listK8sCRDs lists the available CRDs from the specified kubectl context and -// namespace optionally filtering for the specified CRD names. -func listK8sCRDs(kubectlOptions *k8s.KubectlOptions, crdNames ...string) []string { - if len(crdNames) == 0 { - By("Listing CRDs") - } else { - By(fmt.Sprintf("Listing CRDs filtered for CRD names %+v", crdNames)) - } - - args := append([]string{"get", "crd", "-o", "name"}, crdNames...) - output, err := k8s.RunKubectlAndGetOutputE( - GinkgoT(), - kubectlOptions, - args..., - ) - - Expect(err).NotTo(HaveOccurred()) - - return strings.Split(output, "\n") -} - -// listK8sAllResourceType lists all of the available resource type on the K8s cluster -func listK8sAllResourceType(kubectlOptions *k8s.KubectlOptions) []string { - By("Listing available K8s resource types") - - args := []string{"api-resources", "--verbs=list", "-o", "name"} - output, err := k8s.RunKubectlAndGetOutputE( - GinkgoT(), - kubectlOptions, - args..., - ) - - Expect(err).NotTo(HaveOccurred()) - - return strings.Split(output, "\n") -} - -// replaceK8sResourcesFromManifest replaces existing Kubernetes resources from -// the specified manifest to the provided kubectl context and namespace. -func replaceK8sResourcesFromManifest(kubectlOptions *k8s.KubectlOptions, manifestPath string, shouldBeValidated bool) { - By(fmt.Sprintf("Replacing k8s resources from manifest %s", manifestPath)) - k8s.RunKubectl( - GinkgoT(), - kubectlOptions, - "replace", - fmt.Sprintf("--validate=%t", shouldBeValidated), - "--filename", manifestPath, - ) -} - -// requireExistingCRDs checks whether the specified CRDs are existing on -// the provided kubectl context. -func requireExistingCRDs(kubectlOptions *k8s.KubectlOptions, crdNames ...string) { - crds := listK8sCRDs(kubectlOptions, crdNames...) - - crdFullNames := make([]string, 0, len(crds)) - for _, crdName := range crdNames { - crdFullNames = append(crdFullNames, "customresourcedefinition.apiextensions.k8s.io/"+crdName) - } - - Expect(crds).To(ContainElements(crdFullNames)) -} - -// requireRunningPods checks whether the specified pod names are existing in the -// namespace and have a running status. -func requireRunningPods(kubectlOptions *k8s.KubectlOptions, matchingLabelKey string, podNames ...string) { - By(fmt.Sprintf("Verifying running pods for pod names %+v", podNames)) - pods := k8s.ListPods(GinkgoT(), kubectlOptions, v1.ListOptions{}) - - podNamesAsInterfaces := make([]interface{}, 0, len(podNames)) - for _, podName := range podNames { - podNamesAsInterfaces = append(podNamesAsInterfaces, podName) - } - - Expect(pods).To(HaveLen(len(podNames))) - for _, pod := range pods { - Expect(pod.GetLabels()[matchingLabelKey]).To(BeElementOf(podNamesAsInterfaces...)) - Expect(pod.Status.Phase).To(BeEquivalentTo("Running")) - } -} - -// getK8sResources gets the specified K8S resources from the specified kubectl context and -// namespace optionally. Extra arguments can be any of the kubectl get flag arguments. -// Returns a slice of the returned elements. Separator between elements must be newline. -func getK8sResources(kubectlOptions *k8s.KubectlOptions, resourceKind []string, selector string, names string, extraArgs ...string) []string { - logMsg := fmt.Sprintf("Get K8S resources: '%s'", resourceKind) - - args := []string{"get", strings.Join(resourceKind, ",")} - logMsg, args = _kubectlArgExtender(args, logMsg, selector, names, kubectlOptions.Namespace, extraArgs) - - By(logMsg) - - args = append(args, extraArgs...) - - output, err := k8s.RunKubectlAndGetOutputE( - GinkgoT(), - kubectlOptions, - args..., - ) - - Expect(err).NotTo(HaveOccurred()) - - output = strings.Trim(output, "'") - if output == "" { - return nil - } - - output = strings.TrimRight(output, "\n") - outputSlice := strings.Split(output, "\n") - - // Remove warning message pollution from the output - - return _kubectlRemoveWarnings(outputSlice) -} - -// waitK8sResourceCondition waits until the condition is met or the timeout is elapsed for the selected K8s resource(s) -// extraArgs can be any of the kubectl arguments -func waitK8sResourceCondition(kubectlOptions *k8s.KubectlOptions, resourceKind, waitFor string, timeout time.Duration, selector string, names string, extraArgs ...string) { - logMsg := fmt.Sprintf("Waiting K8s resource(s)' condition: '%s' to fulfil", waitFor) - - args := []string{ - "wait", - resourceKind, - fmt.Sprintf("--for=%s", waitFor), - fmt.Sprintf("--timeout=%s", timeout), - } - - logMsg, args = _kubectlArgExtender(args, logMsg, selector, names, kubectlOptions.Namespace, extraArgs) - By(logMsg) - - _, err := k8s.RunKubectlAndGetOutputE( - GinkgoT(), - kubectlOptions, - args..., - ) - - Expect(err).NotTo(HaveOccurred()) -} diff --git a/tests/e2e/koperator_test.go b/tests/e2e/koperator_test.go deleted file mode 100644 index 0723d17d8..000000000 --- a/tests/e2e/koperator_test.go +++ /dev/null @@ -1,256 +0,0 @@ -// Copyright © 2023 Cisco Systems, Inc. and/or its affiliates -// -// 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 ( - "bytes" - "context" - "fmt" - "io" - "net/http" - "os" - "path" - "strings" - "time" - - koperator_v1beta1 "github.com/banzaicloud/koperator/api/v1beta1" - apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" - - "github.com/gruntwork-io/terratest/modules/helm" - "github.com/gruntwork-io/terratest/modules/k8s" - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - "sigs.k8s.io/yaml" -) - -// requireApplyingKoperatorSampleResource deploys the specified sample resource (config/samples). -// The full path of the manifest also can be specified. -// It supports different versions that can be specified with the koperatorVersion parameter. -func requireApplyingKoperatorSampleResource(kubectlOptions *k8s.KubectlOptions, koperatorVersion Version, sampleFile string) { - It("Applying Koperator sample resource", func() { - By(fmt.Sprintf("Retrieving Koperator sample resource: '%s' with version: '%s' ", sampleFile, koperatorVersion)) - - sampleFileSplit := strings.Split(sampleFile, "/") - Expect(sampleFileSplit).ShouldNot(BeEmpty()) - - var err error - var rawKoperatorSampleResource []byte - - switch koperatorVersion { - case LocalVersion: - if len(sampleFileSplit) == 1 { - sampleFile = fmt.Sprintf("../../config/samples/%s", sampleFile) - } - - rawKoperatorSampleResource, err = os.ReadFile(sampleFile) - Expect(err).NotTo(HaveOccurred()) - default: - httpClient := new(http.Client) - httpClient.Timeout = 5 * time.Second - - Expect(sampleFileSplit).Should(HaveLen(1)) - - response, err := httpClient.Get("https://raw.githubusercontent.com/banzaicloud/koperator/" + koperatorVersion + "/config/samples/" + sampleFile) - if response != nil { - defer func() { _ = response.Body.Close() }() - } - - Expect(err).NotTo(HaveOccurred()) - - rawKoperatorSampleResource, err = io.ReadAll(response.Body) - - Expect(err).NotTo(HaveOccurred()) - } - - By(fmt.Sprintf("Applying K8s manifest %s", sampleFile)) - k8s.KubectlApplyFromString(GinkgoT(), kubectlOptions, string(rawKoperatorSampleResource)) - - }) -} - -// requireRemoveKoperatorCRDs deletes the koperator CRDs -func requireRemoveKoperatorCRDs(kubectlOptions *k8s.KubectlOptions) { - It("Removing koperator CRDs", func() { - for _, crd := range koperatorCRDs() { - deleteK8sResourceGlobalNoErrNotFound(kubectlOptions, defaultDeletionTimeout, "crds", crd) - } - }) -} - -// requireApplyingKoperatorCRDs deploys the koperator CRDs and checks their -// existence afterwards. -func requireApplyingKoperatorCRDs(kubectlOptions *k8s.KubectlOptions, koperatorVersion Version) { - It("Applying koperator CRDs", func() { - By(fmt.Sprintf("Retrieving Koperator CRDs (to work around too long CRD) with version %s ", koperatorVersion)) - // Note: had to go lower because none of apply, create, replace works - // properly with the KafkaCluster CRD due to the size (apply cannot - // handle the size, create is not idempotent, replace is only idempotent - // if the resources are existing already). Tried dropping the - // descriptions in the CRDs, but still too large - var rawKoperatorCRDsManifest []byte - var err error - - switch koperatorVersion { - case LocalVersion: - rawKoperatorCRDsManifest = []byte(helm.RenderTemplate( - GinkgoT(), - &helm.Options{ - SetValues: map[string]string{ - "crd.enabled": "true", - }, - }, - "../../charts/kafka-operator", - "dummy", - []string{"templates/crds.yaml"}, - )) - default: - httpClient := new(http.Client) - httpClient.Timeout = 5 * time.Second - - response, err := httpClient.Get("https://github.com/banzaicloud/koperator/releases/download/" + koperatorVersion + "/kafka-operator.crds.yaml") - if response != nil { - defer func() { _ = response.Body.Close() }() - } - - Expect(err).NotTo(HaveOccurred()) - - rawKoperatorCRDsManifest, err = io.ReadAll(response.Body) - - Expect(err).NotTo(HaveOccurred()) - } - - rawKoperatorCRDs := bytes.Split(rawKoperatorCRDsManifest, []byte("\n---\n")) - for rawKoperatorCRDIndex, rawKoperatorCRD := range rawKoperatorCRDs { - rawKoperatorCRDs[rawKoperatorCRDIndex] = bytes.Trim(rawKoperatorCRD, "\n-") - } - - allowedCRDByteCount := 262144 - tempDir := os.TempDir() - tempFile := path.Join(tempDir, "manifest.yaml") - for _, rawKoperatorCRD := range rawKoperatorCRDs { - err = os.WriteFile(tempFile, rawKoperatorCRD, 0o777) - - Expect(err).NotTo(HaveOccurred()) - - if len(rawKoperatorCRD) > allowedCRDByteCount { // Note: too long CRDs cannot be applied, only created or replaced. - var koperatorCRD apiextensionsv1.CustomResourceDefinition - err := yaml.Unmarshal(rawKoperatorCRD, &koperatorCRD) - - Expect(err).NotTo(HaveOccurred()) - - createOrReplaceK8sResourcesFromManifest(kubectlOptions, "crd", koperatorCRD.GetName(), tempFile, false) - } else { - By("Applying koperator CRDs with version " + koperatorVersion) - applyK8sResourceManifest(kubectlOptions, tempFile) - } - } - - By("Verifying koperator CRDs") - requireExistingCRDs( - kubectlOptions, - koperatorCRDs()..., - ) - }) -} - -// requireInstallingKoperator deploys koperator CRDs and Helm chart and checks -// the success of those operations. -func requireInstallingKoperator(kubectlOptions *k8s.KubectlOptions, koperatorVersion Version) { - When("Installing koperator", func() { - requireApplyingKoperatorCRDs(kubectlOptions, koperatorVersion) - requireInstallingKoperatorHelmChartIfDoesNotExist(kubectlOptions, koperatorVersion) - }) -} - -// requireDeployingKoperatorHelmChart checks the existence of the koperator Helm -// release and installs it if it's not present. -func requireInstallingKoperatorHelmChartIfDoesNotExist( - kubectlOptions *k8s.KubectlOptions, - koperatorVersion Version, -) { - It("Installing koperator Helm chart", func() { - switch koperatorVersion { - case LocalVersion: - installHelmChartIfDoesNotExist(kubectlOptions, "", "../../charts/kafka-operator", "", "kafka-operator", nil) - default: - installHelmChartIfDoesNotExist( - kubectlOptions, - "https://kubernetes-charts.banzaicloud.com", - "kafka-operator", - koperatorVersion, - "kafka-operator", - nil, - ) - } - - By("Verifying koperator pods") - //requireRunningPods(kubectlOptions, "app.kubernetes.io/name", "kafka-operator") - }) -} - -// requireUninstallingKoperator uninstall koperator Helm chart and removes Koperator's CRDs. -func requireUninstallingKoperator(kubectlOptions *k8s.KubectlOptions) { - When("Uninstalling Koperator", func() { - requireUninstallingKoperatorHelmChart(kubectlOptions) - requireRemoveKoperatorCRDs(kubectlOptions) - }) -} - -// requireUninstallingKoperatorHelmChart uninstall Koperator Helm chart -// and checks the success of that operation. -func requireUninstallingKoperatorHelmChart(kubectlOptions *k8s.KubectlOptions) { - It("Uninstalling Koperator Helm chart", func() { - uninstallHelmChartIfExists(kubectlOptions, "kafka-operator", true) - By("Verifying Koperator helm chart resources cleanup") - k8sCRDs := listK8sAllResourceType(kubectlOptions) - remainedResources := getK8sResources(kubectlOptions, - k8sCRDs, - fmt.Sprintf(managedByHelmLabelTemplate, "kafka-operator"), - "", - kubectlArgGoTemplateKindNameNamespace, - "--all-namespaces") - Expect(remainedResources).Should(BeEmpty()) - }) -} - -// requireUninstallKafkaCluster uninstall the Kafka cluster -func requireUninstallKafkaCluster(kubectlOptions *k8s.KubectlOptions, name string) { - When("Uninstalling Kafka cluster", func() { - requireDeleteKafkaCluster(kubectlOptions, name) - - }) -} - -// requireDeleteKafkaCluster deletes KafkaCluster resource and -// checks the removal of the Kafka cluster related resources -func requireDeleteKafkaCluster(kubectlOptions *k8s.KubectlOptions, name string) { - It("Delete KafkaCluster custom resource", func() { - deleteK8sResourceGlobalNoErrNotFound(kubectlOptions, defaultDeletionTimeout, "kafkacluster", "kafka") - Eventually(context.Background(), func() []string { - By("Verifying the Kafka cluster resource cleanup") - - // Check only those Koperator related resource types we have in K8s (istio usecase) - k8sCRDs := listK8sAllResourceType(kubectlOptions) - koperatorCRDsSelected := _stringSlicesUnion(getKoperatorRelatedResourceKinds(), k8sCRDs) - koperatorCRDsSelected = append(koperatorCRDsSelected, basicK8sCRDs()...) - - return getK8sResources(kubectlOptions, - koperatorCRDsSelected, - fmt.Sprintf("%s=%s", koperator_v1beta1.KafkaCRLabelKey, name), - "", - "--all-namespaces", kubectlArgGoTemplateKindNameNamespace) - }, kafkaClusterResourceCleanupTimeout, 3*time.Millisecond).Should(BeEmpty()) - }) -} diff --git a/tests/e2e/kafka_prod_consum_test.go b/tests/e2e/produce_consume.go similarity index 69% rename from tests/e2e/kafka_prod_consum_test.go rename to tests/e2e/produce_consume.go index 16b10b676..c04767335 100644 --- a/tests/e2e/kafka_prod_consum_test.go +++ b/tests/e2e/produce_consume.go @@ -23,21 +23,8 @@ import ( . "github.com/onsi/gomega" ) -// requireInternalProducerConsumer deploys a kcat pod and a kafkaTopic into the K8s cluster -// and produces, consumes messages and makes comparisons between them. -// After deletes the kafkaTopic and kcat pod. -func requireInternalProducerConsumer(kubectlOptions *k8s.KubectlOptions) { - When("Internally produce and consume message to Kafka cluster", func() { - requireDeployingKcatPod(kubectlOptions, kcatPodName) - requireDeployingKafkaTopic(kubectlOptions, testTopicName) - requireInternalProducingConsumingMessage(kubectlOptions, "", kcatPodName, testTopicName) - requireDeleteKafkaTopic(kubectlOptions, testTopicName) - requireDeleteKcatPod(kubectlOptions, kcatPodName) - }) -} - // requireDeployingKcatPod deploys kcat pod form a template and checks the pod readiness -func requireDeployingKcatPod(kubectlOptions *k8s.KubectlOptions, podName string) { +func requireDeployingKcatPod(kubectlOptions k8s.KubectlOptions, podName string) { It("Deploying Kcat Pod", func() { applyK8sResourceFromTemplate(kubectlOptions, kcatPodTemplate, @@ -52,7 +39,7 @@ func requireDeployingKcatPod(kubectlOptions *k8s.KubectlOptions, podName string) } // requireDeployingKafkaTopic deploys a kafkaTopic resource from a template -func requireDeployingKafkaTopic(kubectlOptions *k8s.KubectlOptions, topicName string) { +func requireDeployingKafkaTopic(kubectlOptions k8s.KubectlOptions, topicName string) { It("Deploying KafkaTopic CR", func() { applyK8sResourceFromTemplate(kubectlOptions, kafkaTopicTemplate, @@ -62,46 +49,50 @@ func requireDeployingKafkaTopic(kubectlOptions *k8s.KubectlOptions, topicName st "Namespace": kubectlOptions.Namespace, }, ) - waitK8sResourceCondition(kubectlOptions, "kafkatopic", "jsonpath={.status.state}=created", defaultTopicCreationWaitTime, "", topicName) + waitK8sResourceCondition(kubectlOptions, kafkaTopicKind, "jsonpath={.status.state}=created", defaultTopicCreationWaitTime, "", topicName) }) } // requireDeleteKafkaTopic deletes kafkaTopic resource. -func requireDeleteKafkaTopic(kubectlOptions *k8s.KubectlOptions, topicName string) { +func requireDeleteKafkaTopic(kubectlOptions k8s.KubectlOptions, topicName string) { It("Deleting KafkaTopic CR", func() { - deleteK8sResource(kubectlOptions, defaultDeletionTimeout, "kafkatopic", topicName) + deleteK8sResource(kubectlOptions, defaultDeletionTimeout, kafkaTopicKind, "", topicName) }) } // requireDeleteKcatPod deletes kcat pod. -func requireDeleteKcatPod(kubectlOptions *k8s.KubectlOptions, podName string) { +func requireDeleteKcatPod(kubectlOptions k8s.KubectlOptions, podName string) { It("Deleting Kcat pod", func() { - deleteK8sResource(kubectlOptions, defaultDeletionTimeout, "pods", podName) + deleteK8sResource(kubectlOptions, defaultDeletionTimeout, "pods", "", podName) }) } // requireInternalProducingConsumingMessage produces and consumes messages internally through a kcat pod // and makes comparisons between the produced and consumed messages. // When internalAddress parameter is empty, it gets the internal address from the kafkaCluster CR status -func requireInternalProducingConsumingMessage(kubectlOptions *k8s.KubectlOptions, internalAddress, kcatPodName, topicName string) { +func requireInternalProducingConsumingMessage(kubectlOptions k8s.KubectlOptions, internalAddress, kcatPodName, topicName string) { It(fmt.Sprintf("Producing and consuming messages to/from topicName: '%s", topicName), func() { if internalAddress == "" { By("Getting Kafka cluster internal addresses") - internalListenerNames := getK8sResources(kubectlOptions, - []string{"kafkacluster"}, + internalListenerNames, err := getK8sResources(kubectlOptions, + []string{kafkaKind}, "", kafkaClusterName, kubectlArgGoTemplateInternalListenersName, ) + + Expect(err).ShouldNot(HaveOccurred()) Expect(internalListenerNames).ShouldNot(BeEmpty()) - internalListenerAddresses := getK8sResources(kubectlOptions, - []string{"kafkacluster"}, + internalListenerAddresses, err := getK8sResources(kubectlOptions, + []string{kafkaKind}, "", kafkaClusterName, fmt.Sprintf(kubectlArgGoTemplateInternalListenerAddressesTemplate, internalListenerNames[0]), ) + Expect(err).ShouldNot(HaveOccurred()) + Expect(internalListenerAddresses).ShouldNot(BeEmpty()) internalAddress = internalListenerAddresses[0] diff --git a/tests/e2e/produce_consume_test.go b/tests/e2e/produce_consume_test.go new file mode 100644 index 000000000..b2ba7c73e --- /dev/null +++ b/tests/e2e/produce_consume_test.go @@ -0,0 +1,27 @@ +package e2e + +import ( + "github.com/gruntwork-io/terratest/modules/k8s" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func testProduceConsumeInternal() bool { + return When("Internally produce and consume message to/from Kafka cluster", func() { + var kubectlOptions k8s.KubectlOptions + var err error + + It("Acquiring K8s config and context", func() { + kubectlOptions, err = kubectlOptionsForCurrentContext() + Expect(err).NotTo(HaveOccurred()) + }) + + kubectlOptions.Namespace = koperatorLocalHelmDescriptor.Namespace + + requireDeployingKcatPod(kubectlOptions, kcatPodName) + requireDeployingKafkaTopic(kubectlOptions, testTopicName) + requireInternalProducingConsumingMessage(kubectlOptions, "", kcatPodName, testTopicName) + requireDeleteKafkaTopic(kubectlOptions, testTopicName) + requireDeleteKcatPod(kubectlOptions, kcatPodName) + }) +} diff --git a/tests/e2e/prometheus_test.go b/tests/e2e/prometheus_test.go deleted file mode 100644 index 584ad97a2..000000000 --- a/tests/e2e/prometheus_test.go +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright © 2023 Cisco Systems, Inc. and/or its affiliates -// -// 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" - - "github.com/gruntwork-io/terratest/modules/k8s" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" -) - -// requireInstallingPrometheusOperator deploys prometheus-operator Helm chart -// and checks the success of that operation. -func requireInstallingPrometheusOperator(kubectlOptions *k8s.KubectlOptions, prometheusOperatorVersion Version) { - When("Installing prometheus-operator", func() { - requireInstallingPrometheusOperatorHelmChartIfDoesNotExist(kubectlOptions, prometheusOperatorVersion) - }) -} - -// requireDeployingCertManagerHelmChart checks the existence of the cert-manager -// Helm release and installs it if it's not present. -func requireInstallingPrometheusOperatorHelmChartIfDoesNotExist( - kubectlOptions *k8s.KubectlOptions, - prometheusOperatorVersion Version, -) { - It("Installing prometheus-operator Helm chart", func() { - installHelmChartIfDoesNotExist( - kubectlOptions, - "https://prometheus-community.github.io/helm-charts", - "kube-prometheus-stack", - prometheusOperatorVersion, - "prometheus-operator", - map[string]string{ - "prometheusOperator.createCustomResource": "true", - "defaultRules.enabled": "false", - "alertmanager.enabled": "false", - "grafana.enabled": "false", - "kubeApiServer.enabled": "false", - "kubelet.enabled": "false", - "kubeControllerManager.enabled": "false", - "coreDNS.enabled": "false", - "kubeEtcd.enabled": "false", - "kubeScheduler.enabled": "false", - "kubeProxy.enabled": "false", - "kubeStateMetrics.enabled": "false", - "nodeExporter.enabled": "false", - "prometheus.enabled": "false", - }, - ) - - By("Verifying prometheus-operator pods") - requireRunningPods(kubectlOptions, "app", "kube-prometheus-stack-operator") - }) -} - -// requireUninstallingPrometheusOperator uninstall prometheus-operator Helm chart and -// remove CRDs. -func requireUninstallingPrometheusOperator(kubectlOptions *k8s.KubectlOptions) { - When("Uninstalling prometheus-operator", func() { - requireUninstallingPrometheusOperatorHelmChart(kubectlOptions) - requireRemovePrometheusOperatorCRDs(kubectlOptions) - }) -} - -// requireUninstallingPrometheusOperatorHelmChart uninstall prometheus-operator Helm chart -// and checks the success of that operation. -func requireUninstallingPrometheusOperatorHelmChart(kubectlOptions *k8s.KubectlOptions) { - It("Uninstalling Prometheus-operator Helm chart", func() { - uninstallHelmChartIfExists(kubectlOptions, "prometheus-operator", true) - By("Verifying Prometheus-operator helm chart resources cleanup") - - prometheusK8sResources := basicK8sCRDs() - prometheusK8sResources = append(prometheusK8sResources, prometheusCRDs()...) - - remainedResources := getK8sResources(kubectlOptions, - prometheusK8sResources, - fmt.Sprintf(managedByHelmLabelTemplate, "prometheus-operator"), - "", - kubectlArgGoTemplateKindNameNamespace, - "--all-namespaces") - Expect(remainedResources).Should(BeEmpty()) - }) -} - -// requireRemovePrometheusOperatorCRDs deletes the Prometheus-operator CRDs -func requireRemovePrometheusOperatorCRDs(kubectlOptions *k8s.KubectlOptions) { - It("Removing prometheus-operator CRDs", func() { - for _, crd := range prometheusCRDs() { - deleteK8sResourceGlobalNoErrNotFound(kubectlOptions, defaultDeletionTimeout, "crds", crd) - } - }) -} diff --git a/tests/e2e/test_install.go b/tests/e2e/test_install.go index d19f5d3cb..185065644 100644 --- a/tests/e2e/test_install.go +++ b/tests/e2e/test_install.go @@ -20,10 +20,8 @@ import ( . "github.com/onsi/gomega" ) -var _ = testInstall() - func testInstall() bool { - return When("Installing Koperator", Ordered, func() { + return When("Installing Koperator and dependencies", Ordered, func() { var kubectlOptions k8s.KubectlOptions var err error diff --git a/tests/e2e/test_test.go b/tests/e2e/test_test.go new file mode 100644 index 000000000..6e73c1547 --- /dev/null +++ b/tests/e2e/test_test.go @@ -0,0 +1,27 @@ +// Copyright © 2023 Cisco Systems, Inc. and/or its affiliates +// +// 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 ( + . "github.com/onsi/ginkgo/v2" +) + +var _ = When("Testing e2e", Ordered, func() { + //testInstall() + testProduceConsumeInternal() + testUninstallZookeeperCluster() + testUninstallKafkaCluster() + // testUninstall() +}) diff --git a/tests/e2e/test_uninstall.go b/tests/e2e/test_uninstall.go new file mode 100644 index 000000000..0066669e0 --- /dev/null +++ b/tests/e2e/test_uninstall.go @@ -0,0 +1,55 @@ +// Copyright © 2023 Cisco Systems, Inc. and/or its affiliates +// +// 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 ( + "github.com/gruntwork-io/terratest/modules/k8s" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func testUninstall() bool { + return When("Uninstalling Koperator and dependencies", Ordered, func() { + var kubectlOptions k8s.KubectlOptions + var err error + + It("Acquiring K8s config and context", func() { + kubectlOptions, err = kubectlOptionsForCurrentContext() + Expect(err).NotTo(HaveOccurred()) + }) + + requireUninstallingKoperator(k8s.KubectlOptions{ + ContextName: kubectlOptions.ContextName, + ConfigPath: kubectlOptions.ConfigPath, + Namespace: koperatorLocalHelmDescriptor.Namespace, + }) + requireUninstallingZookeeperOperator(k8s.KubectlOptions{ + ContextName: kubectlOptions.ContextName, + ConfigPath: kubectlOptions.ConfigPath, + Namespace: zookeeperOperatorHelmDescriptor.Namespace, + }) + requireUninstallingPrometheusOperator(k8s.KubectlOptions{ + ContextName: kubectlOptions.ContextName, + ConfigPath: kubectlOptions.ConfigPath, + Namespace: prometheusOperatorHelmDescriptor.Namespace, + }) + requireUninstallingCertManager(k8s.KubectlOptions{ + ContextName: kubectlOptions.ContextName, + ConfigPath: kubectlOptions.ConfigPath, + Namespace: certManagerHelmDescriptor.Namespace, + }) + + }) +} diff --git a/tests/e2e/uninstall.go b/tests/e2e/uninstall.go new file mode 100644 index 000000000..1a398b02f --- /dev/null +++ b/tests/e2e/uninstall.go @@ -0,0 +1,194 @@ +// Copyright © 2023 Cisco Systems, Inc. and/or its affiliates +// +// 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" + + "github.com/gruntwork-io/terratest/modules/k8s" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +// requireRemoveKoperatorCRDs deletes the koperator CRDs +func requireRemoveKoperatorCRDs(kubectlOptions k8s.KubectlOptions) { + It("Removing koperator CRDs", func() { + for _, crd := range koperatorCRDs() { + deleteK8sResourceNoErrNotFound(kubectlOptions, defaultDeletionTimeout, crdKind, crd) + } + }) +} + +// requireUninstallingKoperator uninstall koperator Helm chart and removes Koperator's CRDs. +func requireUninstallingKoperator(kubectlOptions k8s.KubectlOptions) { + When("Uninstalling Koperator", func() { + requireUninstallingKoperatorHelmChart(kubectlOptions) + requireRemoveKoperatorCRDs(kubectlOptions) + }) +} + +// requireUninstallingKoperatorHelmChart uninstall Koperator Helm chart +// and checks the success of that operation. +func requireUninstallingKoperatorHelmChart(kubectlOptions k8s.KubectlOptions) { + It("Uninstalling Koperator Helm chart", func() { + uninstallHelmChartIfExists(kubectlOptions, koperatorLocalHelmDescriptor.ReleaseName, true) + By("Verifying Koperator helm chart resources cleanup") + k8sResourceKinds, err := listK8sAllResourceKind(kubectlOptions) + Expect(err).ShouldNot(HaveOccurred()) + + koperatorAvailableResourceKinds := _stringSlicesUnion(koperatorCRDs(), k8sResourceKinds) + koperatorAvailableResourceKinds = append(koperatorAvailableResourceKinds, basicK8sResourceKinds()...) + + remainedResources, err := getK8sResources(kubectlOptions, + koperatorAvailableResourceKinds, + fmt.Sprintf(managedByHelmLabelTemplate, koperatorLocalHelmDescriptor.ReleaseName), + "", + kubectlArgGoTemplateKindNameNamespace, + "--all-namespaces") + + Expect(err).ShouldNot(HaveOccurred()) + Expect(remainedResources).Should(BeEmpty()) + }) +} + +// requireUninstallingZookeeperOperator uninstall Zookeeper-operator Helm chart +// and remove CRDs. +func requireUninstallingZookeeperOperator(kubectlOptions k8s.KubectlOptions) { + When("Uninstalling zookeeper-operator", func() { + requireUninstallingZookeeperOperatorHelmChart(kubectlOptions) + requireRemoveZookeeperOperatorCRDs(kubectlOptions) + }) +} + +// requireUninstallingZookeeperOperatorHelmChart uninstall Zookeeper-operator Helm chart +// and checks the success of that operation. +func requireUninstallingZookeeperOperatorHelmChart(kubectlOptions k8s.KubectlOptions) { + It("Uninstalling zookeeper-operator Helm chart", func() { + uninstallHelmChartIfExists(kubectlOptions, zookeeperOperatorHelmDescriptor.ReleaseName, true) + By("Verifying Zookeeper-operator helm chart resources cleanup") + + k8sResourceKinds, err := listK8sAllResourceKind(kubectlOptions) + Expect(err).ShouldNot(HaveOccurred()) + + zookeeperAvailableResourceKinds := _stringSlicesUnion(zookeeperCRDs(), k8sResourceKinds) + zookeeperAvailableResourceKinds = append(zookeeperAvailableResourceKinds, basicK8sResourceKinds()...) + + remainedResources, err := getK8sResources(kubectlOptions, + zookeeperAvailableResourceKinds, + fmt.Sprintf(managedByHelmLabelTemplate, zookeeperOperatorHelmDescriptor.ReleaseName), + "", + kubectlArgGoTemplateKindNameNamespace, + "--all-namespaces") + Expect(err).ShouldNot(HaveOccurred()) + + Expect(remainedResources).Should(BeEmpty()) + }) +} + +// requireRemoveZookeeperOperatorCRDs deletes the zookeeper-operator CRDs +func requireRemoveZookeeperOperatorCRDs(kubectlOptions k8s.KubectlOptions) { + It("Removing zookeeper-operator CRDs", func() { + for _, crd := range zookeeperCRDs() { + deleteK8sResourceNoErrNotFound(kubectlOptions, defaultDeletionTimeout, crdKind, crd) + } + }) +} + +// requireUninstallingPrometheusOperator uninstall prometheus-operator Helm chart and +// remove CRDs. +func requireUninstallingPrometheusOperator(kubectlOptions k8s.KubectlOptions) { + When("Uninstalling prometheus-operator", func() { + requireUninstallingPrometheusOperatorHelmChart(kubectlOptions) + requireRemovePrometheusOperatorCRDs(kubectlOptions) + }) +} + +// requireUninstallingPrometheusOperatorHelmChart uninstall prometheus-operator Helm chart +// and checks the success of that operation. +func requireUninstallingPrometheusOperatorHelmChart(kubectlOptions k8s.KubectlOptions) { + It("Uninstalling Prometheus-operator Helm chart", func() { + uninstallHelmChartIfExists(kubectlOptions, "prometheus-operator", true) + By("Verifying Prometheus-operator helm chart resources cleanup") + + k8sResourceKinds, err := listK8sAllResourceKind(kubectlOptions) + Expect(err).ShouldNot(HaveOccurred()) + + prometheusAvailableResourceKinds := _stringSlicesUnion(prometheusCRDs(), k8sResourceKinds) + prometheusAvailableResourceKinds = append(prometheusAvailableResourceKinds, basicK8sResourceKinds()...) + + remainedResources, err := getK8sResources(kubectlOptions, + prometheusAvailableResourceKinds, + fmt.Sprintf(managedByHelmLabelTemplate, prometheusOperatorHelmDescriptor.ReleaseName), + "", + kubectlArgGoTemplateKindNameNamespace, + "--all-namespaces") + Expect(err).ShouldNot(HaveOccurred()) + + Expect(remainedResources).Should(BeEmpty()) + }) +} + +// requireRemovePrometheusOperatorCRDs deletes the Prometheus-operator CRDs +func requireRemovePrometheusOperatorCRDs(kubectlOptions k8s.KubectlOptions) { + It("Removing prometheus-operator CRDs", func() { + for _, crd := range prometheusCRDs() { + deleteK8sResourceNoErrNotFound(kubectlOptions, defaultDeletionTimeout, crdKind, crd) + } + }) +} + +// requireUninstallingCertManager uninstall Cert-manager Helm chart and +// remove CRDs. +func requireUninstallingCertManager(kubectlOptions k8s.KubectlOptions) { + When("Uninstalling zookeeper-operator", func() { + requireUninstallingCertManagerHelmChart(kubectlOptions) + requireRemoveCertManagerCRDs(kubectlOptions) + }) +} + +// requireUninstallingCertManagerHelmChart uninstalls cert-manager helm chart +// and checks the success of that operation. +func requireUninstallingCertManagerHelmChart(kubectlOptions k8s.KubectlOptions) { + It("Uninstalling Cert-manager Helm chart", func() { + uninstallHelmChartIfExists(kubectlOptions, certManagerHelmDescriptor.ReleaseName, true) + By("Verifying Cert-manager helm chart resources cleanup") + + k8sResourceKinds, err := listK8sAllResourceKind(kubectlOptions) + Expect(err).ShouldNot(HaveOccurred()) + + certManagerAvailableResourceKinds := _stringSlicesUnion(certManagerCRDs(), k8sResourceKinds) + certManagerAvailableResourceKinds = append(certManagerAvailableResourceKinds, basicK8sResourceKinds()...) + + remainedResources, err := getK8sResources(kubectlOptions, + certManagerAvailableResourceKinds, + fmt.Sprintf(managedByHelmLabelTemplate, certManagerHelmDescriptor.ReleaseName), + "", + kubectlArgGoTemplateKindNameNamespace, + "--all-namespaces") + Expect(err).ShouldNot(HaveOccurred()) + + Expect(remainedResources).Should(BeEmpty()) + }) + +} + +// requireRemoveKoperatorCRDs deletes the cert-manager CRDs +func requireRemoveCertManagerCRDs(kubectlOptions k8s.KubectlOptions) { + It("Removing cert-manager CRDs", func() { + for _, crd := range certManagerCRDs() { + deleteK8sResourceNoErrNotFound(kubectlOptions, defaultDeletionTimeout, crdKind, crd) + } + }) +} diff --git a/tests/e2e/uninstall_cluster.go b/tests/e2e/uninstall_cluster.go new file mode 100644 index 000000000..e88eecc3d --- /dev/null +++ b/tests/e2e/uninstall_cluster.go @@ -0,0 +1,77 @@ +// Copyright © 2023 Cisco Systems, Inc. and/or its affiliates +// +// 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" + "time" + + koperator_v1beta1 "github.com/banzaicloud/koperator/api/v1beta1" + + "github.com/gruntwork-io/terratest/modules/k8s" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +// requireDeleteKafkaCluster deletes KafkaCluster resource and +// checks the removal of the Kafka cluster related resources +func requireDeleteKafkaCluster(kubectlOptions k8s.KubectlOptions, name string) { + It("Delete KafkaCluster custom resource", func() { + err := deleteK8sResourceNoErrNotFound(kubectlOptions, defaultDeletionTimeout, kafkaKind, koperatorLocalHelmDescriptor.Namespace) + Expect(err).ShouldNot(HaveOccurred()) + Eventually(context.Background(), func() []string { + By("Verifying the Kafka cluster resource cleanup") + + // Check only those Koperator related resource types we have in K8s (istio usecase) + k8sResourceKinds, err := listK8sAllResourceKind(kubectlOptions) + Expect(err).ShouldNot(HaveOccurred()) + + koperatorAvailableResourceKinds := _stringSlicesUnion(getKoperatorRelatedResourceKinds(), k8sResourceKinds) + koperatorAvailableResourceKinds = append(koperatorAvailableResourceKinds, basicK8sResourceKinds()...) + + resources, err := getK8sResources(kubectlOptions, + koperatorAvailableResourceKinds, + fmt.Sprintf("%s=%s", koperator_v1beta1.KafkaCRLabelKey, name), + "", + "--all-namespaces", kubectlArgGoTemplateKindNameNamespace) + Expect(err).ShouldNot(HaveOccurred()) + + return resources + }, kafkaClusterResourceCleanupTimeout, 1*time.Second).Should(BeEmpty()) + }) +} + +// requireDeleteZookeeperCluster deletes the ZookeeperCluster CR and verify the corresponding resources cleanup +func requireDeleteZookeeperCluster(kubectlOptions k8s.KubectlOptions, name string) { + It("Delete ZookeeperCluster custom resource", func() { + deleteK8sResourceNoErrNotFound(kubectlOptions, defaultDeletionTimeout, zookeeperKind, name) + Eventually(context.Background(), func() []string { + By("Verifying the Zookeeper cluster resource cleanup") + + zookeeperK8sResources := basicK8sResourceKinds() + zookeeperK8sResources = append(zookeeperK8sResources, zookeeperCRDs()...) + + resources, err := getK8sResources(kubectlOptions, + zookeeperK8sResources, + fmt.Sprintf("app=%s", name), + "", + "--all-namespaces", kubectlArgGoTemplateKindNameNamespace) + Expect(err).ShouldNot(HaveOccurred()) + return resources + + }, zookeeperClusterResourceCleanupTimeout, 1*time.Second).Should(BeEmpty()) + }) +} diff --git a/tests/e2e/uninstall_cluster_test.go b/tests/e2e/uninstall_cluster_test.go new file mode 100644 index 000000000..78d71aad1 --- /dev/null +++ b/tests/e2e/uninstall_cluster_test.go @@ -0,0 +1,52 @@ +// Copyright © 2023 Cisco Systems, Inc. and/or its affiliates +// +// 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 ( + "github.com/gruntwork-io/terratest/modules/k8s" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func testUninstallZookeeperCluster() bool { + return When("Uninstalling Zookeeper cluster", func() { + var kubectlOptions k8s.KubectlOptions + var err error + + It("Acquiring K8s config and context", func() { + kubectlOptions, err = kubectlOptionsForCurrentContext() + Expect(err).NotTo(HaveOccurred()) + }) + + kubectlOptions.Namespace = zookeeperOperatorHelmDescriptor.Namespace + requireDeleteZookeeperCluster(kubectlOptions, zookeeperClusterName) + + }) +} + +func testUninstallKafkaCluster() bool { + return When("Uninstalling Kafka cluster", func() { + var kubectlOptions k8s.KubectlOptions + var err error + + It("Acquiring K8s config and context", func() { + kubectlOptions, err = kubectlOptionsForCurrentContext() + Expect(err).NotTo(HaveOccurred()) + }) + + kubectlOptions.Namespace = koperatorLocalHelmDescriptor.Namespace + requireDeleteKafkaCluster(kubectlOptions, kafkaClusterName) + }) +} diff --git a/tests/e2e/utils.go b/tests/e2e/utils.go index 7440b4b2d..e57bb13d1 100644 --- a/tests/e2e/utils.go +++ b/tests/e2e/utils.go @@ -20,6 +20,10 @@ import ( "strings" ) +const ( + kubectlNotFoundErrorMsg = "NotFound" +) + // Returns the union of the slices from argument. func _stringSlicesUnion(sliceA, sliceB []string) []string { if len(sliceA) == 0 || len(sliceB) == 0 { @@ -59,6 +63,7 @@ func _kubectlArgExtender(args []string, logMsg, selector, names, namespace strin } if len(extraArgs) != 0 { logMsg = fmt.Sprintf("%s extraArgs: '%s'", logMsg, extraArgs) + args = append(args, extraArgs...) } return logMsg, args } diff --git a/tests/e2e/zookeeper_test.go b/tests/e2e/zookeeper_test.go deleted file mode 100644 index 94bc2ba02..000000000 --- a/tests/e2e/zookeeper_test.go +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright © 2023 Cisco Systems, Inc. and/or its affiliates -// -// 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" - "time" - - "github.com/gruntwork-io/terratest/modules/k8s" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" -) - -// requireInstallingZookeeperOperator deploys zookeeper-operator Helm chart and -// checks the success of that operation. -func requireInstallingZookeeperOperator(kubectlOptions *k8s.KubectlOptions, certManagerVersion string) { - When("Installing zookeeper-operator", func() { - requireInstallingZookeeperOperatorHelmChartIfDoesNotExist(kubectlOptions, certManagerVersion) - }) -} - -// requireDeployingCertManagerHelmChart checks the existence of the cert-manager -// Helm release and installs it if it's not present. -func requireInstallingZookeeperOperatorHelmChartIfDoesNotExist( - kubectlOptions *k8s.KubectlOptions, - zookeeperOperatorVersion string, -) { - It("Installing zookeeper-operator Helm chart", func() { - installHelmChartIfDoesNotExist( - kubectlOptions, - "https://charts.pravega.io", - "zookeeper-operator", - zookeeperOperatorVersion, - "zookeeper-operator", - nil, - ) - - By("Verifying zookeeper-operator pods") - requireRunningPods(kubectlOptions, "name", "zookeeper-operator") - }) -} - -// requireUninstallingZookeeperOperator uninstall Zookeeper-operator Helm chart -// and remove CRDs. -func requireUninstallingZookeeperOperator(kubectlOptions *k8s.KubectlOptions) { - When("Uninstalling zookeeper-operator", func() { - requireUninstallingZookeeperOperatorHelmChart(kubectlOptions) - requireRemoveZookeeperOperatorCRDs(kubectlOptions) - }) -} - -// requireUninstallingZookeeperOperatorHelmChart uninstall Zookeeper-operator Helm chart -// and checks the success of that operation. -func requireUninstallingZookeeperOperatorHelmChart(kubectlOptions *k8s.KubectlOptions) { - It("Uninstalling zookeeper-operator Helm chart", func() { - uninstallHelmChartIfExists(kubectlOptions, "zookeeper-operator", true) - By("Verifying Zookeeper-operator helm chart resources cleanup") - k8sCRDs := listK8sAllResourceType(kubectlOptions) - remainedResources := getK8sResources(kubectlOptions, - k8sCRDs, - fmt.Sprintf(managedByHelmLabelTemplate, "zookeeper-operator"), - "", - kubectlArgGoTemplateKindNameNamespace, - "--all-namespaces") - Expect(remainedResources).Should(BeEmpty()) - }) -} - -// requireRemoveZookeeperOperatorCRDs deletes the zookeeper-operator CRDs -func requireRemoveZookeeperOperatorCRDs(kubectlOptions *k8s.KubectlOptions) { - It("Removing zookeeper-operator CRDs", func() { - for _, crd := range zookeeperCRDs() { - deleteK8sResourceGlobalNoErrNotFound(kubectlOptions, defaultDeletionTimeout, "crds", crd) - } - }) -} - -// requireUninstallZookeeperCluster uninstall the Zookeeper cluster -func requireUninstallZookeeperCluster(kubectlOptions *k8s.KubectlOptions, name string) { - When("Uninstalling Zookeeper cluster", func() { - requireDeleteZookeeperCluster(kubectlOptions, name) - - }) -} - -// requireDeleteZookeeperCluster deletes the ZookeeperCluster CR and verify the corresponding resources cleanup -func requireDeleteZookeeperCluster(kubectlOptions *k8s.KubectlOptions, name string) { - It("Delete ZookeeperCluster custom resource", func() { - deleteK8sResourceGlobalNoErrNotFound(kubectlOptions, defaultDeletionTimeout, zookeeperKind, name) - Eventually(context.Background(), func() []string { - By("Verifying the Zookeeper cluster resource cleanup") - - zookeeperK8sResources := basicK8sCRDs() - zookeeperK8sResources = append(zookeeperK8sResources, zookeeperCRDs()...) - - return getK8sResources(kubectlOptions, - zookeeperK8sResources, - fmt.Sprintf("app=%s", name), - "", - "--all-namespaces", kubectlArgGoTemplateKindNameNamespace) - }, zookeeperClusterResourceCleanupTimeout, 3*time.Millisecond).Should(BeEmpty()) - }) -} From b796dcd5f42c9a960d4469b56e8aa8fe8c27af51 Mon Sep 17 00:00:00 2001 From: marbarta Date: Wed, 14 Jun 2023 17:34:32 +0200 Subject: [PATCH 05/24] fix based on review Panyuenlau --- Makefile | 2 +- tests/e2e/helm.go | 4 ++-- tests/e2e/k8s.go | 8 ++++---- tests/e2e/uninstall.go | 8 ++++---- tests/e2e/uninstall_cluster.go | 2 +- tests/e2e/utils.go | 6 +++--- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Makefile b/Makefile index 9a588bc61..3b613d7ff 100644 --- a/Makefile +++ b/Makefile @@ -103,7 +103,7 @@ test-e2e: go test github.com/banzaicloud/koperator/tests/e2e \ -v \ -timeout 15m \ - --ginkgo.fail-fast \ + -tags e2e \ --ginkgo.show-node-events \ --ginkgo.trace \ --ginkgo.v diff --git a/tests/e2e/helm.go b/tests/e2e/helm.go index f97c0c4f7..f9424ca4f 100644 --- a/tests/e2e/helm.go +++ b/tests/e2e/helm.go @@ -74,7 +74,7 @@ func (helmDescriptor *helmDescriptor) crdPath() (string, error) { //nolint:unuse // installHelmChart checks whether the specified named Helm release exists in // the provided kubectl context and namespace, logs it if it does and returns or // alternatively deploys a Helm chart to the specified kubectl context and -// namespace using the specified infos, extra arguments can be any of the helm +// namespace using the specified info, extra arguments can be any of the helm // CLI install flag arguments, flag keys and values must be provided separately. func (helmDescriptor *helmDescriptor) installHelmChart(kubectlOptions k8s.KubectlOptions) error { if helmDescriptor == nil { @@ -340,7 +340,7 @@ func uninstallHelmChartIfExists( purge bool, extraArgs ...string, ) error { - By(fmt.Sprintf("Checking for existing Helm release names %s", helmReleaseName)) + By(fmt.Sprintf("Checking for existing Helm release name %s", helmReleaseName)) _, isInstalled, err := lookUpInstalledHelmReleaseByName(kubectlOptions, helmReleaseName) if err != nil { return err diff --git a/tests/e2e/k8s.go b/tests/e2e/k8s.go index 4dd00febc..6b52a6d69 100644 --- a/tests/e2e/k8s.go +++ b/tests/e2e/k8s.go @@ -412,7 +412,7 @@ func deleteK8sResource( args = append(args, fmt.Sprintf("--timeout=%s", timeout)) logMsg := fmt.Sprintf("Deleting k8s resource: kind: '%s' ", kind) - logMsg, args = _kubectlArgExtender(args, logMsg, selector, name, kubectlOptions.Namespace, extraArgs) + logMsg, args = kubectlArgExtender(args, logMsg, selector, name, kubectlOptions.Namespace, extraArgs) By(logMsg) _, err := k8s.RunKubectlAndGetOutputE( @@ -430,7 +430,7 @@ func deleteK8sResource( // extraArgs can be any of the kubectl arguments. func deleteK8sResourceNoErrNotFound(kubectlOptions k8s.KubectlOptions, timeout time.Duration, kind string, name string, extraArgs ...string) error { err := deleteK8sResource(kubectlOptions, timeout, kind, "", name, extraArgs...) - if _isNotFoundError(err) { + if isKubectlNotFoundError(err) { By("Resource not found") return nil } @@ -497,7 +497,7 @@ func getK8sResources(kubectlOptions k8s.KubectlOptions, resourceKind []string, s logMsg := fmt.Sprintf("Get K8S resources: '%s'", resourceKind) args := []string{"get", strings.Join(resourceKind, ",")} - logMsg, args = _kubectlArgExtender(args, logMsg, selector, names, kubectlOptions.Namespace, extraArgs) + logMsg, args = kubectlArgExtender(args, logMsg, selector, names, kubectlOptions.Namespace, extraArgs) By(logMsg) output, err := k8s.RunKubectlAndGetOutputE( @@ -536,7 +536,7 @@ func waitK8sResourceCondition(kubectlOptions k8s.KubectlOptions, resourceKind, w fmt.Sprintf("--timeout=%s", timeout), } - logMsg, args = _kubectlArgExtender(args, logMsg, selector, names, kubectlOptions.Namespace, extraArgs) + logMsg, args = kubectlArgExtender(args, logMsg, selector, names, kubectlOptions.Namespace, extraArgs) By(logMsg) _, err := k8s.RunKubectlAndGetOutputE( diff --git a/tests/e2e/uninstall.go b/tests/e2e/uninstall.go index 1a398b02f..1af8ee85b 100644 --- a/tests/e2e/uninstall.go +++ b/tests/e2e/uninstall.go @@ -48,7 +48,7 @@ func requireUninstallingKoperatorHelmChart(kubectlOptions k8s.KubectlOptions) { k8sResourceKinds, err := listK8sAllResourceKind(kubectlOptions) Expect(err).ShouldNot(HaveOccurred()) - koperatorAvailableResourceKinds := _stringSlicesUnion(koperatorCRDs(), k8sResourceKinds) + koperatorAvailableResourceKinds := stringSlicesUnion(koperatorCRDs(), k8sResourceKinds) koperatorAvailableResourceKinds = append(koperatorAvailableResourceKinds, basicK8sResourceKinds()...) remainedResources, err := getK8sResources(kubectlOptions, @@ -82,7 +82,7 @@ func requireUninstallingZookeeperOperatorHelmChart(kubectlOptions k8s.KubectlOpt k8sResourceKinds, err := listK8sAllResourceKind(kubectlOptions) Expect(err).ShouldNot(HaveOccurred()) - zookeeperAvailableResourceKinds := _stringSlicesUnion(zookeeperCRDs(), k8sResourceKinds) + zookeeperAvailableResourceKinds := stringSlicesUnion(zookeeperCRDs(), k8sResourceKinds) zookeeperAvailableResourceKinds = append(zookeeperAvailableResourceKinds, basicK8sResourceKinds()...) remainedResources, err := getK8sResources(kubectlOptions, @@ -125,7 +125,7 @@ func requireUninstallingPrometheusOperatorHelmChart(kubectlOptions k8s.KubectlOp k8sResourceKinds, err := listK8sAllResourceKind(kubectlOptions) Expect(err).ShouldNot(HaveOccurred()) - prometheusAvailableResourceKinds := _stringSlicesUnion(prometheusCRDs(), k8sResourceKinds) + prometheusAvailableResourceKinds := stringSlicesUnion(prometheusCRDs(), k8sResourceKinds) prometheusAvailableResourceKinds = append(prometheusAvailableResourceKinds, basicK8sResourceKinds()...) remainedResources, err := getK8sResources(kubectlOptions, @@ -168,7 +168,7 @@ func requireUninstallingCertManagerHelmChart(kubectlOptions k8s.KubectlOptions) k8sResourceKinds, err := listK8sAllResourceKind(kubectlOptions) Expect(err).ShouldNot(HaveOccurred()) - certManagerAvailableResourceKinds := _stringSlicesUnion(certManagerCRDs(), k8sResourceKinds) + certManagerAvailableResourceKinds := stringSlicesUnion(certManagerCRDs(), k8sResourceKinds) certManagerAvailableResourceKinds = append(certManagerAvailableResourceKinds, basicK8sResourceKinds()...) remainedResources, err := getK8sResources(kubectlOptions, diff --git a/tests/e2e/uninstall_cluster.go b/tests/e2e/uninstall_cluster.go index e88eecc3d..47c280c34 100644 --- a/tests/e2e/uninstall_cluster.go +++ b/tests/e2e/uninstall_cluster.go @@ -39,7 +39,7 @@ func requireDeleteKafkaCluster(kubectlOptions k8s.KubectlOptions, name string) { k8sResourceKinds, err := listK8sAllResourceKind(kubectlOptions) Expect(err).ShouldNot(HaveOccurred()) - koperatorAvailableResourceKinds := _stringSlicesUnion(getKoperatorRelatedResourceKinds(), k8sResourceKinds) + koperatorAvailableResourceKinds := stringSlicesUnion(getKoperatorRelatedResourceKinds(), k8sResourceKinds) koperatorAvailableResourceKinds = append(koperatorAvailableResourceKinds, basicK8sResourceKinds()...) resources, err := getK8sResources(kubectlOptions, diff --git a/tests/e2e/utils.go b/tests/e2e/utils.go index e57bb13d1..07bc85057 100644 --- a/tests/e2e/utils.go +++ b/tests/e2e/utils.go @@ -25,7 +25,7 @@ const ( ) // Returns the union of the slices from argument. -func _stringSlicesUnion(sliceA, sliceB []string) []string { +func stringSlicesUnion(sliceA, sliceB []string) []string { if len(sliceA) == 0 || len(sliceB) == 0 { return nil } @@ -50,7 +50,7 @@ func _stringSlicesUnion(sliceA, sliceB []string) []string { return union } -func _kubectlArgExtender(args []string, logMsg, selector, names, namespace string, extraArgs []string) (string, []string) { +func kubectlArgExtender(args []string, logMsg, selector, names, namespace string, extraArgs []string) (string, []string) { if selector != "" { logMsg = fmt.Sprintf("%s selector: '%s'", logMsg, selector) args = append(args, fmt.Sprintf("--selector=%s", selector)) @@ -80,6 +80,6 @@ func _kubectlRemoveWarnings(outputSlice []string) []string { return result } -func _isNotFoundError(err error) bool { +func isKubectlNotFoundError(err error) bool { return err != nil && strings.Contains(err.Error(), kubectlNotFoundErrorMsg) } From 9d78d961a4ed91cb0698ac9d90205c738d5c4778 Mon Sep 17 00:00:00 2001 From: marbarta Date: Wed, 14 Jun 2023 17:36:54 +0200 Subject: [PATCH 06/24] fix: _kubectlRemoveWarnings --- tests/e2e/k8s.go | 4 ++-- tests/e2e/utils.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/e2e/k8s.go b/tests/e2e/k8s.go index 6b52a6d69..1e5565c9a 100644 --- a/tests/e2e/k8s.go +++ b/tests/e2e/k8s.go @@ -487,7 +487,7 @@ func listK8sAllResourceKind(kubectlOptions k8s.KubectlOptions) ([]string, error) return nil, err } - return _kubectlRemoveWarnings(strings.Split(output, "\n")), nil + return kubectlRemoveWarnings(strings.Split(output, "\n")), nil } // getK8sResources gets the specified K8S resources from the specified kubectl context and @@ -521,7 +521,7 @@ func getK8sResources(kubectlOptions k8s.KubectlOptions, resourceKind []string, s // Remove warning message pollution from the output - return _kubectlRemoveWarnings(outputSlice), nil + return kubectlRemoveWarnings(outputSlice), nil } // waitK8sResourceCondition waits until the condition is met or the timeout is elapsed for the selected K8s resource(s) diff --git a/tests/e2e/utils.go b/tests/e2e/utils.go index 07bc85057..440751f2d 100644 --- a/tests/e2e/utils.go +++ b/tests/e2e/utils.go @@ -69,7 +69,7 @@ func kubectlArgExtender(args []string, logMsg, selector, names, namespace string } // _kubectlRemoveWarning removes those elements from the outputSlice parameter which contains kubectl warning message. -func _kubectlRemoveWarnings(outputSlice []string) []string { +func kubectlRemoveWarnings(outputSlice []string) []string { // Remove warning message pollution from the output result := make([]string, 0, len(outputSlice)) for i := range outputSlice { From 2cd5d0d68d68fb96375131e84e3ceff8e51decfb Mon Sep 17 00:00:00 2001 From: marbarta Date: Thu, 15 Jun 2023 07:05:06 +0200 Subject: [PATCH 07/24] add: description for utils --- tests/e2e/utils.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/e2e/utils.go b/tests/e2e/utils.go index 440751f2d..fcc8dd805 100644 --- a/tests/e2e/utils.go +++ b/tests/e2e/utils.go @@ -24,7 +24,7 @@ const ( kubectlNotFoundErrorMsg = "NotFound" ) -// Returns the union of the slices from argument. +// stringSlicesUnion returns the union of the slices from argument. func stringSlicesUnion(sliceA, sliceB []string) []string { if len(sliceA) == 0 || len(sliceB) == 0 { return nil @@ -50,6 +50,7 @@ func stringSlicesUnion(sliceA, sliceB []string) []string { return union } +// kubectlArgExtender extends the kubectl arguments and log message based on the parameters func kubectlArgExtender(args []string, logMsg, selector, names, namespace string, extraArgs []string) (string, []string) { if selector != "" { logMsg = fmt.Sprintf("%s selector: '%s'", logMsg, selector) @@ -68,7 +69,7 @@ func kubectlArgExtender(args []string, logMsg, selector, names, namespace string return logMsg, args } -// _kubectlRemoveWarning removes those elements from the outputSlice parameter which contains kubectl warning message. +// kubectlRemoveWarning removes those elements from the outputSlice parameter which contains kubectl warning message. func kubectlRemoveWarnings(outputSlice []string) []string { // Remove warning message pollution from the output result := make([]string, 0, len(outputSlice)) From 5dd0266892593f90241d4472a14cc3efab5fe5bf Mon Sep 17 00:00:00 2001 From: marbarta Date: Fri, 16 Jun 2023 03:31:27 +0200 Subject: [PATCH 08/24] refactor filenames and utils --- tests/e2e/const.go | 2 + tests/e2e/helm.go | 4 +- tests/e2e/k8s.go | 35 ++++++++++++++++ ..._suite_test.go => test_koperator_suite.go} | 9 ++++ ...onsume_test.go => test_produce_consume.go} | 0 tests/e2e/test_test.go | 27 ------------ ...ster_test.go => test_uninstall_cluster.go} | 0 tests/e2e/utils.go | 41 ------------------- 8 files changed, 48 insertions(+), 70 deletions(-) rename tests/e2e/{koperator_suite_test.go => test_koperator_suite.go} (86%) rename tests/e2e/{produce_consume_test.go => test_produce_consume.go} (100%) delete mode 100644 tests/e2e/test_test.go rename tests/e2e/{uninstall_cluster_test.go => test_uninstall_cluster.go} (100%) diff --git a/tests/e2e/const.go b/tests/e2e/const.go index 79d570f06..9a9f38e31 100644 --- a/tests/e2e/const.go +++ b/tests/e2e/const.go @@ -136,6 +136,8 @@ const ( kcatPodTemplate = "templates/kcat.yaml.tmpl" kafkaTopicTemplate = "templates/topic.yaml.tmpl" + + kubectlNotFoundErrorMsg = "NotFound" ) func basicK8sResourceKinds() []string { diff --git a/tests/e2e/helm.go b/tests/e2e/helm.go index f9424ca4f..aec45b719 100644 --- a/tests/e2e/helm.go +++ b/tests/e2e/helm.go @@ -293,9 +293,9 @@ func lookUpInstalledHelmReleaseByName( return nil, false, nil } -// uninstallHelmChart uninstall Helm chart from the specified kubectl context and +// uninstallHelmChart uninstalls a Helm chart from the specified kubectl context and // namespace using the specified helm release name. When purge is true, it removes records -// and make that name free to be reused for another installation. +// and makes that name free to be reused for another installation. // Extra arguments can be any of the helm CLI uninstall flag arguments. func uninstallHelmChart( kubectlOptions k8s.KubectlOptions, diff --git a/tests/e2e/k8s.go b/tests/e2e/k8s.go index 1e5565c9a..3d7b2654b 100644 --- a/tests/e2e/k8s.go +++ b/tests/e2e/k8s.go @@ -547,3 +547,38 @@ func waitK8sResourceCondition(kubectlOptions k8s.KubectlOptions, resourceKind, w return err } + +// kubectlArgExtender extends the kubectl arguments and log message based on the parameters +func kubectlArgExtender(args []string, logMsg, selector, names, namespace string, extraArgs []string) (string, []string) { + if selector != "" { + logMsg = fmt.Sprintf("%s selector: '%s'", logMsg, selector) + args = append(args, fmt.Sprintf("--selector=%s", selector)) + } else if names != "" { + logMsg = fmt.Sprintf("%s name(s): '%s'", logMsg, names) + args = append(args, names) + } + if namespace != "" { + logMsg = fmt.Sprintf("%s namespace: '%s'", logMsg, namespace) + } + if len(extraArgs) != 0 { + logMsg = fmt.Sprintf("%s extraArgs: '%s'", logMsg, extraArgs) + args = append(args, extraArgs...) + } + return logMsg, args +} + +// kubectlRemoveWarning removes those elements from the outputSlice parameter which contains kubectl warning message. +func kubectlRemoveWarnings(outputSlice []string) []string { + // Remove warning message pollution from the output + result := make([]string, 0, len(outputSlice)) + for i := range outputSlice { + if !strings.Contains(outputSlice[i], "Warning:") { + result = append(result, outputSlice[i]) + } + } + return result +} + +func isKubectlNotFoundError(err error) bool { + return err != nil && strings.Contains(err.Error(), kubectlNotFoundErrorMsg) +} diff --git a/tests/e2e/koperator_suite_test.go b/tests/e2e/test_koperator_suite.go similarity index 86% rename from tests/e2e/koperator_suite_test.go rename to tests/e2e/test_koperator_suite.go index dcc89263c..f9981eddc 100644 --- a/tests/e2e/koperator_suite_test.go +++ b/tests/e2e/test_koperator_suite.go @@ -50,3 +50,12 @@ var _ = BeforeSuite(func() { Expect(len(pods)).To(Not(BeZero())) }) }) + +var _ = When("Testing e2e test altogether", Ordered, func() { + //testInstall() + //testProduceConsumeInternal() + testProduceConsumeExternal() + // testUninstallZookeeperCluster() + // testUninstallKafkaCluster() + // testUninstall() +}) diff --git a/tests/e2e/produce_consume_test.go b/tests/e2e/test_produce_consume.go similarity index 100% rename from tests/e2e/produce_consume_test.go rename to tests/e2e/test_produce_consume.go diff --git a/tests/e2e/test_test.go b/tests/e2e/test_test.go deleted file mode 100644 index 6e73c1547..000000000 --- a/tests/e2e/test_test.go +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright © 2023 Cisco Systems, Inc. and/or its affiliates -// -// 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 ( - . "github.com/onsi/ginkgo/v2" -) - -var _ = When("Testing e2e", Ordered, func() { - //testInstall() - testProduceConsumeInternal() - testUninstallZookeeperCluster() - testUninstallKafkaCluster() - // testUninstall() -}) diff --git a/tests/e2e/uninstall_cluster_test.go b/tests/e2e/test_uninstall_cluster.go similarity index 100% rename from tests/e2e/uninstall_cluster_test.go rename to tests/e2e/test_uninstall_cluster.go diff --git a/tests/e2e/utils.go b/tests/e2e/utils.go index fcc8dd805..0d72422ab 100644 --- a/tests/e2e/utils.go +++ b/tests/e2e/utils.go @@ -15,13 +15,7 @@ package e2e import ( - "fmt" "sort" - "strings" -) - -const ( - kubectlNotFoundErrorMsg = "NotFound" ) // stringSlicesUnion returns the union of the slices from argument. @@ -49,38 +43,3 @@ func stringSlicesUnion(sliceA, sliceB []string) []string { } return union } - -// kubectlArgExtender extends the kubectl arguments and log message based on the parameters -func kubectlArgExtender(args []string, logMsg, selector, names, namespace string, extraArgs []string) (string, []string) { - if selector != "" { - logMsg = fmt.Sprintf("%s selector: '%s'", logMsg, selector) - args = append(args, fmt.Sprintf("--selector=%s", selector)) - } else if names != "" { - logMsg = fmt.Sprintf("%s name(s): '%s'", logMsg, names) - args = append(args, names) - } - if namespace != "" { - logMsg = fmt.Sprintf("%s namespace: '%s'", logMsg, namespace) - } - if len(extraArgs) != 0 { - logMsg = fmt.Sprintf("%s extraArgs: '%s'", logMsg, extraArgs) - args = append(args, extraArgs...) - } - return logMsg, args -} - -// kubectlRemoveWarning removes those elements from the outputSlice parameter which contains kubectl warning message. -func kubectlRemoveWarnings(outputSlice []string) []string { - // Remove warning message pollution from the output - result := make([]string, 0, len(outputSlice)) - for i := range outputSlice { - if !strings.Contains(outputSlice[i], "Warning:") { - result = append(result, outputSlice[i]) - } - } - return result -} - -func isKubectlNotFoundError(err error) bool { - return err != nil && strings.Contains(err.Error(), kubectlNotFoundErrorMsg) -} From 46b2d71f546ae59d508b49f361bfdbc1e6f28753 Mon Sep 17 00:00:00 2001 From: marbarta Date: Fri, 16 Jun 2023 03:37:33 +0200 Subject: [PATCH 09/24] update: go.mod --- go.mod | 6 +++--- go.sum | 11 ++++++----- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index 801c40f83..fb9f7bcd1 100644 --- a/go.mod +++ b/go.mod @@ -86,7 +86,7 @@ require ( github.com/jcmturner/rpc/v2 v2.0.3 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.15.15 // indirect + github.com/klauspost/compress v1.16.3 // indirect github.com/mailru/easyjson v0.7.6 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.16 // indirect @@ -96,7 +96,7 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/pierrec/lz4/v4 v4.1.15 // indirect + github.com/pierrec/lz4/v4 v4.1.17 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.14.0 // indirect @@ -112,7 +112,7 @@ require ( github.com/wayneashleyberry/terminal-dimensions v1.0.0 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.6.0 // indirect - golang.org/x/crypto v0.5.0 // indirect + golang.org/x/crypto v0.7.0 // indirect golang.org/x/net v0.8.0 // indirect golang.org/x/oauth2 v0.4.0 // indirect golang.org/x/sys v0.6.0 // indirect diff --git a/go.sum b/go.sum index a4e5e6c98..cbc8c3c7a 100644 --- a/go.sum +++ b/go.sum @@ -302,8 +302,8 @@ github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8 github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= -github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw= -github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4= +github.com/klauspost/compress v1.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY= +github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= 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/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= @@ -369,8 +369,9 @@ github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE= github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg= github.com/pavlo-v-chernykh/keystore-go/v4 v4.4.1 h1:FyBdsRqqHH4LctMLL+BL2oGO+ONcIPwn96ctofCVtNE= github.com/pavlo-v-chernykh/keystore-go/v4 v4.4.1/go.mod h1:lAVhWwbNaveeJmxrxuSTxMgKpF6DjnuVpn6T8WiBwYQ= -github.com/pierrec/lz4/v4 v4.1.15 h1:MO0/ucJhngq7299dKLwIMtgTfbkoSPF6AoMYDd8Q4q0= github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pierrec/lz4/v4 v4.1.17 h1:kV4Ip+/hUBC+8T6+2EgburRtkE9ef4nbY3f4dFhGjMc= +github.com/pierrec/lz4/v4 v4.1.17/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= 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= @@ -493,8 +494,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= -golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= -golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= +golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= 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= From 16f2904c1a86effa74f198b85d6461078bd5b043 Mon Sep 17 00:00:00 2001 From: marbarta Date: Fri, 16 Jun 2023 04:35:06 +0200 Subject: [PATCH 10/24] fix: _test suffix and listAllK8sResources --- tests/e2e/k8s.go | 17 +++++++++++++---- ...perator_suite.go => koperator_suite_test.go} | 9 +++++---- tests/e2e/uninstall.go | 8 ++++---- tests/e2e/uninstall_cluster.go | 2 +- 4 files changed, 23 insertions(+), 13 deletions(-) rename tests/e2e/{test_koperator_suite.go => koperator_suite_test.go} (93%) diff --git a/tests/e2e/k8s.go b/tests/e2e/k8s.go index 3d7b2654b..c352729c1 100644 --- a/tests/e2e/k8s.go +++ b/tests/e2e/k8s.go @@ -472,11 +472,20 @@ func checkExistenceOfK8sResource( return k8s.RunKubectlE(GinkgoT(), kubectlOptions, "get", resourceKind, resourceName) } -// listK8sAllResourceKind lists all of the available resource type on the K8s cluster -func listK8sAllResourceKind(kubectlOptions k8s.KubectlOptions) ([]string, error) { - By("Listing available K8s resource kind") +// listK8sResourceKinds lists all of the available resource kinds on the K8s cluster +// with the apiGroupSelector parameter the result can be narrowed by the resource group. +// extraArgs can be any kubectl api-resources parameter. +func listK8sResourceKinds(kubectlOptions k8s.KubectlOptions, apiGroupSelector string, extraArgs ...string) ([]string, error) { + logMsg := "Listing K8s resource kind" + args := []string{"api-resources", "--verbs=list", "-o", "name", "--sort-by", "name"} + + if apiGroupSelector != "" { + logMsg = fmt.Sprintf("%s group selector: %s", logMsg, apiGroupSelector) + args = append(args, "--api-group", apiGroupSelector) + } + + args = append(args, extraArgs...) - args := []string{"api-resources", "--verbs=list", "-o", "name"} output, err := k8s.RunKubectlAndGetOutputE( GinkgoT(), &kubectlOptions, diff --git a/tests/e2e/test_koperator_suite.go b/tests/e2e/koperator_suite_test.go similarity index 93% rename from tests/e2e/test_koperator_suite.go rename to tests/e2e/koperator_suite_test.go index f9981eddc..5527a13b5 100644 --- a/tests/e2e/test_koperator_suite.go +++ b/tests/e2e/koperator_suite_test.go @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build e2e + package e2e import ( @@ -54,8 +56,7 @@ var _ = BeforeSuite(func() { var _ = When("Testing e2e test altogether", Ordered, func() { //testInstall() //testProduceConsumeInternal() - testProduceConsumeExternal() - // testUninstallZookeeperCluster() - // testUninstallKafkaCluster() - // testUninstall() + testUninstallZookeeperCluster() + testUninstallKafkaCluster() + testUninstall() }) diff --git a/tests/e2e/uninstall.go b/tests/e2e/uninstall.go index 1af8ee85b..9a385c36d 100644 --- a/tests/e2e/uninstall.go +++ b/tests/e2e/uninstall.go @@ -45,7 +45,7 @@ func requireUninstallingKoperatorHelmChart(kubectlOptions k8s.KubectlOptions) { It("Uninstalling Koperator Helm chart", func() { uninstallHelmChartIfExists(kubectlOptions, koperatorLocalHelmDescriptor.ReleaseName, true) By("Verifying Koperator helm chart resources cleanup") - k8sResourceKinds, err := listK8sAllResourceKind(kubectlOptions) + k8sResourceKinds, err := listK8sResourceKinds(kubectlOptions, "") Expect(err).ShouldNot(HaveOccurred()) koperatorAvailableResourceKinds := stringSlicesUnion(koperatorCRDs(), k8sResourceKinds) @@ -79,7 +79,7 @@ func requireUninstallingZookeeperOperatorHelmChart(kubectlOptions k8s.KubectlOpt uninstallHelmChartIfExists(kubectlOptions, zookeeperOperatorHelmDescriptor.ReleaseName, true) By("Verifying Zookeeper-operator helm chart resources cleanup") - k8sResourceKinds, err := listK8sAllResourceKind(kubectlOptions) + k8sResourceKinds, err := listK8sResourceKinds(kubectlOptions, "") Expect(err).ShouldNot(HaveOccurred()) zookeeperAvailableResourceKinds := stringSlicesUnion(zookeeperCRDs(), k8sResourceKinds) @@ -122,7 +122,7 @@ func requireUninstallingPrometheusOperatorHelmChart(kubectlOptions k8s.KubectlOp uninstallHelmChartIfExists(kubectlOptions, "prometheus-operator", true) By("Verifying Prometheus-operator helm chart resources cleanup") - k8sResourceKinds, err := listK8sAllResourceKind(kubectlOptions) + k8sResourceKinds, err := listK8sResourceKinds(kubectlOptions, "") Expect(err).ShouldNot(HaveOccurred()) prometheusAvailableResourceKinds := stringSlicesUnion(prometheusCRDs(), k8sResourceKinds) @@ -165,7 +165,7 @@ func requireUninstallingCertManagerHelmChart(kubectlOptions k8s.KubectlOptions) uninstallHelmChartIfExists(kubectlOptions, certManagerHelmDescriptor.ReleaseName, true) By("Verifying Cert-manager helm chart resources cleanup") - k8sResourceKinds, err := listK8sAllResourceKind(kubectlOptions) + k8sResourceKinds, err := listK8sResourceKinds(kubectlOptions, "") Expect(err).ShouldNot(HaveOccurred()) certManagerAvailableResourceKinds := stringSlicesUnion(certManagerCRDs(), k8sResourceKinds) diff --git a/tests/e2e/uninstall_cluster.go b/tests/e2e/uninstall_cluster.go index 47c280c34..aacf76f1b 100644 --- a/tests/e2e/uninstall_cluster.go +++ b/tests/e2e/uninstall_cluster.go @@ -36,7 +36,7 @@ func requireDeleteKafkaCluster(kubectlOptions k8s.KubectlOptions, name string) { By("Verifying the Kafka cluster resource cleanup") // Check only those Koperator related resource types we have in K8s (istio usecase) - k8sResourceKinds, err := listK8sAllResourceKind(kubectlOptions) + k8sResourceKinds, err := listK8sResourceKinds(kubectlOptions, "") Expect(err).ShouldNot(HaveOccurred()) koperatorAvailableResourceKinds := stringSlicesUnion(getKoperatorRelatedResourceKinds(), k8sResourceKinds) From 2b05149e9e64ce86472d29eb9b05947edd792ec0 Mon Sep 17 00:00:00 2001 From: marbarta Date: Fri, 16 Jun 2023 04:50:46 +0200 Subject: [PATCH 11/24] fix: using --output not -o --- tests/e2e/k8s.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/k8s.go b/tests/e2e/k8s.go index c352729c1..0514ce36e 100644 --- a/tests/e2e/k8s.go +++ b/tests/e2e/k8s.go @@ -477,7 +477,7 @@ func checkExistenceOfK8sResource( // extraArgs can be any kubectl api-resources parameter. func listK8sResourceKinds(kubectlOptions k8s.KubectlOptions, apiGroupSelector string, extraArgs ...string) ([]string, error) { logMsg := "Listing K8s resource kind" - args := []string{"api-resources", "--verbs=list", "-o", "name", "--sort-by", "name"} + args := []string{"api-resources", "--verbs", "list", "-output", "name", "--sort-by", "name"} if apiGroupSelector != "" { logMsg = fmt.Sprintf("%s group selector: %s", logMsg, apiGroupSelector) From c315b3703d1d84680c7a5336fb499e4a1b8e09d7 Mon Sep 17 00:00:00 2001 From: marbarta Date: Fri, 16 Jun 2023 04:55:26 +0200 Subject: [PATCH 12/24] remove: checkExistenceOfK8sResource --- tests/e2e/k8s.go | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/tests/e2e/k8s.go b/tests/e2e/k8s.go index 0514ce36e..660b054e5 100644 --- a/tests/e2e/k8s.go +++ b/tests/e2e/k8s.go @@ -461,17 +461,6 @@ func applyK8sResourceFromTemplate(kubectlOptions k8s.KubectlOptions, templateFil return applyK8sResourceManifestFromString(kubectlOptions, manifest.String()) } -// checkExistenceOfK8sResource queries a Resource by it's kind, namespace and name and -// returns the output of stderr -func checkExistenceOfK8sResource( - kubectlOptions *k8s.KubectlOptions, - resourceKind string, - resourceName string, -) error { - By(fmt.Sprintf("Checking the existence of resource %s", resourceName)) - return k8s.RunKubectlE(GinkgoT(), kubectlOptions, "get", resourceKind, resourceName) -} - // listK8sResourceKinds lists all of the available resource kinds on the K8s cluster // with the apiGroupSelector parameter the result can be narrowed by the resource group. // extraArgs can be any kubectl api-resources parameter. From 1d66fe39cd9b3a53fdc2fd8d3cb7261fca4f2f82 Mon Sep 17 00:00:00 2001 From: marbarta Date: Fri, 16 Jun 2023 05:00:31 +0200 Subject: [PATCH 13/24] fix: fn description and extend log --- tests/e2e/k8s.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/e2e/k8s.go b/tests/e2e/k8s.go index 660b054e5..7c8d19612 100644 --- a/tests/e2e/k8s.go +++ b/tests/e2e/k8s.go @@ -396,7 +396,7 @@ func listK8sCRDs(kubectlOptions k8s.KubectlOptions, crdNames ...string) ([]strin } // deleteK8sResourceOpts deletes K8s resources based on the kind and name or kind and selector. -// When noErrNotFound is true then the deletion is passed in case when the resource is not found. +// It returns error in case when the resource is not found. // timeout parameter specifies the timeout for the deletion. // extraArgs can be any of the kubectl arguments. func deleteK8sResource( @@ -431,7 +431,7 @@ func deleteK8sResource( func deleteK8sResourceNoErrNotFound(kubectlOptions k8s.KubectlOptions, timeout time.Duration, kind string, name string, extraArgs ...string) error { err := deleteK8sResource(kubectlOptions, timeout, kind, "", name, extraArgs...) if isKubectlNotFoundError(err) { - By("Resource not found") + By(fmt.Sprintf("K8s resource %s not found", name)) return nil } return err From d68b2ca48a680c41c6a71e53d99eafc84eea77e4 Mon Sep 17 00:00:00 2001 From: marbarta Date: Fri, 16 Jun 2023 05:03:11 +0200 Subject: [PATCH 14/24] fix: check returned error for waitK8sResourceCondition --- tests/e2e/produce_consume.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/e2e/produce_consume.go b/tests/e2e/produce_consume.go index c04767335..a1536cd6b 100644 --- a/tests/e2e/produce_consume.go +++ b/tests/e2e/produce_consume.go @@ -33,7 +33,8 @@ func requireDeployingKcatPod(kubectlOptions k8s.KubectlOptions, podName string) "Namespace": kubectlOptions.Namespace, }, ) - waitK8sResourceCondition(kubectlOptions, "pods", "condition=Ready", defaultPodReadinessWaitTime, "", kcatPodName) + err := waitK8sResourceCondition(kubectlOptions, "pods", "condition=Ready", defaultPodReadinessWaitTime, "", kcatPodName) + Expect(err).ShouldNot(HaveOccurred()) }) } @@ -49,7 +50,8 @@ func requireDeployingKafkaTopic(kubectlOptions k8s.KubectlOptions, topicName str "Namespace": kubectlOptions.Namespace, }, ) - waitK8sResourceCondition(kubectlOptions, kafkaTopicKind, "jsonpath={.status.state}=created", defaultTopicCreationWaitTime, "", topicName) + err := waitK8sResourceCondition(kubectlOptions, kafkaTopicKind, "jsonpath={.status.state}=created", defaultTopicCreationWaitTime, "", topicName) + Expect(err).ShouldNot(HaveOccurred()) }) } From 53694b9c85413a5b0f9ebcf18306f92ed784700c Mon Sep 17 00:00:00 2001 From: marbarta Date: Fri, 16 Jun 2023 05:37:49 +0200 Subject: [PATCH 15/24] refactor: topic and consume produce --- tests/e2e/kafka.go | 45 +++++++++++++++++++++++++++ tests/e2e/kcat.go | 59 ++++++++++++++++++++++++++++++++++++ tests/e2e/produce_consume.go | 59 ++---------------------------------- 3 files changed, 107 insertions(+), 56 deletions(-) create mode 100644 tests/e2e/kafka.go create mode 100644 tests/e2e/kcat.go diff --git a/tests/e2e/kafka.go b/tests/e2e/kafka.go new file mode 100644 index 000000000..798104421 --- /dev/null +++ b/tests/e2e/kafka.go @@ -0,0 +1,45 @@ +// Copyright © 2023 Cisco Systems, Inc. and/or its affiliates +// +// 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 ( + "github.com/gruntwork-io/terratest/modules/k8s" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +// requireDeleteKafkaTopic deletes kafkaTopic resource. +func requireDeleteKafkaTopic(kubectlOptions k8s.KubectlOptions, topicName string) { + It("Deleting KafkaTopic CR", func() { + deleteK8sResource(kubectlOptions, defaultDeletionTimeout, kafkaTopicKind, "", topicName) + }) +} + +// requireDeployingKafkaTopic deploys a kafkaTopic resource from a template +func requireDeployingKafkaTopic(kubectlOptions k8s.KubectlOptions, topicName string) { + It("Deploying KafkaTopic CR", func() { + applyK8sResourceFromTemplate(kubectlOptions, + kafkaTopicTemplate, + map[string]interface{}{ + "Name": topicName, + "TopicName": topicName, + "Namespace": kubectlOptions.Namespace, + }, + ) + err := waitK8sResourceCondition(kubectlOptions, kafkaTopicKind, "jsonpath={.status.state}=created", defaultTopicCreationWaitTime, "", topicName) + Expect(err).ShouldNot(HaveOccurred()) + }) + +} diff --git a/tests/e2e/kcat.go b/tests/e2e/kcat.go new file mode 100644 index 000000000..784a723b2 --- /dev/null +++ b/tests/e2e/kcat.go @@ -0,0 +1,59 @@ +// Copyright © 2023 Cisco Systems, Inc. and/or its affiliates +// +// 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" + + "github.com/gruntwork-io/terratest/modules/k8s" + . "github.com/onsi/ginkgo/v2" +) + +// consumingMessagesInternally consuming messages based on parameters from Kafka cluster. +// It returns messages in string slice. +func consumingMessagesInternally(kubectlOptions k8s.KubectlOptions, kcatPodName string, internalKafkaAddress string, topicName string) (string, error) { + + By(fmt.Sprintf("Consuming messages from internalKafkaAddress: '%s' topicName: '%s'", internalKafkaAddress, topicName)) + + consumedMessages, err := k8s.RunKubectlAndGetOutputE(GinkgoT(), + k8s.NewKubectlOptions(kubectlOptions.ContextName, kubectlOptions.ConfigPath, ""), + "exec", kcatPodName, + "-n", kubectlOptions.Namespace, + "--", + "/bin/sh", "-c", fmt.Sprintf("kcat -L -b %s -t %s -e -C ", internalKafkaAddress, topicName), + ) + + if err != nil { + return "", err + } + + return consumedMessages, nil +} + +// producingMessagesInternally produces messages based on the parameters into kafka cluster. +func producingMessagesInternally(kubectlOptions k8s.KubectlOptions, kcatPodName string, internalKafkaAddress string, topicName string, message string) error { + By(fmt.Sprintf("Producing messages: '%s' to internalKafkaAddress: '%s' topicName: '%s'", message, internalKafkaAddress, topicName)) + + _, err := k8s.RunKubectlAndGetOutputE(GinkgoT(), + k8s.NewKubectlOptions(kubectlOptions.ContextName, kubectlOptions.ConfigPath, ""), + "exec", kcatPodName, + "-n", kubectlOptions.Namespace, + "--", + "/bin/sh", "-c", fmt.Sprintf("echo %s | kcat -L -b %s -t %s -P", + message, internalKafkaAddress, topicName), + ) + + return err +} diff --git a/tests/e2e/produce_consume.go b/tests/e2e/produce_consume.go index a1536cd6b..c142f56a1 100644 --- a/tests/e2e/produce_consume.go +++ b/tests/e2e/produce_consume.go @@ -39,30 +39,6 @@ func requireDeployingKcatPod(kubectlOptions k8s.KubectlOptions, podName string) } -// requireDeployingKafkaTopic deploys a kafkaTopic resource from a template -func requireDeployingKafkaTopic(kubectlOptions k8s.KubectlOptions, topicName string) { - It("Deploying KafkaTopic CR", func() { - applyK8sResourceFromTemplate(kubectlOptions, - kafkaTopicTemplate, - map[string]interface{}{ - "Name": topicName, - "TopicName": topicName, - "Namespace": kubectlOptions.Namespace, - }, - ) - err := waitK8sResourceCondition(kubectlOptions, kafkaTopicKind, "jsonpath={.status.state}=created", defaultTopicCreationWaitTime, "", topicName) - Expect(err).ShouldNot(HaveOccurred()) - }) - -} - -// requireDeleteKafkaTopic deletes kafkaTopic resource. -func requireDeleteKafkaTopic(kubectlOptions k8s.KubectlOptions, topicName string) { - It("Deleting KafkaTopic CR", func() { - deleteK8sResource(kubectlOptions, defaultDeletionTimeout, kafkaTopicKind, "", topicName) - }) -} - // requireDeleteKcatPod deletes kcat pod. func requireDeleteKcatPod(kubectlOptions k8s.KubectlOptions, podName string) { It("Deleting Kcat pod", func() { @@ -100,42 +76,13 @@ func requireInternalProducingConsumingMessage(kubectlOptions k8s.KubectlOptions, internalAddress = internalListenerAddresses[0] } - By("Producing message") - // When kubectl exec command is used the namespace flag cannot be at the beginning - // thus we need to specify by hand currentTime := time.Now() - _, err := k8s.RunKubectlAndGetOutputE(GinkgoT(), - k8s.NewKubectlOptions(kubectlOptions.ContextName, kubectlOptions.ConfigPath, ""), - "exec", - "kcat", - "-n", - kubectlOptions.Namespace, - "--", - "/bin/sh", - "-c", - fmt.Sprintf("echo %s | kcat -L -b %s -t %s -P", currentTime.String(), internalAddress, topicName), - ) + err := producingMessagesInternally(kubectlOptions, kcatPodName, internalAddress, topicName, currentTime.String()) Expect(err).NotTo(HaveOccurred()) - By("Consuming message") - consumedMessage, err := k8s.RunKubectlAndGetOutputE(GinkgoT(), - k8s.NewKubectlOptions(kubectlOptions.ContextName, kubectlOptions.ConfigPath, ""), - "exec", - "kcat", - "-n", - kubectlOptions.Namespace, - "--", - "/usr/bin/kcat", - "-L", - "-b", - internalAddress, - "-t", - topicName, - "-e", - "-C", - ) + consumedMessages, err := consumingMessagesInternally(kubectlOptions, kcatPodName, internalAddress, topicName) Expect(err).NotTo(HaveOccurred()) - Expect(consumedMessage).Should(ContainSubstring(currentTime.String())) + Expect(consumedMessages).Should(ContainSubstring(currentTime.String())) }) } From cc6b1fc6950f8408a00aa1ebba0dc2c941315531 Mon Sep 17 00:00:00 2001 From: marbarta Date: Fri, 16 Jun 2023 05:43:32 +0200 Subject: [PATCH 16/24] fix: union to instersect --- tests/e2e/uninstall.go | 8 ++++---- tests/e2e/uninstall_cluster.go | 2 +- tests/e2e/utils.go | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/e2e/uninstall.go b/tests/e2e/uninstall.go index 9a385c36d..539daa4d9 100644 --- a/tests/e2e/uninstall.go +++ b/tests/e2e/uninstall.go @@ -48,7 +48,7 @@ func requireUninstallingKoperatorHelmChart(kubectlOptions k8s.KubectlOptions) { k8sResourceKinds, err := listK8sResourceKinds(kubectlOptions, "") Expect(err).ShouldNot(HaveOccurred()) - koperatorAvailableResourceKinds := stringSlicesUnion(koperatorCRDs(), k8sResourceKinds) + koperatorAvailableResourceKinds := stringSlicesInstersect(koperatorCRDs(), k8sResourceKinds) koperatorAvailableResourceKinds = append(koperatorAvailableResourceKinds, basicK8sResourceKinds()...) remainedResources, err := getK8sResources(kubectlOptions, @@ -82,7 +82,7 @@ func requireUninstallingZookeeperOperatorHelmChart(kubectlOptions k8s.KubectlOpt k8sResourceKinds, err := listK8sResourceKinds(kubectlOptions, "") Expect(err).ShouldNot(HaveOccurred()) - zookeeperAvailableResourceKinds := stringSlicesUnion(zookeeperCRDs(), k8sResourceKinds) + zookeeperAvailableResourceKinds := stringSlicesInstersect(zookeeperCRDs(), k8sResourceKinds) zookeeperAvailableResourceKinds = append(zookeeperAvailableResourceKinds, basicK8sResourceKinds()...) remainedResources, err := getK8sResources(kubectlOptions, @@ -125,7 +125,7 @@ func requireUninstallingPrometheusOperatorHelmChart(kubectlOptions k8s.KubectlOp k8sResourceKinds, err := listK8sResourceKinds(kubectlOptions, "") Expect(err).ShouldNot(HaveOccurred()) - prometheusAvailableResourceKinds := stringSlicesUnion(prometheusCRDs(), k8sResourceKinds) + prometheusAvailableResourceKinds := stringSlicesInstersect(prometheusCRDs(), k8sResourceKinds) prometheusAvailableResourceKinds = append(prometheusAvailableResourceKinds, basicK8sResourceKinds()...) remainedResources, err := getK8sResources(kubectlOptions, @@ -168,7 +168,7 @@ func requireUninstallingCertManagerHelmChart(kubectlOptions k8s.KubectlOptions) k8sResourceKinds, err := listK8sResourceKinds(kubectlOptions, "") Expect(err).ShouldNot(HaveOccurred()) - certManagerAvailableResourceKinds := stringSlicesUnion(certManagerCRDs(), k8sResourceKinds) + certManagerAvailableResourceKinds := stringSlicesInstersect(certManagerCRDs(), k8sResourceKinds) certManagerAvailableResourceKinds = append(certManagerAvailableResourceKinds, basicK8sResourceKinds()...) remainedResources, err := getK8sResources(kubectlOptions, diff --git a/tests/e2e/uninstall_cluster.go b/tests/e2e/uninstall_cluster.go index aacf76f1b..39e0d7b5b 100644 --- a/tests/e2e/uninstall_cluster.go +++ b/tests/e2e/uninstall_cluster.go @@ -39,7 +39,7 @@ func requireDeleteKafkaCluster(kubectlOptions k8s.KubectlOptions, name string) { k8sResourceKinds, err := listK8sResourceKinds(kubectlOptions, "") Expect(err).ShouldNot(HaveOccurred()) - koperatorAvailableResourceKinds := stringSlicesUnion(getKoperatorRelatedResourceKinds(), k8sResourceKinds) + koperatorAvailableResourceKinds := stringSlicesInstersect(getKoperatorRelatedResourceKinds(), k8sResourceKinds) koperatorAvailableResourceKinds = append(koperatorAvailableResourceKinds, basicK8sResourceKinds()...) resources, err := getK8sResources(kubectlOptions, diff --git a/tests/e2e/utils.go b/tests/e2e/utils.go index 0d72422ab..855524d2c 100644 --- a/tests/e2e/utils.go +++ b/tests/e2e/utils.go @@ -18,8 +18,8 @@ import ( "sort" ) -// stringSlicesUnion returns the union of the slices from argument. -func stringSlicesUnion(sliceA, sliceB []string) []string { +// stringSlicesInstersect returns the union of the slices from argument. +func stringSlicesInstersect(sliceA, sliceB []string) []string { if len(sliceA) == 0 || len(sliceB) == 0 { return nil } From 63ed2cdca59f233e329f912c042c39a21ecf3a7c Mon Sep 17 00:00:00 2001 From: marbarta Date: Fri, 16 Jun 2023 09:35:13 +0200 Subject: [PATCH 17/24] refactor: uninstall into helmDescriptior --- tests/e2e/helm.go | 123 +++++++++++++++++++---------------------- tests/e2e/uninstall.go | 16 ++++-- 2 files changed, 70 insertions(+), 69 deletions(-) diff --git a/tests/e2e/helm.go b/tests/e2e/helm.go index aec45b719..b9814fd0f 100644 --- a/tests/e2e/helm.go +++ b/tests/e2e/helm.go @@ -193,6 +193,64 @@ func (helmDescriptor *helmDescriptor) installHelmChart(kubectlOptions k8s.Kubect return nil } +// uninstallHelmChart checks whether the specified named Helm release exists in +// the provided kubectl context and namespace, logs it if it does not and when noErrorNotFound is false then it returns error. +// if the Helm chart present then it uninstalls it from the specified kubectl context +// and namespace using the specified info, extra arguments can be any of the helm +// CLI install flag arguments, flag keys and values must be provided separately. +func (helmDescriptor *helmDescriptor) uninstallHelmChart(kubectlOptions k8s.KubectlOptions, noErrorNotFound bool) error { + if helmDescriptor == nil { + return errors.Errorf("invalid nil Helm descriptor") + } + + kubectlOptions.Namespace = helmDescriptor.Namespace + + By(fmt.Sprintf("Checking for existing Helm release named %s", helmDescriptor.ReleaseName)) + _, isInstalled, err := lookUpInstalledHelmReleaseByName(kubectlOptions, helmDescriptor.ReleaseName) + if err != nil { + return errors.WrapIfWithDetails( + err, + "looking up Helm release failed", + "releaseName", helmDescriptor.ReleaseName, + ) + } + + if !isInstalled { + if !noErrorNotFound { + return errors.Errorf("Helm release: '%s' not found", helmDescriptor.ReleaseName) + } + + By(fmt.Sprintf( + "skipping the uninstallation of %s, because the Helm release is not present.", + helmDescriptor.ReleaseName, + )) + return nil + } + By( + fmt.Sprintf( + "uninstalling Helm chart by name %s", + helmDescriptor.ReleaseName, + ), + ) + + fixedArguments := []string{ + "--debug", + } + purge := true + + return helm.DeleteE( + GinkgoT(), + &helm.Options{ + KubectlOptions: &kubectlOptions, + ExtraArgs: map[string][]string{ + "delete": append(fixedArguments, helmDescriptor.HelmExtraArguments["install"]...), + }, + }, + helmDescriptor.ReleaseName, + purge, + ) +} + // IsRemote returns true when the Helm descriptor uses a remote chart path as // location. In any other case the repository is considered a remote Helm // repository URL. @@ -292,68 +350,3 @@ func lookUpInstalledHelmReleaseByName( return nil, false, nil } - -// uninstallHelmChart uninstalls a Helm chart from the specified kubectl context and -// namespace using the specified helm release name. When purge is true, it removes records -// and makes that name free to be reused for another installation. -// Extra arguments can be any of the helm CLI uninstall flag arguments. -func uninstallHelmChart( - kubectlOptions k8s.KubectlOptions, - helmReleaseName string, - purge bool, - extraArgs ...string, -) error { - By( - fmt.Sprintf( - "uninstalling Helm chart by name %s", - helmReleaseName, - ), - ) - - fixedArguments := []string{ - "--debug", - } - - extraArgs = append(extraArgs, fixedArguments...) - - return helm.DeleteE( - GinkgoT(), - &helm.Options{ - KubectlOptions: &kubectlOptions, - ExtraArgs: map[string][]string{ - "delete": extraArgs, - }, - }, - helmReleaseName, - purge, - ) -} - -// uninstallHelmChartIfExists checks whether the specified named Helm release exists in -// the provided kubectl context and namespace, logs it if it does and returns or -// alternatively uninstall the Helm chart from the specified kubectl context and -// namespace using the release name, extra arguments can be any of the helm -// CLI install flag arguments. -func uninstallHelmChartIfExists( - kubectlOptions k8s.KubectlOptions, - helmReleaseName string, - purge bool, - extraArgs ...string, -) error { - By(fmt.Sprintf("Checking for existing Helm release name %s", helmReleaseName)) - _, isInstalled, err := lookUpInstalledHelmReleaseByName(kubectlOptions, helmReleaseName) - if err != nil { - return err - } - - if !isInstalled { - By(fmt.Sprintf( - "skipping the uninstallation of %s, because the Helm release is not present.", - helmReleaseName, - )) - - return nil - } - - return uninstallHelmChart(kubectlOptions, helmReleaseName, purge, extraArgs...) -} diff --git a/tests/e2e/uninstall.go b/tests/e2e/uninstall.go index 539daa4d9..ed2377e3c 100644 --- a/tests/e2e/uninstall.go +++ b/tests/e2e/uninstall.go @@ -43,7 +43,9 @@ func requireUninstallingKoperator(kubectlOptions k8s.KubectlOptions) { // and checks the success of that operation. func requireUninstallingKoperatorHelmChart(kubectlOptions k8s.KubectlOptions) { It("Uninstalling Koperator Helm chart", func() { - uninstallHelmChartIfExists(kubectlOptions, koperatorLocalHelmDescriptor.ReleaseName, true) + err := koperatorLocalHelmDescriptor.uninstallHelmChart(kubectlOptions, true) + Expect(err).NotTo(HaveOccurred()) + By("Verifying Koperator helm chart resources cleanup") k8sResourceKinds, err := listK8sResourceKinds(kubectlOptions, "") Expect(err).ShouldNot(HaveOccurred()) @@ -76,7 +78,8 @@ func requireUninstallingZookeeperOperator(kubectlOptions k8s.KubectlOptions) { // and checks the success of that operation. func requireUninstallingZookeeperOperatorHelmChart(kubectlOptions k8s.KubectlOptions) { It("Uninstalling zookeeper-operator Helm chart", func() { - uninstallHelmChartIfExists(kubectlOptions, zookeeperOperatorHelmDescriptor.ReleaseName, true) + err := zookeeperOperatorHelmDescriptor.uninstallHelmChart(kubectlOptions, true) + Expect(err).NotTo(HaveOccurred()) By("Verifying Zookeeper-operator helm chart resources cleanup") k8sResourceKinds, err := listK8sResourceKinds(kubectlOptions, "") @@ -119,7 +122,9 @@ func requireUninstallingPrometheusOperator(kubectlOptions k8s.KubectlOptions) { // and checks the success of that operation. func requireUninstallingPrometheusOperatorHelmChart(kubectlOptions k8s.KubectlOptions) { It("Uninstalling Prometheus-operator Helm chart", func() { - uninstallHelmChartIfExists(kubectlOptions, "prometheus-operator", true) + err := prometheusOperatorHelmDescriptor.uninstallHelmChart(kubectlOptions, true) + Expect(err).NotTo(HaveOccurred()) + By("Verifying Prometheus-operator helm chart resources cleanup") k8sResourceKinds, err := listK8sResourceKinds(kubectlOptions, "") @@ -162,7 +167,10 @@ func requireUninstallingCertManager(kubectlOptions k8s.KubectlOptions) { // and checks the success of that operation. func requireUninstallingCertManagerHelmChart(kubectlOptions k8s.KubectlOptions) { It("Uninstalling Cert-manager Helm chart", func() { - uninstallHelmChartIfExists(kubectlOptions, certManagerHelmDescriptor.ReleaseName, true) + + err := certManagerHelmDescriptor.uninstallHelmChart(kubectlOptions, true) + Expect(err).NotTo(HaveOccurred()) + By("Verifying Cert-manager helm chart resources cleanup") k8sResourceKinds, err := listK8sResourceKinds(kubectlOptions, "") From 3addfae60a1074c4bed3554e2acb1b980be742f7 Mon Sep 17 00:00:00 2001 From: marbarta Date: Mon, 19 Jun 2023 10:31:16 +0200 Subject: [PATCH 18/24] refactor: using dynamically dependencies CRDs --- tests/e2e/const.go | 128 +++------------------------------ tests/e2e/global.go | 111 ++++++++++++++++++++++++++++ tests/e2e/k8s.go | 2 +- tests/e2e/test_uninstall.go | 14 +++- tests/e2e/types.go | 52 ++++++++++++++ tests/e2e/uninstall.go | 12 ++-- tests/e2e/uninstall_cluster.go | 4 +- 7 files changed, 192 insertions(+), 131 deletions(-) create mode 100644 tests/e2e/global.go create mode 100644 tests/e2e/types.go diff --git a/tests/e2e/const.go b/tests/e2e/const.go index 9a9f38e31..441be55c5 100644 --- a/tests/e2e/const.go +++ b/tests/e2e/const.go @@ -16,94 +16,6 @@ package e2e import "time" -// HelmDescriptors. -var ( - // certManagerHelmDescriptor describes the cert-manager Helm component. - certManagerHelmDescriptor = helmDescriptor{ - Repository: "https://charts.jetstack.io", - ChartName: "cert-manager", - ChartVersion: "v1.11.0", - ReleaseName: "cert-manager", - Namespace: "cert-manager", - SetValues: map[string]string{ - "installCRDs": "true", - }, - RemoteCRDPathVersionTemplate: "https://github.com/jetstack/cert-manager/releases/download/v%s/cert-manager.crds.yaml", - } - - // koperatorLocalHelmDescriptor describes the Koperator Helm component with - // a local chart and version. - koperatorLocalHelmDescriptor = helmDescriptor{ - Repository: "../../charts/kafka-operator", - ChartVersion: LocalVersion, - ReleaseName: "kafka-operator", - Namespace: "kafka", - SetValues: map[string]string{ - "crd.enabled": "true", - }, - LocalCRDSubpaths: []string{"templates/crds.yaml"}, - LocalCRDTemplateRenderValues: map[string]string{ - "crd.enabled": "true", - }, - } - - // koperatorLocalHelmDescriptor describes the Koperator Helm component with - // a remote latest chart and version. - koperatorRemoteLatestHelmDescriptor = helmDescriptor{ //nolint:unused // Note: intentional possibly needed in the future for upgrade test. - Repository: "https://kubernetes-charts.banzaicloud.com", - ChartName: "kafka-operator", - ChartVersion: "", // Note: empty string translates to latest final version. - ReleaseName: "kafka-operator", - Namespace: "kafka", - SetValues: map[string]string{ - "crd.enabled": "true", - }, - RemoteCRDPathVersionTemplate: "https://github.com/banzaicloud/koperator/releases/download/%s/kafka-operator.crds.yaml", - } - - // prometheusOperatorHelmDescriptor describes the prometheus-operator Helm - // component. - prometheusOperatorHelmDescriptor = helmDescriptor{ - Repository: "https://prometheus-community.github.io/helm-charts", - ChartName: "kube-prometheus-stack", - ChartVersion: "42.0.1", - ReleaseName: "prometheus-operator", - Namespace: "prometheus", - SetValues: map[string]string{ - "prometheusOperator.createCustomResource": "true", - "defaultRules.enabled": "false", - "alertmanager.enabled": "false", - "grafana.enabled": "false", - "kubeApiServer.enabled": "false", - "kubelet.enabled": "false", - "kubeControllerManager.enabled": "false", - "coreDNS.enabled": "false", - "kubeEtcd.enabled": "false", - "kubeScheduler.enabled": "false", - "kubeProxy.enabled": "false", - "kubeStateMetrics.enabled": "false", - "nodeExporter.enabled": "false", - "prometheus.enabled": "false", - }, - } - - // zookeeperOperatorHelmDescriptor describes the zookeeper-operator Helm - // component. - zookeeperOperatorHelmDescriptor = helmDescriptor{ - Repository: "https://charts.pravega.io", - ChartName: "zookeeper-operator", - ChartVersion: "0.2.14", - ReleaseName: "zookeeper-operator", - Namespace: "zookeeper", - SetValues: map[string]string{ - "crd.create": "true", - }, - } -) - -// Versions. -type Version = string - const ( // LocalVersion means using the files in the local repository snapshot. @@ -140,6 +52,14 @@ const ( kubectlNotFoundErrorMsg = "NotFound" ) +func apiGroupKoperatorDependencies() map[string]string { + return map[string]string{ + "cert-manager": "cert-manager.io", + "zookeeper": "zookeeper.pravega.io", + "prometheus": "monitoring.coreos.com", + } +} + func basicK8sResourceKinds() []string { return []string{ "pods", @@ -162,36 +82,6 @@ func basicK8sResourceKinds() []string { } } -func certManagerCRDs() []string { - return []string{ - "certificaterequests.cert-manager.io", - "certificates.cert-manager.io", - "challenges.acme.cert-manager.io", - "clusterissuers.cert-manager.io", - "issuers.cert-manager.io", - "orders.acme.cert-manager.io", - } -} - -func prometheusCRDs() []string { - return []string{ - "alertmanagerconfigs.monitoring.coreos.com", - "alertmanagers.monitoring.coreos.com", - "probes.monitoring.coreos.com", - "prometheuses.monitoring.coreos.com", - "prometheusrules.monitoring.coreos.com", - "servicemonitors.monitoring.coreos.com", - "thanosrulers.monitoring.coreos.com", - "podmonitors.monitoring.coreos.com", - } -} - -func zookeeperCRDs() []string { - return []string{ - "zookeeperclusters.zookeeper.pravega.io", - } -} - func koperatorCRDs() []string { return []string{ "kafkatopics.kafka.banzaicloud.io", @@ -201,7 +91,7 @@ func koperatorCRDs() []string { } } -func getKoperatorRelatedResourceKinds() []string { +func koperatorRelatedResourceKinds() []string { return []string{ "nodepoollabelsets.labels.banzaicloud.io", "kafkatopics.kafka.banzaicloud.io", diff --git a/tests/e2e/global.go b/tests/e2e/global.go new file mode 100644 index 000000000..ba97b2edb --- /dev/null +++ b/tests/e2e/global.go @@ -0,0 +1,111 @@ +// Copyright © 2023 Cisco Systems, Inc. and/or its affiliates +// +// 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 ( + "errors" +) + +// HelmDescriptors. +var ( + // certManagerHelmDescriptor describes the cert-manager Helm component. + certManagerHelmDescriptor = helmDescriptor{ + Repository: "https://charts.jetstack.io", + ChartName: "cert-manager", + ChartVersion: "v1.11.0", + ReleaseName: "cert-manager", + Namespace: "cert-manager", + SetValues: map[string]string{ + "installCRDs": "true", + }, + RemoteCRDPathVersionTemplate: "https://github.com/jetstack/cert-manager/releases/download/v%s/cert-manager.crds.yaml", + } + + // koperatorLocalHelmDescriptor describes the Koperator Helm component with + // a local chart and version. + koperatorLocalHelmDescriptor = helmDescriptor{ + Repository: "../../charts/kafka-operator", + ChartVersion: LocalVersion, + ReleaseName: "kafka-operator", + Namespace: "kafka", + SetValues: map[string]string{ + "crd.enabled": "true", + }, + LocalCRDSubpaths: []string{"templates/crds.yaml"}, + LocalCRDTemplateRenderValues: map[string]string{ + "crd.enabled": "true", + }, + } + + // koperatorLocalHelmDescriptor describes the Koperator Helm component with + // a remote latest chart and version. + koperatorRemoteLatestHelmDescriptor = helmDescriptor{ //nolint:unused // Note: intentional possibly needed in the future for upgrade test. + Repository: "https://kubernetes-charts.banzaicloud.com", + ChartName: "kafka-operator", + ChartVersion: "", // Note: empty string translates to latest final version. + ReleaseName: "kafka-operator", + Namespace: "kafka", + SetValues: map[string]string{ + "crd.enabled": "true", + }, + RemoteCRDPathVersionTemplate: "https://github.com/banzaicloud/koperator/releases/download/%s/kafka-operator.crds.yaml", + } + + // prometheusOperatorHelmDescriptor describes the prometheus-operator Helm + // component. + prometheusOperatorHelmDescriptor = helmDescriptor{ + Repository: "https://prometheus-community.github.io/helm-charts", + ChartName: "kube-prometheus-stack", + ChartVersion: "42.0.1", + ReleaseName: "prometheus-operator", + Namespace: "prometheus", + SetValues: map[string]string{ + "prometheusOperator.createCustomResource": "true", + "defaultRules.enabled": "false", + "alertmanager.enabled": "false", + "grafana.enabled": "false", + "kubeApiServer.enabled": "false", + "kubelet.enabled": "false", + "kubeControllerManager.enabled": "false", + "coreDNS.enabled": "false", + "kubeEtcd.enabled": "false", + "kubeScheduler.enabled": "false", + "kubeProxy.enabled": "false", + "kubeStateMetrics.enabled": "false", + "nodeExporter.enabled": "false", + "prometheus.enabled": "false", + }, + } + + // zookeeperOperatorHelmDescriptor describes the zookeeper-operator Helm + // component. + zookeeperOperatorHelmDescriptor = helmDescriptor{ + Repository: "https://charts.pravega.io", + ChartName: "zookeeper-operator", + ChartVersion: "0.2.14", + ReleaseName: "zookeeper-operator", + Namespace: "zookeeper", + SetValues: map[string]string{ + "crd.create": "true", + }, + } + + // dependencyCRDs storing the Koperator dependencies CRDs name + // It should be initialized once with the Initialize() member function + dependencyCRDs dependencyCRDsType + + // ErrorNotFound is for handling that error case when resource is not found + ErrorNotFound = errors.New("not found") +) diff --git a/tests/e2e/k8s.go b/tests/e2e/k8s.go index 7c8d19612..69298a644 100644 --- a/tests/e2e/k8s.go +++ b/tests/e2e/k8s.go @@ -466,7 +466,7 @@ func applyK8sResourceFromTemplate(kubectlOptions k8s.KubectlOptions, templateFil // extraArgs can be any kubectl api-resources parameter. func listK8sResourceKinds(kubectlOptions k8s.KubectlOptions, apiGroupSelector string, extraArgs ...string) ([]string, error) { logMsg := "Listing K8s resource kind" - args := []string{"api-resources", "--verbs", "list", "-output", "name", "--sort-by", "name"} + args := []string{"api-resources", "--verbs", "list", "--output", "name", "--sort-by", "name"} if apiGroupSelector != "" { logMsg = fmt.Sprintf("%s group selector: %s", logMsg, apiGroupSelector) diff --git a/tests/e2e/test_uninstall.go b/tests/e2e/test_uninstall.go index 0066669e0..6c1bdaf3d 100644 --- a/tests/e2e/test_uninstall.go +++ b/tests/e2e/test_uninstall.go @@ -25,9 +25,17 @@ func testUninstall() bool { var kubectlOptions k8s.KubectlOptions var err error - It("Acquiring K8s config and context", func() { - kubectlOptions, err = kubectlOptionsForCurrentContext() - Expect(err).NotTo(HaveOccurred()) + When("Initializing", func() { + It("Acquiring K8s config and context", func() { + kubectlOptions, err = kubectlOptionsForCurrentContext() + Expect(err).NotTo(HaveOccurred()) + }) + + It("Setting globals", func() { + err := dependencyCRDs.Initialize(kubectlOptions) + Expect(err).NotTo(HaveOccurred()) + }) + }) requireUninstallingKoperator(k8s.KubectlOptions{ diff --git a/tests/e2e/types.go b/tests/e2e/types.go new file mode 100644 index 000000000..ec2e4c4c5 --- /dev/null +++ b/tests/e2e/types.go @@ -0,0 +1,52 @@ +package e2e + +import ( + "fmt" + + "github.com/gruntwork-io/terratest/modules/k8s" +) + +// Versions. +type Version = string + +type dependencyCRDsType struct { + zookeeper []string + prometheus []string + certManager []string +} + +func (c *dependencyCRDsType) Zookeeper() []string { + return c.zookeeper +} +func (c *dependencyCRDsType) Prometheus() []string { + return c.prometheus +} +func (c *dependencyCRDsType) CertManager() []string { + return c.certManager +} + +func (c *dependencyCRDsType) Initialize(kubectlOptions k8s.KubectlOptions) error { + var err error + c.certManager, err = listK8sResourceKinds(kubectlOptions, apiGroupKoperatorDependencies()["cert-manager"]) + if len(c.certManager) == 0 { + if err != nil { + return fmt.Errorf("initialize Cert-manager CRDs error: %w", err) + } + return fmt.Errorf("Cert-manager CRDs %w", ErrorNotFound) + } + c.prometheus, err = listK8sResourceKinds(kubectlOptions, apiGroupKoperatorDependencies()["prometheus"]) + if len(c.prometheus) == 0 { + if err != nil { + return fmt.Errorf("initialize Prometheus CRDs error: %w", err) + } + return fmt.Errorf("Prometheus CRDs %w", ErrorNotFound) + } + c.zookeeper, err = listK8sResourceKinds(kubectlOptions, apiGroupKoperatorDependencies()["zookeeper"]) + if len(c.zookeeper) == 0 { + if err != nil { + return fmt.Errorf("initialize Zookeeper CRDs error: %w", err) + } + return fmt.Errorf("Zookeeper CRDs %w", ErrorNotFound) + } + return nil +} diff --git a/tests/e2e/uninstall.go b/tests/e2e/uninstall.go index ed2377e3c..dabdcf956 100644 --- a/tests/e2e/uninstall.go +++ b/tests/e2e/uninstall.go @@ -85,7 +85,7 @@ func requireUninstallingZookeeperOperatorHelmChart(kubectlOptions k8s.KubectlOpt k8sResourceKinds, err := listK8sResourceKinds(kubectlOptions, "") Expect(err).ShouldNot(HaveOccurred()) - zookeeperAvailableResourceKinds := stringSlicesInstersect(zookeeperCRDs(), k8sResourceKinds) + zookeeperAvailableResourceKinds := stringSlicesInstersect(dependencyCRDs.Zookeeper(), k8sResourceKinds) zookeeperAvailableResourceKinds = append(zookeeperAvailableResourceKinds, basicK8sResourceKinds()...) remainedResources, err := getK8sResources(kubectlOptions, @@ -103,7 +103,7 @@ func requireUninstallingZookeeperOperatorHelmChart(kubectlOptions k8s.KubectlOpt // requireRemoveZookeeperOperatorCRDs deletes the zookeeper-operator CRDs func requireRemoveZookeeperOperatorCRDs(kubectlOptions k8s.KubectlOptions) { It("Removing zookeeper-operator CRDs", func() { - for _, crd := range zookeeperCRDs() { + for _, crd := range dependencyCRDs.Zookeeper() { deleteK8sResourceNoErrNotFound(kubectlOptions, defaultDeletionTimeout, crdKind, crd) } }) @@ -130,7 +130,7 @@ func requireUninstallingPrometheusOperatorHelmChart(kubectlOptions k8s.KubectlOp k8sResourceKinds, err := listK8sResourceKinds(kubectlOptions, "") Expect(err).ShouldNot(HaveOccurred()) - prometheusAvailableResourceKinds := stringSlicesInstersect(prometheusCRDs(), k8sResourceKinds) + prometheusAvailableResourceKinds := stringSlicesInstersect(dependencyCRDs.Prometheus(), k8sResourceKinds) prometheusAvailableResourceKinds = append(prometheusAvailableResourceKinds, basicK8sResourceKinds()...) remainedResources, err := getK8sResources(kubectlOptions, @@ -148,7 +148,7 @@ func requireUninstallingPrometheusOperatorHelmChart(kubectlOptions k8s.KubectlOp // requireRemovePrometheusOperatorCRDs deletes the Prometheus-operator CRDs func requireRemovePrometheusOperatorCRDs(kubectlOptions k8s.KubectlOptions) { It("Removing prometheus-operator CRDs", func() { - for _, crd := range prometheusCRDs() { + for _, crd := range dependencyCRDs.Prometheus() { deleteK8sResourceNoErrNotFound(kubectlOptions, defaultDeletionTimeout, crdKind, crd) } }) @@ -176,7 +176,7 @@ func requireUninstallingCertManagerHelmChart(kubectlOptions k8s.KubectlOptions) k8sResourceKinds, err := listK8sResourceKinds(kubectlOptions, "") Expect(err).ShouldNot(HaveOccurred()) - certManagerAvailableResourceKinds := stringSlicesInstersect(certManagerCRDs(), k8sResourceKinds) + certManagerAvailableResourceKinds := stringSlicesInstersect(dependencyCRDs.CertManager(), k8sResourceKinds) certManagerAvailableResourceKinds = append(certManagerAvailableResourceKinds, basicK8sResourceKinds()...) remainedResources, err := getK8sResources(kubectlOptions, @@ -195,7 +195,7 @@ func requireUninstallingCertManagerHelmChart(kubectlOptions k8s.KubectlOptions) // requireRemoveKoperatorCRDs deletes the cert-manager CRDs func requireRemoveCertManagerCRDs(kubectlOptions k8s.KubectlOptions) { It("Removing cert-manager CRDs", func() { - for _, crd := range certManagerCRDs() { + for _, crd := range dependencyCRDs.CertManager() { deleteK8sResourceNoErrNotFound(kubectlOptions, defaultDeletionTimeout, crdKind, crd) } }) diff --git a/tests/e2e/uninstall_cluster.go b/tests/e2e/uninstall_cluster.go index 39e0d7b5b..8ee85d999 100644 --- a/tests/e2e/uninstall_cluster.go +++ b/tests/e2e/uninstall_cluster.go @@ -39,7 +39,7 @@ func requireDeleteKafkaCluster(kubectlOptions k8s.KubectlOptions, name string) { k8sResourceKinds, err := listK8sResourceKinds(kubectlOptions, "") Expect(err).ShouldNot(HaveOccurred()) - koperatorAvailableResourceKinds := stringSlicesInstersect(getKoperatorRelatedResourceKinds(), k8sResourceKinds) + koperatorAvailableResourceKinds := stringSlicesInstersect(koperatorRelatedResourceKinds(), k8sResourceKinds) koperatorAvailableResourceKinds = append(koperatorAvailableResourceKinds, basicK8sResourceKinds()...) resources, err := getK8sResources(kubectlOptions, @@ -62,7 +62,7 @@ func requireDeleteZookeeperCluster(kubectlOptions k8s.KubectlOptions, name strin By("Verifying the Zookeeper cluster resource cleanup") zookeeperK8sResources := basicK8sResourceKinds() - zookeeperK8sResources = append(zookeeperK8sResources, zookeeperCRDs()...) + zookeeperK8sResources = append(zookeeperK8sResources, dependencyCRDs.Zookeeper()...) resources, err := getK8sResources(kubectlOptions, zookeeperK8sResources, From 3efc5f92e73093a477784196d6bcf64ffcc0a417 Mon Sep 17 00:00:00 2001 From: marbarta Date: Mon, 19 Jun 2023 10:51:14 +0200 Subject: [PATCH 19/24] fix: missing error checks --- tests/e2e/kafka.go | 9 ++++++--- tests/e2e/produce_consume.go | 9 ++++++--- tests/e2e/uninstall.go | 13 +++++++++---- tests/e2e/uninstall_cluster.go | 4 +++- 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/tests/e2e/kafka.go b/tests/e2e/kafka.go index 798104421..af20c6800 100644 --- a/tests/e2e/kafka.go +++ b/tests/e2e/kafka.go @@ -23,14 +23,15 @@ import ( // requireDeleteKafkaTopic deletes kafkaTopic resource. func requireDeleteKafkaTopic(kubectlOptions k8s.KubectlOptions, topicName string) { It("Deleting KafkaTopic CR", func() { - deleteK8sResource(kubectlOptions, defaultDeletionTimeout, kafkaTopicKind, "", topicName) + err := deleteK8sResource(kubectlOptions, defaultDeletionTimeout, kafkaTopicKind, "", topicName) + Expect(err).NotTo(HaveOccurred()) }) } // requireDeployingKafkaTopic deploys a kafkaTopic resource from a template func requireDeployingKafkaTopic(kubectlOptions k8s.KubectlOptions, topicName string) { It("Deploying KafkaTopic CR", func() { - applyK8sResourceFromTemplate(kubectlOptions, + err := applyK8sResourceFromTemplate(kubectlOptions, kafkaTopicTemplate, map[string]interface{}{ "Name": topicName, @@ -38,7 +39,9 @@ func requireDeployingKafkaTopic(kubectlOptions k8s.KubectlOptions, topicName str "Namespace": kubectlOptions.Namespace, }, ) - err := waitK8sResourceCondition(kubectlOptions, kafkaTopicKind, "jsonpath={.status.state}=created", defaultTopicCreationWaitTime, "", topicName) + Expect(err).ShouldNot(HaveOccurred()) + + err = waitK8sResourceCondition(kubectlOptions, kafkaTopicKind, "jsonpath={.status.state}=created", defaultTopicCreationWaitTime, "", topicName) Expect(err).ShouldNot(HaveOccurred()) }) diff --git a/tests/e2e/produce_consume.go b/tests/e2e/produce_consume.go index c142f56a1..062ed35b1 100644 --- a/tests/e2e/produce_consume.go +++ b/tests/e2e/produce_consume.go @@ -26,14 +26,16 @@ import ( // requireDeployingKcatPod deploys kcat pod form a template and checks the pod readiness func requireDeployingKcatPod(kubectlOptions k8s.KubectlOptions, podName string) { It("Deploying Kcat Pod", func() { - applyK8sResourceFromTemplate(kubectlOptions, + err := applyK8sResourceFromTemplate(kubectlOptions, kcatPodTemplate, map[string]interface{}{ "Name": kcatPodName, "Namespace": kubectlOptions.Namespace, }, ) - err := waitK8sResourceCondition(kubectlOptions, "pods", "condition=Ready", defaultPodReadinessWaitTime, "", kcatPodName) + Expect(err).ShouldNot(HaveOccurred()) + + err = waitK8sResourceCondition(kubectlOptions, "pods", "condition=Ready", defaultPodReadinessWaitTime, "", kcatPodName) Expect(err).ShouldNot(HaveOccurred()) }) @@ -42,7 +44,8 @@ func requireDeployingKcatPod(kubectlOptions k8s.KubectlOptions, podName string) // requireDeleteKcatPod deletes kcat pod. func requireDeleteKcatPod(kubectlOptions k8s.KubectlOptions, podName string) { It("Deleting Kcat pod", func() { - deleteK8sResource(kubectlOptions, defaultDeletionTimeout, "pods", "", podName) + err := deleteK8sResource(kubectlOptions, defaultDeletionTimeout, "pods", "", podName) + Expect(err).NotTo(HaveOccurred()) }) } diff --git a/tests/e2e/uninstall.go b/tests/e2e/uninstall.go index dabdcf956..4644fb064 100644 --- a/tests/e2e/uninstall.go +++ b/tests/e2e/uninstall.go @@ -26,7 +26,9 @@ import ( func requireRemoveKoperatorCRDs(kubectlOptions k8s.KubectlOptions) { It("Removing koperator CRDs", func() { for _, crd := range koperatorCRDs() { - deleteK8sResourceNoErrNotFound(kubectlOptions, defaultDeletionTimeout, crdKind, crd) + err := deleteK8sResourceNoErrNotFound(kubectlOptions, defaultDeletionTimeout, crdKind, crd) + Expect(err).ShouldNot(HaveOccurred()) + } }) } @@ -104,7 +106,8 @@ func requireUninstallingZookeeperOperatorHelmChart(kubectlOptions k8s.KubectlOpt func requireRemoveZookeeperOperatorCRDs(kubectlOptions k8s.KubectlOptions) { It("Removing zookeeper-operator CRDs", func() { for _, crd := range dependencyCRDs.Zookeeper() { - deleteK8sResourceNoErrNotFound(kubectlOptions, defaultDeletionTimeout, crdKind, crd) + err := deleteK8sResourceNoErrNotFound(kubectlOptions, defaultDeletionTimeout, crdKind, crd) + Expect(err).ShouldNot(HaveOccurred()) } }) } @@ -149,7 +152,8 @@ func requireUninstallingPrometheusOperatorHelmChart(kubectlOptions k8s.KubectlOp func requireRemovePrometheusOperatorCRDs(kubectlOptions k8s.KubectlOptions) { It("Removing prometheus-operator CRDs", func() { for _, crd := range dependencyCRDs.Prometheus() { - deleteK8sResourceNoErrNotFound(kubectlOptions, defaultDeletionTimeout, crdKind, crd) + err := deleteK8sResourceNoErrNotFound(kubectlOptions, defaultDeletionTimeout, crdKind, crd) + Expect(err).ShouldNot(HaveOccurred()) } }) } @@ -196,7 +200,8 @@ func requireUninstallingCertManagerHelmChart(kubectlOptions k8s.KubectlOptions) func requireRemoveCertManagerCRDs(kubectlOptions k8s.KubectlOptions) { It("Removing cert-manager CRDs", func() { for _, crd := range dependencyCRDs.CertManager() { - deleteK8sResourceNoErrNotFound(kubectlOptions, defaultDeletionTimeout, crdKind, crd) + err := deleteK8sResourceNoErrNotFound(kubectlOptions, defaultDeletionTimeout, crdKind, crd) + Expect(err).ShouldNot(HaveOccurred()) } }) } diff --git a/tests/e2e/uninstall_cluster.go b/tests/e2e/uninstall_cluster.go index 8ee85d999..585224a77 100644 --- a/tests/e2e/uninstall_cluster.go +++ b/tests/e2e/uninstall_cluster.go @@ -57,7 +57,9 @@ func requireDeleteKafkaCluster(kubectlOptions k8s.KubectlOptions, name string) { // requireDeleteZookeeperCluster deletes the ZookeeperCluster CR and verify the corresponding resources cleanup func requireDeleteZookeeperCluster(kubectlOptions k8s.KubectlOptions, name string) { It("Delete ZookeeperCluster custom resource", func() { - deleteK8sResourceNoErrNotFound(kubectlOptions, defaultDeletionTimeout, zookeeperKind, name) + err := deleteK8sResourceNoErrNotFound(kubectlOptions, defaultDeletionTimeout, zookeeperKind, name) + Expect(err).ShouldNot(HaveOccurred()) + Eventually(context.Background(), func() []string { By("Verifying the Zookeeper cluster resource cleanup") From abea29cdc9b82b193cc0eec56baf682c4ec43540 Mon Sep 17 00:00:00 2001 From: marbarta Date: Mon, 19 Jun 2023 10:57:53 +0200 Subject: [PATCH 20/24] formatting: waitK8sResourceCondition --- tests/e2e/produce_consume.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/e2e/produce_consume.go b/tests/e2e/produce_consume.go index 062ed35b1..f0777c01b 100644 --- a/tests/e2e/produce_consume.go +++ b/tests/e2e/produce_consume.go @@ -35,7 +35,9 @@ func requireDeployingKcatPod(kubectlOptions k8s.KubectlOptions, podName string) ) Expect(err).ShouldNot(HaveOccurred()) - err = waitK8sResourceCondition(kubectlOptions, "pods", "condition=Ready", defaultPodReadinessWaitTime, "", kcatPodName) + err = waitK8sResourceCondition(kubectlOptions, "pods", + "condition=Ready", defaultPodReadinessWaitTime, "", kcatPodName) + Expect(err).ShouldNot(HaveOccurred()) }) From b6683a24f59cf2bfcfb5978bad12f6800ac94824 Mon Sep 17 00:00:00 2001 From: marbarta Date: Mon, 19 Jun 2023 14:00:37 +0200 Subject: [PATCH 21/24] refactor: move version type into const.go --- tests/e2e/const.go | 3 +++ tests/e2e/types.go | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/e2e/const.go b/tests/e2e/const.go index 441be55c5..daa85bca9 100644 --- a/tests/e2e/const.go +++ b/tests/e2e/const.go @@ -16,6 +16,9 @@ package e2e import "time" +// Versions. +type Version = string + const ( // LocalVersion means using the files in the local repository snapshot. diff --git a/tests/e2e/types.go b/tests/e2e/types.go index ec2e4c4c5..c53b9776d 100644 --- a/tests/e2e/types.go +++ b/tests/e2e/types.go @@ -6,9 +6,6 @@ import ( "github.com/gruntwork-io/terratest/modules/k8s" ) -// Versions. -type Version = string - type dependencyCRDsType struct { zookeeper []string prometheus []string From 917afad2d4a9f0dd21abecaae1612d557c256f3f Mon Sep 17 00:00:00 2001 From: marbarta Date: Mon, 19 Jun 2023 14:00:50 +0200 Subject: [PATCH 22/24] formatting: waitK8sResourceCondition --- tests/e2e/kafka.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/e2e/kafka.go b/tests/e2e/kafka.go index af20c6800..7553913fe 100644 --- a/tests/e2e/kafka.go +++ b/tests/e2e/kafka.go @@ -41,7 +41,9 @@ func requireDeployingKafkaTopic(kubectlOptions k8s.KubectlOptions, topicName str ) Expect(err).ShouldNot(HaveOccurred()) - err = waitK8sResourceCondition(kubectlOptions, kafkaTopicKind, "jsonpath={.status.state}=created", defaultTopicCreationWaitTime, "", topicName) + err = waitK8sResourceCondition(kubectlOptions, kafkaTopicKind, + "jsonpath={.status.state}=created", defaultTopicCreationWaitTime, "", topicName) + Expect(err).ShouldNot(HaveOccurred()) }) From 0e03f843cc92a38634d4adb4b1c22330b51cd011 Mon Sep 17 00:00:00 2001 From: marbarta Date: Mon, 19 Jun 2023 17:17:06 +0200 Subject: [PATCH 23/24] add(e2e-test): external consume produce plaintext/SSL --- pkg/util/util.go | 4 +- tests/e2e/const.go | 7 +- tests/e2e/go.mod | 37 +++++---- tests/e2e/go.sum | 123 ++++++++++++++++++++++++------ tests/e2e/kafka_client.go | 113 +++++++++++++++++++++++++++ tests/e2e/koperator_suite_test.go | 9 ++- tests/e2e/produce_consume.go | 88 +++++++++++++++++++++ tests/e2e/test_produce_consume.go | 29 ++++++- 8 files changed, 363 insertions(+), 47 deletions(-) create mode 100644 tests/e2e/kafka_client.go diff --git a/pkg/util/util.go b/pkg/util/util.go index 7f637ecb7..ad1ecb50f 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -437,14 +437,14 @@ func GetClientTLSConfig(client clientCtrl.Reader, secretNamespaceName types.Name return nil, err } - config, err := createTLSConfigFromSecret(tlsKeys) + config, err := CreateTLSConfigFromSecret(tlsKeys) if err != nil { return nil, errorfactory.New(errorfactory.InternalError{}, err, fmt.Sprintf("could not get client certificate for kafka client, name: %s namespace: %s", secretNamespaceName.Name, secretNamespaceName.Namespace)) } return config, nil } -func createTLSConfigFromSecret(tlsKeys *corev1.Secret) (*tls.Config, error) { +func CreateTLSConfigFromSecret(tlsKeys *corev1.Secret) (*tls.Config, error) { rootCAs := x509.NewCertPool() if err := cert.CheckSSLCertSecret(tlsKeys); err != nil { return nil, err diff --git a/tests/e2e/const.go b/tests/e2e/const.go index daa85bca9..31b26ad6a 100644 --- a/tests/e2e/const.go +++ b/tests/e2e/const.go @@ -28,14 +28,15 @@ const ( kubectlArgGoTemplateKindNameNamespace = `-o=go-template='{{range .items}}{{.kind}}{{"/"}}{{.metadata.name}}{{if .metadata.namespace}}{{"."}}{{.metadata.namespace}}{{end}}{{"\n"}}{{end}}'` kubectlArgGoTemplateInternalListenersName = `-o=go-template='{{range $key,$value := .status.listenerStatuses.internalListeners}}{{$key}}{{"\n"}}{{end}}` kubectlArgGoTemplateInternalListenerAddressesTemplate = `-o=go-template='{{range .status.listenerStatuses.internalListeners.%s}}{{.address}}{{"\n"}}{{end}}` - // kubectlArgGoTemplateExternalListenersName = `-o=go-template='{{range $key,$value := .status.listenerStatuses.externallListeners}}{{$key}}{{"\n"}}{{end}}` - // kubectlArgGoTemplateExternalListenerAddressesTemplate = `-o=go-template='{{range .status.listenerStatuses.externalListeners.%s}}{{.address}}{{"\n"}}{{end}}` + kubectlArgGoTemplateExternalListenersName = `-o=go-template='{{range $key,$value := .status.listenerStatuses.externalListeners}}{{$key}}{{"\n"}}{{end}}` + kubectlArgGoTemplateExternalListenerAddressesTemplate = `-o=go-template='{{range .status.listenerStatuses.externalListeners.%s}}{{.address}}{{"\n"}}{{end}}` crdKind = "customresourcedefinitions.apiextensions.k8s.io" kafkaKind = "kafkaclusters.kafka.banzaicloud.io" kafkaTopicKind = "kafkatopics.kafka.banzaicloud.io" kafkaClusterName = "kafka" - testTopicName = "topic-test" + testExternalTopicName = "topic-test-external" + testInternalTopicName = "topic-test-internal" kcatPodName = "kcat" zookeeperKind = "zookeeperclusters.zookeeper.pravega.io" zookeeperClusterName = "zookeeper-server" diff --git a/tests/e2e/go.mod b/tests/e2e/go.mod index 00dd8e12d..b356a9458 100644 --- a/tests/e2e/go.mod +++ b/tests/e2e/go.mod @@ -8,18 +8,31 @@ require ( github.com/gruntwork-io/terratest v0.41.24 github.com/onsi/ginkgo/v2 v2.9.5 github.com/onsi/gomega v1.27.6 + github.com/twmb/franz-go v1.13.5 k8s.io/apiextensions-apiserver v0.27.2 k8s.io/apimachinery v0.27.2 sigs.k8s.io/yaml v1.3.0 ) require ( - github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver v1.5.0 // indirect - github.com/Masterminds/sprig v2.22.0+incompatible // indirect + github.com/banzaicloud/istio-client-go v0.0.17 // indirect + github.com/huandu/xstrings v1.3.3 // indirect + github.com/klauspost/compress v1.16.3 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/pierrec/lz4/v4 v4.1.17 // indirect + github.com/twmb/franz-go/pkg/kmsg v1.4.0 // indirect + sigs.k8s.io/controller-runtime v0.14.6 // indirect +) + +require ( + github.com/Masterminds/goutils v1.1.1 // indirect + github.com/Masterminds/sprig v2.22.0+incompatible github.com/aws/aws-sdk-go v1.44.122 // indirect + github.com/banzaicloud/koperator/api v0.28.2 github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect + github.com/cert-manager/cert-manager v1.11.2 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/emicklei/go-restful/v3 v3.9.0 // indirect github.com/evanphx/json-patch v5.6.0+incompatible // indirect @@ -33,22 +46,20 @@ require ( github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/google/gnostic v0.5.7-v3refs // indirect + github.com/google/gnostic v0.6.9 // indirect github.com/google/go-cmp v0.5.9 // indirect - github.com/google/gofuzz v1.1.0 // indirect + github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect github.com/google/uuid v1.3.0 // indirect github.com/gruntwork-io/go-commons v0.8.0 // indirect - github.com/hashicorp/errwrap v1.0.0 // indirect - github.com/hashicorp/go-multierror v1.1.0 // indirect - github.com/huandu/xstrings v1.4.0 // indirect - github.com/imdario/mergo v0.3.11 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/imdario/mergo v0.3.13 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326 // indirect - github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/moby/spdystream v0.2.0 // indirect @@ -62,11 +73,11 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/testify v1.8.1 // indirect github.com/urfave/cli v1.22.2 // indirect - go.uber.org/atomic v1.7.0 // indirect + go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.6.0 // indirect - golang.org/x/crypto v0.1.0 // indirect + golang.org/x/crypto v0.7.0 // indirect golang.org/x/net v0.10.0 // indirect - golang.org/x/oauth2 v0.1.0 // indirect + golang.org/x/oauth2 v0.4.0 // indirect golang.org/x/sys v0.8.0 // indirect golang.org/x/term v0.8.0 // indirect golang.org/x/text v0.9.0 // indirect diff --git a/tests/e2e/go.sum b/tests/e2e/go.sum index 8db5daf55..97a013bba 100644 --- a/tests/e2e/go.sum +++ b/tests/e2e/go.sum @@ -1,4 +1,5 @@ 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= emperror.dev/errors v0.8.1 h1:UavXZ5cSX/4u9iyvH6aDcuGkVjeexUGJ7Ij7G4VfQT0= emperror.dev/errors v0.8.1/go.mod h1:YcRvLPh626Ubn2xqtoprejnA5nFha+TJ+2vew48kWuE= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= @@ -8,22 +9,35 @@ github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3Q github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60= github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/aws/aws-sdk-go v1.44.122 h1:p6mw01WBaNpbdP2xrisz5tIkcNwzj/HysobNoaAHjgo= github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= +github.com/banzaicloud/istio-client-go v0.0.17 h1:wiplbM7FDiIHopujInAnin3zuovtVcphtKy9En39q5I= +github.com/banzaicloud/istio-client-go v0.0.17/go.mod h1:rpnEYYGHzisx8nARl2d30Oq38EeCX0/PPaxMaREfE9I= +github.com/banzaicloud/koperator/api v0.28.2 h1:x3n9dl+zhePgfwXFZlbzqeoI8veF4gL7JJAdKvfc61M= +github.com/banzaicloud/koperator/api v0.28.2/go.mod h1:MpHo+CO1TmVyHooJ3n3+o6ibL/AKlBp7L9bdyKy5Ec0= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI= github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= +github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cert-manager/cert-manager v1.11.2 h1:rJMZv9VtN0YhHZn1esj+V0+KhrYUF8d0BMJWUeIrKX4= +github.com/cert-manager/cert-manager v1.11.2/go.mod h1:hZshV9rYSanOsbRcQHyRmrvhtq/pj0L9+Hg10Do9NgI= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= 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/cisco-open/k8s-objectmatcher v1.9.0 h1:/sfuO0BD09fpynZjXsqeZrh28Juc4VEwc2P6Ov/Q6fM= github.com/cisco-open/k8s-objectmatcher v1.9.0/go.mod h1:CH4E6qAK+q+JwKFJn0DaTNqxrbmWCaDQzGthKLK4nZ0= 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= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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= @@ -31,16 +45,22 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 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/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -54,6 +74,7 @@ github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZp github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -61,60 +82,72 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb 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/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54= -github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= +github.com/google/gnostic v0.6.9 h1:ZK/5VhkoX835RikCHpSUJV9a+S3e1zLh59YnyWeBW+0= +github.com/google/gnostic v0.6.9/go.mod h1:Nm8234We1lq6iB9OmlgNv3nH91XLLVZHCDayfA3xq+E= 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.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 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/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/gruntwork-io/go-commons v0.8.0 h1:k/yypwrPqSeYHevLlEDmvmgQzcyTwrlZGRaxEM6G0ro= github.com/gruntwork-io/go-commons v0.8.0/go.mod h1:gtp0yTtIBExIZp7vyIV9I0XQkVwiQZze678hvDXof78= github.com/gruntwork-io/terratest v0.41.24 h1:j6T6qe4deVvynTG2UmnjGwZy83he6xKgTaYWiSdFv/w= github.com/gruntwork-io/terratest v0.41.24/go.mod h1:O6gajNBjO1wvc7Wl9WtbO+ORcdnhAV2GQiBE71ycwIk= -github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI= -github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= -github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU= -github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4= +github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA= -github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= +github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY= +github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -138,6 +171,7 @@ github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0Gq 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 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= @@ -146,6 +180,8 @@ github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q= github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k= github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE= github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg= +github.com/pierrec/lz4/v4 v4.1.17 h1:kV4Ip+/hUBC+8T6+2EgburRtkE9ef4nbY3f4dFhGjMc= +github.com/pierrec/lz4/v4 v4.1.17/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= 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= @@ -153,12 +189,15 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/pquerna/otp v1.2.0 h1:/A3+Jn+cagqayeR3iHs/L62m5ue7710D35zl1zJ1kok= github.com/pquerna/otp v1.2.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +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/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= @@ -175,19 +214,28 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/twmb/franz-go v1.13.5 h1:7Hk47eZ7XRb4yWXQZk1GZU4BthkrKuZUfKOuP9Sgp24= +github.com/twmb/franz-go v1.13.5/go.mod h1:jm/FtYxmhxDTN0gNSb26XaJY0irdSVcsckLiR5tQNMk= +github.com/twmb/franz-go/pkg/kmsg v1.4.0 h1:tbp9hxU6m8qZhQTlpGiaIJOm4BXix5lsuEZ7K00dF0s= +github.com/twmb/franz-go/pkg/kmsg v1.4.0/go.mod h1:SxG/xJKhgPu25SamAq0rrucfp7lbzCpEXOC+vH/ELrY= github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= -golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 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= @@ -197,21 +245,28 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= 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-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-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/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-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.1.0 h1:isLCZuhj4v+tYv7eskaN4v/TM+A1begWWgyVJDdl1+Y= -golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.4.0 h1:NF0gk8LVPg1Ml7SSbGyySuoxdsXitj7TvgvuRxIMc/M= +golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= 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-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/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -222,23 +277,32 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/text v0.3.0/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/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/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-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -258,57 +322,72 @@ google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6 google.golang.org/appengine v1.6.7/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-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= 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/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 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/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/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/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= k8s.io/api v0.27.2 h1:+H17AJpUMvl+clT+BPnKf0E3ksMAzoBBg7CntpSuADo= k8s.io/api v0.27.2/go.mod h1:ENmbocXfBT2ADujUXcBhHV55RIT31IIEvkntP6vZKS4= k8s.io/apiextensions-apiserver v0.27.2 h1:iwhyoeS4xj9Y7v8YExhUwbVuBhMr3Q4bd/laClBV6Bo= k8s.io/apiextensions-apiserver v0.27.2/go.mod h1:Oz9UdvGguL3ULgRdY9QMUzL2RZImotgxvGjdWRq6ZXQ= +k8s.io/apimachinery v0.0.0-20190704094733-8f6ac2502e51/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= k8s.io/apimachinery v0.27.2 h1:vBjGaKKieaIreI+oQwELalVG4d8f3YAMNpWLzDXkxeg= k8s.io/apimachinery v0.27.2/go.mod h1:XNfZ6xklnMCOGGFNqXG7bUrQCoR04dh/E7FprV6pb+E= k8s.io/client-go v0.27.2 h1:vDLSeuYvCHKeoQRhCXjxXO45nHVv2Ip4Fe0MfioMrhE= k8s.io/client-go v0.27.2/go.mod h1:tY0gVmUsHrAmjzHX9zs7eCjxcBsf8IiNe7KQ52biTcQ= +k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog/v2 v2.90.1 h1:m4bYOKall2MmOiRaR1J+We67Do7vm9KiQVlT96lnHUw= k8s.io/klog/v2 v2.90.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f h1:2kWPakN3i/k81b0gvD5C5FJ2kxm1WrQFanWchyKuqGg= k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f/go.mod h1:byini6yhqGC14c3ebc/QwanvYwhuMWF6yz2F8uwW8eg= k8s.io/utils v0.0.0-20230209194617-a36077c30491 h1:r0BAOLElQnnFhE/ApUsg3iHdVYYPBjNSSOMowRZxxsY= k8s.io/utils v0.0.0-20230209194617-a36077c30491/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/controller-runtime v0.14.6 h1:oxstGVvXGNnMvY7TAESYk+lzr6S3V5VFxQ6d92KcwQA= +sigs.k8s.io/controller-runtime v0.14.6/go.mod h1:WqIdsAY6JBsjfc/CqO0CORmNtoCtE4S6qbPc9s68h+0= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/tests/e2e/kafka_client.go b/tests/e2e/kafka_client.go new file mode 100644 index 000000000..1e3eed7ec --- /dev/null +++ b/tests/e2e/kafka_client.go @@ -0,0 +1,113 @@ +// Copyright © 2023 Cisco Systems, Inc. and/or its affiliates +// +// 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" + "crypto/tls" + "fmt" + + "emperror.dev/errors" + "github.com/gruntwork-io/terratest/modules/k8s" + . "github.com/onsi/ginkgo/v2" + "github.com/twmb/franz-go/pkg/kgo" + + koperatorUtil "github.com/banzaicloud/koperator/pkg/util" +) + +// producingMessagesExternally produces messages based on the parameters into the kafka cluster synchronously. +func producingMessagesExternally(externalKafkaAddresses []string, topicName string, messages []string, clientOptions ...kgo.Opt) error { + By(fmt.Sprintf("Producing messages: '%s' to externalKafkaAddresses: '%s' topicName: '%s'", messages, externalKafkaAddresses, topicName)) + + clientOptions = append(clientOptions, kgo.SeedBrokers(externalKafkaAddresses...)) + + cl, err := kgo.NewClient( + clientOptions..., + ) + if err != nil { + return err + } + defer cl.Close() + + ctx := context.Background() + ctxProducerTimeout, cancelCtxProducerTimeout := context.WithTimeout(ctx, externalProducerTimeout) + defer cancelCtxProducerTimeout() + + for i := range messages { + record := &kgo.Record{Topic: topicName, Value: []byte(messages[i])} + // Exits at the first error occurrence + err = cl.ProduceSync(ctxProducerTimeout, record).FirstErr() + if err != nil { + return err + } + } + return nil +} + +// consumingMessagesExternally consuming messages based on parameters from Kafka cluster. +// It returns messages as string slice. +func consumingMessagesExternally(externalKafkaAddresses []string, topicName string, clientOptions ...kgo.Opt) ([]string, error) { + By(fmt.Sprintf("Consuming messages from externalKafkaAddresses: '%s' topicName: '%s'", externalKafkaAddresses, topicName)) + + clientOptions = append(clientOptions, kgo.SeedBrokers(externalKafkaAddresses...), kgo.ConsumeTopics(topicName)) + + cl, err := kgo.NewClient( + clientOptions..., + ) + if err != nil { + return nil, err + } + + defer cl.Close() + + ctx := context.Background() + ctxConsumerTimeout, cancelCtxConsumerTimeout := context.WithTimeout(ctx, externalProducerTimeout) + defer cancelCtxConsumerTimeout() + + // Send fetch request for the Kafka cluster + fetches := cl.PollFetches(ctxConsumerTimeout) + errs := fetches.Errors() + + if len(errs) > 0 { + var combinedError error + for _, err := range errs { + combinedError = errors.Append(combinedError, + fmt.Errorf("error: '%w', when consuming message from topic: '%s' partition: '%d'", err.Err, err.Topic, err.Partition)) + } + return nil, combinedError + } + + iter := fetches.RecordIter() + var messages []string + for !iter.Done() { + consumedRecord := iter.Next() + messages = append(messages, string(consumedRecord.Value)) + } + + return messages, nil +} + +func getTLSConfigFromSecret(kubectlOptions k8s.KubectlOptions, secretName string) (*tls.Config, error) { + By(fmt.Sprintf("Getting TLS config from secret name: '%s' namespace: '%s'", secretName, kubectlOptions.Namespace)) + tlsSecret, err := k8s.GetSecretE(GinkgoT(), &kubectlOptions, secretName) + if err != nil { + return nil, fmt.Errorf("could not get TLS secret for kafka client: %w", err) + } + tlsConfig, err := koperatorUtil.CreateTLSConfigFromSecret(tlsSecret) + if err != nil { + return nil, fmt.Errorf("could not create TLS config from secret: %w", err) + } + return tlsConfig, nil +} diff --git a/tests/e2e/koperator_suite_test.go b/tests/e2e/koperator_suite_test.go index 5527a13b5..a08987e17 100644 --- a/tests/e2e/koperator_suite_test.go +++ b/tests/e2e/koperator_suite_test.go @@ -55,8 +55,9 @@ var _ = BeforeSuite(func() { var _ = When("Testing e2e test altogether", Ordered, func() { //testInstall() - //testProduceConsumeInternal() - testUninstallZookeeperCluster() - testUninstallKafkaCluster() - testUninstall() + testProduceConsumeExternal("kafka-controller") + // testProduceConsumeInternal() + // testUninstallZookeeperCluster() + // testUninstallKafkaCluster() + // testUninstall() }) diff --git a/tests/e2e/produce_consume.go b/tests/e2e/produce_consume.go index f0777c01b..23b08564b 100644 --- a/tests/e2e/produce_consume.go +++ b/tests/e2e/produce_consume.go @@ -15,12 +15,14 @@ package e2e import ( + "crypto/tls" "fmt" "time" "github.com/gruntwork-io/terratest/modules/k8s" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + "github.com/twmb/franz-go/pkg/kgo" ) // requireDeployingKcatPod deploys kcat pod form a template and checks the pod readiness @@ -91,3 +93,89 @@ func requireInternalProducingConsumingMessage(kubectlOptions k8s.KubectlOptions, Expect(consumedMessages).Should(ContainSubstring(currentTime.String())) }) } + +// requireExternalProducingConsumingMessage gets the Kafka cluster external addresses from the kafkaCluster CR status +// when externalAddresses is not specified. It also produces and consumes messages and makes a comparison between them. +func requireExternalProducingConsumingMessage(kubectlOptions k8s.KubectlOptions, topicName, tlsSecretName string, externalAddresses ...string) { + It("Producing and consuming messages", func() { + if len(externalAddresses) == 0 { + var err error + externalAddresses, err = getExternalListenerAddresses(kubectlOptions, "", kafkaClusterName) + Expect(err).ShouldNot(HaveOccurred()) + } + + var tlsConfig *tls.Config + var clientOptions []kgo.Opt + if tlsSecretName != "" { + var err error + tlsConfig, err = getTLSConfigFromSecret(kubectlOptions, tlsSecretName) + Expect(err).ShouldNot(HaveOccurred()) + clientOptions = append(clientOptions, kgo.DialTLSConfig(tlsConfig)) + } + + message := time.Now().String() + + err := producingMessagesExternally(externalAddresses, topicName, []string{message}, clientOptions...) + Expect(err).ShouldNot(HaveOccurred()) + + consumedMessages, err := consumingMessagesExternally(externalAddresses, topicName, clientOptions...) + Expect(err).ShouldNot(HaveOccurred()) + + By(fmt.Sprintf("Comparing produced: '%s' and consumed message: '%s'", message, consumedMessages)) + found := false + for i := range consumedMessages { + if consumedMessages[i] == message { + found = true + break + } + } + Expect(found).Should(BeTrue()) + }) +} + +// getExternalListenerAddresses gets the Kafka cluster external addresses from the kafkaCluster CR. +// When externalListenerName is not specified it uses the first externalListener name in the CR to get addresses. +func getExternalListenerAddresses(kubectlOptions k8s.KubectlOptions, externalListenerName, kafkaClusterName string) ([]string, error) { + By(fmt.Sprintf("Getting Kafka cluster '%s' external listener addresses", kafkaClusterName)) + if externalListenerName == "" { + By("Getting external listener names") + externalListenerNames, err := getK8sResources(kubectlOptions, + []string{kafkaKind}, + "", + kafkaClusterName, + kubectlArgGoTemplateExternalListenersName, + ) + if err != nil { + return nil, fmt.Errorf("getting external listeners name: %w", err) + } + if len(externalListenerNames) == 0 { + return nil, fmt.Errorf("external listener %w", ErrorNotFound) + } + + externalListenerName = externalListenerNames[0] + } + By(fmt.Sprintf("Using external listener name: '%s'", externalListenerName)) + externalListenerAddresses, err := getK8sResources(kubectlOptions, + []string{kafkaKind}, + "", + kafkaClusterName, + fmt.Sprintf(kubectlArgGoTemplateExternalListenerAddressesTemplate, externalListenerName), + ) + if err != nil { + return nil, fmt.Errorf("getting external listener addresses: %w", err) + } + if len(externalListenerAddresses) == 0 { + return nil, fmt.Errorf("external listener address %w", ErrorNotFound) + } + + return externalListenerAddresses, nil + +} + +// requireAvailableExternalKafkaAddress checks that is there any available external address for the Kafka cluster. +func requireAvailableExternalKafkaAddress(kubectlOptions k8s.KubectlOptions, externalListenerName, kafkaClusterName string) { + It(fmt.Sprintf("Checks that the KafkaCluster '%s' has external address", kafkaClusterName), func() { + _, err := getExternalListenerAddresses(kubectlOptions, externalListenerName, kafkaClusterName) + Expect(err).ShouldNot(HaveOccurred()) + }) +} diff --git a/tests/e2e/test_produce_consume.go b/tests/e2e/test_produce_consume.go index b2ba7c73e..a20b0f1be 100644 --- a/tests/e2e/test_produce_consume.go +++ b/tests/e2e/test_produce_consume.go @@ -19,9 +19,32 @@ func testProduceConsumeInternal() bool { kubectlOptions.Namespace = koperatorLocalHelmDescriptor.Namespace requireDeployingKcatPod(kubectlOptions, kcatPodName) - requireDeployingKafkaTopic(kubectlOptions, testTopicName) - requireInternalProducingConsumingMessage(kubectlOptions, "", kcatPodName, testTopicName) - requireDeleteKafkaTopic(kubectlOptions, testTopicName) + requireDeployingKafkaTopic(kubectlOptions, testInternalTopicName) + requireInternalProducingConsumingMessage(kubectlOptions, "", kcatPodName, testInternalTopicName) + requireDeleteKafkaTopic(kubectlOptions, testInternalTopicName) requireDeleteKcatPod(kubectlOptions, kcatPodName) }) } + +func testProduceConsumeExternal(tlsSecretName string) bool { + return When("Externally produce and consume message to/from Kafka cluster", func() { + var kubectlOptions k8s.KubectlOptions + var err error + + It("Acquiring K8s config and context", func() { + kubectlOptions, err = kubectlOptionsForCurrentContext() + Expect(err).NotTo(HaveOccurred()) + }) + + kubectlOptions.Namespace = koperatorLocalHelmDescriptor.Namespace + + requireDeployingKafkaTopic(kubectlOptions, testExternalTopicName) + // requireAvailableExternalKafkaAddress is not necessary now but I think later can be useful + // when we need to wait before consuming producing to get LB service ip address and domain resolution + // in those cases when externalListener added dynamically. + // Currently we dont know much about our testing environment. + // requireAvailableExternalKafkaAddress(kubectlOptions, "", kafkaClusterName) + requireExternalProducingConsumingMessage(kubectlOptions, testExternalTopicName, tlsSecretName) + requireDeleteKafkaTopic(kubectlOptions, testExternalTopicName) + }) +} From 61584fd7105766c3f8bc86bd54c1babaa4cb085b Mon Sep 17 00:00:00 2001 From: marbarta Date: Thu, 22 Jun 2023 06:12:19 +0200 Subject: [PATCH 24/24] refactor: getting external listeners name --- tests/e2e/produce_consume.go | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/tests/e2e/produce_consume.go b/tests/e2e/produce_consume.go index 23b08564b..d54dee9fb 100644 --- a/tests/e2e/produce_consume.go +++ b/tests/e2e/produce_consume.go @@ -133,25 +133,31 @@ func requireExternalProducingConsumingMessage(kubectlOptions k8s.KubectlOptions, }) } +// getExternalListenerNames gets the names of the KafkaCluster CR's external listeners. +func getExternalListenerNames(kubectlOptions k8s.KubectlOptions, kafkaClusterName string) ([]string, error) { + By("Getting external listener names from KafkaCluster status") + externalListenerNames, err := getK8sResources(kubectlOptions, + []string{kafkaKind}, + "", + kafkaClusterName, + kubectlArgGoTemplateExternalListenersName, + ) + if err != nil { + return nil, fmt.Errorf("getting external listeners name: %w", err) + } + return externalListenerNames, nil +} + // getExternalListenerAddresses gets the Kafka cluster external addresses from the kafkaCluster CR. // When externalListenerName is not specified it uses the first externalListener name in the CR to get addresses. func getExternalListenerAddresses(kubectlOptions k8s.KubectlOptions, externalListenerName, kafkaClusterName string) ([]string, error) { By(fmt.Sprintf("Getting Kafka cluster '%s' external listener addresses", kafkaClusterName)) if externalListenerName == "" { - By("Getting external listener names") - externalListenerNames, err := getK8sResources(kubectlOptions, - []string{kafkaKind}, - "", - kafkaClusterName, - kubectlArgGoTemplateExternalListenersName, - ) + externalListenerNames, err := getExternalListenerNames(kubectlOptions, kafkaClusterName) if err != nil { - return nil, fmt.Errorf("getting external listeners name: %w", err) + return nil, err } - if len(externalListenerNames) == 0 { - return nil, fmt.Errorf("external listener %w", ErrorNotFound) - } - + Expect(getExternalListenerNames).ShouldNot(BeEmpty()) externalListenerName = externalListenerNames[0] } By(fmt.Sprintf("Using external listener name: '%s'", externalListenerName))