M8: add command to append a single device to config
New 'arca add <device>' subcommand detects a LUKS device via udisks2 and appends it to the config with passphrase as default method. Supports --alias/-a to override the generated name. Skips if UUID already configured. Adds Config.Save() and Config.HasUUID() to config package. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
87
cmd/add.go
Normal file
87
cmd/add.go
Normal file
@@ -0,0 +1,87 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"git.wntrmute.dev/kyle/arca/internal/config"
|
||||
"git.wntrmute.dev/kyle/arca/internal/udisks"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var addAlias string
|
||||
|
||||
var addCmd = &cobra.Command{
|
||||
Use: "add <device>",
|
||||
Short: "Add a device to the config",
|
||||
Long: "Detects a LUKS device via udisks2 and adds it to the config file with a default passphrase method.",
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: runAdd,
|
||||
}
|
||||
|
||||
func init() {
|
||||
addCmd.Flags().StringVarP(&addAlias, "alias", "a", "", "alias name (default: first 8 chars of UUID)")
|
||||
rootCmd.AddCommand(addCmd)
|
||||
}
|
||||
|
||||
func runAdd(cmd *cobra.Command, args []string) error {
|
||||
target := args[0]
|
||||
|
||||
client, err := udisks.NewClient()
|
||||
if err != nil {
|
||||
return fmt.Errorf("connecting to udisks2: %w", err)
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
// Find the device to get its UUID.
|
||||
dev, err := client.FindDevice("", target)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !dev.HasEncrypted {
|
||||
return fmt.Errorf("%s is not a LUKS-encrypted device", target)
|
||||
}
|
||||
|
||||
if dev.UUID == "" {
|
||||
return fmt.Errorf("%s has no UUID", target)
|
||||
}
|
||||
|
||||
cfg := config.Load()
|
||||
|
||||
// Check if already configured.
|
||||
if existing := cfg.AliasFor(dev.UUID); existing != "" {
|
||||
fmt.Printf("Device %s (UUID %s) already configured as %q\n", dev.DevicePath, dev.UUID, existing)
|
||||
return nil
|
||||
}
|
||||
|
||||
alias := addAlias
|
||||
if alias == "" {
|
||||
alias = aliasFromUUID(dev.UUID)
|
||||
}
|
||||
|
||||
// Check for alias collision.
|
||||
if _, exists := cfg.Devices[alias]; exists {
|
||||
return fmt.Errorf("alias %q already in use — choose a different name with --alias", alias)
|
||||
}
|
||||
|
||||
cfg.Devices[alias] = config.DeviceConfig{
|
||||
UUID: dev.UUID,
|
||||
Methods: []string{"passphrase"},
|
||||
}
|
||||
|
||||
if err := cfg.Save(); err != nil {
|
||||
return fmt.Errorf("saving config: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Added %s (UUID %s) as %q\n", dev.DevicePath, dev.UUID, alias)
|
||||
return nil
|
||||
}
|
||||
|
||||
func aliasFromUUID(uuid string) string {
|
||||
clean := strings.ReplaceAll(uuid, "-", "")
|
||||
if len(clean) > 8 {
|
||||
clean = clean[:8]
|
||||
}
|
||||
return clean
|
||||
}
|
||||
Reference in New Issue
Block a user