Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 131 additions & 0 deletions cmd/dmr/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@
package main

import (
"bufio"
"context"
"fmt"
"os"
"os/exec"
"os/signal"
"path/filepath"
"strings"
Comment thread
CoderHariswar marked this conversation as resolved.
Outdated
"syscall"

"github.com/docker/cli/cli/command"
Expand All @@ -27,6 +31,15 @@ func main() {
}

func run() error {
if len(os.Args) > 1 {
switch os.Args[1] {
case "config":
return runConfig(os.Args[2:])
case "launch":
return runLaunch(os.Args[2:])
}
Comment thread
CoderHariswar marked this conversation as resolved.
Outdated
}
Comment thread
CoderHariswar marked this conversation as resolved.
Outdated

cli, err := command.NewDockerCli()
if err != nil {
return fmt.Errorf("unable to initialize CLI: %w", err)
Expand Down Expand Up @@ -67,3 +80,121 @@ func newServeCmd() *cobra.Command {
},
}
}

func runConfig(args []string) error {
if len(args) != 2 {
return fmt.Errorf("usage: dmr config sandbox.tool <tool>")
}

key := args[0]
value := args[1]

if key != "sandbox.tool" {
return fmt.Errorf("unsupported config key %q", key)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

perhaps much better if we can add a list of supported tools in the top of the file and only support here like


var allowedSandboxTools = map[string]struct{}{
    "firejail":   {},
    "bubblewrap": {},
    "bwrap":      {},
}

if _, ok := allowedSandboxTools[value]; !ok {
        return fmt.Errorf("unsupported sandbox tool %q", sandboxTool)
    }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Sure but lets just start with sbx for this PR, these can be follow on PRs

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@ericcurtin yes, this was my exact point, like it's better if we can specify the supported ones, both here and the launch

return writeSandboxToolConfig(value)
}

func runLaunch(args []string) error {
if len(args) == 0 {
return fmt.Errorf("usage: dmr launch <tool> [args...]")
}

sandboxTool, err := readSandboxToolConfig()
if err != nil {
return err
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

same thing like above can be done here for verifying supported tools

if sandboxTool == "" {
return fmt.Errorf("sandbox.tool is not configured. Run: dmr config sandbox.tool <tool>")
}

cmd := exec.Command(sandboxTool, args...)
Comment thread
sourcery-ai[bot] marked this conversation as resolved.
Outdated
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr

return cmd.Run()
}
Comment thread
CoderHariswar marked this conversation as resolved.
Outdated

func dmrConfigPath() (string, error) {
configDir, err := os.UserConfigDir()
if err != nil {
return "", fmt.Errorf("unable to determine config directory: %w", err)
}

return filepath.Join(configDir, "dmr", "config.toml"), nil
}

func writeSandboxToolConfig(tool string) error {
path, err := dmrConfigPath()
if err != nil {
return err
}

if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
return fmt.Errorf("unable to create config directory: %w", err)
}

content := fmt.Sprintf("[sandbox]\ntool = %q\n", tool)

if err := os.WriteFile(path, []byte(content), 0o644); err != nil {
Comment thread
CoderHariswar marked this conversation as resolved.
Outdated
return fmt.Errorf("unable to write config: %w", err)
}
Comment thread
CoderHariswar marked this conversation as resolved.
Outdated

return nil
}

func readSandboxToolConfig() (string, error) {
path, err := dmrConfigPath()
if err != nil {
return "", err
}

file, err := os.Open(path)
if os.IsNotExist(err) {
return "", nil
}
if err != nil {
return "", fmt.Errorf("unable to read config: %w", err)
}
defer file.Close()

inSandboxSection := false
scanner := bufio.NewScanner(file)

for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())

if line == "" || strings.HasPrefix(line, "#") {
continue
}

if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") {
inSandboxSection = line == "[sandbox]"
continue
}

if !inSandboxSection {
continue
}

key, value, ok := strings.Cut(line, "=")
if !ok {
continue
}

if strings.TrimSpace(key) != "tool" {
continue
}

return strings.Trim(strings.TrimSpace(value), `"`), nil
Comment thread
CoderHariswar marked this conversation as resolved.
Outdated
Comment thread
CoderHariswar marked this conversation as resolved.
Outdated
}

if err := scanner.Err(); err != nil {
return "", fmt.Errorf("unable to parse config: %w", err)
}

return "", nil
}