feat: read managed database passwords from secrets
This commit is contained in:
@@ -9,10 +9,11 @@ import (
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
config "cloud.campbellwireless.net/git/barkstack/barkfile-parser"
|
||||
config "cloud.campbellwireless.net/git/barkstack/barkfile-parser/v2"
|
||||
)
|
||||
|
||||
const managedDatabaseLabel = "io.barkstack.pawsql.database"
|
||||
@@ -20,8 +21,9 @@ const managedDatabaseLabel = "io.barkstack.pawsql.database"
|
||||
// Provisioner ensures configured PostgreSQL containers exist and exposes their
|
||||
// loopback-published PostgreSQL address to PawSQL's static router.
|
||||
type Provisioner struct {
|
||||
DockerPath string
|
||||
Logger *slog.Logger
|
||||
DockerPath string
|
||||
SecretDirectory string
|
||||
Logger *slog.Logger
|
||||
}
|
||||
|
||||
// NewProvisioner creates a Docker CLI-backed provisioner.
|
||||
@@ -29,7 +31,7 @@ func NewProvisioner(logger *slog.Logger) *Provisioner {
|
||||
if logger == nil {
|
||||
logger = slog.Default()
|
||||
}
|
||||
return &Provisioner{DockerPath: "docker", Logger: logger}
|
||||
return &Provisioner{DockerPath: "docker", SecretDirectory: "/run/secrets", Logger: logger}
|
||||
}
|
||||
|
||||
// Ensure provisions each PostgreSQL-backed database and returns configuration
|
||||
@@ -65,13 +67,13 @@ func (p *Provisioner) EnsureDatabase(ctx context.Context, database string, postg
|
||||
return "", err
|
||||
}
|
||||
if !exists {
|
||||
password, ok := os.LookupEnv(postgres.PasswordEnv)
|
||||
if !ok || password == "" {
|
||||
return "", fmt.Errorf("environment variable %q is required to create the container", postgres.PasswordEnv)
|
||||
password, err := p.readSecret(postgres.PasswordSecret)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
p.Logger.Info("creating PostgreSQL container", "database", database, "container", name, "image", postgres.Image, "volume", postgres.Volume)
|
||||
mount := postgresDataMount(postgres.Image)
|
||||
_, err := p.run(ctx, []string{"POSTGRES_PASSWORD=" + password},
|
||||
_, err = p.run(ctx, []string{"POSTGRES_PASSWORD=" + password},
|
||||
"container", "create",
|
||||
"--name", name,
|
||||
"--label", managedDatabaseLabel+"="+database,
|
||||
@@ -110,6 +112,26 @@ func (p *Provisioner) EnsureDatabase(ctx context.Context, database string, postg
|
||||
return address, nil
|
||||
}
|
||||
|
||||
func (p *Provisioner) readSecret(reference string) (string, error) {
|
||||
if !config.ValidSecretReference(reference) {
|
||||
return "", fmt.Errorf("invalid password secret reference %q", reference)
|
||||
}
|
||||
directory := p.SecretDirectory
|
||||
if directory == "" {
|
||||
directory = "/run/secrets"
|
||||
}
|
||||
name := config.DockerSecretName(reference)
|
||||
contents, err := os.ReadFile(filepath.Join(directory, name))
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("read Docker secret %q: %w", name, err)
|
||||
}
|
||||
password := strings.TrimRight(string(contents), "\r\n")
|
||||
if password == "" {
|
||||
return "", fmt.Errorf("Docker secret %q is empty", name)
|
||||
}
|
||||
return password, nil
|
||||
}
|
||||
|
||||
// StopDatabase stops a managed PostgreSQL container without removing its data volume.
|
||||
func (p *Provisioner) StopDatabase(ctx context.Context, database string) error {
|
||||
name := containerName(database)
|
||||
|
||||
Reference in New Issue
Block a user