4ae7335b31
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.
167 lines
2.7 KiB
Go
167 lines
2.7 KiB
Go
package importer
|
|
|
|
import (
|
|
"testing"
|
|
)
|
|
|
|
func TestParseSambaConf(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
wantLen int
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "basic share",
|
|
input: `[global]
|
|
workgroup = WORKGROUP
|
|
security = user
|
|
|
|
[share1]
|
|
path = /srv/samba/share1
|
|
comment = Test Share
|
|
read only = no
|
|
guest ok = no
|
|
`,
|
|
wantLen: 1,
|
|
},
|
|
{
|
|
name: "multiple shares with valid users and groups",
|
|
input: `[global]
|
|
server string = Test Server
|
|
|
|
[public]
|
|
path = /srv/samba/public
|
|
comment = Public Files
|
|
read only = yes
|
|
guest ok = yes
|
|
|
|
[data]
|
|
path = /srv/samba/data
|
|
comment = Data Share
|
|
read only = no
|
|
writable = yes
|
|
guest ok = no
|
|
valid users = alice, bob
|
|
valid groups = staff
|
|
`,
|
|
wantLen: 2,
|
|
},
|
|
{
|
|
name: "ignores global section",
|
|
input: `[global]
|
|
workgroup = WORKGROUP
|
|
security = user
|
|
server string = test
|
|
|
|
[global]
|
|
printing = cups
|
|
|
|
[myshare]
|
|
path = /srv/samba/myshare
|
|
`,
|
|
wantLen: 1,
|
|
},
|
|
{
|
|
name: "ignores printers section",
|
|
input: `[printers]
|
|
comment = All Printers
|
|
path = /var/spool/samba
|
|
printable = yes
|
|
guest ok = yes
|
|
|
|
[global]
|
|
workgroup = WORKGROUP
|
|
|
|
[myshare]
|
|
path = /srv/samba/myshare
|
|
`,
|
|
wantLen: 1,
|
|
},
|
|
{
|
|
name: "handles comments with semicolon",
|
|
input: `; This is a comment
|
|
[global]
|
|
workgroup = WORKGROUP
|
|
|
|
[myshare]
|
|
path = /srv/samba/myshare
|
|
`,
|
|
wantLen: 1,
|
|
},
|
|
{
|
|
name: "handles continuation lines",
|
|
input: `[myshare]
|
|
path = /srv/samba/\
|
|
myshare
|
|
comment = continued\
|
|
line
|
|
`,
|
|
wantLen: 1,
|
|
},
|
|
{
|
|
name: "handles quoted values",
|
|
input: `[myshare]
|
|
path = "/srv/samba/myshare"
|
|
comment = "Test comment"
|
|
`,
|
|
wantLen: 1,
|
|
},
|
|
{
|
|
name: "empty input",
|
|
input: "",
|
|
wantLen: 0,
|
|
},
|
|
{
|
|
name: "skip share without path",
|
|
input: `[nopath]
|
|
comment = No path here
|
|
`,
|
|
wantLen: 0,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := parseSambaConf([]byte(tt.input))
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("parseSambaConf() error = %v, wantErr %v", err, tt.wantErr)
|
|
return
|
|
}
|
|
if len(got) != tt.wantLen {
|
|
t.Errorf("parseSambaConf() got %d shares, want %d", len(got), tt.wantLen)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestParseBool(t *testing.T) {
|
|
tests := []struct {
|
|
input string
|
|
expected bool
|
|
}{
|
|
{"yes", true},
|
|
{"no", false},
|
|
{"true", true},
|
|
{"false", false},
|
|
{"1", true},
|
|
{"0", false},
|
|
{"on", true},
|
|
{"off", false},
|
|
{"YES", true},
|
|
{"NO", false},
|
|
{"True", true},
|
|
{"False", false},
|
|
{"", false},
|
|
{"maybe", false},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.input, func(t *testing.T) {
|
|
if got := parseBool(tt.input); got != tt.expected {
|
|
t.Errorf("parseBool(%q) = %v, want %v", tt.input, got, tt.expected)
|
|
}
|
|
})
|
|
}
|
|
}
|