| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- /*
- Copyright © The ESO Authors
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- https://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 addon
- import (
- "fmt"
- "os"
- "path/filepath"
- "strconv"
- "strings"
- "github.com/onsi/ginkgo/v2"
- "github.com/onsi/gomega"
- "k8s.io/client-go/kubernetes"
- "k8s.io/client-go/rest"
- crclient "sigs.k8s.io/controller-runtime/pkg/client"
- "github.com/external-secrets/external-secrets-e2e/framework/log"
- "github.com/external-secrets/external-secrets-e2e/framework/util"
- )
- var globalAddons []Addon
- func init() {
- globalAddons = make([]Addon, 0)
- }
- type Config struct {
- // KubeConfig which was used to create the connection.
- KubeConfig *rest.Config
- // Kubernetes API clientsets
- KubeClientSet kubernetes.Interface
- // controller-runtime client for newer controllers
- CRClient crclient.Client
- }
- type Addon interface {
- Setup(*Config) error
- Install() error
- Logs() error
- Uninstall() error
- }
- func InstallGlobalAddon(addon Addon) {
- globalAddons = append(globalAddons, addon)
- cfg := &Config{}
- cfg.KubeConfig, cfg.KubeClientSet, cfg.CRClient = util.NewConfig()
- ginkgo.By("installing global addon")
- err := addon.Setup(cfg)
- gomega.Expect(err).NotTo(gomega.HaveOccurred())
- err = addon.Install()
- if err != nil {
- addon.Logs() // Print logs in case installation fails
- }
- gomega.Expect(err).NotTo(gomega.HaveOccurred())
- }
- func UninstallGlobalAddons() {
- for _, addon := range globalAddons {
- ginkgo.By("uninstalling addon")
- err := addon.Uninstall()
- gomega.Expect(err).NotTo(gomega.HaveOccurred())
- }
- }
- const skipGlobalTeardownVar = "E2E_SKIP_GLOBAL_TEARDOWN"
- // SkipGlobalTeardown reports whether to leave the global addons installed, for a
- // cluster that is about to be discarded. Off unless asked for, and refused when
- // several suites share the cluster, since two of them install the same release.
- func SkipGlobalTeardown() bool {
- raw, ok := os.LookupEnv(skipGlobalTeardownVar)
- if !ok || raw == "" {
- return false
- }
- skip, err := strconv.ParseBool(raw)
- if err != nil {
- // Failing here would unwind the whole AfterSuite, losing the teardown
- // and the logs, so fall back to tearing down and say so.
- teardownLogf("%s is not a boolean (%q), so the teardown will run: %v",
- skipGlobalTeardownVar, raw, err)
- return false
- }
- if !skip {
- return false
- }
- // Only sees this process. Two separate single-suite runs against one cluster
- // would still collide.
- if suites := strings.Fields(os.Getenv("TEST_SUITES")); len(suites) > 1 {
- teardownLogf("%s ignored: suites %q share one cluster, so the global "+
- "addons have to come out between them", skipGlobalTeardownVar,
- strings.Join(suites, " "))
- return false
- }
- teardownLogf("%s set: leaving the global addons installed for the cluster to "+
- "be discarded with", skipGlobalTeardownVar)
- return true
- }
- // teardownLogf logs to stderr, not log.Logf: ginkgo drops GinkgoWriter output
- // for a passing node without -v, and these lines must survive a green run.
- func teardownLogf(format string, args ...any) {
- fmt.Fprintf(os.Stderr, format+"\n", args...)
- }
- // AssetDir returns the path to the k8s asset directory
- // which holds the helm charts, vault and conjur configuration.
- // It starts at the cwd, and walks its way up to the root.
- // It returns /k8s as a fallback.
- // When running the e2e suite locally, this should return $REPO/e2e/k8s,
- // when ran in CI this returns /k8s because the tests run in a dedicated pod where
- // the assets are copied into the container.
- func AssetDir() string {
- // Start from current working directory
- currentDir, err := os.Getwd()
- if err != nil {
- return ""
- }
- // Traverse up the directory tree looking for "k8s" directory
- for {
- k8sPath := filepath.Join(currentDir, "k8s")
- // Check if "k8s" directory exists
- if info, err := os.Stat(k8sPath); err == nil && info.IsDir() {
- return k8sPath
- }
- // Get parent directory
- parentDir := filepath.Dir(currentDir)
- // If we've reached the root directory, stop searching
- if parentDir == currentDir {
- break
- }
- currentDir = parentDir
- }
- return "/k8s"
- }
- func PrintLogs() {
- for _, addon := range globalAddons {
- err := addon.Logs()
- if err != nil {
- log.Logf("error fetching logs: %s", err.Error())
- }
- }
- }
|