Skip to content

Commit

Permalink
containers.conf: add database backend option
Browse files Browse the repository at this point in the history
The on-going work of adding a new database backend to Podman requires it
to be configurable in containers.conf.  To prevent any breaking changes,
the backend defaults to Podman's current boltdb backend.  Also export
the parsing function for it be usable by Podman.

NOTE: documentation will be added once the database rewrite in Podman
has been completed.  I want to avoid any incomplete docs from leaking
into a release.

Fixes: https://issues.redhat.com/browse/RUN-1772
Signed-off-by: Valentin Rothberg <[email protected]>
  • Loading branch information
vrothberg committed Feb 20, 2023
1 parent dbef45f commit e7f5764
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 0 deletions.
8 changes: 8 additions & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,9 @@ type EngineConfig struct {
// in containers-registries.conf(5).
CompatAPIEnforceDockerHub bool `toml:"compat_api_enforce_docker_hub,omitempty"`

// DBBackend is the database backend to be used by Podman.
DBBackend string `toml:"database_backend,omitempty"`

// DetachKeys is the sequence of keys used to detach a container.
DetachKeys string `toml:"detach_keys,omitempty"`

Expand Down Expand Up @@ -898,6 +901,11 @@ func (c *EngineConfig) Validate() error {
if _, err := ValidatePullPolicy(pullPolicy); err != nil {
return fmt.Errorf("invalid pull type from containers.conf %q: %w", c.PullPolicy, err)
}

if _, err := ParseDBBackend(c.DBBackend); err != nil {
return err
}

return nil
}

Expand Down
16 changes: 16 additions & 0 deletions pkg/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ var _ = Describe("Config", func() {
gomega.Expect(defaultConfig.Engine.ImageVolumeMode).To(gomega.BeEquivalentTo("bind"))
gomega.Expect(defaultConfig.Engine.SSHConfig).To(gomega.ContainSubstring("/.ssh/config"))
gomega.Expect(defaultConfig.Engine.EventsContainerCreateInspectData).To(gomega.BeFalse())
gomega.Expect(defaultConfig.Engine.DBBackend).To(gomega.BeEquivalentTo(stringBoltDB))

dbBackend, err := defaultConfig.DBBackend()
gomega.Expect(dbBackend).To(gomega.BeEquivalentTo(DBBackendBoltDB))
gomega.Expect(err).To(gomega.BeNil())
path, err := defaultConfig.ImageCopyTmpDir()
gomega.Expect(err).To(gomega.BeNil())
gomega.Expect(path).To(gomega.BeEquivalentTo("/var/tmp"))
Expand Down Expand Up @@ -410,6 +415,11 @@ image_copy_tmp_dir="storage"`
gomega.Expect(config.Containers.HostContainersInternalIP).To(gomega.BeEquivalentTo("1.2.3.4"))
gomega.Expect(config.Engine.ImageVolumeMode).To(gomega.BeEquivalentTo("tmpfs"))
gomega.Expect(config.Engine.SSHConfig).To(gomega.Equal("/foo/bar/.ssh/config"))

gomega.Expect(config.Engine.DBBackend).To(gomega.Equal(stringSQLite))
dbBackend, err := config.DBBackend()
gomega.Expect(err).To(gomega.BeNil())
gomega.Expect(dbBackend).To(gomega.BeEquivalentTo(DBBackendSQLite))
})

It("contents of passed-in file should override others", func() {
Expand Down Expand Up @@ -553,6 +563,12 @@ image_copy_tmp_dir="storage"`
err := sut.Engine.Validate()
gomega.Expect(err).ToNot(gomega.BeNil())
})

It("should fail with invalid database_backend", func() {
sut.Engine.DBBackend = ""
err := sut.Engine.Validate()
gomega.Expect(err).ToNot(gomega.BeNil())
})
})

Describe("Service Destinations", func() {
Expand Down
60 changes: 60 additions & 0 deletions pkg/config/db_backend.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package config

import "fmt"

// DBBackend determines which supported database backend Podman should use.
type DBBackend int

const (
// Unsupported database backend. Used as a sane base value for the type.
DBBackendUnsupported DBBackend = iota
// BoltDB backend.
DBBackendBoltDB
// SQLite backend.
DBBackendSQLite

stringBoltDB = "boltdb"
stringSQLite = "sqlite"
)

// String returns the DBBackend's string representation.
func (d DBBackend) String() string {
switch d {
case DBBackendBoltDB:
return stringBoltDB
case DBBackendSQLite:
return stringSQLite
default:
return fmt.Sprintf("unsupported database backend: %d", d)
}
}

// Validate returns whether the DBBackend is supported.
func (d DBBackend) Validate() error {
switch d {
case DBBackendBoltDB, DBBackendSQLite:
return nil
default:
return fmt.Errorf("unsupported database backend: %d", d)
}
}

// ParseDBBackend parses the specified string into a DBBackend.
// An error is return for unsupported backends.
func ParseDBBackend(raw string) (DBBackend, error) {
// NOTE: this function should be used for parsing the user-specified
// values on Podman's CLI.
switch raw {
case stringBoltDB:
return DBBackendBoltDB, nil
case stringSQLite:
return DBBackendSQLite, nil
default:
return DBBackendUnsupported, fmt.Errorf("unsupported database backend: %q", raw)
}
}

// DBBackend returns the configured database backend.
func (c *Config) DBBackend() (DBBackend, error) {
return ParseDBBackend(c.Engine.DBBackend)
}
33 changes: 33 additions & 0 deletions pkg/config/db_backend_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package config

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestDBBackend(t *testing.T) {
tests := []struct {
input string
valid bool
expected DBBackend
}{
{stringBoltDB, true, DBBackendBoltDB},
{stringSQLite, true, DBBackendSQLite},
{"", false, DBBackendUnsupported},
{stringSQLite + " ", false, DBBackendUnsupported},
}

for _, test := range tests {
result, err := ParseDBBackend(test.input)
if test.valid {
require.NoError(t, err, "should parse %v", test)
require.NoError(t, result.Validate(), "should validate %v", test)
require.Equal(t, test.expected, result)
} else {
require.Error(t, err, "should NOT parse %v", test)
require.Error(t, result.Validate(), "should NOT validate %v", test)
require.Equal(t, test.expected, result)
}
}
}
3 changes: 3 additions & 0 deletions pkg/config/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ const (
CgroupfsCgroupsManager = "cgroupfs"
// DefaultApparmorProfile specifies the default apparmor profile for the container.
DefaultApparmorProfile = apparmor.Profile
// DefaultDBBackend specifies the default database backend to be used by Podman.
DefaultDBBackend = DBBackendBoltDB
// DefaultHostsFile is the default path to the hosts file.
DefaultHostsFile = "/etc/hosts"
// SystemdCgroupsManager represents systemd native cgroup manager.
Expand Down Expand Up @@ -387,6 +389,7 @@ func defaultConfigFromMemory() (*EngineConfig, error) {
"/run/current-system/sw/bin/conmonrs",
}
c.PullPolicy = DefaultPullPolicy
c.DBBackend = stringBoltDB
c.RuntimeSupportsJSON = []string{
"crun",
"runc",
Expand Down
2 changes: 2 additions & 0 deletions pkg/config/testdata/containers_default.conf
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ dns_bind_port = 1153
# Cgroup management implementation used for the runtime.
cgroup_manager = "systemd"

database_backend = "sqlite"

# Default transport method for pulling and pushing for images
image_default_transport = "docker://"

Expand Down

0 comments on commit e7f5764

Please sign in to comment.