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 on port 50000 (enabled via DEBUG_MODE).
    • Registration service command is now configurable via an environment variable/template parameter.
  • Chores

    • Added a multi-stage debug container image and entrypoint support to run under the debugger.
    • Added build and publish targets to produce and push 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, a DEBUG_MODE path in the entrypoint to run the operator under dlv, a debug Go build target and podman image/push targets, and a templated/overridable 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 builds Delve and produces a debug runtime image; entrypoint conditionally runs the operator under dlv (headless, listening on port 50000) when DEBUG_MODE is set.
Build System (make)
make/go.mk, make/podman.mk
Added build-debug target (Go debug build with -gcflags "all=-N -l"). Added podman-image-debug and podman-push-debug targets and PHONY 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 set COMMAND from env or default to ["registration-service"].
Deployment Template
deploy/templates/registration-service/registration-service.yaml
Replaced hardcoded container command with templated COMMAND parameter (default ["registration-service"]) and updated deployment to use ${{COMMAND}}.
sequenceDiagram
  autonumber
  participant Dev as Developer/CI
  participant Builder as Delve Builder
  participant Runtime as Debug Runtime Image
  participant Entrypoint as Container Entrypoint
  participant Delve as Delve (dlv)
  participant Operator as Operator Binary

  Dev->>Builder: build stage (build/Dockerfile.debug) → produce `dlv`
  Dev->>Runtime: assemble runtime image (copy operator, dlv, entrypoint)
  Runtime->>Entrypoint: start container (ENV: DEBUG_MODE, OPERATOR, USER_UID)
  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
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • xcoulon

Poem

🐰 I tunneled through Docker, built a tiny spy,
Brought Delve to listen where the operators lie.
A headless port, a gentle debugging hum,
Hop in my burrow — bring your breakpoint some. 🥕🔎

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ 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%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ 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 directly and clearly summarizes the main change: adding debug builds for the host operator, which aligns with the PR's primary objective of enabling live debugging with Delve.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 29d520b and df71d6b.

📒 Files selected for processing (1)
  • controllers/toolchainconfig/toolchainconfig_controller.go
🧰 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). (1)
  • GitHub Check: Build & push operator bundles & dashboard image for e2e tests
🔇 Additional comments (1)
controllers/toolchainconfig/toolchainconfig_controller.go (1)

154-162: LGTM - Environment-based command override for debug support.

The implementation correctly provides an environment-based override for the registration service command with a sensible JSON array default ["registration-service"] that aligns with Kubernetes container command specifications. The template at line 104 correctly uses command: ${{COMMAND}}.

One consideration: if a malformed value is provided via the environment variable (e.g., invalid JSON), the template processing may fail silently or produce invalid YAML. Since this is specifically for debug builds and requires explicit operator action to set, this is acceptable. However, you may want to add a brief note in documentation (or a comment) about the expected format.


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/[email protected]

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.

@MikelAlejoBR MikelAlejoBR force-pushed the SANDBOX-1561-debug-sandbox-resources branch from a3e01d5 to 9a5e69f Compare January 6, 2026 12:55
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 9a5e69f to 29d520b Compare January 6, 2026 23:04
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: 0

🧹 Nitpick comments (1)
deploy/templates/registration-service/registration-service.yaml (1)

273-274: LGTM! Default value preserves original behavior.

The new COMMAND parameter is correctly defined with a default value that preserves the original behavior. The value '["registration-service"]' will be parsed as a JSON array when substituted via ${{COMMAND}}.

💡 Optional: Add description field for clarity

Consider adding a description field to document the parameter's purpose:

   - name: COMMAND
     value: '["registration-service"]'
+    description: 'Command to execute in the registration-service container. Override for debugging (e.g., with Delve).'

This helps operators understand when and why to override this parameter.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

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

📒 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 (5)
  • build/bin/entrypoint
  • build/Dockerfile.debug
  • make/go.mk
  • controllers/toolchainconfig/toolchainconfig_controller.go
  • make/podman.mk
⏰ 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 (2)
controllers/toolchainconfig/env.go (1)

3-6: LGTM! Clean constant addition.

The new RegistrationServiceCommandEnvKey constant follows the same naming pattern as the existing constant and enables the command override functionality for debug builds. The grouped const block is idiomatic Go.

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

104-104: LGTM! Command override enables debug functionality.

The templated command field correctly uses ${{COMMAND}} syntax to enable runtime command override, which is essential for launching the registration service under Delve for debugging. The OpenShift template syntax is correct.

@sonarqubecloud
Copy link

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 12, 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 df71d6b 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.

@MikelAlejoBR
Copy link
Author

Closing in favor of #1228.

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.

2 participants