Skip to content

Commit

Permalink
feat: support docker image label to start debugger in wait mode for g…
Browse files Browse the repository at this point in the history
…o, jvm, nodejs, python
  • Loading branch information
pkoutsovasilis committed Sep 30, 2023
1 parent 0602422 commit 8e4f6c0
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 13 deletions.
23 changes: 20 additions & 3 deletions pkg/skaffold/debug/transform_go.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,12 @@ type dlvSpec struct {
port uint16
headless bool
log bool
wait bool
apiVersion int
}

func newDlvSpec(port uint16) dlvSpec {
return dlvSpec{mode: "exec", port: port, apiVersion: defaultAPIVersion, headless: true}
return dlvSpec{mode: "exec", port: port, apiVersion: defaultAPIVersion, headless: true, wait: true}
}

// isLaunchingDlv determines if the arguments seems to be invoking Delve
Expand Down Expand Up @@ -116,6 +117,15 @@ func (t dlvTransformer) Apply(adapter types.ContainerAdapter, config ImageConfig
if spec == nil {
newSpec := newDlvSpec(uint16(portAlloc(defaultDlvPort)))
spec = &newSpec

suspendLabel := config.Labels["skaffold.dev/debug/suspend"]
if strings.EqualFold(suspendLabel, "true") {
spec.wait = true
} else {
// maintain existing behavior that invokes dlv with --continue
spec.wait = false
}

switch {
case len(config.Entrypoint) > 0 && !isEntrypointLauncher(config.Entrypoint):
container.Command = rewriteDlvCommandLine(config.Entrypoint, *spec, container.Args)
Expand Down Expand Up @@ -151,7 +161,7 @@ func extractDlvSpec(args []string) *dlvSpec {
return nil
}
// delve's defaults
spec := dlvSpec{apiVersion: 2, log: false, headless: false}
spec := dlvSpec{apiVersion: 2, log: false, headless: false, wait: true}
arguments:
for _, arg := range args {
switch {
Expand All @@ -163,6 +173,8 @@ arguments:
spec.headless = true
case arg == "--log":
spec.log = true
case arg == "--continue":
spec.wait = false
case strings.HasPrefix(arg, "--listen="):
address := strings.SplitN(arg, "=", 2)[1]
split := strings.SplitN(address, ":", 2)
Expand Down Expand Up @@ -203,7 +215,12 @@ func (spec dlvSpec) asArguments() []string {
if spec.headless {
args = append(args, "--headless")
}
args = append(args, "--continue", "--accept-multiclient")

if !spec.wait {
args = append(args, "--continue")
}

args = append(args, "--accept-multiclient")
if spec.port > 0 {
args = append(args, fmt.Sprintf("--listen=%s:%d", spec.host, spec.port))
} else {
Expand Down
19 changes: 10 additions & 9 deletions pkg/skaffold/debug/transform_go_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import (

func TestNewDlvSpecDefaults(t *testing.T) {
spec := newDlvSpec(20)
expected := dlvSpec{mode: "exec", port: 20, apiVersion: 2, headless: true, log: false}
expected := dlvSpec{mode: "exec", port: 20, apiVersion: 2, headless: true, log: false, wait: true}
testutil.CheckDeepEqual(t, expected, spec, cmp.AllowUnexported(spec))
}

Expand All @@ -40,14 +40,15 @@ func TestExtractDlvArg(t *testing.T) {
{nil, nil},
{[]string{"foo"}, nil},
{[]string{"foo", "--foo"}, nil},
{[]string{"dlv", "debug", "--headless"}, &dlvSpec{mode: "debug", headless: true, apiVersion: 2, log: false}},
{[]string{"dlv", "--headless", "exec"}, &dlvSpec{mode: "exec", headless: true, apiVersion: 2, log: false}},
{[]string{"dlv", "--headless", "exec", "--", "--listen=host:4345"}, &dlvSpec{mode: "exec", headless: true, apiVersion: 2, log: false}},
{[]string{"dlv", "test", "--headless", "--listen=host:4345"}, &dlvSpec{mode: "test", host: "host", port: 4345, headless: true, apiVersion: 2, log: false}},
{[]string{"dlv", "debug", "--headless", "--api-version=1"}, &dlvSpec{mode: "debug", headless: true, apiVersion: 1, log: false}},
{[]string{"dlv", "debug", "--listen=host:4345", "--headless", "--api-version=2", "--log"}, &dlvSpec{mode: "debug", host: "host", port: 4345, headless: true, apiVersion: 2, log: true}},
{[]string{"dlv", "debug", "--listen=:4345"}, &dlvSpec{mode: "debug", port: 4345, apiVersion: 2}},
{[]string{"dlv", "debug", "--listen=host:"}, &dlvSpec{mode: "debug", host: "host", apiVersion: 2}},
{[]string{"dlv", "debug", "--headless"}, &dlvSpec{mode: "debug", headless: true, apiVersion: 2, log: false, wait: true}},
{[]string{"dlv", "--headless", "exec"}, &dlvSpec{mode: "exec", headless: true, apiVersion: 2, log: false, wait: true}},
{[]string{"dlv", "--headless", "exec", "--", "--listen=host:4345"}, &dlvSpec{mode: "exec", headless: true, apiVersion: 2, log: false, wait: true}},
{[]string{"dlv", "test", "--headless", "--listen=host:4345"}, &dlvSpec{mode: "test", host: "host", port: 4345, headless: true, apiVersion: 2, log: false, wait: true}},
{[]string{"dlv", "debug", "--headless", "--api-version=1"}, &dlvSpec{mode: "debug", headless: true, apiVersion: 1, log: false, wait: true}},
{[]string{"dlv", "debug", "--listen=host:4345", "--headless", "--api-version=2", "--log"}, &dlvSpec{mode: "debug", host: "host", port: 4345, headless: true, apiVersion: 2, log: true, wait: true}},
{[]string{"dlv", "debug", "--listen=:4345"}, &dlvSpec{mode: "debug", port: 4345, apiVersion: 2, wait: true}},
{[]string{"dlv", "debug", "--listen=host:"}, &dlvSpec{mode: "debug", host: "host", apiVersion: 2, wait: true}},
{[]string{"dlv", "debug", "--listen=host:", "--continue"}, &dlvSpec{mode: "debug", host: "host", apiVersion: 2, wait: false}},
}
for _, test := range tests {
testutil.Run(t, strings.Join(test.in, " "), func(t *testutil.T) {
Expand Down
13 changes: 12 additions & 1 deletion pkg/skaffold/debug/transform_jvm.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,18 @@ func (t jdwpTransformer) Apply(adapter types.ContainerAdapter, config ImageConfi
port = int32(spec.port)
} else {
port = portAlloc(defaultJdwpPort)
jto := fmt.Sprintf("-agentlib:jdwp=transport=dt_socket,server=y,address=%d,suspend=n,quiet=y", port)

var suspendParam string
suspendLabel := config.Labels["skaffold.dev/debug/suspend"]
if strings.EqualFold(suspendLabel, "true") {
spec.suspend = true
suspendParam = "y"
} else {
spec.suspend = false
suspendParam = "n"
}

jto := fmt.Sprintf("-agentlib:jdwp=transport=dt_socket,server=y,address=%d,suspend=%s,quiet=y", port, suspendParam)
if existing, found := config.Env["JAVA_TOOL_OPTIONS"]; found {
jto = existing + " " + jto
}
Expand Down
6 changes: 6 additions & 0 deletions pkg/skaffold/debug/transform_nodejs.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,12 @@ func (t nodeTransformer) Apply(adapter types.ContainerAdapter, config ImageConfi
spec := retrieveNodeInspectSpec(config)
if spec == nil {
spec = &inspectSpec{host: "0.0.0.0", port: portAlloc(defaultDevtoolsPort)}

suspendLabel := config.Labels["skaffold.dev/debug/suspend"]
if strings.EqualFold(suspendLabel, "true") {
spec.brk = true
}

switch {
case isLaunchingNode(config.Entrypoint):
container.Command = rewriteNodeCommandLine(config.Entrypoint, *spec)
Expand Down
5 changes: 5 additions & 0 deletions pkg/skaffold/debug/transform_python.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,11 @@ func (t pythonTransformer) Apply(adapter types.ContainerAdapter, config ImageCon

spec := createPythonDebugSpec(overrideProtocols, portAlloc)

suspendLabel := config.Labels["skaffold.dev/debug/suspend"]
if strings.EqualFold(suspendLabel, "true") {
spec.wait = true
}

switch {
case isLaunchingPython(config.Entrypoint):
container.Command = rewritePythonCommandLine(config.Entrypoint, *spec)
Expand Down

0 comments on commit 8e4f6c0

Please sign in to comment.