Go parser for Systemd unit files.
- Go 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
All checks were successful
ci/woodpecker/push/change_log Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/tag/release Pipeline was successful
ci/woodpecker/cron/vulnerability Pipeline was successful
ci/woodpecker/cron/auto_merge Pipeline was successful
ci/woodpecker/cron/renovate Pipeline was successful
ci/woodpecker/cron/release Pipeline was successful
A cont_sign ('\\') is meant to fold only the single line right after it, but the lexer inferred "still folding" from whether the last emitted token was a cont_sign. Blank lines emit no token, so that check stayed true across any number of blank lines and even leaked into the next, unrelated keyword's parse (readKeyValuePair is re-entered once per keyword), silently merging it into the previous value.
Track fold state explicitly on the Lexer instead of inferring it from the token stream, so a continuation ends after exactly one folded line.
Reviewed-on: #21
|
||
| dist | ||
| encoding/systemd | ||
| testutils | ||
| .gitignore | ||
| .markdownlint.json | ||
| .prettierrc | ||
| go.mod | ||
| go.sum | ||
| LICENSE | ||
| README.md | ||
| renovate.json | ||
Systemd unit file parser
This is a parser library to parse Systemd unit files, which can be any unit file or Podman Quadlet or any configuration file that wants to follow this pattern.
The interface is very similar than encoding/json in the standard library.
Install
Run the following command:
go get -u code.thinkaboutit.tech/pandora/systemd-file.gopack
Examples to use
Parse existing file with specific struct
If we had the following unit file:
[Unit]
SourcePath=/etc/fstab
Documentation=man:fstab(5) man:systemd-fstab-generator(8)
[Automount]
Where=/var/mnt/data
[X-Other]
Property=Value is here
Property=Another value is here
We can parse it from Go:
type AutoMountFile struct {
Unit AutoMountUnit
Automount AutoMount
XOther XOther `systemd:"X-Other"`
}
type AutoMountUnit struct {
SourcePath string
Documentation string
}
type AutoMount struct {
Where string
}
type XOther struct {
Property []string
}
func main() {
input, err := os.ReadFile("path/to/test.automount")
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
var file AutoMountFile
err = systemd.Unmarshal([]byte(input), &file)
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
fmt.Printf("%+v\n", file)
}
Read the whole file
input = `
[Setup]
TargetRegistry=code.thinkaboutit.tech
ProdOwner=pandora
StagingOwner=staging
[WolifBase]
Source=cgr.dev/chainguard/wolfi-base:latest@sha256:195c8853f52e0463d217aa8bdf14f6730ae97305de399559d86b76403f9528af
[DebianBase]
Source=dhi.io/debian-base:trixie@sha256:5a539a75a33da9019e8f667c3e7e3e1eb00b52a69cace95b0225f8134aee17b3
TargetName=debian-base
[DebianDev]
Source=dhi.io/debian-base:trixie-dev@sha256:57c88d9180b30314a04650426af8d4301c5c9738e4c5672a1db99a03f6a54721
TargetName=debian-dev
`
var result map[string]map[string]any
err = systemd.Unmarshal([]byte(input), &result)
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
for sName, sValue := range result {
for k, v := range sValue {
fmt.Printf("%s.%s ==> %v\n", sName, k, v)
}
}
Convert map to systemd file
The library can parse map or struct to string in Systemd file format.
data := map[string]any{
"Service": map[string]any{
"Restart": "always",
"TimeoutSec": 30,
"Environment": []string{
"ENV=prod",
"DEBUG=false",
},
},
}
marshaled, err := systemd.Marshal(data)
require.NoError(t, err)
expected := `[Service]
Environment=ENV=prod
Environment=DEBUG=false
Restart=always
TimeoutSec=30
`
assert.Equal(t, expected, string(marshaled))