summaryrefslogtreecommitdiff
path: root/internal/cli
diff options
context:
space:
mode:
Diffstat (limited to 'internal/cli')
-rw-r--r--internal/cli/cli.go114
-rw-r--r--internal/cli/cli_test.go34
2 files changed, 148 insertions, 0 deletions
diff --git a/internal/cli/cli.go b/internal/cli/cli.go
new file mode 100644
index 0000000..cb95202
--- /dev/null
+++ b/internal/cli/cli.go
@@ -0,0 +1,114 @@
+package cli
+
+import (
+ "flag"
+ "fmt"
+
+ "git.theodohertyfamily.com/tools/wg-wrap/internal/config"
+)
+
+type App struct {
+ Args []string
+ ConfigDir string // Optional override for profile storage location
+}
+
+func NewApp(args []string) *App {
+ return &App{Args: args}
+}
+
+func (a *App) Run() error {
+ // Handle subcommands first (profile list, import, configure, delete, stop)
+ if len(a.Args) > 1 && a.Args[1] == "profile" {
+ return a.handleProfileCmd()
+ }
+
+ cfg := &config.Config{}
+
+ fs := flag.NewFlagSet("wg-wrap", flag.ExitOnError)
+ fs.StringVar(&cfg.Profile, "profile", "", "WireGuard profile to use (filename without extension in ~/.config/wg-wrap/profiles/)")
+ fs.StringVar(&cfg.DNSServer, "dns-server", "", "Override DNS server to use")
+
+ args := a.Args[1:]
+ sepIdx := -1
+ for i, arg := range args {
+ if arg == "--" {
+ sepIdx = i
+ break
+ }
+ }
+
+ var flagsToParse []string
+ if sepIdx != -1 {
+ flagsToParse = args[:sepIdx]
+ cfg.Command = args[sepIdx+1:]
+ } else {
+ flagsToParse = args
+ }
+
+ err := fs.Parse(flagsToParse)
+ if err != nil {
+ return fmt.Errorf("error parsing flags: %w", err)
+ }
+
+ if sepIdx == -1 {
+ cfg.Command = fs.Args()
+ }
+
+ if len(cfg.Command) == 0 {
+ return fmt.Errorf("no command provided. use --help for usage")
+ }
+
+ if cfg.Profile == "" {
+ cfg.Profile = "default"
+ }
+
+ profilesDir := a.ConfigDir
+ if profilesDir == "" {
+ profilesDir = config.GetDefaultProfilesDir()
+ }
+
+ fmt.Printf("Profile: %s\n", cfg.Profile)
+ fmt.Printf("Profiles Directory: %s\n", profilesDir)
+ fmt.Printf("DNS Server: %s\n", cfg.DNSServer)
+ fmt.Printf("Command: %v\n", cfg.Command)
+ return nil
+}
+
+func (a *App) handleProfileCmd() error {
+ if len(a.Args) < 3 {
+ return fmt.Errorf("usage: wg-wrap profile <list|import|configure|delete|stop> [args]")
+ }
+
+ subCmd := a.Args[2]
+ switch subCmd {
+ case "list":
+ fmt.Println("Listing profiles...")
+ return fmt.Errorf("profile list not yet implemented")
+ case "import":
+ if len(a.Args) < 4 {
+ return fmt.Errorf("usage: wg-wrap profile import <path>")
+ }
+ fmt.Printf("Importing profile from %s...\n", a.Args[3])
+ return fmt.Errorf("profile import not yet implemented")
+ case "configure":
+ if len(a.Args) < 4 {
+ return fmt.Errorf("usage: wg-wrap profile configure <name>")
+ }
+ fmt.Printf("Configuring profile %s...\n", a.Args[3])
+ return fmt.Errorf("profile configure not yet implemented")
+ case "delete":
+ if len(a.Args) < 4 {
+ return fmt.Errorf("usage: wg-wrap profile delete <name>")
+ }
+ fmt.Printf("Deleting profile %s...\n", a.Args[3])
+ return fmt.Errorf("profile delete not yet implemented")
+ case "stop":
+ if len(a.Args) < 4 {
+ return fmt.Errorf("usage: wg-wrap profile stop <name>")
+ }
+ fmt.Printf("Stopping profile %s and unpinning namespace...\n", a.Args[3])
+ return fmt.Errorf("profile stop not yet implemented")
+ default:
+ return fmt.Errorf("unknown profile subcommand: %s", subCmd)
+ }
+}
diff --git a/internal/cli/cli_test.go b/internal/cli/cli_test.go
new file mode 100644
index 0000000..71ff6cb
--- /dev/null
+++ b/internal/cli/cli_test.go
@@ -0,0 +1,34 @@
+package cli
+
+import (
+ "testing"
+)
+
+func TestAppRun_ProfileDirInjection(t *testing.T) {
+ // Set up a temporary directory to simulate XDG_CONFIG_HOME/wg-wrap/profiles
+ tmpDir := t.TempDir()
+
+ tests := []struct {
+ name string
+ args []string
+ wantErr bool
+ }{
+ {
+ name: "valid profile with injected dir",
+ args: []string{"wg-wrap", "--profile", "test-vpn", "curl", "google.com"},
+ wantErr: false,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ app := NewApp(tt.args)
+ app.ConfigDir = tmpDir // Inject temporary directory
+
+ err := app.Run()
+ if (err != nil) != tt.wantErr {
+ t.Errorf("App.Run() error = %v, wantErr %v", err, tt.wantErr)
+ }
+ })
+ }
+}