Skip to content

Commit 450d120

Browse files
Configure ENVTEST Binaries for IDE Debugging
This change introduces downloading the specific binaries required to run ENVTEST-based tests into the project/bin directory. This setup makes it easier to configure tests for debugging directly in an IDE. Furthermore, no longer install binaries required for ENVTEST based tests on the project/bin instead of global path.
1 parent 7ad65d6 commit 450d120

File tree

3 files changed

+67
-8
lines changed

3 files changed

+67
-8
lines changed

CONTRIBUTING.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,32 @@ you can follow the steps below to test your changes:
5959
make kind-load kind-deploy
6060
```
6161

62+
## How to debug controller tests using ENVTEST
63+
64+
[ENVTEST](https://book.kubebuilder.io/reference/envtest) requires k8s binaries to be downloaded to run the tests.
65+
To download the necessary binaries, follow the steps below:
66+
67+
```sh
68+
make envtest-k8s-bins
69+
```
70+
71+
Note that the binaries are downloaded to the `bin/envtest-binaries` directory.
72+
73+
```sh
74+
$ tree
75+
.
76+
├── envtest-binaries
77+
│   └── k8s
78+
│   └── 1.31.0-darwin-arm64
79+
│   ├── etcd
80+
│   ├── kube-apiserver
81+
│   └── kubectl
82+
```
83+
84+
Now, you can debug them with your IDE:
85+
86+
![Screenshot IDE example](https://github.com/user-attachments/assets/3096d524-0686-48ca-911c-5b843093ad1f)
87+
6288
### Communication Channels
6389

6490
- Email: [operator-framework-olm-dev](mailto:operator-framework-olm-dev@googlegroups.com)

Makefile

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ export WAIT_TIMEOUT := 60s
2929
# Install default ClusterCatalogs
3030
export INSTALL_DEFAULT_CATALOGS := true
3131

32-
# By default setup-envtest will write to $XDG_DATA_HOME, or $HOME/.local/share if that is not defined.
32+
# By default setup-envtest binary will write to $XDG_DATA_HOME, or $HOME/.local/share if that is not defined.
3333
# If $HOME is not set, we need to specify a binary directory to prevent an error in setup-envtest.
3434
# Useful for some CI/CD environments that set neither $XDG_DATA_HOME nor $HOME.
35-
SETUP_ENVTEST_BIN_DIR_OVERRIDE=
35+
SETUP_ENVTEST_BIN_DIR_OVERRIDE += --bin-dir $(ROOT_DIR)/bin/envtest-binaries
3636
ifeq ($(shell [[ $$HOME == "" || $$HOME == "/" ]] && [[ $$XDG_DATA_HOME == "" ]] && echo true ), true)
3737
SETUP_ENVTEST_BIN_DIR_OVERRIDE += --bin-dir /tmp/envtest-binaries
3838
endif
@@ -158,19 +158,25 @@ test-ext-dev-e2e: $(OPERATOR_SDK) $(KUSTOMIZE) $(KIND) #HELP Run extension creat
158158
test/extension-developer-e2e/setup.sh $(OPERATOR_SDK) $(CONTAINER_RUNTIME) $(KUSTOMIZE) $(KIND) $(KIND_CLUSTER_NAME) $(E2E_REGISTRY_NAMESPACE)
159159
go test -count=1 -v ./test/extension-developer-e2e/...
160160

161-
.PHONY: test-unit
162161
ENVTEST_VERSION := $(shell go list -m k8s.io/client-go | cut -d" " -f2 | sed 's/^v0\.\([[:digit:]]\{1,\}\)\.[[:digit:]]\{1,\}$$/1.\1.x/')
163162
UNIT_TEST_DIRS := $(shell go list ./... | grep -v /test/)
164163
COVERAGE_UNIT_DIR := $(ROOT_DIR)/coverage/unit
165-
test-unit: $(SETUP_ENVTEST) #HELP Run the unit tests
164+
165+
.PHONY: envtest-k8s-bins #HELP Uses setup-envtest to download and install the binaries required to run ENVTEST-test based locally at the project/bin directory.
166+
envtest-k8s-bins: $(SETUP_ENVTEST)
167+
mkdir -p $(ROOT_DIR)/bin
168+
$(SETUP_ENVTEST) use -p env $(ENVTEST_VERSION) $(SETUP_ENVTEST_BIN_DIR_OVERRIDE)
169+
170+
.PHONY: test-unit
171+
test-unit: $(SETUP_ENVTEST) envtest-k8s-bins #HELP Run the unit tests
166172
rm -rf $(COVERAGE_UNIT_DIR) && mkdir -p $(COVERAGE_UNIT_DIR)
167-
eval $$($(SETUP_ENVTEST) use -p env $(ENVTEST_VERSION) $(SETUP_ENVTEST_BIN_DIR_OVERRIDE)) && \
173+
KUBEBUILDER_ASSETS="$(shell $(SETUP_ENVTEST) use -p path $(ENVTEST_VERSION) $(SETUP_ENVTEST_BIN_DIR_OVERRIDE))" \
168174
CGO_ENABLED=1 go test \
169175
-tags '$(GO_BUILD_TAGS)' \
170176
-cover -coverprofile ${ROOT_DIR}/coverage/unit.out \
171177
-count=1 -race -short \
172178
$(UNIT_TEST_DIRS) \
173-
-test.gocoverdir=$(ROOT_DIR)/coverage/unit
179+
-test.gocoverdir=$(COVERAGE_UNIT_DIR)
174180

175181
.PHONY: image-registry
176182
E2E_REGISTRY_IMAGE=localhost/e2e-test-registry:devel

internal/controllers/suite_test.go

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import (
2626

2727
"github.com/stretchr/testify/require"
2828
"k8s.io/apimachinery/pkg/api/meta"
29-
"k8s.io/apimachinery/pkg/runtime"
29+
apimachineryruntime "k8s.io/apimachinery/pkg/runtime"
3030
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
3131
"k8s.io/client-go/rest"
3232
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -64,7 +64,7 @@ func (m *MockUnpacker) Cleanup(_ context.Context, _ *source.BundleSource) error
6464
func newClient(t *testing.T) client.Client {
6565
// TODO: this is a live client, which behaves differently than a cache client.
6666
// We may want to use a caching client instead to get closer to real behavior.
67-
sch := runtime.NewScheme()
67+
sch := apimachineryruntime.NewScheme()
6868
require.NoError(t, ocv1.AddToScheme(sch))
6969
cl, err := client.New(config, client.Options{Scheme: sch})
7070
require.NoError(t, err)
@@ -162,6 +162,21 @@ func TestMain(m *testing.M) {
162162
ErrorIfCRDPathMissing: true,
163163
}
164164

165+
// ENVTEST-based tests require specific binaries. By default, these binaries are located
166+
// in paths defined by controller-runtime. However, the `BinaryAssetsDirectory` needs
167+
// to be explicitly set when running tests directly (e.g., debugging tests in an IDE)
168+
// without using the Makefile targets.
169+
//
170+
// This is equivalent to configuring your IDE to export the `KUBEBUILDER_ASSETS` environment
171+
// variable before each test execution. The following function simplifies this process
172+
// by handling the configuration for you.
173+
//
174+
// To ensure the binaries are in the expected path without manual configuration, run:
175+
// `make envtest-k8s-bins`
176+
if getFirstFoundEnvTestBinaryDir() != "" {
177+
testEnv.BinaryAssetsDirectory = getFirstFoundEnvTestBinaryDir()
178+
}
179+
165180
var err error
166181
config, err = testEnv.Start()
167182
utilruntime.Must(err)
@@ -179,3 +194,15 @@ func TestMain(m *testing.M) {
179194
utilruntime.Must(testEnv.Stop())
180195
os.Exit(code)
181196
}
197+
198+
// getFirstFoundEnvTestBinaryDir finds and returns the first directory under the given path.
199+
func getFirstFoundEnvTestBinaryDir() string {
200+
basePath := filepath.Join("..", "..", "bin", "envtest-binaries", "k8s")
201+
entries, _ := os.ReadDir(basePath)
202+
for _, entry := range entries {
203+
if entry.IsDir() {
204+
return filepath.Join(basePath, entry.Name())
205+
}
206+
}
207+
return ""
208+
}

0 commit comments

Comments
 (0)