feat: make TLS optional in Barkfile schema
All checks were successful
Test and Release Module / test (push) Successful in 21s
Test and Release Module / release (push) Successful in 12s

This commit is contained in:
2026-09-15 21:59:48 -04:00
parent 1851797a3f
commit c3ad476b1a
3 changed files with 52 additions and 7 deletions

View File

@@ -21,7 +21,7 @@ if err != nil {
`Load` reads, parses, and validates a file. `Parse` parses bytes when a caller owns file I/O; call `Config.Validate` before applying a parsed configuration. `Load` reads, parses, and validates a file. `Parse` parses bytes when a caller owns file I/O; call `Config.Validate` before applying a parsed configuration.
The current schema defines one `pawsql` block with a listener, TLS certificate/key paths, and one or more `database` routes. A route has exactly one of: The current schema defines one `pawsql` block with a listener, an optional TLS `cert`/`key` pair, and one or more `database` routes. A route has exactly one of:
- `upstream <host:port>` for an external PostgreSQL server. - `upstream <host:port>` for an external PostgreSQL server.
- `postgres { ... }` for a managed PostgreSQL container. Its `image`, `volume`, and `password_env` directives are required. `idle_timeout` and `traffic_idle_timeout` accept Go duration strings. - `postgres { ... }` for a managed PostgreSQL container. Its `image`, `volume`, and `password_env` directives are required. `idle_timeout` and `traffic_idle_timeout` accept Go duration strings.

View File

@@ -81,13 +81,59 @@ func TestValidateMissingFieldsAndDuplicateHostname(t *testing.T) {
if err == nil { if err == nil {
t.Fatal("Validate() error = nil") t.Fatal("Validate() error = nil")
} }
for _, want := range []string{"TLS private key is required", "upstream or postgres is required", "duplicate hostname"} { for _, want := range []string{"tls requires both cert and key", "upstream or postgres is required", "duplicate hostname"} {
if !strings.Contains(err.Error(), want) { if !strings.Contains(err.Error(), want) {
t.Errorf("Validate() error = %q, missing %q", err, want) t.Errorf("Validate() error = %q, missing %q", err, want)
} }
} }
} }
func TestValidateAllowsConfigurationWithoutTLS(t *testing.T) {
cfg := Config{
Listen: ":5432",
Databases: []DatabaseConfig{{
Name: "analytics",
Upstream: "postgres-foo:5432",
}},
}
if err := cfg.Validate(); err != nil {
t.Fatalf("Validate() error = %v", err)
}
}
func TestParseAndValidateWithoutTLSBlock(t *testing.T) {
cfg, err := Parse([]byte(`pawsql {
listen :5432
database analytics {
upstream postgres-foo:5432
}
}`))
if err != nil {
t.Fatalf("Parse() error = %v", err)
}
if cfg.TLS.CertFile != "" || cfg.TLS.KeyFile != "" {
t.Errorf("TLS = %#v, want unset", cfg.TLS)
}
if err := cfg.Validate(); err != nil {
t.Fatalf("Validate() error = %v", err)
}
}
func TestValidateRejectsHalfConfiguredTLS(t *testing.T) {
cfg := Config{
Listen: ":5432",
TLS: TLSConfig{CertFile: "cert.pem"},
Databases: []DatabaseConfig{{
Name: "analytics",
Upstream: "postgres-foo:5432",
}},
}
err := cfg.Validate()
if err == nil || !strings.Contains(err.Error(), "tls requires both cert and key") {
t.Fatalf("Validate() error = %v, want tls requires both cert and key", err)
}
}
func TestValidateRejectsMalformedUpstreamAddress(t *testing.T) { func TestValidateRejectsMalformedUpstreamAddress(t *testing.T) {
cfg := Config{ cfg := Config{
Listen: ":5432", Listen: ":5432",

View File

@@ -21,11 +21,10 @@ func (c Config) Validate() error {
} else if err := validateListenAddress(c.Listen); err != nil { } else if err := validateListenAddress(c.Listen); err != nil {
errs = append(errs, fmt.Errorf("listen address %q: %w", c.Listen, err)) errs = append(errs, fmt.Errorf("listen address %q: %w", c.Listen, err))
} }
if strings.TrimSpace(c.TLS.CertFile) == "" { certificateSet := strings.TrimSpace(c.TLS.CertFile) != ""
errs = append(errs, errors.New("TLS certificate is required")) keySet := strings.TrimSpace(c.TLS.KeyFile) != ""
} if certificateSet != keySet {
if strings.TrimSpace(c.TLS.KeyFile) == "" { errs = append(errs, errors.New("tls requires both cert and key"))
errs = append(errs, errors.New("TLS private key is required"))
} }
if len(c.Databases) == 0 { if len(c.Databases) == 0 {
errs = append(errs, errors.New("at least one database route is required")) errs = append(errs, errors.New("at least one database route is required"))