Skip to content

Conversation

@MikelAlejoBR
Copy link

@MikelAlejoBR MikelAlejoBR commented Dec 23, 2025

In order to be able to debug the operator live in the local cluster, we need the binary to be executed with Delve instead, and we need it to be built without any code optimizations or minimization so that the breakpoints work.

For that purpose, a new Dockerfile is added which can build the image that way, and the corresponding Make targets make it easy to kick off the whole process with a single command.

The Makefile targets also enable the "toolchain-e2e" repository to easily build the "debug" image.

Also, when Developer Sandbox is deployed locally, usually the registration service gets managed by the "ToolChain config controller", which launches it with a specific command. In order to be able to launch the registration service with Delve, a few minor modifications are made so that that launch command can be overridden.

Related PRs

Jira ticket

[SANDBOX-1561]

Summary by CodeRabbit

  • New Features

    • Run the operator in debug mode with a remote debugger listening on port 50000 (activated via DEBUG_MODE).
    • Registration service command is now configurable via an environment variable/template parameter.
  • Chores

    • Added a multi-stage debug image and build flow plus make targets to build and publish debug-ready operator images.

✏️ Tip: You can customize this high-level summary in your review settings.

@openshift-ci
Copy link

openshift-ci bot commented Dec 23, 2025

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: MikelAlejoBR
Once this PR has been reviewed and has the lgtm label, please assign xcoulon for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@coderabbitai
Copy link

coderabbitai bot commented Dec 23, 2025

Walkthrough

Adds a Delve-enabled multi-stage debug Dockerfile and entrypoint changes to run the operator under Delve, a debug build target and podman targets to build/push the debug image, and an environment-driven override to parameterize the registration service command in the deployment template.

Changes

Cohort / File(s) Summary
Debug Docker & Entrypoint
build/Dockerfile.debug, build/bin/entrypoint
New multi-stage Dockerfile that builds Delve and produces a debug-ready runtime image; entrypoint conditionally runs the operator under dlv (headless, port 50000) when DEBUG_MODE is set.
Build System (make)
make/go.mk, make/podman.mk
Added build-debug target to compile operator with debug-friendly flags (-gcflags "all=-N -l"). Added podman-image-debug and podman-push-debug targets and PHONYs to build/push the Delve-enabled image using build/Dockerfile.debug.
Registration Service config
controllers/toolchainconfig/env.go, controllers/toolchainconfig/toolchainconfig_controller.go
Added RegistrationServiceCommandEnvKey constant and logic to allow overriding the registration service COMMAND via env; defaults to ["registration-service"].
Deployment Template
deploy/templates/registration-service/registration-service.yaml
Parameterized container command with new COMMAND template parameter (default ["registration-service"]) and replaced hardcoded command with ${{COMMAND}}.
sequenceDiagram
  autonumber
  participant Dev as Developer/CI
  participant Builder as Delve Builder Stage
  participant Runtime as Debug Runtime Image
  participant Entrypoint as Container Entrypoint
  participant Delve as Delve (dlv)
  participant Operator as Operator Binary

  Dev->>Builder: build (build/Dockerfile.debug) with GOLANG_VERSION
  Builder-->>Dev: produce `dlv` binary (/tmp/bin/dlv)
  Dev->>Runtime: assemble runtime image (copy operator, dlv, entrypoint)
  Dev->>Runtime: push image (podman-image-debug / podman-push-debug)
  Runtime->>Entrypoint: start container (ENV: DEBUG_MODE, USER_UID, OPERATOR)
  Entrypoint->>Entrypoint: check DEBUG_MODE
  alt DEBUG_MODE set
    Entrypoint->>Delve: exec dlv --headless --listen=:50000 --api-version=2 --continue --accept-multiclient -- /path/to/operator
    Delve->>Operator: run operator (debug build)
  else DEBUG_MODE unset
    Entrypoint->>Operator: exec /path/to/operator
  end
  Note over Runtime,Operator: Registration-service command drawn from templated `COMMAND` (env override possible)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested labels

lgtm

Suggested reviewers

  • alexeykazakov
  • rajivnathan
  • MatousJobanek

Poem

🐰 I tunneled through Docker, built a tiny spy,
Brought Delve to listen where the operators lie.
A port, a flag, a quiet headless hum—
Hop in my burrow, debugging has come. 🥕🔎

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'SANDBOX-1561 | feature: debug builds for the host operator' is clear, specific, and directly summarizes the main change: adding debug build support for the host operator.
✨ Finishing touches
  • 📝 Generate docstrings

📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a3e01d5 and 9a5e69f.

📒 Files selected for processing (7)
  • build/Dockerfile.debug
  • build/bin/entrypoint
  • controllers/toolchainconfig/env.go
  • controllers/toolchainconfig/toolchainconfig_controller.go
  • deploy/templates/registration-service/registration-service.yaml
  • make/go.mk
  • make/podman.mk
🚧 Files skipped from review as they are similar to previous changes (6)
  • build/bin/entrypoint
  • build/Dockerfile.debug
  • make/go.mk
  • controllers/toolchainconfig/toolchainconfig_controller.go
  • make/podman.mk
  • deploy/templates/registration-service/registration-service.yaml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: GolangCI Lint
  • GitHub Check: Build & push operator bundles & dashboard image for e2e tests
  • GitHub Check: Test with Coverage
🔇 Additional comments (1)
controllers/toolchainconfig/env.go (1)

3-6: LGTM! Clean addition of the command override constant.

The grouped const block is properly formatted and the new RegistrationServiceCommandEnvKey constant follows the same naming convention as the existing image key. This addition cleanly supports the debugging feature by allowing the registration service command to be overridden via environment variable.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (4)
build/bin/entrypoint (1)

12-17: Consider using exec for the Delve command to ensure proper signal handling.

Line 14 runs Delve without the exec prefix, while line 16 uses it. Without exec, the shell process remains as PID 1 in the container, which can lead to signal handling issues and zombie processes. Consider adding exec before /usr/local/bin/dlv unless there's a specific reason to keep the shell alive during debugging.

🔎 Proposed fix
 if [ -n "${DEBUG_MODE}" ]
 then
-  /usr/local/bin/dlv --listen=:50000 --headless --continue --api-version=2 --accept-multiclient exec "${OPERATOR}" "$@"
+  exec /usr/local/bin/dlv --listen=:50000 --headless --continue --api-version=2 --accept-multiclient exec "${OPERATOR}" "$@"
 else
   exec ${OPERATOR} "$@"
 fi
controllers/toolchainconfig/toolchainconfig_controller.go (1)

154-162: Consider documenting the expected JSON array format for the override.

The environment variable REGISTRATION_SERVICE_COMMAND is used directly without validation. Users must provide it in JSON array format (e.g., ["dlv", "exec", ...]) to match the template's expectation. Consider adding a comment or documentation to clarify the expected format, or optionally add basic validation to catch common mistakes.

💡 Optional: Add validation for JSON array format
 	// Allow overriding the registration service's command via an environment
 	// variable.
+	// Note: The value must be a valid JSON array, e.g., `["registration-service"]` or `["dlv", "exec", "..."]`
 	command := os.Getenv(RegistrationServiceCommandEnvKey)
 	if command != "" {
 		vars["COMMAND"] = command
 	} else {
 		vars["COMMAND"] = `["registration-service"]`
 	}

Alternatively, you could add JSON validation:

if command != "" {
	// Basic check that it looks like a JSON array
	if !strings.HasPrefix(strings.TrimSpace(command), "[") {
		// Log warning or return error
	}
	vars["COMMAND"] = command
} else {
	vars["COMMAND"] = `["registration-service"]`
}
build/Dockerfile.debug (2)

1-23: Consider pinning base image versions for reproducibility.

Lines 2 and 23 use :latest tags, which can lead to non-reproducible builds. For debug images, this may be acceptable, but consider using specific versions (e.g., ubi8:8.9 and a specific Delve version) to ensure consistent behavior across builds.

💡 Example with pinned versions
-FROM registry.access.redhat.com/ubi8/ubi:latest AS delve-builder
+FROM registry.access.redhat.com/ubi8/ubi:8.9 AS delve-builder

 # ... rest of the file ...

-RUN GOBIN=/tmp/bin go install github.com/go-delve/delve/cmd/dlv@latest
+RUN GOBIN=/tmp/bin go install github.com/go-delve/delve/cmd/dlv@v1.22.0

25-52: The debug runtime image is correctly configured.

The runtime stage properly:

  • Enables DEBUG_MODE for the entrypoint script
  • Copies both the operator binary and Delve
  • Exposes port 50000 for remote debugging
  • Runs as non-root user for security

Line 26 also uses :latest tag (same suggestion as the builder stage regarding version pinning).

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 060beea and ec9e7ab.

📒 Files selected for processing (7)
  • build/Dockerfile.debug
  • build/bin/entrypoint
  • controllers/toolchainconfig/env.go
  • controllers/toolchainconfig/toolchainconfig_controller.go
  • deploy/templates/registration-service/registration-service.yaml
  • make/go.mk
  • make/podman.mk
🧰 Additional context used
🧬 Code graph analysis (1)
controllers/toolchainconfig/toolchainconfig_controller.go (1)
controllers/toolchainconfig/env.go (1)
  • RegistrationServiceCommandEnvKey (5-5)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: GolangCI Lint
  • GitHub Check: Build & push operator bundles & dashboard image for e2e tests
  • GitHub Check: Test with Coverage
🔇 Additional comments (5)
make/podman.mk (2)

13-16: The Go version extraction is stable for standard Go distributions.

The command go version | awk '{print $$3}' extracts the Go version (e.g., "go1.21.5") and passes it to the Dockerfile. This approach is appropriate for standard Go installations.


23-26: LGTM!

The debug push target correctly mirrors the standard push workflow and depends on the appropriate debug image build.

controllers/toolchainconfig/env.go (1)

3-6: LGTM!

The new constant follows the existing naming convention and provides a clear environment variable key for the registration service command override.

deploy/templates/registration-service/registration-service.yaml (2)

104-104: LGTM!

The templated command field correctly integrates with the controller's environment-based override logic, enabling dynamic command injection for debugging scenarios.


273-274: LGTM!

The COMMAND parameter is correctly defined with an appropriate default value that maintains backward compatibility.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ec9e7ab and a3e01d5.

📒 Files selected for processing (7)
  • build/Dockerfile.debug
  • build/bin/entrypoint
  • controllers/toolchainconfig/env.go
  • controllers/toolchainconfig/toolchainconfig_controller.go
  • deploy/templates/registration-service/registration-service.yaml
  • make/go.mk
  • make/podman.mk
🚧 Files skipped from review as they are similar to previous changes (2)
  • build/Dockerfile.debug
  • make/go.mk
🧰 Additional context used
🧬 Code graph analysis (1)
controllers/toolchainconfig/toolchainconfig_controller.go (1)
controllers/toolchainconfig/env.go (1)
  • RegistrationServiceCommandEnvKey (5-5)
🪛 GitHub Actions: ci-build
controllers/toolchainconfig/env.go

[error] 4-4: File is not properly formatted (gofmt). Run 'gofmt -w' or 'go fmt' to fix formatting.

🪛 GitHub Check: GolangCI Lint
controllers/toolchainconfig/env.go

[failure] 4-4:
File is not properly formatted (gofmt)

🔇 Additional comments (4)
controllers/toolchainconfig/toolchainconfig_controller.go (1)

154-162: LGTM! Clean environment-driven override pattern.

The implementation correctly allows debugging workflows to override the registration service command while preserving the default production behavior.

make/podman.mk (1)

13-16: LGTM! Debug targets follow existing patterns.

The new debug-specific targets correctly mirror the structure of existing podman targets and maintain consistent dependency chains.

Also applies to: 23-26

deploy/templates/registration-service/registration-service.yaml (1)

104-104: LGTM! Templating correctly preserves the default behavior.

The command is now templated with an appropriate default value that matches the original hardcoded command. The ${{COMMAND}} syntax ensures proper JSON array parsing.

Also applies to: 273-274

build/bin/entrypoint (1)

12-17: DEBUG_MODE is properly isolated to debug builds and not enabled in production.

The production build/Dockerfile does not set DEBUG_MODE, while only build/Dockerfile.debug enables it for local debugging. No deployment configurations reference DEBUG_MODE. The code is secure as deployed.

In order to be able to debug the operator live in the local cluster, we
need the binary to be executed with Delve instead, and we need it to be
built without any code optimizations or minimization so that the
breakpoints work.

For that purpose, a new Dockerfile is added which can build the image
that way, and the corresponding Make targets make it easy to kick off
the whole process with a single command.

The Makefile targets also enable the "toolchain-e2e" repository to
easily build the "debug" image.

Also, when Developer Sandbox is deployed locally, usually the
registration service gets managed by the "ToolChain config controller",
which launches it with a specific command. In order to be able to launch
the registration service with Delve, a few minor modifications are made
so that that launch command can be overridden.

SANDBOX-1561
@MikelAlejoBR MikelAlejoBR force-pushed the SANDBOX-1561-debug-sandbox-resources branch from a3e01d5 to 9a5e69f Compare January 6, 2026 12:55
@sonarqubecloud
Copy link

sonarqubecloud bot commented Jan 6, 2026

Quality Gate Failed Quality Gate failed

Failed conditions
C Reliability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@openshift-ci
Copy link

openshift-ci bot commented Jan 6, 2026

@MikelAlejoBR: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/e2e 9a5e69f link true /test e2e

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant