As part of my effort to better understand OPA I fired up Delve to understand how different CLI options got wired up. It was pretty straight forward to understand the basics but I wanted to debug the run command which needs stdin but Delve uses stdin to take its own commands.
After many failed attempts and searching I stumbled onto a post by Laurent Stacul which covered this case. I’m documenting it here as well for personal reference.
Terminal 1 Link to heading
A headless run of the project needs to be started in the first terminal. If --listen
isn’t provided a random port is assigned so we provide a static port for ease of use.
~/opa > dlv debug --headless --listen :4747 . -- run
API server listening at: [::]:4747
Terminal 2 Link to heading
In the second terminal you connect to the headless process from the first. From there we can set a break point and then resume execution.
~/opa > dlv connect :4747
Type 'help' for list of commands.
(dlv) break bar opa/runtime/runtime.go:470
Breakpoint bar set at 0xf7cdb2 for github.com/open-policy-agent/opa/runtime.(*Runtime).StartREPL() ./opa/runtime/runtime.go:47
(dlv) continue
> [bar] github.com/open-policy-agent/opa/runtime.(*Runtime).StartREPL() ./opa/runtime/runtime.go:470 (hits goroutine(1):1 total:1) (PC: 0xf7cdb2)
465: }
466:
467: // StartREPL starts the runtime in REPL mode. This function will block the calling goroutine.
468: func (rt *Runtime) StartREPL(ctx context.Context) {
469:
=> 470: if err := rt.Manager.Start(ctx); err != nil {
471: fmt.Fprintln(rt.Params.Output, "error starting plugins:", err)
472: os.Exit(1)
473: }
474:
475: defer rt.Manager.Stop(ctx)