mirror of
https://github.com/navidrome/navidrome.git
synced 2026-07-09 17:18:45 +00:00
fix(service): rewrite systemd service template for kardianos/service v1.3.0 (#5743)
Some checks are pending
Pipeline: Test, Lint, Build / Get version info (push) Waiting to run
Pipeline: Test, Lint, Build / Lint Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test Go code (Windows) (push) Waiting to run
Pipeline: Test, Lint, Build / Test JS code (push) Waiting to run
Pipeline: Test, Lint, Build / Lint i18n files (push) Waiting to run
Pipeline: Test, Lint, Build / Check Docker configuration (push) Waiting to run
Pipeline: Test, Lint, Build / Build (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-1 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-2 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-3 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-4 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-5 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-6 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-7 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-8 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-9 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-10 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to GHCR (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to Docker Hub (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Cleanup digest artifacts (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build Windows installers (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Package/Release (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Upload Linux PKG (push) Blocked by required conditions
Some checks are pending
Pipeline: Test, Lint, Build / Get version info (push) Waiting to run
Pipeline: Test, Lint, Build / Lint Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test Go code (Windows) (push) Waiting to run
Pipeline: Test, Lint, Build / Test JS code (push) Waiting to run
Pipeline: Test, Lint, Build / Lint i18n files (push) Waiting to run
Pipeline: Test, Lint, Build / Check Docker configuration (push) Waiting to run
Pipeline: Test, Lint, Build / Build (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-1 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-2 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-3 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-4 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-5 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-6 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-7 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-8 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-9 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-10 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to GHCR (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to Docker Hub (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Cleanup digest artifacts (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build Windows installers (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Package/Release (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Upload Linux PKG (push) Blocked by required conditions
kardianos/service v1.3.0 (shipped in Navidrome 0.63.0) replaced Go's
text/template with a small custom engine that uses bare keys ({{Description}})
instead of dotted fields ({{.Description}}). Our custom SystemdScript was
still written in text/template syntax, so 'navidrome service install' failed
with 'FATA service: unknown template key ".Description"', breaking the .deb
postinst and leaving an empty/masked systemd unit.
Rewrite the template in the new engine's syntax and add a test that validates
every key and pipeline function used in the template against the set the
library provides to systemd templates, so future engine/key drift is caught
at test time. Verified end-to-end on Linux: the previous binary reproduces
the reported fatal error and the fixed one generates a complete unit file.
Fixes #5742
This commit is contained in:
parent
4652b46602
commit
42d4363f61
2 changed files with 66 additions and 12 deletions
23
cmd/svc.go
23
cmd/svc.go
|
|
@ -232,22 +232,21 @@ func buildExecuteCmd() *cobra.Command {
|
|||
}
|
||||
|
||||
const systemdScript = `[Unit]
|
||||
Description={{.Description}}
|
||||
ConditionFileIsExecutable={{.Path|cmdEscape}}
|
||||
{{range $i, $dep := .Dependencies}}
|
||||
{{$dep}} {{end}}
|
||||
|
||||
Description={{Description}}
|
||||
ConditionFileIsExecutable={{Path | cmdEscape}}
|
||||
{{range Dependencies}}{{.}}
|
||||
{{end}}
|
||||
[Service]
|
||||
StartLimitInterval=5
|
||||
StartLimitBurst=10
|
||||
ExecStart={{.Path|cmdEscape}}{{range .Arguments}} {{.|cmd}}{{end}}
|
||||
{{if .WorkingDirectory}}WorkingDirectory={{.WorkingDirectory|cmdEscape}}{{end}}
|
||||
{{if .UserName}}User={{.UserName}}{{end}}
|
||||
{{if .Restart}}Restart={{.Restart}}{{end}}
|
||||
{{if .SuccessExitStatus}}SuccessExitStatus={{.SuccessExitStatus}}{{end}}
|
||||
ExecStart={{Path | cmdEscape}}{{range Arguments}} {{. | cmd}}{{end}}
|
||||
{{if WorkingDirectory}}WorkingDirectory={{WorkingDirectory | cmdEscape}}{{end}}
|
||||
{{if UserName}}User={{UserName}}{{end}}
|
||||
{{if Restart}}Restart={{Restart}}{{end}}
|
||||
{{if SuccessExitStatus}}SuccessExitStatus={{SuccessExitStatus}}{{end}}
|
||||
TimeoutStopSec=20
|
||||
RestartSec=120
|
||||
EnvironmentFile=-/etc/sysconfig/{{.Name}}
|
||||
EnvironmentFile=-/etc/sysconfig/{{Name}}
|
||||
Environment="ND_SYSTEMD_PRIORITY_LOGGING=1"
|
||||
|
||||
DevicePolicy=closed
|
||||
|
|
@ -260,7 +259,7 @@ RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
|
|||
RestrictNamespaces=yes
|
||||
RestrictRealtime=yes
|
||||
SystemCallFilter=~@clock @debug @module @mount @obsolete @reboot @setuid @swap
|
||||
{{if .WorkingDirectory}}ReadWritePaths={{.WorkingDirectory|cmdEscape}}{{end}}
|
||||
{{if WorkingDirectory}}ReadWritePaths={{WorkingDirectory | cmdEscape}}{{end}}
|
||||
ProtectSystem=full
|
||||
|
||||
[Install]
|
||||
|
|
|
|||
55
cmd/svc_test.go
Normal file
55
cmd/svc_test.go
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
var _ = Describe("systemdScript template", func() {
|
||||
systemdKeys := map[string]bool{
|
||||
"Description": true, "Path": true, "Name": true, "Dependencies": true,
|
||||
"Arguments": true, "ChRoot": true, "WorkingDirectory": true,
|
||||
"UserName": true, "ReloadSignal": true, "PIDFile": true,
|
||||
"LogDirectory": true, "OutputFileSupport": true, "LimitNOFILE": true,
|
||||
"Restart": true, "SuccessExitStatus": true, "EnvVars": true,
|
||||
}
|
||||
systemdFuncs := map[string]bool{"cmd": true, "cmdEscape": true}
|
||||
|
||||
actionRe := regexp.MustCompile(`\{\{(.*?)\}\}`)
|
||||
|
||||
parseAction := func(action string) (key string, funcs []string) {
|
||||
action = strings.TrimSpace(strings.TrimSuffix(strings.TrimPrefix(action, "-"), "-"))
|
||||
kw, rest, _ := strings.Cut(action, " ")
|
||||
switch kw {
|
||||
case "end", "else":
|
||||
return "", nil
|
||||
case "if", "range":
|
||||
return strings.TrimSpace(rest), nil
|
||||
}
|
||||
parts := strings.Split(action, "|")
|
||||
for _, p := range parts[1:] {
|
||||
funcs = append(funcs, strings.TrimSpace(p))
|
||||
}
|
||||
return strings.TrimSpace(parts[0]), funcs
|
||||
}
|
||||
|
||||
It("only references keys and functions the service library provides", func() {
|
||||
matches := actionRe.FindAllStringSubmatch(systemdScript, -1)
|
||||
Expect(matches).ToNot(BeEmpty())
|
||||
|
||||
for _, m := range matches {
|
||||
key, funcs := parseAction(m[1])
|
||||
if key != "" && key != "." {
|
||||
Expect(systemdKeys).To(HaveKey(key),
|
||||
"template action %q uses a key unknown to kardianos/service", m[0])
|
||||
}
|
||||
for _, fn := range funcs {
|
||||
Expect(systemdFuncs).To(HaveKey(fn),
|
||||
"template action %q uses an unknown pipeline function", m[0])
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue