feat: import existing smb.conf and /etc/exports on first boot
Adds auto-detection of pre-existing Samba shares and NFS exports when nasctl is installed on a host that already has these configs. New package internal/importer parses smb.conf (INI-style) and /etc/exports (line-based) and imports them into SQLite. Imported shares/exports are marked dirty so the user must review and apply manually before any file is overwritten. Backup: before the first Apply, each module backs up the original config to <path>.nasctl.bak.<timestamp> (one time only). New CLI flag --import-on-boot / NASCTL_IMPORT_ON_BOOT env var (default false, opt-in). New API endpoints: GET /api/import/status POST /api/import/samba POST /api/import/nfs New DB methods ReplaceSambaShares/ReplaceNFSExports (transactional replace-all), guarded by import.samba.done / import.nfs.done settings flags.
This commit is contained in:
@@ -9,6 +9,7 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/darroyo/nasctl/internal/db"
|
||||
"github.com/darroyo/nasctl/internal/system"
|
||||
@@ -58,6 +59,10 @@ func (m *Module) IsDirty(ctx context.Context, database *db.DB) (bool, error) {
|
||||
}
|
||||
|
||||
func (m *Module) Apply(ctx context.Context, database *db.DB) error {
|
||||
if err := m.maybeBackup(database); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
shares, err := database.ListSambaShares()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -121,6 +126,31 @@ func (m *Module) renderConfig(shares []db.SambaShare) ([]byte, error) {
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
func (m *Module) maybeBackup(database *db.DB) error {
|
||||
done, ok, err := database.GetSetting("backup.samba.done")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if ok && done == "true" {
|
||||
return nil
|
||||
}
|
||||
if _, err := os.Stat(m.cfg.SMBConfPath); os.IsNotExist(err) {
|
||||
return nil
|
||||
} else if err != nil {
|
||||
return nil
|
||||
}
|
||||
src, err := os.ReadFile(m.cfg.SMBConfPath)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
backupPath := m.cfg.SMBConfPath + ".nasctl.bak." + time.Now().Format("20060102T150405")
|
||||
if err := os.WriteFile(backupPath, src, 0o644); err != nil {
|
||||
return fmt.Errorf("backup smb.conf: %w", err)
|
||||
}
|
||||
_ = database.SetSetting("backup.samba.done", "true")
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeAtomic(path string, content []byte) error {
|
||||
dir := filepath.Dir(path)
|
||||
if err := os.MkdirAll(dir, 0o755); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user