Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ test-testdata: ## Run the tests of the testdata directory
.PHONY: test-e2e-local
test-e2e-local: ## Run the end-to-end tests locally
## To keep the same kind cluster between test runs, use `SKIP_KIND_CLEANUP=1 make test-e2e-local`
## To lock to a specific kubectl context, use `KUBE_CONTEXT=kind-test make test-e2e-local`
./test/e2e/local.sh

.PHONY: test-e2e-ci
Expand Down
7 changes: 5 additions & 2 deletions docs/book/src/cronjob-tutorial/testdata/project/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,11 @@ test: manifests generate fmt vet setup-envtest ## Run tests.

# TODO(user): To use a different vendor for e2e tests, modify the setup under 'tests/e2e'.
# The default setup assumes Kind is pre-installed and builds/loads the Manager Docker image locally.
# CertManager is installed by default; skip with:
# - CERT_MANAGER_INSTALL_SKIP=true
# Environment variables:
# - KIND_CLUSTER: Name of the Kind cluster (default: project-test-e2e)
# - KUBE_CONTEXT: Kubectl context to use (default: current-context)
# - CERT_MANAGER_INSTALL_SKIP=true: Skip CertManager installation
# Note: When KIND_CLUSTER=my-cluster, the kubectl context will be "kind-my-cluster"
KIND_CLUSTER ?= project-test-e2e

.PHONY: setup-test-e2e
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"fmt"
"os"
"os/exec"
"strings"
"testing"

. "github.com/onsi/ginkgo/v2"
Expand All @@ -43,7 +44,12 @@ var (
// TestE2E runs the e2e test suite to validate the solution in an isolated environment.
// The default setup requires Kind and CertManager.
//
// To skip CertManager installation, set: CERT_MANAGER_INSTALL_SKIP=true
// Environment variables (see Makefile target 'test-e2e' for examples):
// - KIND_CLUSTER: Name of the Kind cluster (default: kind)
// - KUBE_CONTEXT: Kubectl context to use (default: current-context)
// - CERT_MANAGER_INSTALL_SKIP=true: Skip CertManager installation
//
// Note: When KIND_CLUSTER=my-cluster, the kubectl context will be "kind-my-cluster"
func TestE2E(t *testing.T) {
RegisterFailHandler(Fail)
_, _ = fmt.Fprintf(GinkgoWriter, "Starting project e2e test suite\n")
Expand All @@ -54,6 +60,13 @@ var _ = BeforeSuite(func() {
By("Ensure that Prometheus is enabled")
_ = utils.UncommentCode("config/default/kustomization.yaml", "#- ../prometheus", "#")

// Display kubectl context being used
if kubectx := os.Getenv("KUBE_CONTEXT"); kubectx != "" {
_, _ = fmt.Fprintf(GinkgoWriter, "Using context: %s\n", kubectx)
} else if currentCtx, err := getCurrentContext(); err == nil {
_, _ = fmt.Fprintf(GinkgoWriter, "Using context: %s\n", currentCtx)
}

By("building the manager image")
cmd := exec.Command("make", "docker-build", fmt.Sprintf("IMG=%s", managerImage))
_, err := utils.Run(cmd)
Expand Down Expand Up @@ -119,3 +132,13 @@ func teardownCertManager() {
By("uninstalling CertManager")
utils.UninstallCertManager()
}

// getCurrentContext returns the current kubectl context name
func getCurrentContext() (string, error) {
cmd := exec.Command("kubectl", "config", "current-context")
output, err := cmd.Output()
if err != nil {
return "", err
}
return strings.TrimSpace(string(output)), nil
}
7 changes: 5 additions & 2 deletions docs/book/src/getting-started/testdata/project/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,11 @@ test: manifests generate fmt vet setup-envtest ## Run tests.

# TODO(user): To use a different vendor for e2e tests, modify the setup under 'tests/e2e'.
# The default setup assumes Kind is pre-installed and builds/loads the Manager Docker image locally.
# CertManager is installed by default; skip with:
# - CERT_MANAGER_INSTALL_SKIP=true
# Environment variables:
# - KIND_CLUSTER: Name of the Kind cluster (default: project-test-e2e)
# - KUBE_CONTEXT: Kubectl context to use (default: current-context)
# - CERT_MANAGER_INSTALL_SKIP=true: Skip CertManager installation
# Note: When KIND_CLUSTER=my-cluster, the kubectl context will be "kind-my-cluster"
KIND_CLUSTER ?= project-test-e2e

.PHONY: setup-test-e2e
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"fmt"
"os"
"os/exec"
"strings"
"testing"

. "github.com/onsi/ginkgo/v2"
Expand All @@ -41,14 +42,26 @@ var (
// TestE2E runs the e2e test suite to validate the solution in an isolated environment.
// The default setup requires Kind and CertManager.
//
// To skip CertManager installation, set: CERT_MANAGER_INSTALL_SKIP=true
// Environment variables (see Makefile target 'test-e2e' for examples):
// - KIND_CLUSTER: Name of the Kind cluster (default: kind)
// - KUBE_CONTEXT: Kubectl context to use (default: current-context)
// - CERT_MANAGER_INSTALL_SKIP=true: Skip CertManager installation
//
// Note: When KIND_CLUSTER=my-cluster, the kubectl context will be "kind-my-cluster"
func TestE2E(t *testing.T) {
RegisterFailHandler(Fail)
_, _ = fmt.Fprintf(GinkgoWriter, "Starting project e2e test suite\n")
RunSpecs(t, "e2e suite")
}

var _ = BeforeSuite(func() {
// Display kubectl context being used
if kubectx := os.Getenv("KUBE_CONTEXT"); kubectx != "" {
_, _ = fmt.Fprintf(GinkgoWriter, "Using context: %s\n", kubectx)
} else if currentCtx, err := getCurrentContext(); err == nil {
_, _ = fmt.Fprintf(GinkgoWriter, "Using context: %s\n", currentCtx)
}

By("building the manager image")
cmd := exec.Command("make", "docker-build", fmt.Sprintf("IMG=%s", managerImage))
_, err := utils.Run(cmd)
Expand Down Expand Up @@ -99,3 +112,13 @@ func teardownCertManager() {
By("uninstalling CertManager")
utils.UninstallCertManager()
}

// getCurrentContext returns the current kubectl context name
func getCurrentContext() (string, error) {
cmd := exec.Command("kubectl", "config", "current-context")
output, err := cmd.Output()
if err != nil {
return "", err
}
return strings.TrimSpace(string(output)), nil
}
7 changes: 5 additions & 2 deletions docs/book/src/multiversion-tutorial/testdata/project/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,11 @@ test: manifests generate fmt vet setup-envtest ## Run tests.

# TODO(user): To use a different vendor for e2e tests, modify the setup under 'tests/e2e'.
# The default setup assumes Kind is pre-installed and builds/loads the Manager Docker image locally.
# CertManager is installed by default; skip with:
# - CERT_MANAGER_INSTALL_SKIP=true
# Environment variables:
# - KIND_CLUSTER: Name of the Kind cluster (default: project-test-e2e)
# - KUBE_CONTEXT: Kubectl context to use (default: current-context)
# - CERT_MANAGER_INSTALL_SKIP=true: Skip CertManager installation
# Note: When KIND_CLUSTER=my-cluster, the kubectl context will be "kind-my-cluster"
KIND_CLUSTER ?= project-test-e2e

.PHONY: setup-test-e2e
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"fmt"
"os"
"os/exec"
"strings"
"testing"

. "github.com/onsi/ginkgo/v2"
Expand All @@ -43,7 +44,12 @@ var (
// TestE2E runs the e2e test suite to validate the solution in an isolated environment.
// The default setup requires Kind and CertManager.
//
// To skip CertManager installation, set: CERT_MANAGER_INSTALL_SKIP=true
// Environment variables (see Makefile target 'test-e2e' for examples):
// - KIND_CLUSTER: Name of the Kind cluster (default: kind)
// - KUBE_CONTEXT: Kubectl context to use (default: current-context)
// - CERT_MANAGER_INSTALL_SKIP=true: Skip CertManager installation
//
// Note: When KIND_CLUSTER=my-cluster, the kubectl context will be "kind-my-cluster"
func TestE2E(t *testing.T) {
RegisterFailHandler(Fail)
_, _ = fmt.Fprintf(GinkgoWriter, "Starting project e2e test suite\n")
Expand All @@ -54,6 +60,13 @@ var _ = BeforeSuite(func() {
By("Ensure that Prometheus is enabled")
_ = utils.UncommentCode("config/default/kustomization.yaml", "#- ../prometheus", "#")

// Display kubectl context being used
if kubectx := os.Getenv("KUBE_CONTEXT"); kubectx != "" {
_, _ = fmt.Fprintf(GinkgoWriter, "Using context: %s\n", kubectx)
} else if currentCtx, err := getCurrentContext(); err == nil {
_, _ = fmt.Fprintf(GinkgoWriter, "Using context: %s\n", currentCtx)
}

By("building the manager image")
cmd := exec.Command("make", "docker-build", fmt.Sprintf("IMG=%s", managerImage))
_, err := utils.Run(cmd)
Expand Down Expand Up @@ -119,3 +132,13 @@ func teardownCertManager() {
By("uninstalling CertManager")
utils.UninstallCertManager()
}

// getCurrentContext returns the current kubectl context name
func getCurrentContext() (string, error) {
cmd := exec.Command("kubectl", "config", "current-context")
output, err := cmd.Output()
if err != nil {
return "", err
}
return strings.TrimSpace(string(output)), nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,11 @@ test: manifests generate fmt vet setup-envtest ## Run tests.
# TODO(user): To use a different vendor for e2e tests, modify the setup under 'tests/e2e'.
# The default setup assumes Kind is pre-installed and builds/loads the Manager Docker image locally.
# CertManager is installed by default; skip with:
# - CERT_MANAGER_INSTALL_SKIP=true
# Environment variables:
# - KIND_CLUSTER: Name of the Kind cluster (default: {{ .ProjectName }}-test-e2e)
# - KUBE_CONTEXT: Kubectl context to use (default: current-context)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ran make test-e2e without passing the KUBE_CONTEXT env var and got this:

@vitorfloriano ➜ /workspaces/test-operator $ make test-e2e
No kind clusters found.
Creating Kind cluster 'test-operator-test-e2e'...
Creating cluster "test-operator-test-e2e" ...
 ✓ Ensuring node image (kindest/node:v1.35.0) 🖼
 ✓ Preparing nodes 📦  
 ✓ Writing configuration 📜 
 ✓ Starting control-plane 🕹️ 
 ✓ Installing CNI 🔌 
 ✓ Installing StorageClass 💾 
Set kubectl context to "kind-test-operator-test-e2e"
You can now use your cluster with:

kubectl cluster-info --context kind-test-operator-test-e2e

Have a question, bug, or feature request? Let us know! https://kind.sigs.k8s.io/#community 🙂
mkdir -p "/workspaces/test-operator/bin"
Downloading sigs.k8s.io/controller-tools/cmd/[email protected]
"/workspaces/test-operator/bin/controller-gen" rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases
"/workspaces/test-operator/bin/controller-gen" object:headerFile="hack/boilerplate.go.txt" paths="./..."
go fmt ./...
go vet ./...
KIND=kind KIND_CLUSTER=test-operator-test-e2e go test -tags=e2e ./test/e2e/ -v -ginkgo.v

So I believe the default KUBE_CONTEXT would be kind-{{ .ProjectName }}-test-e2e, right?

Suggested change
# - KUBE_CONTEXT: Kubectl context to use (default: current-context)
# - KUBE_CONTEXT: Kubectl context to use (default: kind-{{ .ProjectName }}-test-e2e)

# - CERT_MANAGER_INSTALL_SKIP=true: Skip CertManager installation
# Note: When KIND_CLUSTER=my-cluster, the kubectl context will be "kind-my-cluster"
KIND_CLUSTER ?= {{ .ProjectName }}-test-e2e
.PHONY: setup-test-e2e
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import (
"fmt"
"os"
"os/exec"
"strings"
"testing"

. "github.com/onsi/ginkgo/v2"
Expand All @@ -69,14 +70,26 @@ var (
// TestE2E runs the e2e test suite to validate the solution in an isolated environment.
// The default setup requires Kind and CertManager.
//
// To skip CertManager installation, set: CERT_MANAGER_INSTALL_SKIP=true
// Environment variables (see Makefile target 'test-e2e' for examples):
// - KIND_CLUSTER: Name of the Kind cluster (default: kind)
// - KUBE_CONTEXT: Kubectl context to use (default: current-context)
// - CERT_MANAGER_INSTALL_SKIP=true: Skip CertManager installation
//
// Note: When KIND_CLUSTER=my-cluster, the kubectl context will be "kind-my-cluster"
Comment on lines +73 to +78
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be the exact same as in the Makefile?

Suggested change
// Environment variables (see Makefile target 'test-e2e' for examples):
// - KIND_CLUSTER: Name of the Kind cluster (default: kind)
// - KUBE_CONTEXT: Kubectl context to use (default: current-context)
// - CERT_MANAGER_INSTALL_SKIP=true: Skip CertManager installation
//
// Note: When KIND_CLUSTER=my-cluster, the kubectl context will be "kind-my-cluster"
// Environment variables:
// - KIND_CLUSTER: Name of the Kind cluster (default: {{ .ProjectName }}-test-e2e)
// - KUBE_CONTEXT: Kubectl context to use (default: kind-{{ .ProjectName }}-test-e2e)
// - CERT_MANAGER_INSTALL_SKIP=true: Skip CertManager installation
//
// Note: When KIND_CLUSTER=my-cluster, the kubectl context will be "kind-my-cluster"

func TestE2E(t *testing.T) {
RegisterFailHandler(Fail)
_, _ = fmt.Fprintf(GinkgoWriter, "Starting {{ .ProjectName }} e2e test suite\n")
RunSpecs(t, "e2e suite")
}

var _ = BeforeSuite(func() {
// Display kubectl context being used
if kubectx := os.Getenv("KUBE_CONTEXT"); kubectx != "" {
_, _ = fmt.Fprintf(GinkgoWriter, "Using context: %s\n", kubectx)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ran KUBE_CONTEXT=kind-inexistent-cluster make test-e2e to check if the test suite would fail but it seems that we are not checking if the context is valid before running the tests. And again, kind created the default test cluster, ignoring KUBE_CONTEXT:

@vitorfloriano ➜ /workspaces/test-operator $ KUBE_CONTEXT=kind-inexistent-cluster make test-e2e
Creating Kind cluster 'test-operator-test-e2e'...
Creating cluster "test-operator-test-e2e" ...
 ✓ Ensuring node image (kindest/node:v1.35.0) 🖼
 ✓ Preparing nodes 📦  
 ✓ Writing configuration 📜 
 ✓ Starting control-plane 🕹️ 
 ✓ Installing CNI 🔌 
 ✓ Installing StorageClass 💾 
Set kubectl context to "kind-test-operator-test-e2e"
You can now use your cluster with:

kubectl cluster-info --context kind-test-operator-test-e2e

Not sure what to do next? 😅  Check out https://kind.sigs.k8s.io/docs/user/quick-start/
"/workspaces/test-operator/bin/controller-gen" rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases
"/workspaces/test-operator/bin/controller-gen" object:headerFile="hack/boilerplate.go.txt" paths="./..."
go fmt ./...
go vet ./...
KIND=kind KIND_CLUSTER=test-operator-test-e2e go test -tags=e2e ./test/e2e/ -v -ginkgo.v
=== RUN   TestE2E
  Starting test-operator e2e test suite
Running Suite: e2e suite - /workspaces/test-operator/test/e2e
=============================================================
Random Seed: 1769785208

Will run 2 of 2 specs
------------------------------
[BeforeSuite] 
/workspaces/test-operator/test/e2e/e2e_suite_test.go:57
  Using context: kind-inexistent-cluster
...
...
...
[AfterSuite] PASSED [13.291 seconds]
------------------------------

Ran 2 of 2 Specs in 98.106 seconds
SUCCESS! -- 2 Passed | 0 Failed | 0 Pending | 0 Skipped
--- PASS: TestE2E (98.11s)
PASS
ok      myoperator/my-operator/test/e2e 98.118s
make cleanup-test-e2e
make[1]: Entering directory '/workspaces/test-operator'
Deleting cluster "test-operator-test-e2e" ...
Deleted nodes: ["test-operator-test-e2e-control-plane"]
make[1]: Leaving directory '/workspaces/test-operator'

} else if currentCtx, err := getCurrentContext(); err == nil {
_, _ = fmt.Fprintf(GinkgoWriter, "Using context: %s\n", currentCtx)
}

By("building the manager image")
cmd := exec.Command("make", "docker-build", fmt.Sprintf("IMG=%s", managerImage))
_, err := utils.Run(cmd)
Expand Down Expand Up @@ -127,4 +140,14 @@ func teardownCertManager() {
By("uninstalling CertManager")
utils.UninstallCertManager()
}

// getCurrentContext returns the current kubectl context name
func getCurrentContext() (string, error) {
cmd := exec.Command("kubectl", "config", "current-context")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't we simply extract the context that is create by default by kind when running the e2e test (kind-{{ .ProjectName }}-test-e2e) and assign it to KUBE_CONTEXT?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would make the test fail if I just create kind and run the tests via IDE, for example

output, err := cmd.Output()
if err != nil {
return "", err
}
return strings.TrimSpace(string(output)), nil
}
`
11 changes: 10 additions & 1 deletion test/e2e/utils/kubectl.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,20 @@ type Kubectl struct {
*CmdContext
Namespace string
ServiceAccount string
KubeContext string
}

// cmdOptionsWithContext prepends --context flag to kubectl commands if KubeContext is set
func (k *Kubectl) cmdOptionsWithContext(cmdOptions ...string) []string {
if k.KubeContext != "" {
return append([]string{"--context", k.KubeContext}, cmdOptions...)
}
return cmdOptions
Comment on lines +37 to +41
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One more thing: I created the new cluster (my-beloved-cluster), checked that it was the current context, and ran KUBE_CONTEXT=kind-my-beloved-cluster make test-e2e and noticed that --context kind-my-beloved-cluster is not appended to the commands in the logs, so I believe all the commands are still being run against the default context that kind creates for the test, not the one that was informed:

@vitorfloriano ➜ /workspaces/test-operator $ kubectl config get-contexts
CURRENT   NAME                      CLUSTER                   AUTHINFO                  NAMESPACE
          kind-kind                 kind-kind                 kind-kind                 
*         kind-my-beloved-cluster   kind-my-beloved-cluster   kind-my-beloved-cluster   
          kind-my-other-cluster     kind-my-other-cluster     kind-my-other-cluster     
@vitorfloriano ➜ /workspaces/test-operator $ kubectl config current-context
kind-my-beloved-cluster
@vitorfloriano ➜ /workspaces/test-operator $ KUBE_CONTEXT=kind-my-beloved-cluster make test-e2e
Creating Kind cluster 'test-operator-test-e2e'...
Creating cluster "test-operator-test-e2e" ...
 ✓ Ensuring node image (kindest/node:v1.35.0) 🖼
 ✓ Preparing nodes 📦  
 ✓ Writing configuration 📜 
 ✓ Starting control-plane 🕹️ 
 ✓ Installing CNI 🔌 
 ✓ Installing StorageClass 💾 
Set kubectl context to "kind-test-operator-test-e2e"
You can now use your cluster with:

kubectl cluster-info --context kind-test-operator-test-e2e

Not sure what to do next? 😅  Check out https://kind.sigs.k8s.io/docs/user/quick-start/
"/workspaces/test-operator/bin/controller-gen" rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases
"/workspaces/test-operator/bin/controller-gen" object:headerFile="hack/boilerplate.go.txt" paths="./..."
go fmt ./...
go vet ./...
KIND=kind KIND_CLUSTER=test-operator-test-e2e go test -tags=e2e ./test/e2e/ -v -ginkgo.v
=== RUN   TestE2E
  Starting test-operator e2e test suite
Running Suite: e2e suite - /workspaces/test-operator/test/e2e
=============================================================
Random Seed: 1769800186

Will run 2 of 2 specs
------------------------------
[BeforeSuite] 
/workspaces/test-operator/test/e2e/e2e_suite_test.go:57
  Using context: kind-my-beloved-cluster
  STEP: building the manager image @ 01/30/26 19:09:46.913
  running: "make docker-build IMG=example.com/test-operator:v0.0.1"
  STEP: loading the manager image on Kind @ 01/30/26 19:09:50.887
  running: "kind load docker-image example.com/test-operator:v0.0.1 --name test-operator-test-e2e"
  STEP: checking if CertManager is already installed @ 01/30/26 19:10:03.03
  running: "kubectl get crds"
  STEP: installing CertManager @ 01/30/26 19:10:03.977
  running: "kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.19.2/cert-manager.yaml"
  running: "kubectl wait deployment.apps/cert-manager-webhook --for condition=Available --namespace cert-manager --timeout 5m"
[BeforeSuite] PASSED [46.131 seconds]
------------------------------
Manager Manager should run successfully
/workspaces/test-operator/test/e2e/e2e_test.go:144
  STEP: creating manager namespace @ 01/30/26 19:10:33.053
  running: "kubectl create ns test-operator-system"
  STEP: labeling the namespace to enforce the restricted security policy @ 01/30/26 19:10:33.233
  running: "kubectl label --overwrite ns test-operator-system pod-security.kubernetes.io/enforce=restricted"
  STEP: installing CRDs @ 01/30/26 19:10:33.399
  running: "make install"
  STEP: deploying the controller-manager @ 01/30/26 19:10:47.954
  running: "make deploy IMG=example.com/test-operator:v0.0.1"
  STEP: validating that the controller-manager pod is running as expected @ 01/30/26 19:11:00.311
  running: "kubectl get pods -l control-plane=controller-manager -o go-template={{ range .items }}{{ if not .metadata.deletionTimestamp }}{{ .metadata.name }}{{ \"\\n\" }}{{ end }}{{ end }} -n test-operator-system"
  running: "kubectl get pods test-operator-controller-manager-5d47b4fbc8-8wb27 -o jsonpath={.status.phase} -n test-operator-system"
  running: "kubectl get pods -l control-plane=controller-manager -o go-template={{ range .items }}{{ if not .metadata.deletionTimestamp }}{{ .metadata.name }}{{ \"\\n\" }}{{ end }}{{ end }} -n test-operator-system"
  running: "kubectl get pods test-operator-controller-manager-5d47b4fbc8-8wb27 -o jsonpath={.status.phase} -n test-operator-system"
  running: "kubectl get pods -l control-plane=controller-manager -o go-template={{ range .items }}{{ if not .metadata.deletionTimestamp }}{{ .metadata.name }}{{ \"\\n\" }}{{ end }}{{ end }} -n test-operator-system"
  running: "kubectl get pods test-operator-controller-manager-5d47b4fbc8-8wb27 -o jsonpath={.status.phase} -n test-operator-system"
• [30.363 seconds]
------------------------------
Manager Manager should ensure the metrics endpoint is serving metrics
/workspaces/test-operator/test/e2e/e2e_test.go:176
  STEP: creating a ClusterRoleBinding for the service account to allow access to metrics @ 01/30/26 19:11:03.414
  running: "kubectl create clusterrolebinding test-operator-metrics-binding --clusterrole=test-operator-metrics-reader --serviceaccount=test-operator-system:test-operator-controller-manager"
  STEP: validating that the metrics service is available @ 01/30/26 19:11:03.559
  running: "kubectl get service test-operator-controller-manager-metrics-service -n test-operator-system"
  STEP: getting the service account token @ 01/30/26 19:11:03.708
  STEP: ensuring the controller pod is ready @ 01/30/26 19:11:03.839
  running: "kubectl get pod test-operator-controller-manager-5d47b4fbc8-8wb27 -n test-operator-system -o jsonpath={.status.conditions[?(@.type=='Ready')].status}"
  running: "kubectl get pod test-operator-controller-manager-5d47b4fbc8-8wb27 -n test-operator-system -o jsonpath={.status.conditions[?(@.type=='Ready')].status}"
  running: "kubectl get pod test-operator-controller-manager-5d47b4fbc8-8wb27 -n test-operator-system -o jsonpath={.status.conditions[?(@.type=='Ready')].status}"
  running: "kubectl get pod test-operator-controller-manager-5d47b4fbc8-8wb27 -n test-operator-system -o jsonpath={.status.conditions[?(@.type=='Ready')].status}"
  running: "kubectl get pod test-operator-controller-manager-5d47b4fbc8-8wb27 -n test-operator-system -o jsonpath={.status.conditions[?(@.type=='Ready')].status}"
  running: "kubectl get pod test-operator-controller-manager-5d47b4fbc8-8wb27 -n test-operator-system -o jsonpath={.status.conditions[?(@.type=='Ready')].status}"
  running: "kubectl get pod test-operator-controller-manager-5d47b4fbc8-8wb27 -n test-operator-system -o jsonpath={.status.conditions[?(@.type=='Ready')].status}"
  running: "kubectl get pod test-operator-controller-manager-5d47b4fbc8-8wb27 -n test-operator-system -o jsonpath={.status.conditions[?(@.type=='Ready')].status}"
  running: "kubectl get pod test-operator-controller-manager-5d47b4fbc8-8wb27 -n test-operator-system -o jsonpath={.status.conditions[?(@.type=='Ready')].status}"
  STEP: verifying that the controller manager is serving the metrics server @ 01/30/26 19:11:12.977
  running: "kubectl logs test-operator-controller-manager-5d47b4fbc8-8wb27 -n test-operator-system"
  STEP: creating the curl-metrics pod to access the metrics endpoint @ 01/30/26 19:11:13.184
  running: "kubectl run curl-metrics --restart=Never --namespace test-operator-system --image=curlimages/curl:latest --overrides {\n\t\t\t\t\t\"spec\": {\n\t\t\t\t\t\t\"containers\": [{\n\t\t\t\t\t\t\t\"name\": \"curl\",\n\t\t\t\t\t\t\t\"image\": \"curlimages/curl:latest\",\n\t\t\t\t\t\t\t\"command\": [\"/bin/sh\", \"-c\"],\n\t\t\t\t\t\t\t\"args\": [\"curl -v -k -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IjZHTzJMSGtOdDdpcHpkVnowY2ttcmFtT2RoTDh3YU8wNC1BNjliaHNGekkifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNzY5ODAzODYzLCJpYXQiOjE3Njk4MDAyNjMsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwianRpIjoiNzU5NjllZDUtZWM4MC00ODJmLTlkMTctYzg3NzU4ZDYwMzZkIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJ0ZXN0LW9wZXJhdG9yLXN5c3RlbSIsInNlcnZpY2VhY2NvdW50Ijp7Im5hbWUiOiJ0ZXN0LW9wZXJhdG9yLWNvbnRyb2xsZXItbWFuYWdlciIsInVpZCI6ImJlYzE5YjcxLTIyOTYtNGI1Mi1hNDI5LThhY2YzMTA0NmE1ZSJ9fSwibmJmIjoxNzY5ODAwMjYzLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6dGVzdC1vcGVyYXRvci1zeXN0ZW06dGVzdC1vcGVyYXRvci1jb250cm9sbGVyLW1hbmFnZXIifQ.U20ttwPDjNq1sqbyzIT5I5Ugw7_fai2KgAJkvylyGIeGXDEtJW-L7ohQv29-7YKDBRri4dRgbOXHaC8drCySMIXZU9xNFLD37o7CGtJC3WJdG03jf3rlfveNU8E60LyUllZpoTzwt6sY8EmIJrllcjumQxFF4aYrblxpvl5rru8GhPDD7NB3CPP0WwZ0-SCGByQnPiYXyaL0OD9sCjaxc3ORwpKqvDQEwyvPJugarJdv-ThIqGTid6ZaWcRoaZgHQJIdzjUxykG7d_auab5R_ipYXitfE-YQ6jI-6wXHsIi_XEHDeH1dPteNfSSSknPZjntw9INlt1ML4Hv-X97sqQ' https://test-operator-controller-manager-metrics-service.test-operator-system.svc.cluster.local:8443/metrics\"],\n\t\t\t\t\t\t\t\"securityContext\": {\n\t\t\t\t\t\t\t\t\"readOnlyRootFilesystem\": true,\n\t\t\t\t\t\t\t\t\"allowPrivilegeEscalation\": false,\n\t\t\t\t\t\t\t\t\"capabilities\": {\n\t\t\t\t\t\t\t\t\t\"drop\": [\"ALL\"]\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"runAsNonRoot\": true,\n\t\t\t\t\t\t\t\t\"runAsUser\": 1000,\n\t\t\t\t\t\t\t\t\"seccompProfile\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"RuntimeDefault\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}],\n\t\t\t\t\t\t\"serviceAccountName\": \"test-operator-controller-manager\"\n\t\t\t\t\t}\n\t\t\t\t}"
  STEP: waiting for the curl-metrics pod to complete. @ 01/30/26 19:11:13.284
  running: "kubectl get pods curl-metrics -o jsonpath={.status.phase} -n test-operator-system"
  running: "kubectl get pods curl-metrics -o jsonpath={.status.phase} -n test-operator-system"
  running: "kubectl get pods curl-metrics -o jsonpath={.status.phase} -n test-operator-system"
  running: "kubectl get pods curl-metrics -o jsonpath={.status.phase} -n test-operator-system"
  running: "kubectl get pods curl-metrics -o jsonpath={.status.phase} -n test-operator-system"
  running: "kubectl get pods curl-metrics -o jsonpath={.status.phase} -n test-operator-system"
  STEP: getting the metrics by checking curl-metrics logs @ 01/30/26 19:11:19.045
  STEP: getting the curl-metrics logs @ 01/30/26 19:11:19.046
  running: "kubectl logs curl-metrics -n test-operator-system"
  STEP: cleaning up the curl pod for metrics @ 01/30/26 19:11:19.172
  running: "kubectl delete pod curl-metrics -n test-operator-system"
  STEP: undeploying the controller-manager @ 01/30/26 19:11:19.266
  running: "make undeploy"
  STEP: uninstalling CRDs @ 01/30/26 19:11:25.375
  running: "make uninstall"
  STEP: removing manager namespace @ 01/30/26 19:11:41.654
  running: "kubectl delete ns test-operator-system"
• [38.914 seconds]
------------------------------
[AfterSuite] 
/workspaces/test-operator/test/e2e/e2e_suite_test.go:79
  STEP: uninstalling CertManager @ 01/30/26 19:11:42.331
  running: "kubectl delete -f https://github.com/cert-manager/cert-manager/releases/download/v1.19.2/cert-manager.yaml"
  running: "kubectl delete lease cert-manager-cainjector-leader-election -n kube-system --ignore-not-found --force --grace-period=0"
  running: "kubectl delete lease cert-manager-controller -n kube-system --ignore-not-found --force --grace-period=0"
[AfterSuite] PASSED [19.090 seconds]
------------------------------

Ran 2 of 2 Specs in 134.508 seconds
SUCCESS! -- 2 Passed | 0 Failed | 0 Pending | 0 Skipped
--- PASS: TestE2E (134.51s)
PASS
ok      myoperator/my-operator/test/e2e 134.517s
make cleanup-test-e2e
make[1]: Entering directory '/workspaces/test-operator'
Deleting cluster "test-operator-test-e2e" ...
Deleted nodes: ["test-operator-test-e2e-control-plane"]
make[1]: Leaving directory '/workspaces/test-operator'

}

// Command is a general func to run kubectl commands
func (k *Kubectl) Command(cmdOptions ...string) (string, error) {
cmd := exec.Command("kubectl", cmdOptions...)
cmd := exec.Command("kubectl", k.cmdOptionsWithContext(cmdOptions...)...)
output, err := k.Run(cmd)
return string(output), err
}
Expand Down
2 changes: 2 additions & 0 deletions test/e2e/utils/test_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ func NewTestContext(binaryName string, env ...string) (*TestContext, error) {
Namespace: fmt.Sprintf("e2e-%s-system", testSuffix),
ServiceAccount: fmt.Sprintf("e2e-%s-controller-manager", testSuffix),
CmdContext: cc,
// Optional context lock from env var
KubeContext: os.Getenv("KUBE_CONTEXT"),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created a new cluster (my-beloved-cluster) and and then ran KUBE_CONTEXT=kind-my-beloved-cluster make test-e2e and got this:

@vitorfloriano ➜ /workspaces/test-operator $ kind create cluster --name my-beloved-cluster
Creating cluster "my-beloved-cluster" ...
 ✓ Ensuring node image (kindest/node:v1.35.0) 🖼
 ✓ Preparing nodes 📦  
 ✓ Writing configuration 📜 
 ✓ Starting control-plane 🕹️ 
 ✓ Installing CNI 🔌 
 ✓ Installing StorageClass 💾 
Set kubectl context to "kind-my-beloved-cluster"
You can now use your cluster with:

kubectl cluster-info --context kind-my-beloved-cluster

Have a question, bug, or feature request? Let us know! https://kind.sigs.k8s.io/#community 🙂
@vitorfloriano ➜ /workspaces/test-operator $ KUBE_CONTEXT=kind-my-beloved-cluster make test-e2e
Creating Kind cluster 'test-operator-test-e2e'...
Creating cluster "test-operator-test-e2e" ...
 ✓ Ensuring node image (kindest/node:v1.35.0) 🖼
 ✓ Preparing nodes 📦  
 ✓ Writing configuration 📜 
 ✓ Starting control-plane 🕹️ 
 ✓ Installing CNI 🔌 
 ✓ Installing StorageClass 💾 
Set kubectl context to "kind-test-operator-test-e2e"
You can now use your cluster with:

kubectl cluster-info --context kind-test-operator-test-e2e

Thanks for using kind! 😊
"/workspaces/test-operator/bin/controller-gen" rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases
"/workspaces/test-operator/bin/controller-gen" object:headerFile="hack/boilerplate.go.txt" paths="./..."
go fmt ./...
go vet ./...
KIND=kind KIND_CLUSTER=test-operator-test-e2e go test -tags=e2e ./test/e2e/ -v -ginkgo.v
=== RUN   TestE2E
  Starting test-operator e2e test suite
Running Suite: e2e suite - /workspaces/test-operator/test/e2e
=============================================================
Random Seed: 1769783531

Will run 2 of 2 specs
------------------------------
[BeforeSuite] 
/workspaces/test-operator/test/e2e/e2e_suite_test.go:57
  Using context: kind-my-beloved-cluster
  STEP: building the manager image @ 01/30/26 14:32:11.868
  running: "make docker-build IMG=example.com/test-operator:v0.0.1"

Kind still checked for the default {{ .ProjectName }}-test-e2e cluster and created it, instead of using my-beloved-cluster.

It also passed KIND_CLUSTER=test-operator-test-e2e to go test, instead of passing KIND_CLUSTER=my-beloved-cluster.

But then, before each test, it used the context that was passed, kind-my-beloved-cluster.

So it seems we should either fix the kind cluster creation logic for e2e tests or just adopt the context that is already created by default by kind and lock that one to kubectl --context. WDYT?

}

// For test outside of cluster we do not need to have kubectl
Expand Down
7 changes: 5 additions & 2 deletions testdata/project-v4-multigroup/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,11 @@ test: manifests generate fmt vet setup-envtest ## Run tests.

# TODO(user): To use a different vendor for e2e tests, modify the setup under 'tests/e2e'.
# The default setup assumes Kind is pre-installed and builds/loads the Manager Docker image locally.
# CertManager is installed by default; skip with:
# - CERT_MANAGER_INSTALL_SKIP=true
# Environment variables:
# - KIND_CLUSTER: Name of the Kind cluster (default: project-v4-multigroup-test-e2e)
# - KUBE_CONTEXT: Kubectl context to use (default: current-context)
# - CERT_MANAGER_INSTALL_SKIP=true: Skip CertManager installation
# Note: When KIND_CLUSTER=my-cluster, the kubectl context will be "kind-my-cluster"
KIND_CLUSTER ?= project-v4-multigroup-test-e2e

.PHONY: setup-test-e2e
Expand Down
25 changes: 24 additions & 1 deletion testdata/project-v4-multigroup/test/e2e/e2e_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"fmt"
"os"
"os/exec"
"strings"
"testing"

. "github.com/onsi/ginkgo/v2"
Expand All @@ -41,14 +42,26 @@ var (
// TestE2E runs the e2e test suite to validate the solution in an isolated environment.
// The default setup requires Kind and CertManager.
//
// To skip CertManager installation, set: CERT_MANAGER_INSTALL_SKIP=true
// Environment variables (see Makefile target 'test-e2e' for examples):
// - KIND_CLUSTER: Name of the Kind cluster (default: kind)
// - KUBE_CONTEXT: Kubectl context to use (default: current-context)
// - CERT_MANAGER_INSTALL_SKIP=true: Skip CertManager installation
//
// Note: When KIND_CLUSTER=my-cluster, the kubectl context will be "kind-my-cluster"
func TestE2E(t *testing.T) {
RegisterFailHandler(Fail)
_, _ = fmt.Fprintf(GinkgoWriter, "Starting project-v4-multigroup e2e test suite\n")
RunSpecs(t, "e2e suite")
}

var _ = BeforeSuite(func() {
// Display kubectl context being used
if kubectx := os.Getenv("KUBE_CONTEXT"); kubectx != "" {
_, _ = fmt.Fprintf(GinkgoWriter, "Using context: %s\n", kubectx)
} else if currentCtx, err := getCurrentContext(); err == nil {
_, _ = fmt.Fprintf(GinkgoWriter, "Using context: %s\n", currentCtx)
}

By("building the manager image")
cmd := exec.Command("make", "docker-build", fmt.Sprintf("IMG=%s", managerImage))
_, err := utils.Run(cmd)
Expand Down Expand Up @@ -99,3 +112,13 @@ func teardownCertManager() {
By("uninstalling CertManager")
utils.UninstallCertManager()
}

// getCurrentContext returns the current kubectl context name
func getCurrentContext() (string, error) {
cmd := exec.Command("kubectl", "config", "current-context")
output, err := cmd.Output()
if err != nil {
return "", err
}
return strings.TrimSpace(string(output)), nil
}
7 changes: 5 additions & 2 deletions testdata/project-v4-with-plugins/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,11 @@ test: manifests generate fmt vet setup-envtest ## Run tests.

# TODO(user): To use a different vendor for e2e tests, modify the setup under 'tests/e2e'.
# The default setup assumes Kind is pre-installed and builds/loads the Manager Docker image locally.
# CertManager is installed by default; skip with:
# - CERT_MANAGER_INSTALL_SKIP=true
# Environment variables:
# - KIND_CLUSTER: Name of the Kind cluster (default: project-v4-with-plugins-test-e2e)
# - KUBE_CONTEXT: Kubectl context to use (default: current-context)
# - CERT_MANAGER_INSTALL_SKIP=true: Skip CertManager installation
# Note: When KIND_CLUSTER=my-cluster, the kubectl context will be "kind-my-cluster"
KIND_CLUSTER ?= project-v4-with-plugins-test-e2e

.PHONY: setup-test-e2e
Expand Down
Loading
Loading