Skip to content

Commit

Permalink
Add --detach flag support for Docker and Kubernetes runtimes
Browse files Browse the repository at this point in the history
  • Loading branch information
iximiuz committed Apr 13, 2024
1 parent 6073abb commit 04ac915
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 22 deletions.
6 changes: 2 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -416,11 +416,9 @@ $ curl localhost:49176

## F.A.Q

**Q:** Running `cdebug exec` fails with `rm: cannot remove '/proc/1/root/nix': Permission denied` or
`ln: /proc/1/root/.cdebug-XXXXXXXX: Permission denied`.
**Q:** `cdebug exec` fails with `ln: /proc/1/root/...: Permission denied` or the like error?

Chances are your target container has been started with elevated permissions while you're trying to run a non-privileged debugger sidecar.
Try `cdebug exec --privileged` instead.
Non-privileged targets can cause this error because by default, `cdebug` tries to start the debugger container with the same privileges as the target container. Try `cdebug exec --privileged` instead.

## Similar tools

Expand Down
26 changes: 23 additions & 3 deletions cmd/exec/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ type options struct {
image string
tty bool
stdin bool
detach bool
cmd []string
user string
privileged bool
Expand Down Expand Up @@ -143,13 +144,13 @@ func NewCommand(cli cliutil.CLI) *cobra.Command {

switch opts.schema {
case schemaContainerd, schemaNerdctl:
return cliutil.WrapStatusError(runDebuggerContainerd(ctx, cli, &opts))
return cliutil.WrapStatusError(wrapExitError(runDebuggerContainerd(ctx, cli, &opts)))

case schemaDocker:
return cliutil.WrapStatusError(runDebuggerDocker(ctx, cli, &opts))
return cliutil.WrapStatusError(wrapExitError(runDebuggerDocker(ctx, cli, &opts)))

case schemaKubeLong, schemaKubeShort:
return cliutil.WrapStatusError(runDebuggerKubernetes(ctx, cli, &opts))
return cliutil.WrapStatusError(wrapExitError(runDebuggerKubernetes(ctx, cli, &opts)))

case schemaPodman, schemaOCI, schemaKubeCRI:
return cliutil.WrapStatusError(errors.New("coming soon"))
Expand Down Expand Up @@ -196,6 +197,13 @@ func NewCommand(cli cliutil.CLI) *cobra.Command {
false,
`Allocate a pseudo-TTY (as in "docker exec -t")`,
)
flags.BoolVarP(
&opts.detach,
"detach",
"d",
false,
`Detached mode: execute the command in the background`,
)
flags.StringVarP(
&opts.user,
"user",
Expand Down Expand Up @@ -379,3 +387,15 @@ func shellescape(args []string) (escaped []string) {
func isRootUser(user string) bool {
return len(user) == 0 || user == "root" || user == "0" || user == "0:0"
}

func wrapExitError(err error) error {
if err == nil {
return nil
}

if strings.Contains(strings.ToLower(err.Error()), "permission denied") {
return fmt.Errorf("%s\n\nHint: try running `cdebug exec` with the --privileged flag", err)
}

return err
}
4 changes: 4 additions & 0 deletions cmd/exec/exec_containerd.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ import (
)

func runDebuggerContainerd(ctx context.Context, cli cliutil.CLI, opts *options) error {
if opts.detach {
return errors.New("--detach|-d flag is not supported for containerd runtime yet")
}

if strings.Contains(opts.namespace, "/") {
return errors.New("namespaces with '/' are unsupported")
}
Expand Down
32 changes: 18 additions & 14 deletions cmd/exec/exec_docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,27 +98,31 @@ func runDebuggerDocker(ctx context.Context, cli cliutil.CLI, opts *options) erro
return errCannotCreate(err)
}

close, err := attachDebugger(ctx, cli, client, opts, resp.ID)
if err != nil {
return fmt.Errorf("cannot attach to debugger container: %w", err)
if !opts.detach {
close, err := attachDebugger(ctx, cli, client, opts, resp.ID)
if err != nil {
return fmt.Errorf("cannot attach to debugger container: %w", err)
}
defer close()
}
defer close()

if err := client.ContainerStart(ctx, resp.ID, container.StartOptions{}); err != nil {
return fmt.Errorf("cannot start debugger container: %w", err)
}

if opts.tty && cli.OutputStream().IsTerminal() {
tty.StartResizing(ctx, cli.OutputStream(), client, resp.ID)
}
if !opts.detach {
if opts.tty && cli.OutputStream().IsTerminal() {
tty.StartResizing(ctx, cli.OutputStream(), client, resp.ID)
}

statusCh, errCh := client.ContainerWait(ctx, resp.ID, container.WaitConditionNotRunning)
select {
case err := <-errCh:
if err != nil {
return fmt.Errorf("waiting debugger container failed: %w", err)
statusCh, errCh := client.ContainerWait(ctx, resp.ID, container.WaitConditionNotRunning)
select {
case err := <-errCh:
if err != nil {
return fmt.Errorf("waiting debugger container failed: %w", err)
}
case <-statusCh:
}
case <-statusCh:
}

return nil
Expand All @@ -131,7 +135,7 @@ func attachDebugger(
opts *options,
contID string,
) (func(), error) {
resp, err := client.ContainerAttach(ctx, contID, types.ContainerAttachOptions{
resp, err := client.ContainerAttach(ctx, contID, container.AttachOptions{
Stream: true,
Stdin: opts.stdin,
Stdout: true,
Expand Down
17 changes: 16 additions & 1 deletion cmd/exec/exec_kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import (

func runDebuggerKubernetes(ctx context.Context, cli cliutil.CLI, opts *options) error {
if opts.autoRemove {
return fmt.Errorf("--rm flag is not supported for Kubernetes")
return fmt.Errorf("--rm flag is not supported for Kubernetes runtime")
}
if err := validateUserFlag(opts.user); err != nil {
return err
Expand Down Expand Up @@ -107,6 +107,21 @@ func runDebuggerKubernetes(ctx context.Context, cli cliutil.CLI, opts *options)
return fmt.Errorf("error adding debugger container: %v", err)
}

if opts.detach {
attachCmd := []string{"kubectl", "attach", "-n", namespace, "-c", debuggerName}
if opts.stdin {
attachCmd = append(attachCmd, "-i")
}
if opts.tty {
attachCmd = append(attachCmd, "-t")
}
attachCmd = append(attachCmd, podName)

cli.PrintAux("Debugger container %q started in the background.\n", debuggerName)
cli.PrintAux("Use %#q if you need to attach to it.\n", strings.Join(attachCmd, " "))
return nil
}

return attachPodDebugger(
ctx,
cli,
Expand Down

0 comments on commit 04ac915

Please sign in to comment.