Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions pkg/unikontainers/urunc_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,27 @@ func defaultUruncConfig() *UruncConfig {
}
}

// ParseUruncConfigBytes parses the urunc configuration from a byte slice (TOML format).
// If decoding fails, it returns the default configuration alongside the error.
func ParseUruncConfigBytes(data []byte) (*UruncConfig, error) {
cfg := defaultUruncConfig()
_, err := toml.Decode(string(data), cfg)
if err != nil {
return defaultUruncConfig(), err
}
for name, mon := range cfg.Monitors {
if mon.DefaultMemoryMB == 0 {
mon.DefaultMemoryMB = defaultMonitorMemoryMB
}
if mon.DefaultVCPUs == 0 {
mon.DefaultVCPUs = defaultMonitorVCPUs
}
cfg.Monitors[name] = mon
}

return cfg, nil
}

// LoadUruncConfig loads the urunc configuration from the specified path.
// If the file does not exist or is malformed, it returns the default configuration.
func LoadUruncConfig(path string) (*UruncConfig, error) {
Expand Down
51 changes: 51 additions & 0 deletions pkg/unikontainers/urunc_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -618,3 +618,54 @@ path = "/usr/bin/mon"
assert.Equal(t, defaultMonitorsConfig(), config.Monitors)
})
}

func TestParseUruncConfigBytes(t *testing.T) {
t.Run("valid toml bytes", func(t *testing.T) {
t.Parallel()
data := []byte(`
[log]
level = "debug"
syslog = true

[monitors.qemu]
default_memory_mb = 512
default_vcpus = 2
`)
config, err := ParseUruncConfigBytes(data)
assert.NoError(t, err)
assert.Equal(t, "debug", config.Log.Level)
assert.True(t, config.Log.Syslog)
assert.Equal(t, uint(512), config.Monitors["qemu"].DefaultMemoryMB)
})

t.Run("invalid toml bytes returns default config and error", func(t *testing.T) {
t.Parallel()
data := []byte(`invalid toml [syntax`)
config, err := ParseUruncConfigBytes(data)
assert.Error(t, err)
assert.NotNil(t, config)
assert.Equal(t, defaultMonitorsConfig(), config.Monitors)
})
}

func FuzzLoadUruncConfig(f *testing.F) {
// Seed corpus with valid TOML configurations and edge cases
f.Add([]byte(""))
f.Add([]byte("[log]\nlevel = \"debug\"\nsyslog = true\n"))
f.Add([]byte("[monitors.qemu]\ndefault_memory_mb = 512\ndefault_vcpus = 2\npath = \"/usr/bin/qemu\"\n"))
f.Add([]byte("[extra_binaries.virtiofsd]\npath = \"/usr/libexec/virtiofsd\"\noptions = \"--cache always\"\n"))
f.Add([]byte("[monitors.custom]\ndefault_memory_mb = 0\ndefault_vcpus = 0\n"))

f.Fuzz(func(t *testing.T, data []byte) {
cfg, err := ParseUruncConfigBytes(data)
if err != nil {
if cfg == nil {
t.Fatalf("ParseUruncConfigBytes returned nil config on error")
}
return
}
// Invariant: parsed config must produce valid map representation without panics
_ = cfg.Map()
})
}