From 95d34972b01245b7cb321f1e76e5a225b88c7144 Mon Sep 17 00:00:00 2001 From: moizpgedge Date: Thu, 4 Jun 2026 16:43:31 +0500 Subject: [PATCH 1/2] feat: add pg_hba_conf/pg_ident_conf to db spec Add user-managed `pg_hba_conf` and `pg_ident_conf` fields to the database spec, at both the database and per-node level, as arrays of strings (matching Patroni's `pg_hba`/`pg_ident` contract). - Per-node entries are **prepended** to database-level entries, giving node rules first-match priority while keeping the database-level list as the baseline. Empty/unset is identical to today's behavior. - Add a pg_hba/pg_ident line parser (`postgres/hba`) and minimal spec-time validation: reject `hba_file`/`ident_file` in `postgresql_conf` (they would make the entries ineffective) and lines that fail to parse, surfacing the offending line. No enum-style restriction on auth methods. Scope: spec contract, parser, and validation only. The orchestrator generators do not yet emit these entries into the generated `pg_hba.conf`/`pg_ident.conf`; that lands in a follow-up. See internal-design-docs: pg_hba / pg_ident User Configuration. PLAT-615 --- api/apiv1/design/database.go | 23 + api/apiv1/gen/control_plane/service.go | 19 + .../control_plane/client/encode_decode.go | 120 + .../gen/http/control_plane/client/types.go | 57 + .../control_plane/server/encode_decode.go | 72 + .../gen/http/control_plane/server/types.go | 57 + api/apiv1/gen/http/openapi.json | 890 +-- api/apiv1/gen/http/openapi.yaml | 626 +- api/apiv1/gen/http/openapi3.json | 6175 ++++++++++------- api/apiv1/gen/http/openapi3.yaml | 4311 +++++++----- server/internal/api/apiv1/convert.go | 8 + server/internal/api/apiv1/validate.go | 60 + server/internal/api/apiv1/validate_test.go | 65 +- server/internal/database/spec.go | 29 + server/internal/database/spec_test.go | 56 + server/internal/postgres/hba/parse.go | 201 + server/internal/postgres/hba/parse_test.go | 151 + 17 files changed, 8047 insertions(+), 4873 deletions(-) create mode 100644 server/internal/postgres/hba/parse.go create mode 100644 server/internal/postgres/hba/parse_test.go diff --git a/api/apiv1/design/database.go b/api/apiv1/design/database.go index 1b9842f1..4aa3a982 100644 --- a/api/apiv1/design/database.go +++ b/api/apiv1/design/database.go @@ -72,6 +72,16 @@ var DatabaseNodeSpec = g.Type("DatabaseNodeSpec", func() { }) g.Meta("struct:tag:json", "postgresql_conf,omitempty") }) + g.Attribute("pg_hba_conf", g.ArrayOf(g.String), func() { + g.Description("Additional pg_hba.conf entries for this particular node, one rule per array element. Prepended to the database-level pg_hba_conf entries, so node entries take first-match priority. Entries are inserted between control-plane's system-user rules and its catch-all, and cannot affect control-plane-internal connectivity.") + g.Example([]string{"host example myapp_user 10.0.0.0/8 scram-sha-256"}) + g.Meta("struct:tag:json", "pg_hba_conf,omitempty") + }) + g.Attribute("pg_ident_conf", g.ArrayOf(g.String), func() { + g.Description("Additional pg_ident.conf entries for this particular node, one mapping per array element. Prepended to the database-level pg_ident_conf entries.") + g.Example([]string{"ssl_users CN=alice,O=example alice"}) + g.Meta("struct:tag:json", "pg_ident_conf,omitempty") + }) g.Attribute("backup_config", BackupConfigSpec, func() { g.Description("The backup configuration for this node. Overrides the backup configuration set in the DatabaseSpec.") g.Meta("struct:tag:json", "backup_config,omitempty") @@ -667,6 +677,19 @@ var DatabaseSpec = g.Type("DatabaseSpec", func() { }) g.Meta("struct:tag:json", "postgresql_conf,omitempty") }) + g.Attribute("pg_hba_conf", g.ArrayOf(g.String), func() { + g.Description("Additional pg_hba.conf entries, one rule per array element. Inserted between control-plane's system-user rules and its catch-all, so they cannot affect control-plane-internal connectivity (Patroni, replication, health checks). Node-level pg_hba_conf entries are prepended to these.") + g.Example([]string{ + "hostssl all myapp_user 203.0.113.0/24 scram-sha-256", + "hostssl all alice 0.0.0.0/0 cert clientcert=verify-full map=ssl_users", + }) + g.Meta("struct:tag:json", "pg_hba_conf,omitempty") + }) + g.Attribute("pg_ident_conf", g.ArrayOf(g.String), func() { + g.Description("Additional pg_ident.conf entries, one mapping per array element. Purely additive; control-plane writes no pg_ident entries of its own. The primary use case is cert auth with map= translating certificate CNs to PostgreSQL usernames.") + g.Example([]string{"ssl_users CN=alice,O=example alice"}) + g.Meta("struct:tag:json", "pg_ident_conf,omitempty") + }) g.Attribute("orchestrator_opts", OrchestratorOpts, func() { g.Description("Orchestrator-specific configuration options.") g.Meta("struct:tag:json", "orchestrator_opts,omitempty") diff --git a/api/apiv1/gen/control_plane/service.go b/api/apiv1/gen/control_plane/service.go index 7af72de9..31ef6af8 100644 --- a/api/apiv1/gen/control_plane/service.go +++ b/api/apiv1/gen/control_plane/service.go @@ -365,6 +365,15 @@ type DatabaseNodeSpec struct { // Additional postgresql.conf settings for this particular node. Will be merged // with the settings provided by control-plane. PostgresqlConf map[string]any `json:"postgresql_conf,omitempty"` + // Additional pg_hba.conf entries for this particular node, one rule per array + // element. Prepended to the database-level pg_hba_conf entries, so node + // entries take first-match priority. Entries are inserted between + // control-plane's system-user rules and its catch-all, and cannot affect + // control-plane-internal connectivity. + PgHbaConf []string `json:"pg_hba_conf,omitempty"` + // Additional pg_ident.conf entries for this particular node, one mapping per + // array element. Prepended to the database-level pg_ident_conf entries. + PgIdentConf []string `json:"pg_ident_conf,omitempty"` // The backup configuration for this node. Overrides the backup configuration // set in the DatabaseSpec. BackupConfig *BackupConfigSpec `json:"backup_config,omitempty"` @@ -431,6 +440,16 @@ type DatabaseSpec struct { // Additional postgresql.conf settings. Will be merged with the settings // provided by control-plane. PostgresqlConf map[string]any `json:"postgresql_conf,omitempty"` + // Additional pg_hba.conf entries, one rule per array element. Inserted between + // control-plane's system-user rules and its catch-all, so they cannot affect + // control-plane-internal connectivity (Patroni, replication, health checks). + // Node-level pg_hba_conf entries are prepended to these. + PgHbaConf []string `json:"pg_hba_conf,omitempty"` + // Additional pg_ident.conf entries, one mapping per array element. Purely + // additive; control-plane writes no pg_ident entries of its own. The primary + // use case is cert auth with map= translating certificate CNs to PostgreSQL + // usernames. + PgIdentConf []string `json:"pg_ident_conf,omitempty"` // Orchestrator-specific configuration options. OrchestratorOpts *OrchestratorOpts `json:"orchestrator_opts,omitempty"` // User-defined SQL scripts that run at different points during the database diff --git a/api/apiv1/gen/http/control_plane/client/encode_decode.go b/api/apiv1/gen/http/control_plane/client/encode_decode.go index b61db4b6..11996804 100644 --- a/api/apiv1/gen/http/control_plane/client/encode_decode.go +++ b/api/apiv1/gen/http/control_plane/client/encode_decode.go @@ -4373,6 +4373,18 @@ func marshalControlplaneDatabaseSpecToDatabaseSpecRequestBody(v *controlplane.Da res.PostgresqlConf[tk] = tv } } + if v.PgHbaConf != nil { + res.PgHbaConf = make([]string, len(v.PgHbaConf)) + for i, val := range v.PgHbaConf { + res.PgHbaConf[i] = val + } + } + if v.PgIdentConf != nil { + res.PgIdentConf = make([]string, len(v.PgIdentConf)) + for i, val := range v.PgIdentConf { + res.PgIdentConf[i] = val + } + } if v.OrchestratorOpts != nil { res.OrchestratorOpts = marshalControlplaneOrchestratorOptsToOrchestratorOptsRequestBody(v.OrchestratorOpts) } @@ -4412,6 +4424,18 @@ func marshalControlplaneDatabaseNodeSpecToDatabaseNodeSpecRequestBody(v *control res.PostgresqlConf[tk] = tv } } + if v.PgHbaConf != nil { + res.PgHbaConf = make([]string, len(v.PgHbaConf)) + for i, val := range v.PgHbaConf { + res.PgHbaConf[i] = val + } + } + if v.PgIdentConf != nil { + res.PgIdentConf = make([]string, len(v.PgIdentConf)) + for i, val := range v.PgIdentConf { + res.PgIdentConf[i] = val + } + } if v.BackupConfig != nil { res.BackupConfig = marshalControlplaneBackupConfigSpecToBackupConfigSpecRequestBody(v.BackupConfig) } @@ -4845,6 +4869,18 @@ func marshalDatabaseSpecRequestBodyToControlplaneDatabaseSpec(v *DatabaseSpecReq res.PostgresqlConf[tk] = tv } } + if v.PgHbaConf != nil { + res.PgHbaConf = make([]string, len(v.PgHbaConf)) + for i, val := range v.PgHbaConf { + res.PgHbaConf[i] = val + } + } + if v.PgIdentConf != nil { + res.PgIdentConf = make([]string, len(v.PgIdentConf)) + for i, val := range v.PgIdentConf { + res.PgIdentConf[i] = val + } + } if v.OrchestratorOpts != nil { res.OrchestratorOpts = marshalOrchestratorOptsRequestBodyToControlplaneOrchestratorOpts(v.OrchestratorOpts) } @@ -4884,6 +4920,18 @@ func marshalDatabaseNodeSpecRequestBodyToControlplaneDatabaseNodeSpec(v *Databas res.PostgresqlConf[tk] = tv } } + if v.PgHbaConf != nil { + res.PgHbaConf = make([]string, len(v.PgHbaConf)) + for i, val := range v.PgHbaConf { + res.PgHbaConf[i] = val + } + } + if v.PgIdentConf != nil { + res.PgIdentConf = make([]string, len(v.PgIdentConf)) + for i, val := range v.PgIdentConf { + res.PgIdentConf[i] = val + } + } if v.BackupConfig != nil { res.BackupConfig = marshalBackupConfigSpecRequestBodyToControlplaneBackupConfigSpec(v.BackupConfig) } @@ -5447,6 +5495,18 @@ func unmarshalDatabaseSpecResponseBodyToControlplaneDatabaseSpec(v *DatabaseSpec res.PostgresqlConf[tk] = tv } } + if v.PgHbaConf != nil { + res.PgHbaConf = make([]string, len(v.PgHbaConf)) + for i, val := range v.PgHbaConf { + res.PgHbaConf[i] = val + } + } + if v.PgIdentConf != nil { + res.PgIdentConf = make([]string, len(v.PgIdentConf)) + for i, val := range v.PgIdentConf { + res.PgIdentConf[i] = val + } + } if v.OrchestratorOpts != nil { res.OrchestratorOpts = unmarshalOrchestratorOptsResponseBodyToControlplaneOrchestratorOpts(v.OrchestratorOpts) } @@ -5482,6 +5542,18 @@ func unmarshalDatabaseNodeSpecResponseBodyToControlplaneDatabaseNodeSpec(v *Data res.PostgresqlConf[tk] = tv } } + if v.PgHbaConf != nil { + res.PgHbaConf = make([]string, len(v.PgHbaConf)) + for i, val := range v.PgHbaConf { + res.PgHbaConf[i] = val + } + } + if v.PgIdentConf != nil { + res.PgIdentConf = make([]string, len(v.PgIdentConf)) + for i, val := range v.PgIdentConf { + res.PgIdentConf[i] = val + } + } if v.BackupConfig != nil { res.BackupConfig = unmarshalBackupConfigSpecResponseBodyToControlplaneBackupConfigSpec(v.BackupConfig) } @@ -5905,6 +5977,18 @@ func marshalControlplaneDatabaseSpecToDatabaseSpecRequestBodyRequestBody(v *cont res.PostgresqlConf[tk] = tv } } + if v.PgHbaConf != nil { + res.PgHbaConf = make([]string, len(v.PgHbaConf)) + for i, val := range v.PgHbaConf { + res.PgHbaConf[i] = val + } + } + if v.PgIdentConf != nil { + res.PgIdentConf = make([]string, len(v.PgIdentConf)) + for i, val := range v.PgIdentConf { + res.PgIdentConf[i] = val + } + } if v.OrchestratorOpts != nil { res.OrchestratorOpts = marshalControlplaneOrchestratorOptsToOrchestratorOptsRequestBodyRequestBody(v.OrchestratorOpts) } @@ -5944,6 +6028,18 @@ func marshalControlplaneDatabaseNodeSpecToDatabaseNodeSpecRequestBodyRequestBody res.PostgresqlConf[tk] = tv } } + if v.PgHbaConf != nil { + res.PgHbaConf = make([]string, len(v.PgHbaConf)) + for i, val := range v.PgHbaConf { + res.PgHbaConf[i] = val + } + } + if v.PgIdentConf != nil { + res.PgIdentConf = make([]string, len(v.PgIdentConf)) + for i, val := range v.PgIdentConf { + res.PgIdentConf[i] = val + } + } if v.BackupConfig != nil { res.BackupConfig = marshalControlplaneBackupConfigSpecToBackupConfigSpecRequestBodyRequestBody(v.BackupConfig) } @@ -6379,6 +6475,18 @@ func marshalDatabaseSpecRequestBodyRequestBodyToControlplaneDatabaseSpec(v *Data res.PostgresqlConf[tk] = tv } } + if v.PgHbaConf != nil { + res.PgHbaConf = make([]string, len(v.PgHbaConf)) + for i, val := range v.PgHbaConf { + res.PgHbaConf[i] = val + } + } + if v.PgIdentConf != nil { + res.PgIdentConf = make([]string, len(v.PgIdentConf)) + for i, val := range v.PgIdentConf { + res.PgIdentConf[i] = val + } + } if v.OrchestratorOpts != nil { res.OrchestratorOpts = marshalOrchestratorOptsRequestBodyRequestBodyToControlplaneOrchestratorOpts(v.OrchestratorOpts) } @@ -6418,6 +6526,18 @@ func marshalDatabaseNodeSpecRequestBodyRequestBodyToControlplaneDatabaseNodeSpec res.PostgresqlConf[tk] = tv } } + if v.PgHbaConf != nil { + res.PgHbaConf = make([]string, len(v.PgHbaConf)) + for i, val := range v.PgHbaConf { + res.PgHbaConf[i] = val + } + } + if v.PgIdentConf != nil { + res.PgIdentConf = make([]string, len(v.PgIdentConf)) + for i, val := range v.PgIdentConf { + res.PgIdentConf[i] = val + } + } if v.BackupConfig != nil { res.BackupConfig = marshalBackupConfigSpecRequestBodyRequestBodyToControlplaneBackupConfigSpec(v.BackupConfig) } diff --git a/api/apiv1/gen/http/control_plane/client/types.go b/api/apiv1/gen/http/control_plane/client/types.go index cbaa33dd..ad3e3013 100644 --- a/api/apiv1/gen/http/control_plane/client/types.go +++ b/api/apiv1/gen/http/control_plane/client/types.go @@ -1840,6 +1840,16 @@ type DatabaseSpecRequestBody struct { // Additional postgresql.conf settings. Will be merged with the settings // provided by control-plane. PostgresqlConf map[string]any `json:"postgresql_conf,omitempty"` + // Additional pg_hba.conf entries, one rule per array element. Inserted between + // control-plane's system-user rules and its catch-all, so they cannot affect + // control-plane-internal connectivity (Patroni, replication, health checks). + // Node-level pg_hba_conf entries are prepended to these. + PgHbaConf []string `json:"pg_hba_conf,omitempty"` + // Additional pg_ident.conf entries, one mapping per array element. Purely + // additive; control-plane writes no pg_ident entries of its own. The primary + // use case is cert auth with map= translating certificate CNs to PostgreSQL + // usernames. + PgIdentConf []string `json:"pg_ident_conf,omitempty"` // Orchestrator-specific configuration options. OrchestratorOpts *OrchestratorOptsRequestBody `json:"orchestrator_opts,omitempty"` // User-defined SQL scripts that run at different points during the database @@ -1881,6 +1891,15 @@ type DatabaseNodeSpecRequestBody struct { // Additional postgresql.conf settings for this particular node. Will be merged // with the settings provided by control-plane. PostgresqlConf map[string]any `json:"postgresql_conf,omitempty"` + // Additional pg_hba.conf entries for this particular node, one rule per array + // element. Prepended to the database-level pg_hba_conf entries, so node + // entries take first-match priority. Entries are inserted between + // control-plane's system-user rules and its catch-all, and cannot affect + // control-plane-internal connectivity. + PgHbaConf []string `json:"pg_hba_conf,omitempty"` + // Additional pg_ident.conf entries for this particular node, one mapping per + // array element. Prepended to the database-level pg_ident_conf entries. + PgIdentConf []string `json:"pg_ident_conf,omitempty"` // The backup configuration for this node. Overrides the backup configuration // set in the DatabaseSpec. BackupConfig *BackupConfigSpecRequestBody `json:"backup_config,omitempty"` @@ -2263,6 +2282,16 @@ type DatabaseSpecResponseBody struct { // Additional postgresql.conf settings. Will be merged with the settings // provided by control-plane. PostgresqlConf map[string]any `json:"postgresql_conf,omitempty"` + // Additional pg_hba.conf entries, one rule per array element. Inserted between + // control-plane's system-user rules and its catch-all, so they cannot affect + // control-plane-internal connectivity (Patroni, replication, health checks). + // Node-level pg_hba_conf entries are prepended to these. + PgHbaConf []string `json:"pg_hba_conf,omitempty"` + // Additional pg_ident.conf entries, one mapping per array element. Purely + // additive; control-plane writes no pg_ident entries of its own. The primary + // use case is cert auth with map= translating certificate CNs to PostgreSQL + // usernames. + PgIdentConf []string `json:"pg_ident_conf,omitempty"` // Orchestrator-specific configuration options. OrchestratorOpts *OrchestratorOptsResponseBody `json:"orchestrator_opts,omitempty"` // User-defined SQL scripts that run at different points during the database @@ -2304,6 +2333,15 @@ type DatabaseNodeSpecResponseBody struct { // Additional postgresql.conf settings for this particular node. Will be merged // with the settings provided by control-plane. PostgresqlConf map[string]any `json:"postgresql_conf,omitempty"` + // Additional pg_hba.conf entries for this particular node, one rule per array + // element. Prepended to the database-level pg_hba_conf entries, so node + // entries take first-match priority. Entries are inserted between + // control-plane's system-user rules and its catch-all, and cannot affect + // control-plane-internal connectivity. + PgHbaConf []string `json:"pg_hba_conf,omitempty"` + // Additional pg_ident.conf entries for this particular node, one mapping per + // array element. Prepended to the database-level pg_ident_conf entries. + PgIdentConf []string `json:"pg_ident_conf,omitempty"` // The backup configuration for this node. Overrides the backup configuration // set in the DatabaseSpec. BackupConfig *BackupConfigSpecResponseBody `json:"backup_config,omitempty"` @@ -2608,6 +2646,16 @@ type DatabaseSpecRequestBodyRequestBody struct { // Additional postgresql.conf settings. Will be merged with the settings // provided by control-plane. PostgresqlConf map[string]any `json:"postgresql_conf,omitempty"` + // Additional pg_hba.conf entries, one rule per array element. Inserted between + // control-plane's system-user rules and its catch-all, so they cannot affect + // control-plane-internal connectivity (Patroni, replication, health checks). + // Node-level pg_hba_conf entries are prepended to these. + PgHbaConf []string `json:"pg_hba_conf,omitempty"` + // Additional pg_ident.conf entries, one mapping per array element. Purely + // additive; control-plane writes no pg_ident entries of its own. The primary + // use case is cert auth with map= translating certificate CNs to PostgreSQL + // usernames. + PgIdentConf []string `json:"pg_ident_conf,omitempty"` // Orchestrator-specific configuration options. OrchestratorOpts *OrchestratorOptsRequestBodyRequestBody `json:"orchestrator_opts,omitempty"` // User-defined SQL scripts that run at different points during the database @@ -2650,6 +2698,15 @@ type DatabaseNodeSpecRequestBodyRequestBody struct { // Additional postgresql.conf settings for this particular node. Will be merged // with the settings provided by control-plane. PostgresqlConf map[string]any `json:"postgresql_conf,omitempty"` + // Additional pg_hba.conf entries for this particular node, one rule per array + // element. Prepended to the database-level pg_hba_conf entries, so node + // entries take first-match priority. Entries are inserted between + // control-plane's system-user rules and its catch-all, and cannot affect + // control-plane-internal connectivity. + PgHbaConf []string `json:"pg_hba_conf,omitempty"` + // Additional pg_ident.conf entries for this particular node, one mapping per + // array element. Prepended to the database-level pg_ident_conf entries. + PgIdentConf []string `json:"pg_ident_conf,omitempty"` // The backup configuration for this node. Overrides the backup configuration // set in the DatabaseSpec. BackupConfig *BackupConfigSpecRequestBodyRequestBody `json:"backup_config,omitempty"` diff --git a/api/apiv1/gen/http/control_plane/server/encode_decode.go b/api/apiv1/gen/http/control_plane/server/encode_decode.go index 8a2d0a3b..eb08b886 100644 --- a/api/apiv1/gen/http/control_plane/server/encode_decode.go +++ b/api/apiv1/gen/http/control_plane/server/encode_decode.go @@ -3750,6 +3750,18 @@ func unmarshalDatabaseSpecRequestBodyToControlplaneDatabaseSpec(v *DatabaseSpecR res.PostgresqlConf[tk] = tv } } + if v.PgHbaConf != nil { + res.PgHbaConf = make([]string, len(v.PgHbaConf)) + for i, val := range v.PgHbaConf { + res.PgHbaConf[i] = val + } + } + if v.PgIdentConf != nil { + res.PgIdentConf = make([]string, len(v.PgIdentConf)) + for i, val := range v.PgIdentConf { + res.PgIdentConf[i] = val + } + } if v.OrchestratorOpts != nil { res.OrchestratorOpts = unmarshalOrchestratorOptsRequestBodyToControlplaneOrchestratorOpts(v.OrchestratorOpts) } @@ -3785,6 +3797,18 @@ func unmarshalDatabaseNodeSpecRequestBodyToControlplaneDatabaseNodeSpec(v *Datab res.PostgresqlConf[tk] = tv } } + if v.PgHbaConf != nil { + res.PgHbaConf = make([]string, len(v.PgHbaConf)) + for i, val := range v.PgHbaConf { + res.PgHbaConf[i] = val + } + } + if v.PgIdentConf != nil { + res.PgIdentConf = make([]string, len(v.PgIdentConf)) + for i, val := range v.PgIdentConf { + res.PgIdentConf[i] = val + } + } if v.BackupConfig != nil { res.BackupConfig = unmarshalBackupConfigSpecRequestBodyToControlplaneBackupConfigSpec(v.BackupConfig) } @@ -4342,6 +4366,18 @@ func marshalControlplaneDatabaseSpecToDatabaseSpecResponseBody(v *controlplane.D res.PostgresqlConf[tk] = tv } } + if v.PgHbaConf != nil { + res.PgHbaConf = make([]string, len(v.PgHbaConf)) + for i, val := range v.PgHbaConf { + res.PgHbaConf[i] = val + } + } + if v.PgIdentConf != nil { + res.PgIdentConf = make([]string, len(v.PgIdentConf)) + for i, val := range v.PgIdentConf { + res.PgIdentConf[i] = val + } + } if v.OrchestratorOpts != nil { res.OrchestratorOpts = marshalControlplaneOrchestratorOptsToOrchestratorOptsResponseBody(v.OrchestratorOpts) } @@ -4381,6 +4417,18 @@ func marshalControlplaneDatabaseNodeSpecToDatabaseNodeSpecResponseBody(v *contro res.PostgresqlConf[tk] = tv } } + if v.PgHbaConf != nil { + res.PgHbaConf = make([]string, len(v.PgHbaConf)) + for i, val := range v.PgHbaConf { + res.PgHbaConf[i] = val + } + } + if v.PgIdentConf != nil { + res.PgIdentConf = make([]string, len(v.PgIdentConf)) + for i, val := range v.PgIdentConf { + res.PgIdentConf[i] = val + } + } if v.BackupConfig != nil { res.BackupConfig = marshalControlplaneBackupConfigSpecToBackupConfigSpecResponseBody(v.BackupConfig) } @@ -4810,6 +4858,18 @@ func unmarshalDatabaseSpecRequestBodyRequestBodyToControlplaneDatabaseSpec(v *Da res.PostgresqlConf[tk] = tv } } + if v.PgHbaConf != nil { + res.PgHbaConf = make([]string, len(v.PgHbaConf)) + for i, val := range v.PgHbaConf { + res.PgHbaConf[i] = val + } + } + if v.PgIdentConf != nil { + res.PgIdentConf = make([]string, len(v.PgIdentConf)) + for i, val := range v.PgIdentConf { + res.PgIdentConf[i] = val + } + } if v.OrchestratorOpts != nil { res.OrchestratorOpts = unmarshalOrchestratorOptsRequestBodyRequestBodyToControlplaneOrchestratorOpts(v.OrchestratorOpts) } @@ -4845,6 +4905,18 @@ func unmarshalDatabaseNodeSpecRequestBodyRequestBodyToControlplaneDatabaseNodeSp res.PostgresqlConf[tk] = tv } } + if v.PgHbaConf != nil { + res.PgHbaConf = make([]string, len(v.PgHbaConf)) + for i, val := range v.PgHbaConf { + res.PgHbaConf[i] = val + } + } + if v.PgIdentConf != nil { + res.PgIdentConf = make([]string, len(v.PgIdentConf)) + for i, val := range v.PgIdentConf { + res.PgIdentConf[i] = val + } + } if v.BackupConfig != nil { res.BackupConfig = unmarshalBackupConfigSpecRequestBodyRequestBodyToControlplaneBackupConfigSpec(v.BackupConfig) } diff --git a/api/apiv1/gen/http/control_plane/server/types.go b/api/apiv1/gen/http/control_plane/server/types.go index e03edc97..54d39bb3 100644 --- a/api/apiv1/gen/http/control_plane/server/types.go +++ b/api/apiv1/gen/http/control_plane/server/types.go @@ -1922,6 +1922,16 @@ type DatabaseSpecResponseBody struct { // Additional postgresql.conf settings. Will be merged with the settings // provided by control-plane. PostgresqlConf map[string]any `json:"postgresql_conf,omitempty"` + // Additional pg_hba.conf entries, one rule per array element. Inserted between + // control-plane's system-user rules and its catch-all, so they cannot affect + // control-plane-internal connectivity (Patroni, replication, health checks). + // Node-level pg_hba_conf entries are prepended to these. + PgHbaConf []string `json:"pg_hba_conf,omitempty"` + // Additional pg_ident.conf entries, one mapping per array element. Purely + // additive; control-plane writes no pg_ident entries of its own. The primary + // use case is cert auth with map= translating certificate CNs to PostgreSQL + // usernames. + PgIdentConf []string `json:"pg_ident_conf,omitempty"` // Orchestrator-specific configuration options. OrchestratorOpts *OrchestratorOptsResponseBody `json:"orchestrator_opts,omitempty"` // User-defined SQL scripts that run at different points during the database @@ -1963,6 +1973,15 @@ type DatabaseNodeSpecResponseBody struct { // Additional postgresql.conf settings for this particular node. Will be merged // with the settings provided by control-plane. PostgresqlConf map[string]any `json:"postgresql_conf,omitempty"` + // Additional pg_hba.conf entries for this particular node, one rule per array + // element. Prepended to the database-level pg_hba_conf entries, so node + // entries take first-match priority. Entries are inserted between + // control-plane's system-user rules and its catch-all, and cannot affect + // control-plane-internal connectivity. + PgHbaConf []string `json:"pg_hba_conf,omitempty"` + // Additional pg_ident.conf entries for this particular node, one mapping per + // array element. Prepended to the database-level pg_ident_conf entries. + PgIdentConf []string `json:"pg_ident_conf,omitempty"` // The backup configuration for this node. Overrides the backup configuration // set in the DatabaseSpec. BackupConfig *BackupConfigSpecResponseBody `json:"backup_config,omitempty"` @@ -2276,6 +2295,16 @@ type DatabaseSpecRequestBody struct { // Additional postgresql.conf settings. Will be merged with the settings // provided by control-plane. PostgresqlConf map[string]any `json:"postgresql_conf,omitempty"` + // Additional pg_hba.conf entries, one rule per array element. Inserted between + // control-plane's system-user rules and its catch-all, so they cannot affect + // control-plane-internal connectivity (Patroni, replication, health checks). + // Node-level pg_hba_conf entries are prepended to these. + PgHbaConf []string `json:"pg_hba_conf,omitempty"` + // Additional pg_ident.conf entries, one mapping per array element. Purely + // additive; control-plane writes no pg_ident entries of its own. The primary + // use case is cert auth with map= translating certificate CNs to PostgreSQL + // usernames. + PgIdentConf []string `json:"pg_ident_conf,omitempty"` // Orchestrator-specific configuration options. OrchestratorOpts *OrchestratorOptsRequestBody `json:"orchestrator_opts,omitempty"` // User-defined SQL scripts that run at different points during the database @@ -2317,6 +2346,15 @@ type DatabaseNodeSpecRequestBody struct { // Additional postgresql.conf settings for this particular node. Will be merged // with the settings provided by control-plane. PostgresqlConf map[string]any `json:"postgresql_conf,omitempty"` + // Additional pg_hba.conf entries for this particular node, one rule per array + // element. Prepended to the database-level pg_hba_conf entries, so node + // entries take first-match priority. Entries are inserted between + // control-plane's system-user rules and its catch-all, and cannot affect + // control-plane-internal connectivity. + PgHbaConf []string `json:"pg_hba_conf,omitempty"` + // Additional pg_ident.conf entries for this particular node, one mapping per + // array element. Prepended to the database-level pg_ident_conf entries. + PgIdentConf []string `json:"pg_ident_conf,omitempty"` // The backup configuration for this node. Overrides the backup configuration // set in the DatabaseSpec. BackupConfig *BackupConfigSpecRequestBody `json:"backup_config,omitempty"` @@ -2618,6 +2656,16 @@ type DatabaseSpecRequestBodyRequestBody struct { // Additional postgresql.conf settings. Will be merged with the settings // provided by control-plane. PostgresqlConf map[string]any `json:"postgresql_conf,omitempty"` + // Additional pg_hba.conf entries, one rule per array element. Inserted between + // control-plane's system-user rules and its catch-all, so they cannot affect + // control-plane-internal connectivity (Patroni, replication, health checks). + // Node-level pg_hba_conf entries are prepended to these. + PgHbaConf []string `json:"pg_hba_conf,omitempty"` + // Additional pg_ident.conf entries, one mapping per array element. Purely + // additive; control-plane writes no pg_ident entries of its own. The primary + // use case is cert auth with map= translating certificate CNs to PostgreSQL + // usernames. + PgIdentConf []string `json:"pg_ident_conf,omitempty"` // Orchestrator-specific configuration options. OrchestratorOpts *OrchestratorOptsRequestBodyRequestBody `json:"orchestrator_opts,omitempty"` // User-defined SQL scripts that run at different points during the database @@ -2660,6 +2708,15 @@ type DatabaseNodeSpecRequestBodyRequestBody struct { // Additional postgresql.conf settings for this particular node. Will be merged // with the settings provided by control-plane. PostgresqlConf map[string]any `json:"postgresql_conf,omitempty"` + // Additional pg_hba.conf entries for this particular node, one rule per array + // element. Prepended to the database-level pg_hba_conf entries, so node + // entries take first-match priority. Entries are inserted between + // control-plane's system-user rules and its catch-all, and cannot affect + // control-plane-internal connectivity. + PgHbaConf []string `json:"pg_hba_conf,omitempty"` + // Additional pg_ident.conf entries for this particular node, one mapping per + // array element. Prepended to the database-level pg_ident_conf entries. + PgIdentConf []string `json:"pg_ident_conf,omitempty"` // The backup configuration for this node. Overrides the backup configuration // set in the DatabaseSpec. BackupConfig *BackupConfigSpecRequestBodyRequestBody `json:"backup_config,omitempty"` diff --git a/api/apiv1/gen/http/openapi.json b/api/apiv1/gen/http/openapi.json index 39fbff73..8832cd86 100644 --- a/api/apiv1/gen/http/openapi.json +++ b/api/apiv1/gen/http/openapi.json @@ -2447,6 +2447,29 @@ }, "description": "The repositories for this backup configuration.", "example": [ + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + }, { "azure_account": "pgedge-backups", "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", @@ -2524,29 +2547,6 @@ "s3_region": "us-east-1", "type": "s3" }, - { - "azure_account": "pgedge-backups", - "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "azure_endpoint": "blob.core.usgovcloudapi.net", - "azure_key": "YXpLZXk=", - "base_path": "/backups", - "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", - "storage-upload-chunk-size": "5MiB" - }, - "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "gcs_endpoint": "localhost", - "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", - "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "retention_full": 2, - "retention_full_type": "count", - "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "s3_endpoint": "s3.us-east-1.amazonaws.com", - "s3_key": "AKIAIOSFODNN7EXAMPLE", - "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - "s3_region": "us-east-1", - "type": "s3" - }, { "azure_account": "pgedge-backups", "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", @@ -2626,7 +2626,7 @@ }, "additionalProperties": { "type": "string", - "example": "Quidem occaecati." + "example": "Beatae quasi ipsum." } }, "backup_options": { @@ -2637,7 +2637,7 @@ }, "additionalProperties": { "type": "string", - "example": "Nobis explicabo eum dolores quae." + "example": "Et est et dolorem labore explicabo." } }, "type": { @@ -2710,7 +2710,7 @@ }, "additionalProperties": { "type": "string", - "example": "Nobis velit fugiat rerum dicta optio." + "example": "Id reprehenderit." } }, "gcs_bucket": { @@ -3842,7 +3842,7 @@ "type": "array", "items": { "type": "string", - "example": "Voluptatem mollitia est." + "example": "Eum dolores quae minima." }, "description": "Optional ordered list of database node names. When set, the service's database connection includes only the listed nodes in the specified order.", "example": [ @@ -3924,6 +3924,28 @@ "minimum": 0, "maximum": 65535 }, + "pg_hba_conf": { + "type": "array", + "items": { + "type": "string", + "example": "Nobis velit fugiat rerum dicta optio." + }, + "description": "Additional pg_hba.conf entries for this particular node, one rule per array element. Prepended to the database-level pg_hba_conf entries, so node entries take first-match priority. Entries are inserted between control-plane's system-user rules and its catch-all, and cannot affect control-plane-internal connectivity.", + "example": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ] + }, + "pg_ident_conf": { + "type": "array", + "items": { + "type": "string", + "example": "Voluptas enim maiores sint voluptatibus earum." + }, + "description": "Additional pg_ident.conf entries for this particular node, one mapping per array element. Prepended to the database-level pg_ident_conf entries.", + "example": [ + "ssl_users CN=alice,O=example alice" + ] + }, "port": { "type": "integer", "description": "The port used by the Postgres database for this node. Overrides the Postgres port set in the DatabaseSpec.", @@ -4109,6 +4131,12 @@ } }, "patroni_port": 8888, + "pg_hba_conf": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], "port": 5432, "postgres_version": "17.6", "postgresql_conf": { @@ -4159,7 +4187,7 @@ "type": "array", "items": { "type": "string", - "example": "r0", + "example": "fm9", "minLength": 1, "maxLength": 1024 }, @@ -4176,7 +4204,7 @@ "type": "array", "items": { "type": "string", - "example": "p", + "example": "yv", "minLength": 1, "maxLength": 1024 }, @@ -4438,6 +4466,12 @@ } }, "patroni_port": 8888, + "pg_hba_conf": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], "port": 5432, "postgres_version": "17.6", "postgresql_conf": { @@ -4474,105 +4508,101 @@ "source_node_name": "n1" }, "source_node": "n1" - }, + } + ], + "minItems": 1, + "maxItems": 9 + }, + "orchestrator_opts": { + "$ref": "#/definitions/OrchestratorOpts" + }, + "patroni_port": { + "type": "integer", + "description": "The port used by Patroni for this database. If the port is 0, each instance will be assigned a random port. NOTE: This field is not currently supported for Docker Swarm.", + "example": 8888, + "format": "int64", + "minimum": 0, + "maximum": 65535 + }, + "pg_hba_conf": { + "type": "array", + "items": { + "type": "string", + "example": "Ipsa et itaque aut reprehenderit." + }, + "description": "Additional pg_hba.conf entries, one rule per array element. Inserted between control-plane's system-user rules and its catch-all, so they cannot affect control-plane-internal connectivity (Patroni, replication, health checks). Node-level pg_hba_conf entries are prepended to these.", + "example": [ + "hostssl all myapp_user 203.0.113.0/24 scram-sha-256", + "hostssl all alice 0.0.0.0/0 cert clientcert=verify-full map=ssl_users" + ] + }, + "pg_ident_conf": { + "type": "array", + "items": { + "type": "string", + "example": "Ea velit consequatur sequi error et quibusdam." + }, + "description": "Additional pg_ident.conf entries, one mapping per array element. Purely additive; control-plane writes no pg_ident entries of its own. The primary use case is cert auth with map= translating certificate CNs to PostgreSQL usernames.", + "example": [ + "ssl_users CN=alice,O=example alice" + ] + }, + "port": { + "type": "integer", + "description": "The port used by the Postgres database. If the port is 0, each instance will be assigned a random port. If the port is unspecified, the database will not be exposed on any port, dependent on orchestrator support for that feature.", + "example": 5432, + "format": "int64", + "minimum": 0, + "maximum": 65535 + }, + "postgres_version": { + "type": "string", + "description": "The Postgres version in 'major.minor' format.", + "example": "17.6", + "pattern": "^\\d{2}\\.\\d{1,2}$" + }, + "postgresql_conf": { + "type": "object", + "description": "Additional postgresql.conf settings. Will be merged with the settings provided by control-plane.", + "example": { + "max_connections": 1000 + }, + "maxLength": 64, + "additionalProperties": true + }, + "restore_config": { + "$ref": "#/definitions/RestoreConfigSpec" + }, + "scripts": { + "$ref": "#/definitions/DatabaseScripts" + }, + "services": { + "type": "array", + "items": { + "$ref": "#/definitions/ServiceSpec" + }, + "description": "Service instances to run alongside the database (e.g., MCP servers).", + "example": [ { - "backup_config": { - "repositories": [ - { - "azure_account": "pgedge-backups", - "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "azure_endpoint": "blob.core.usgovcloudapi.net", - "azure_key": "YXpLZXk=", - "base_path": "/backups", - "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", - "storage-upload-chunk-size": "5MiB" - }, - "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "gcs_endpoint": "localhost", - "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", - "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "retention_full": 2, - "retention_full_type": "count", - "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "s3_endpoint": "s3.us-east-1.amazonaws.com", - "s3_key": "AKIAIOSFODNN7EXAMPLE", - "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - "s3_region": "us-east-1", - "type": "s3" - }, - { - "azure_account": "pgedge-backups", - "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "azure_endpoint": "blob.core.usgovcloudapi.net", - "azure_key": "YXpLZXk=", - "base_path": "/backups", - "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", - "storage-upload-chunk-size": "5MiB" - }, - "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "gcs_endpoint": "localhost", - "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", - "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "retention_full": 2, - "retention_full_type": "count", - "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "s3_endpoint": "s3.us-east-1.amazonaws.com", - "s3_key": "AKIAIOSFODNN7EXAMPLE", - "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - "s3_region": "us-east-1", - "type": "s3" - }, - { - "azure_account": "pgedge-backups", - "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "azure_endpoint": "blob.core.usgovcloudapi.net", - "azure_key": "YXpLZXk=", - "base_path": "/backups", - "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", - "storage-upload-chunk-size": "5MiB" - }, - "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "gcs_endpoint": "localhost", - "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", - "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "retention_full": 2, - "retention_full_type": "count", - "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "s3_endpoint": "s3.us-east-1.amazonaws.com", - "s3_key": "AKIAIOSFODNN7EXAMPLE", - "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - "s3_region": "us-east-1", - "type": "s3" - } - ], - "schedules": [ - { - "cron_expression": "0 6 * * ?", - "id": "daily-full-backup", - "type": "full" - }, - { - "cron_expression": "0 6 * * ?", - "id": "daily-full-backup", - "type": "full" - }, - { - "cron_expression": "0 6 * * ?", - "id": "daily-full-backup", - "type": "full" - } - ] + "config": { + "llm_model": "gpt-4", + "llm_provider": "openai", + "openai_api_key": "sk-..." }, + "connect_as": "app", "cpus": "500m", + "database_connection": { + "target_nodes": [ + "n1", + "n2" + ], + "target_session_attrs": "primary" + }, "host_ids": [ "76f9b8c0-4958-11f0-a489-3bb29577c696", "76f9b8c0-4958-11f0-a489-3bb29577c696" ], - "memory": "500M", - "name": "n1", + "memory": "512M", "orchestrator_opts": { "swarm": { "extra_labels": { @@ -4627,95 +4657,90 @@ ] } }, - "patroni_port": 8888, - "port": 5432, - "postgres_version": "17.6", - "postgresql_conf": { - "max_connections": 1000 + "port": 0, + "service_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "service_type": "rag", + "version": "latest" + }, + { + "config": { + "llm_model": "gpt-4", + "llm_provider": "openai", + "openai_api_key": "sk-..." }, - "restore_config": { - "repository": { - "azure_account": "pgedge-backups", - "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "azure_endpoint": "blob.core.usgovcloudapi.net", - "azure_key": "YXpLZXk=", - "base_path": "/backups", - "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab" + "connect_as": "app", + "cpus": "500m", + "database_connection": { + "target_nodes": [ + "n1", + "n2" + ], + "target_session_attrs": "primary" + }, + "host_ids": [ + "76f9b8c0-4958-11f0-a489-3bb29577c696", + "76f9b8c0-4958-11f0-a489-3bb29577c696" + ], + "memory": "512M", + "orchestrator_opts": { + "swarm": { + "extra_labels": { + "traefik.enable": "true", + "traefik.tcp.routers.mydb.rule": "HostSNI(`mydb.example.com`)" }, - "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "gcs_endpoint": "localhost", - "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", - "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "s3_endpoint": "s3.us-east-1.amazonaws.com", - "s3_key": "AKIAIOSFODNN7EXAMPLE", - "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - "s3_region": "us-east-1", - "type": "s3" - }, - "restore_options": { - "set": "20250505-153628F", - "target": "123456", - "type": "xid" - }, - "source_database_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "source_database_name": "northwind", - "source_node_name": "n1" + "extra_networks": [ + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + }, + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + }, + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + } + ], + "extra_volumes": [ + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + }, + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + }, + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + } + ] + } }, - "source_node": "n1" - } - ], - "minItems": 1, - "maxItems": 9 - }, - "orchestrator_opts": { - "$ref": "#/definitions/OrchestratorOpts" - }, - "patroni_port": { - "type": "integer", - "description": "The port used by Patroni for this database. If the port is 0, each instance will be assigned a random port. NOTE: This field is not currently supported for Docker Swarm.", - "example": 8888, - "format": "int64", - "minimum": 0, - "maximum": 65535 - }, - "port": { - "type": "integer", - "description": "The port used by the Postgres database. If the port is 0, each instance will be assigned a random port. If the port is unspecified, the database will not be exposed on any port, dependent on orchestrator support for that feature.", - "example": 5432, - "format": "int64", - "minimum": 0, - "maximum": 65535 - }, - "postgres_version": { - "type": "string", - "description": "The Postgres version in 'major.minor' format.", - "example": "17.6", - "pattern": "^\\d{2}\\.\\d{1,2}$" - }, - "postgresql_conf": { - "type": "object", - "description": "Additional postgresql.conf settings. Will be merged with the settings provided by control-plane.", - "example": { - "max_connections": 1000 - }, - "maxLength": 64, - "additionalProperties": true - }, - "restore_config": { - "$ref": "#/definitions/RestoreConfigSpec" - }, - "scripts": { - "$ref": "#/definitions/DatabaseScripts" - }, - "services": { - "type": "array", - "items": { - "$ref": "#/definitions/ServiceSpec" - }, - "description": "Service instances to run alongside the database (e.g., MCP servers).", - "example": [ + "port": 0, + "service_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "service_type": "rag", + "version": "latest" + }, { "config": { "llm_model": "gpt-4", @@ -4996,29 +5021,225 @@ "CREATEDB", "CREATEROLE" ], - "db_owner": false, - "password": "secret", - "roles": [ - "pgedge_superuser" + "db_owner": false, + "password": "secret", + "roles": [ + "pgedge_superuser" + ], + "username": "admin" + }, + { + "attributes": [ + "LOGIN", + "CREATEDB", + "CREATEROLE" + ], + "db_owner": false, + "password": "secret", + "roles": [ + "pgedge_superuser" + ], + "username": "admin" + } + ], + "memory": "500M", + "nodes": [ + { + "backup_config": { + "repositories": [ + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + }, + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + }, + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + } + ], + "schedules": [ + { + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" + }, + { + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" + }, + { + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" + } + ] + }, + "cpus": "500m", + "host_ids": [ + "76f9b8c0-4958-11f0-a489-3bb29577c696", + "76f9b8c0-4958-11f0-a489-3bb29577c696" + ], + "memory": "500M", + "name": "n1", + "orchestrator_opts": { + "swarm": { + "extra_labels": { + "traefik.enable": "true", + "traefik.tcp.routers.mydb.rule": "HostSNI(`mydb.example.com`)" + }, + "extra_networks": [ + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + }, + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + }, + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + } + ], + "extra_volumes": [ + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + }, + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + }, + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + } + ] + } + }, + "patroni_port": 8888, + "pg_hba_conf": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" ], - "username": "admin" + "port": 5432, + "postgres_version": "17.6", + "postgresql_conf": { + "max_connections": 1000 + }, + "restore_config": { + "repository": { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + }, + "restore_options": { + "set": "20250505-153628F", + "target": "123456", + "type": "xid" + }, + "source_database_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "source_database_name": "northwind", + "source_node_name": "n1" + }, + "source_node": "n1" }, - { - "attributes": [ - "LOGIN", - "CREATEDB", - "CREATEROLE" - ], - "db_owner": false, - "password": "secret", - "roles": [ - "pgedge_superuser" - ], - "username": "admin" - } - ], - "memory": "500M", - "nodes": [ { "backup_config": { "repositories": [ @@ -5172,6 +5393,12 @@ } }, "patroni_port": 8888, + "pg_hba_conf": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], "port": 5432, "postgres_version": "17.6", "postgresql_conf": { @@ -5265,6 +5492,13 @@ } }, "patroni_port": 8888, + "pg_hba_conf": [ + "hostssl all myapp_user 203.0.113.0/24 scram-sha-256", + "hostssl all alice 0.0.0.0/0 cert clientcert=verify-full map=ssl_users" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], "port": 5432, "postgres_version": "17.6", "postgresql_conf": { @@ -5392,164 +5626,6 @@ "service_type": "rag", "version": "latest" }, - { - "config": { - "llm_model": "gpt-4", - "llm_provider": "openai", - "openai_api_key": "sk-..." - }, - "connect_as": "app", - "cpus": "500m", - "database_connection": { - "target_nodes": [ - "n1", - "n2" - ], - "target_session_attrs": "primary" - }, - "host_ids": [ - "76f9b8c0-4958-11f0-a489-3bb29577c696", - "76f9b8c0-4958-11f0-a489-3bb29577c696" - ], - "memory": "512M", - "orchestrator_opts": { - "swarm": { - "extra_labels": { - "traefik.enable": "true", - "traefik.tcp.routers.mydb.rule": "HostSNI(`mydb.example.com`)" - }, - "extra_networks": [ - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - }, - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - }, - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - } - ], - "extra_volumes": [ - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - }, - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - }, - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - } - ] - } - }, - "port": 0, - "service_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "service_type": "rag", - "version": "latest" - }, - { - "config": { - "llm_model": "gpt-4", - "llm_provider": "openai", - "openai_api_key": "sk-..." - }, - "connect_as": "app", - "cpus": "500m", - "database_connection": { - "target_nodes": [ - "n1", - "n2" - ], - "target_session_attrs": "primary" - }, - "host_ids": [ - "76f9b8c0-4958-11f0-a489-3bb29577c696", - "76f9b8c0-4958-11f0-a489-3bb29577c696" - ], - "memory": "512M", - "orchestrator_opts": { - "swarm": { - "extra_labels": { - "traefik.enable": "true", - "traefik.tcp.routers.mydb.rule": "HostSNI(`mydb.example.com`)" - }, - "extra_networks": [ - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - }, - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - }, - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - } - ], - "extra_volumes": [ - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - }, - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - }, - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - } - ] - } - }, - "port": 0, - "service_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "service_type": "rag", - "version": "latest" - }, { "config": { "llm_model": "gpt-4", @@ -5987,7 +6063,7 @@ "type": "array", "items": { "type": "string", - "example": "Aperiam voluptatem enim dignissimos quasi nihil." + "example": "Delectus dolorum fugit quo aut." }, "description": "The attributes to assign to this database user.", "example": [ @@ -6012,7 +6088,7 @@ "type": "array", "items": { "type": "string", - "example": "Ut minima esse ut quaerat quae fugiat." + "example": "Asperiores iusto nostrum commodi quidem." }, "description": "The roles to assign to this database user.", "example": [ @@ -6073,7 +6149,7 @@ "type": "array", "items": { "type": "string", - "example": "Unde maiores." + "example": "Rerum soluta aliquam neque velit." }, "description": "Optional network-scoped aliases for the container.", "example": [ @@ -6090,7 +6166,7 @@ }, "additionalProperties": { "type": "string", - "example": "Voluptatem sed voluptatem autem quis." + "example": "Voluptatem enim dignissimos quasi nihil ea ut." } }, "id": { @@ -6154,12 +6230,12 @@ "type": "boolean", "description": "If true, skip the health validations that prevent running failover on a healthy cluster.", "default": false, - "example": true + "example": false } }, "example": { "candidate_instance_id": "68f50878-44d2-4524-a823-e31bd478706d-n1-689qacsi", - "skip_validation": true + "skip_validation": false } }, "FailoverDatabaseNodeResponse": { @@ -6794,26 +6870,6 @@ }, "description": "The tasks for the given database.", "example": [ - { - "completed_at": "2025-06-18T16:52:35Z", - "created_at": "2025-06-18T16:52:05Z", - "database_id": "storefront", - "entity_id": "storefront", - "scope": "database", - "status": "completed", - "task_id": "019783f4-75f4-71e7-85a3-c9b96b345d77", - "type": "create" - }, - { - "completed_at": "2025-06-18T16:52:35Z", - "created_at": "2025-06-18T16:52:05Z", - "database_id": "storefront", - "entity_id": "storefront", - "scope": "database", - "status": "completed", - "task_id": "019783f4-75f4-71e7-85a3-c9b96b345d77", - "type": "create" - }, { "completed_at": "2025-06-18T16:52:35Z", "created_at": "2025-06-18T16:52:05Z", @@ -8190,7 +8246,7 @@ "maxLength": 32, "additionalProperties": { "type": "string", - "example": "Id reprehenderit." + "example": "Ab fugit." } }, "source_database_id": { @@ -8262,7 +8318,7 @@ "type": "array", "items": { "type": "string", - "example": "Reprehenderit totam ea velit consequatur sequi error." + "example": "Aperiam qui sed quis architecto magnam." }, "description": "The nodes to restore. Defaults to all nodes if empty or unspecified.", "example": [ @@ -8573,7 +8629,7 @@ }, "additionalProperties": { "type": "string", - "example": "Voluptatibus earum." + "example": "Voluptatem sed voluptatem autem quis." } }, "gcs_bucket": { @@ -8921,8 +8977,6 @@ }, "description": "The IDs of the hosts that should run this service. One service instance will be created per host.", "example": [ - "76f9b8c0-4958-11f0-a489-3bb29577c696", - "76f9b8c0-4958-11f0-a489-3bb29577c696", "76f9b8c0-4958-11f0-a489-3bb29577c696" ], "minItems": 1 @@ -9113,7 +9167,7 @@ }, "additionalProperties": { "type": "string", - "example": "Fugit ipsam." + "example": "Ut quaerat quae fugiat dignissimos qui." } }, "extra_networks": { diff --git a/api/apiv1/gen/http/openapi.yaml b/api/apiv1/gen/http/openapi.yaml index fbd15958..ecdd8adc 100644 --- a/api/apiv1/gen/http/openapi.yaml +++ b/api/apiv1/gen/http/openapi.yaml @@ -1726,6 +1726,26 @@ definitions: s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY s3_region: us-east-1 type: s3 + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 minItems: 1 schedules: type: array @@ -1785,26 +1805,6 @@ definitions: s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY s3_region: us-east-1 type: s3 - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 schedules: - cron_expression: 0 6 * * ? id: daily-full-backup @@ -1843,7 +1843,7 @@ definitions: key: value additionalProperties: type: string - example: Quidem occaecati. + example: Beatae quasi ipsum. backup_options: type: object description: Options for the backup. @@ -1851,7 +1851,7 @@ definitions: archive-check: "n" additionalProperties: type: string - example: Nobis explicabo eum dolores quae. + example: Et est et dolorem labore explicabo. type: type: string description: The type of backup. @@ -1908,7 +1908,7 @@ definitions: storage-upload-chunk-size: 5MiB additionalProperties: type: string - example: Nobis velit fugiat rerum dicta optio. + example: Id reprehenderit. gcs_bucket: type: string description: The GCS bucket name for this repository. Only applies when type = 'gcs'. @@ -2719,7 +2719,7 @@ definitions: type: array items: type: string - example: Voluptatem mollitia est. + example: Eum dolores quae minima. description: Optional ordered list of database node names. When set, the service's database connection includes only the listed nodes in the specified order. example: - n1 @@ -2783,6 +2783,22 @@ definitions: format: int64 minimum: 0 maximum: 65535 + pg_hba_conf: + type: array + items: + type: string + example: Nobis velit fugiat rerum dicta optio. + description: Additional pg_hba.conf entries for this particular node, one rule per array element. Prepended to the database-level pg_hba_conf entries, so node entries take first-match priority. Entries are inserted between control-plane's system-user rules and its catch-all, and cannot affect control-plane-internal connectivity. + example: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + type: array + items: + type: string + example: Voluptas enim maiores sint voluptatibus earum. + description: Additional pg_ident.conf entries for this particular node, one mapping per array element. Prepended to the database-level pg_ident_conf entries. + example: + - ssl_users CN=alice,O=example alice port: type: integer description: The port used by the Postgres database for this node. Overrides the Postgres port set in the DatabaseSpec. @@ -2919,6 +2935,10 @@ definitions: - destination_path: /backups/container host_path: /Users/user/backups/host patroni_port: 8888 + pg_hba_conf: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + - ssl_users CN=alice,O=example alice port: 5432 postgres_version: "17.6" postgresql_conf: @@ -2961,7 +2981,7 @@ definitions: type: array items: type: string - example: r0 + example: fm9 minLength: 1 maxLength: 1024 description: The `post_database_create` script runs once on each primary instance of each node after the application database is created for the first time. Each element of the array is a single SQL statement. These statements run within a transaction in the application database after Spock is initialized, but before subscriptions are created. @@ -2975,7 +2995,7 @@ definitions: type: array items: type: string - example: p + example: yv minLength: 1 maxLength: 1024 description: The `post_init` script runs on each primary instance of each node after the instance is created for the first time. Each element of the array is single SQL statement. These statements run within a transaction in the `postgres` database before the users are created, so this feature can be used to create nologin roles that can be assigned to the database users via their `roles` field. @@ -3166,147 +3186,10 @@ definitions: - destination_path: /backups/container host_path: /Users/user/backups/host patroni_port: 8888 - port: 5432 - postgres_version: "17.6" - postgresql_conf: - max_connections: 1000 - restore_config: - repository: - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - restore_options: - set: 20250505-153628F - target: "123456" - type: xid - source_database_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - source_database_name: northwind - source_node_name: n1 - source_node: n1 - - backup_config: - repositories: - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - schedules: - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - cpus: 500m - host_ids: - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - memory: 500M - name: n1 - orchestrator_opts: - swarm: - extra_labels: - traefik.enable: "true" - traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) - extra_networks: - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - extra_volumes: - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - patroni_port: 8888 + pg_hba_conf: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + - ssl_users CN=alice,O=example alice port: 5432 postgres_version: "17.6" postgresql_conf: @@ -3349,6 +3232,23 @@ definitions: format: int64 minimum: 0 maximum: 65535 + pg_hba_conf: + type: array + items: + type: string + example: Ipsa et itaque aut reprehenderit. + description: Additional pg_hba.conf entries, one rule per array element. Inserted between control-plane's system-user rules and its catch-all, so they cannot affect control-plane-internal connectivity (Patroni, replication, health checks). Node-level pg_hba_conf entries are prepended to these. + example: + - hostssl all myapp_user 203.0.113.0/24 scram-sha-256 + - hostssl all alice 0.0.0.0/0 cert clientcert=verify-full map=ssl_users + pg_ident_conf: + type: array + items: + type: string + example: Ea velit consequatur sequi error et quibusdam. + description: Additional pg_ident.conf entries, one mapping per array element. Purely additive; control-plane writes no pg_ident entries of its own. The primary use case is cert auth with map= translating certificate CNs to PostgreSQL usernames. + example: + - ssl_users CN=alice,O=example alice port: type: integer description: The port used by the Postgres database. If the port is 0, each instance will be assigned a random port. If the port is unspecified, the database will not be exposed on any port, dependent on orchestrator support for that feature. @@ -3478,6 +3378,106 @@ definitions: service_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 service_type: rag version: latest + - config: + llm_model: gpt-4 + llm_provider: openai + openai_api_key: sk-... + connect_as: app + cpus: 500m + database_connection: + target_nodes: + - n1 + - n2 + target_session_attrs: primary + host_ids: + - 76f9b8c0-4958-11f0-a489-3bb29577c696 + - 76f9b8c0-4958-11f0-a489-3bb29577c696 + memory: 512M + orchestrator_opts: + swarm: + extra_labels: + traefik.enable: "true" + traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) + extra_networks: + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + extra_volumes: + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + port: 0 + service_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + service_type: rag + version: latest + - config: + llm_model: gpt-4 + llm_provider: openai + openai_api_key: sk-... + connect_as: app + cpus: 500m + database_connection: + target_nodes: + - n1 + - n2 + target_session_attrs: primary + host_ids: + - 76f9b8c0-4958-11f0-a489-3bb29577c696 + - 76f9b8c0-4958-11f0-a489-3bb29577c696 + memory: 512M + orchestrator_opts: + swarm: + extra_labels: + traefik.enable: "true" + traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) + extra_networks: + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + extra_volumes: + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + port: 0 + service_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + service_type: rag + version: latest spock_version: type: string description: The major version of the Spock extension. @@ -3698,6 +3698,155 @@ definitions: - destination_path: /backups/container host_path: /Users/user/backups/host patroni_port: 8888 + pg_hba_conf: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + - ssl_users CN=alice,O=example alice + port: 5432 + postgres_version: "17.6" + postgresql_conf: + max_connections: 1000 + restore_config: + repository: + azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + restore_options: + set: 20250505-153628F + target: "123456" + type: xid + source_database_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + source_database_name: northwind + source_node_name: n1 + source_node: n1 + - backup_config: + repositories: + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + schedules: + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + cpus: 500m + host_ids: + - 76f9b8c0-4958-11f0-a489-3bb29577c696 + - 76f9b8c0-4958-11f0-a489-3bb29577c696 + memory: 500M + name: n1 + orchestrator_opts: + swarm: + extra_labels: + traefik.enable: "true" + traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) + extra_networks: + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + extra_volumes: + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + patroni_port: 8888 + pg_hba_conf: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + - ssl_users CN=alice,O=example alice port: 5432 postgres_version: "17.6" postgresql_conf: @@ -3761,6 +3910,11 @@ definitions: - destination_path: /backups/container host_path: /Users/user/backups/host patroni_port: 8888 + pg_hba_conf: + - hostssl all myapp_user 203.0.113.0/24 scram-sha-256 + - hostssl all alice 0.0.0.0/0 cert clientcert=verify-full map=ssl_users + pg_ident_conf: + - ssl_users CN=alice,O=example alice port: 5432 postgres_version: "17.6" postgresql_conf: @@ -3901,106 +4055,6 @@ definitions: service_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 service_type: rag version: latest - - config: - llm_model: gpt-4 - llm_provider: openai - openai_api_key: sk-... - connect_as: app - cpus: 500m - database_connection: - target_nodes: - - n1 - - n2 - target_session_attrs: primary - host_ids: - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - memory: 512M - orchestrator_opts: - swarm: - extra_labels: - traefik.enable: "true" - traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) - extra_networks: - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - extra_volumes: - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - port: 0 - service_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - service_type: rag - version: latest - - config: - llm_model: gpt-4 - llm_provider: openai - openai_api_key: sk-... - connect_as: app - cpus: 500m - database_connection: - target_nodes: - - n1 - - n2 - target_session_attrs: primary - host_ids: - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - memory: 512M - orchestrator_opts: - swarm: - extra_labels: - traefik.enable: "true" - traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) - extra_networks: - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - extra_volumes: - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - port: 0 - service_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - service_type: rag - version: latest spock_version: "5" required: - database_name @@ -4263,7 +4317,7 @@ definitions: type: array items: type: string - example: Aperiam voluptatem enim dignissimos quasi nihil. + example: Delectus dolorum fugit quo aut. description: The attributes to assign to this database user. example: - LOGIN @@ -4283,7 +4337,7 @@ definitions: type: array items: type: string - example: Ut minima esse ut quaerat quae fugiat. + example: Asperiores iusto nostrum commodi quidem. description: The roles to assign to this database user. example: - pgedge_superuser @@ -4328,7 +4382,7 @@ definitions: type: array items: type: string - example: Unde maiores. + example: Rerum soluta aliquam neque velit. description: Optional network-scoped aliases for the container. example: - pg-db @@ -4341,7 +4395,7 @@ definitions: com.docker.network.endpoint.expose: "true" additionalProperties: type: string - example: Voluptatem sed voluptatem autem quis. + example: Voluptatem enim dignissimos quasi nihil ea ut. id: type: string description: The name or ID of the network to connect to. @@ -4389,10 +4443,10 @@ definitions: type: boolean description: If true, skip the health validations that prevent running failover on a healthy cluster. default: false - example: true + example: false example: candidate_instance_id: 68f50878-44d2-4524-a823-e31bd478706d-n1-689qacsi - skip_validation: true + skip_validation: false FailoverDatabaseNodeResponse: title: FailoverDatabaseNodeResponse type: object @@ -4876,22 +4930,6 @@ definitions: status: completed task_id: 019783f4-75f4-71e7-85a3-c9b96b345d77 type: create - - completed_at: "2025-06-18T16:52:35Z" - created_at: "2025-06-18T16:52:05Z" - database_id: storefront - entity_id: storefront - scope: database - status: completed - task_id: 019783f4-75f4-71e7-85a3-c9b96b345d77 - type: create - - completed_at: "2025-06-18T16:52:35Z" - created_at: "2025-06-18T16:52:05Z" - database_id: storefront - entity_id: storefront - scope: database - status: completed - task_id: 019783f4-75f4-71e7-85a3-c9b96b345d77 - type: create example: tasks: - completed_at: "2025-06-18T17:54:36Z" @@ -5849,7 +5887,7 @@ definitions: maxLength: 32 additionalProperties: type: string - example: Id reprehenderit. + example: Ab fugit. source_database_id: type: string description: The ID of the database to restore this database from. @@ -5908,7 +5946,7 @@ definitions: type: array items: type: string - example: Reprehenderit totam ea velit consequatur sequi error. + example: Aperiam qui sed quis architecto magnam. description: The nodes to restore. Defaults to all nodes if empty or unspecified. example: - n1 @@ -6132,7 +6170,7 @@ definitions: s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab additionalProperties: type: string - example: Voluptatibus earum. + example: Voluptatem sed voluptatem autem quis. gcs_bucket: type: string description: The GCS bucket name for this repository. Only applies when type = 'gcs'. @@ -6404,8 +6442,6 @@ definitions: description: The IDs of the hosts that should run this service. One service instance will be created per host. example: - 76f9b8c0-4958-11f0-a489-3bb29577c696 - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - - 76f9b8c0-4958-11f0-a489-3bb29577c696 minItems: 1 memory: type: string @@ -6542,7 +6578,7 @@ definitions: traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) additionalProperties: type: string - example: Fugit ipsam. + example: Ut quaerat quae fugiat dignissimos qui. extra_networks: type: array items: diff --git a/api/apiv1/gen/http/openapi3.json b/api/apiv1/gen/http/openapi3.json index e4b98126..3766c31d 100644 --- a/api/apiv1/gen/http/openapi3.json +++ b/api/apiv1/gen/http/openapi3.json @@ -1750,20 +1750,21 @@ "type": "array", "items": { "type": "string", - "example": "Doloribus consequatur voluptatibus sed et nisi." + "example": "Qui excepturi debitis aperiam rerum at." }, "description": "Host IDs to treat as removed during this update. Events targeting these hosts will be skipped.", "example": [ - "Perspiciatis et veniam blanditiis et.", - "Repellat fuga occaecati optio accusantium.", - "Voluptatibus sunt deserunt sapiente doloribus est." + "Facilis autem molestiae voluptatem.", + "Dolorem sed alias est mollitia.", + "Possimus id laudantium sed delectus.", + "Ut distinctio expedita." ] }, "example": [ - "Officiis sint.", - "Ad aut velit distinctio sed.", - "Rem voluptas qui.", - "Voluptatem nesciunt dignissimos voluptas vel earum." + "Esse odit placeat quod facere.", + "Sit commodi in dolor unde optio illo.", + "Sint cumque quia non.", + "Perferendis doloremque nam cumque." ] }, { @@ -5775,7 +5776,7 @@ }, "additionalProperties": { "type": "string", - "example": "Quibusdam veniam." + "example": "Ipsa et et." } }, "backup_options": { @@ -5786,7 +5787,7 @@ }, "additionalProperties": { "type": "string", - "example": "Non expedita sequi eligendi delectus sit quas." + "example": "Et nam quo qui qui natus." } }, "type": { @@ -5858,7 +5859,7 @@ }, "additionalProperties": { "type": "string", - "example": "Placeat a." + "example": "Ut dolorem." } }, "gcs_bucket": { @@ -6448,7 +6449,7 @@ "type": "array", "items": { "type": "string", - "example": "76l", + "example": "k0t", "minLength": 3, "maxLength": 128 }, @@ -6500,7 +6501,7 @@ "type": "array", "items": { "type": "string", - "example": "Quasi ipsum officiis et est et." + "example": "Placeat temporibus aut." }, "description": "Existing server to join", "example": [ @@ -6530,7 +6531,7 @@ "state": { "type": "string", "description": "The current state of the cluster.", - "example": "available", + "example": "error", "enum": [ "available", "error" @@ -6876,7 +6877,7 @@ ], "port": 5432 }, - "created_at": "1970-12-24T01:48:39Z", + "created_at": "2001-11-21T07:07:15Z", "error": "failed to get patroni status: connection refused", "host_id": "de3b1388-1f0c-42f1-a86c-59ab72f255ec", "id": "a67cbb36-c3c3-49c9-8aac-f4a0438a883d", @@ -6884,7 +6885,7 @@ "postgres": { "patroni_paused": true, "patroni_state": "unknown", - "pending_restart": true, + "pending_restart": false, "role": "primary", "version": "18.1" }, @@ -6896,6 +6897,11 @@ "provider_node": "n2", "status": "down" }, + { + "name": "sub_n1n2", + "provider_node": "n2", + "status": "down" + }, { "name": "sub_n1n2", "provider_node": "n2", @@ -6904,9 +6910,9 @@ ], "version": "4.10.0" }, - "state": "unknown", - "status_updated_at": "1978-12-17T01:14:06Z", - "updated_at": "2010-08-13T18:38:44Z" + "state": "degraded", + "status_updated_at": "1990-07-23T01:22:30Z", + "updated_at": "2013-01-29T23:51:44Z" }, { "connection_info": { @@ -6916,7 +6922,7 @@ ], "port": 5432 }, - "created_at": "1970-12-24T01:48:39Z", + "created_at": "2001-11-21T07:07:15Z", "error": "failed to get patroni status: connection refused", "host_id": "de3b1388-1f0c-42f1-a86c-59ab72f255ec", "id": "a67cbb36-c3c3-49c9-8aac-f4a0438a883d", @@ -6924,7 +6930,7 @@ "postgres": { "patroni_paused": true, "patroni_state": "unknown", - "pending_restart": true, + "pending_restart": false, "role": "primary", "version": "18.1" }, @@ -6936,6 +6942,11 @@ "provider_node": "n2", "status": "down" }, + { + "name": "sub_n1n2", + "provider_node": "n2", + "status": "down" + }, { "name": "sub_n1n2", "provider_node": "n2", @@ -6944,9 +6955,9 @@ ], "version": "4.10.0" }, - "state": "unknown", - "status_updated_at": "1978-12-17T01:14:06Z", - "updated_at": "2010-08-13T18:38:44Z" + "state": "degraded", + "status_updated_at": "1990-07-23T01:22:30Z", + "updated_at": "2013-01-29T23:51:44Z" }, { "connection_info": { @@ -6956,7 +6967,7 @@ ], "port": 5432 }, - "created_at": "1970-12-24T01:48:39Z", + "created_at": "2001-11-21T07:07:15Z", "error": "failed to get patroni status: connection refused", "host_id": "de3b1388-1f0c-42f1-a86c-59ab72f255ec", "id": "a67cbb36-c3c3-49c9-8aac-f4a0438a883d", @@ -6964,7 +6975,52 @@ "postgres": { "patroni_paused": true, "patroni_state": "unknown", - "pending_restart": true, + "pending_restart": false, + "role": "primary", + "version": "18.1" + }, + "spock": { + "read_only": "off", + "subscriptions": [ + { + "name": "sub_n1n2", + "provider_node": "n2", + "status": "down" + }, + { + "name": "sub_n1n2", + "provider_node": "n2", + "status": "down" + }, + { + "name": "sub_n1n2", + "provider_node": "n2", + "status": "down" + } + ], + "version": "4.10.0" + }, + "state": "degraded", + "status_updated_at": "1990-07-23T01:22:30Z", + "updated_at": "2013-01-29T23:51:44Z" + }, + { + "connection_info": { + "addresses": [ + "10.24.34.2", + "i-0123456789abcdef.ec2.internal" + ], + "port": 5432 + }, + "created_at": "2001-11-21T07:07:15Z", + "error": "failed to get patroni status: connection refused", + "host_id": "de3b1388-1f0c-42f1-a86c-59ab72f255ec", + "id": "a67cbb36-c3c3-49c9-8aac-f4a0438a883d", + "node_name": "n1", + "postgres": { + "patroni_paused": true, + "patroni_state": "unknown", + "pending_restart": false, "role": "primary", "version": "18.1" }, @@ -6976,6 +7032,11 @@ "provider_node": "n2", "status": "down" }, + { + "name": "sub_n1n2", + "provider_node": "n2", + "status": "down" + }, { "name": "sub_n1n2", "provider_node": "n2", @@ -6984,9 +7045,9 @@ ], "version": "4.10.0" }, - "state": "unknown", - "status_updated_at": "1978-12-17T01:14:06Z", - "updated_at": "2010-08-13T18:38:44Z" + "state": "degraded", + "status_updated_at": "1990-07-23T01:22:30Z", + "updated_at": "2013-01-29T23:51:44Z" } ] }, @@ -7089,7 +7150,7 @@ "state": { "type": "string", "description": "Current state of the database.", - "example": "available", + "example": "creating", "enum": [ "creating", "modifying", @@ -7434,110 +7495,61 @@ "state": "available", "status_updated_at": "1993-04-25T23:06:28Z", "updated_at": "1981-08-22T23:20:01Z" - } - ] - }, - "service_instances": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ServiceInstance" - }, - "description": "Service instances running alongside this database.", - "example": [ - { - "created_at": "2025-01-28T10:00:00Z", - "database_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "error": "failed to start container: image not found", - "host_id": "host-1", - "service_id": "mcp-server", - "service_instance_id": "mcp-server-host-1", - "state": "running", - "status": { - "addresses": [ - "10.24.34.2", - "i-0123456789abcdef.ec2.internal" - ], - "container_id": "a1b2c3d4e5f6", - "health_check": { - "checked_at": "2025-01-28T10:00:00Z", - "message": "Connection refused", - "status": "healthy" - }, - "image_version": "1.0.0", - "last_health_at": "2025-01-28T10:00:00Z", - "ports": [ - { - "container_port": 8080, - "host_port": 8080, - "name": "web-client" - }, - { - "container_port": 8080, - "host_port": 8080, - "name": "web-client" - }, - { - "container_port": 8080, - "host_port": 8080, - "name": "web-client" - }, - { - "container_port": 8080, - "host_port": 8080, - "name": "web-client" - } - ], - "service_ready": true - }, - "updated_at": "2025-01-28T10:05:00Z" }, { - "created_at": "2025-01-28T10:00:00Z", - "database_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "error": "failed to start container: image not found", - "host_id": "host-1", - "service_id": "mcp-server", - "service_instance_id": "mcp-server-host-1", - "state": "running", - "status": { + "connection_info": { "addresses": [ "10.24.34.2", "i-0123456789abcdef.ec2.internal" ], - "container_id": "a1b2c3d4e5f6", - "health_check": { - "checked_at": "2025-01-28T10:00:00Z", - "message": "Connection refused", - "status": "healthy" - }, - "image_version": "1.0.0", - "last_health_at": "2025-01-28T10:00:00Z", - "ports": [ - { - "container_port": 8080, - "host_port": 8080, - "name": "web-client" - }, + "port": 5432 + }, + "created_at": "2011-03-15T17:48:48Z", + "error": "failed to get patroni status: connection refused", + "host_id": "de3b1388-1f0c-42f1-a86c-59ab72f255ec", + "id": "a67cbb36-c3c3-49c9-8aac-f4a0438a883d", + "node_name": "n1", + "postgres": { + "patroni_paused": false, + "patroni_state": "unknown", + "pending_restart": true, + "role": "primary", + "version": "18.1" + }, + "spock": { + "read_only": "off", + "subscriptions": [ { - "container_port": 8080, - "host_port": 8080, - "name": "web-client" + "name": "sub_n1n2", + "provider_node": "n2", + "status": "down" }, { - "container_port": 8080, - "host_port": 8080, - "name": "web-client" + "name": "sub_n1n2", + "provider_node": "n2", + "status": "down" }, { - "container_port": 8080, - "host_port": 8080, - "name": "web-client" + "name": "sub_n1n2", + "provider_node": "n2", + "status": "down" } ], - "service_ready": true + "version": "4.10.0" }, - "updated_at": "2025-01-28T10:05:00Z" - }, + "state": "available", + "status_updated_at": "1993-04-25T23:06:28Z", + "updated_at": "1981-08-22T23:20:01Z" + } + ] + }, + "service_instances": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ServiceInstance" + }, + "description": "Service instances running alongside this database.", + "example": [ { "created_at": "2025-01-28T10:00:00Z", "database_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", @@ -7640,7 +7652,7 @@ "state": { "type": "string", "description": "Current state of the database.", - "example": "modifying", + "example": "unknown", "enum": [ "creating", "modifying", @@ -7941,6 +7953,51 @@ "status_updated_at": "1993-04-25T23:06:28Z", "updated_at": "1981-08-22T23:20:01Z" }, + { + "connection_info": { + "addresses": [ + "10.24.34.2", + "i-0123456789abcdef.ec2.internal" + ], + "port": 5432 + }, + "created_at": "2011-03-15T17:48:48Z", + "error": "failed to get patroni status: connection refused", + "host_id": "de3b1388-1f0c-42f1-a86c-59ab72f255ec", + "id": "a67cbb36-c3c3-49c9-8aac-f4a0438a883d", + "node_name": "n1", + "postgres": { + "patroni_paused": false, + "patroni_state": "unknown", + "pending_restart": true, + "role": "primary", + "version": "18.1" + }, + "spock": { + "read_only": "off", + "subscriptions": [ + { + "name": "sub_n1n2", + "provider_node": "n2", + "status": "down" + }, + { + "name": "sub_n1n2", + "provider_node": "n2", + "status": "down" + }, + { + "name": "sub_n1n2", + "provider_node": "n2", + "status": "down" + } + ], + "version": "4.10.0" + }, + "state": "available", + "status_updated_at": "1993-04-25T23:06:28Z", + "updated_at": "1981-08-22T23:20:01Z" + }, { "connection_info": { "addresses": [ @@ -8088,23 +8145,117 @@ "service_ready": true }, "updated_at": "2025-01-28T10:05:00Z" - } - ] - }, - "spec": { - "$ref": "#/components/schemas/DatabaseSpec4" - }, - "state": { - "type": "string", - "description": "Current state of the database.", - "example": "degraded", - "enum": [ - "creating", - "modifying", - "available", - "deleting", - "degraded", - "failed", + }, + { + "created_at": "2025-01-28T10:00:00Z", + "database_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "error": "failed to start container: image not found", + "host_id": "host-1", + "service_id": "mcp-server", + "service_instance_id": "mcp-server-host-1", + "state": "running", + "status": { + "addresses": [ + "10.24.34.2", + "i-0123456789abcdef.ec2.internal" + ], + "container_id": "a1b2c3d4e5f6", + "health_check": { + "checked_at": "2025-01-28T10:00:00Z", + "message": "Connection refused", + "status": "healthy" + }, + "image_version": "1.0.0", + "last_health_at": "2025-01-28T10:00:00Z", + "ports": [ + { + "container_port": 8080, + "host_port": 8080, + "name": "web-client" + }, + { + "container_port": 8080, + "host_port": 8080, + "name": "web-client" + }, + { + "container_port": 8080, + "host_port": 8080, + "name": "web-client" + }, + { + "container_port": 8080, + "host_port": 8080, + "name": "web-client" + } + ], + "service_ready": true + }, + "updated_at": "2025-01-28T10:05:00Z" + }, + { + "created_at": "2025-01-28T10:00:00Z", + "database_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "error": "failed to start container: image not found", + "host_id": "host-1", + "service_id": "mcp-server", + "service_instance_id": "mcp-server-host-1", + "state": "running", + "status": { + "addresses": [ + "10.24.34.2", + "i-0123456789abcdef.ec2.internal" + ], + "container_id": "a1b2c3d4e5f6", + "health_check": { + "checked_at": "2025-01-28T10:00:00Z", + "message": "Connection refused", + "status": "healthy" + }, + "image_version": "1.0.0", + "last_health_at": "2025-01-28T10:00:00Z", + "ports": [ + { + "container_port": 8080, + "host_port": 8080, + "name": "web-client" + }, + { + "container_port": 8080, + "host_port": 8080, + "name": "web-client" + }, + { + "container_port": 8080, + "host_port": 8080, + "name": "web-client" + }, + { + "container_port": 8080, + "host_port": 8080, + "name": "web-client" + } + ], + "service_ready": true + }, + "updated_at": "2025-01-28T10:05:00Z" + } + ] + }, + "spec": { + "$ref": "#/components/schemas/DatabaseSpec4" + }, + "state": { + "type": "string", + "description": "Current state of the database.", + "example": "deleting", + "enum": [ + "creating", + "modifying", + "available", + "deleting", + "degraded", + "failed", "restoring", "unknown" ] @@ -8993,106 +9144,63 @@ "state": "available", "status_updated_at": "1993-04-25T23:06:28Z", "updated_at": "1981-08-22T23:20:01Z" - }, + } + ] + }, + "service_instances": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ServiceInstance" + }, + "description": "Service instances running alongside this database.", + "example": [ { - "connection_info": { + "created_at": "2025-01-28T10:00:00Z", + "database_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "error": "failed to start container: image not found", + "host_id": "host-1", + "service_id": "mcp-server", + "service_instance_id": "mcp-server-host-1", + "state": "running", + "status": { "addresses": [ "10.24.34.2", "i-0123456789abcdef.ec2.internal" ], - "port": 5432 - }, - "created_at": "2011-03-15T17:48:48Z", - "error": "failed to get patroni status: connection refused", - "host_id": "de3b1388-1f0c-42f1-a86c-59ab72f255ec", - "id": "a67cbb36-c3c3-49c9-8aac-f4a0438a883d", - "node_name": "n1", - "postgres": { - "patroni_paused": false, - "patroni_state": "unknown", - "pending_restart": true, - "role": "primary", - "version": "18.1" - }, - "spock": { - "read_only": "off", - "subscriptions": [ - { - "name": "sub_n1n2", - "provider_node": "n2", - "status": "down" - }, + "container_id": "a1b2c3d4e5f6", + "health_check": { + "checked_at": "2025-01-28T10:00:00Z", + "message": "Connection refused", + "status": "healthy" + }, + "image_version": "1.0.0", + "last_health_at": "2025-01-28T10:00:00Z", + "ports": [ { - "name": "sub_n1n2", - "provider_node": "n2", - "status": "down" + "container_port": 8080, + "host_port": 8080, + "name": "web-client" }, { - "name": "sub_n1n2", - "provider_node": "n2", - "status": "down" - } - ], - "version": "4.10.0" - }, - "state": "available", - "status_updated_at": "1993-04-25T23:06:28Z", - "updated_at": "1981-08-22T23:20:01Z" - }, - { - "connection_info": { - "addresses": [ - "10.24.34.2", - "i-0123456789abcdef.ec2.internal" - ], - "port": 5432 - }, - "created_at": "2011-03-15T17:48:48Z", - "error": "failed to get patroni status: connection refused", - "host_id": "de3b1388-1f0c-42f1-a86c-59ab72f255ec", - "id": "a67cbb36-c3c3-49c9-8aac-f4a0438a883d", - "node_name": "n1", - "postgres": { - "patroni_paused": false, - "patroni_state": "unknown", - "pending_restart": true, - "role": "primary", - "version": "18.1" - }, - "spock": { - "read_only": "off", - "subscriptions": [ - { - "name": "sub_n1n2", - "provider_node": "n2", - "status": "down" + "container_port": 8080, + "host_port": 8080, + "name": "web-client" }, { - "name": "sub_n1n2", - "provider_node": "n2", - "status": "down" + "container_port": 8080, + "host_port": 8080, + "name": "web-client" }, { - "name": "sub_n1n2", - "provider_node": "n2", - "status": "down" + "container_port": 8080, + "host_port": 8080, + "name": "web-client" } ], - "version": "4.10.0" + "service_ready": true }, - "state": "available", - "status_updated_at": "1993-04-25T23:06:28Z", - "updated_at": "1981-08-22T23:20:01Z" - } - ] - }, - "service_instances": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ServiceInstance" - }, - "description": "Service instances running alongside this database.", - "example": [ + "updated_at": "2025-01-28T10:05:00Z" + }, { "created_at": "2025-01-28T10:00:00Z", "database_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", @@ -9195,7 +9303,7 @@ "state": { "type": "string", "description": "Current state of the database.", - "example": "unknown", + "example": "failed", "enum": [ "creating", "modifying", @@ -9390,7 +9498,7 @@ "type": "array", "items": { "type": "string", - "example": "Ab sed exercitationem rerum animi et itaque." + "example": "Eius at." }, "description": "Optional ordered list of database node names. When set, the service's database connection includes only the listed nodes in the specified order.", "example": [ @@ -9443,6 +9551,8 @@ }, "description": "The IDs of the hosts that should run this node. When multiple hosts are specified, one host will chosen as a primary, and the others will be read replicas.", "example": [ + "de3b1388-1f0c-42f1-a86c-59ab72f255ec", + "de3b1388-1f0c-42f1-a86c-59ab72f255ec", "de3b1388-1f0c-42f1-a86c-59ab72f255ec" ], "minItems": 1 @@ -9470,6 +9580,28 @@ "minimum": 0, "maximum": 65535 }, + "pg_hba_conf": { + "type": "array", + "items": { + "type": "string", + "example": "Modi explicabo." + }, + "description": "Additional pg_hba.conf entries for this particular node, one rule per array element. Prepended to the database-level pg_hba_conf entries, so node entries take first-match priority. Entries are inserted between control-plane's system-user rules and its catch-all, and cannot affect control-plane-internal connectivity.", + "example": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ] + }, + "pg_ident_conf": { + "type": "array", + "items": { + "type": "string", + "example": "Alias qui et eius." + }, + "description": "Additional pg_ident.conf entries for this particular node, one mapping per array element. Prepended to the database-level pg_ident_conf entries.", + "example": [ + "ssl_users CN=alice,O=example alice" + ] + }, "port": { "type": "integer", "description": "The port used by the Postgres database for this node. Overrides the Postgres port set in the DatabaseSpec.", @@ -9571,6 +9703,7 @@ }, "cpus": "500m", "host_ids": [ + "de3b1388-1f0c-42f1-a86c-59ab72f255ec", "de3b1388-1f0c-42f1-a86c-59ab72f255ec", "de3b1388-1f0c-42f1-a86c-59ab72f255ec" ], @@ -9631,7 +9764,13 @@ } }, "patroni_port": 8888, - "port": 5432, + "pg_hba_conf": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], + "port": 5432, "postgres_version": "17.6", "postgresql_conf": { "max_connections": 1000 @@ -9695,6 +9834,7 @@ }, "description": "The IDs of the hosts that should run this node. When multiple hosts are specified, one host will chosen as a primary, and the others will be read replicas.", "example": [ + "76f9b8c0-4958-11f0-a489-3bb29577c696", "76f9b8c0-4958-11f0-a489-3bb29577c696", "76f9b8c0-4958-11f0-a489-3bb29577c696" ], @@ -9723,6 +9863,28 @@ "minimum": 0, "maximum": 65535 }, + "pg_hba_conf": { + "type": "array", + "items": { + "type": "string", + "example": "Ut quae eos." + }, + "description": "Additional pg_hba.conf entries for this particular node, one rule per array element. Prepended to the database-level pg_hba_conf entries, so node entries take first-match priority. Entries are inserted between control-plane's system-user rules and its catch-all, and cannot affect control-plane-internal connectivity.", + "example": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ] + }, + "pg_ident_conf": { + "type": "array", + "items": { + "type": "string", + "example": "Voluptates quo." + }, + "description": "Additional pg_ident.conf entries for this particular node, one mapping per array element. Prepended to the database-level pg_ident_conf entries.", + "example": [ + "ssl_users CN=alice,O=example alice" + ] + }, "port": { "type": "integer", "description": "The port used by the Postgres database for this node. Overrides the Postgres port set in the DatabaseSpec.", @@ -9847,8 +10009,6 @@ }, "cpus": "500m", "host_ids": [ - "76f9b8c0-4958-11f0-a489-3bb29577c696", - "76f9b8c0-4958-11f0-a489-3bb29577c696", "76f9b8c0-4958-11f0-a489-3bb29577c696" ], "memory": "500M", @@ -9908,6 +10068,12 @@ } }, "patroni_port": 8888, + "pg_hba_conf": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], "port": 5432, "postgres_version": "17.6", "postgresql_conf": { @@ -9972,8 +10138,6 @@ }, "description": "The IDs of the hosts that should run this node. When multiple hosts are specified, one host will chosen as a primary, and the others will be read replicas.", "example": [ - "76f9b8c0-4958-11f0-a489-3bb29577c696", - "76f9b8c0-4958-11f0-a489-3bb29577c696", "76f9b8c0-4958-11f0-a489-3bb29577c696" ], "minItems": 1 @@ -10001,6 +10165,28 @@ "minimum": 0, "maximum": 65535 }, + "pg_hba_conf": { + "type": "array", + "items": { + "type": "string", + "example": "Distinctio atque." + }, + "description": "Additional pg_hba.conf entries for this particular node, one rule per array element. Prepended to the database-level pg_hba_conf entries, so node entries take first-match priority. Entries are inserted between control-plane's system-user rules and its catch-all, and cannot affect control-plane-internal connectivity.", + "example": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ] + }, + "pg_ident_conf": { + "type": "array", + "items": { + "type": "string", + "example": "Autem doloremque et excepturi." + }, + "description": "Additional pg_ident.conf entries for this particular node, one mapping per array element. Prepended to the database-level pg_ident_conf entries.", + "example": [ + "ssl_users CN=alice,O=example alice" + ] + }, "port": { "type": "integer", "description": "The port used by the Postgres database for this node. Overrides the Postgres port set in the DatabaseSpec.", @@ -10186,6 +10372,12 @@ } }, "patroni_port": 8888, + "pg_hba_conf": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], "port": 5432, "postgres_version": "17.6", "postgresql_conf": { @@ -10250,8 +10442,6 @@ }, "description": "The IDs of the hosts that should run this node. When multiple hosts are specified, one host will chosen as a primary, and the others will be read replicas.", "example": [ - "76f9b8c0-4958-11f0-a489-3bb29577c696", - "76f9b8c0-4958-11f0-a489-3bb29577c696", "76f9b8c0-4958-11f0-a489-3bb29577c696" ], "minItems": 1 @@ -10279,6 +10469,28 @@ "minimum": 0, "maximum": 65535 }, + "pg_hba_conf": { + "type": "array", + "items": { + "type": "string", + "example": "Est temporibus molestias officiis sint." + }, + "description": "Additional pg_hba.conf entries for this particular node, one rule per array element. Prepended to the database-level pg_hba_conf entries, so node entries take first-match priority. Entries are inserted between control-plane's system-user rules and its catch-all, and cannot affect control-plane-internal connectivity.", + "example": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ] + }, + "pg_ident_conf": { + "type": "array", + "items": { + "type": "string", + "example": "Ad aut velit distinctio sed." + }, + "description": "Additional pg_ident.conf entries for this particular node, one mapping per array element. Prepended to the database-level pg_ident_conf entries.", + "example": [ + "ssl_users CN=alice,O=example alice" + ] + }, "port": { "type": "integer", "description": "The port used by the Postgres database for this node. Overrides the Postgres port set in the DatabaseSpec.", @@ -10462,6 +10674,12 @@ } }, "patroni_port": 8888, + "pg_hba_conf": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], "port": 5432, "postgres_version": "17.6", "postgresql_conf": { @@ -10526,8 +10744,6 @@ }, "description": "The IDs of the hosts that should run this node. When multiple hosts are specified, one host will chosen as a primary, and the others will be read replicas.", "example": [ - "76f9b8c0-4958-11f0-a489-3bb29577c696", - "76f9b8c0-4958-11f0-a489-3bb29577c696", "76f9b8c0-4958-11f0-a489-3bb29577c696" ], "minItems": 1 @@ -10555,6 +10771,28 @@ "minimum": 0, "maximum": 65535 }, + "pg_hba_conf": { + "type": "array", + "items": { + "type": "string", + "example": "Quaerat rem." + }, + "description": "Additional pg_hba.conf entries for this particular node, one rule per array element. Prepended to the database-level pg_hba_conf entries, so node entries take first-match priority. Entries are inserted between control-plane's system-user rules and its catch-all, and cannot affect control-plane-internal connectivity.", + "example": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ] + }, + "pg_ident_conf": { + "type": "array", + "items": { + "type": "string", + "example": "Qui numquam incidunt eaque totam at." + }, + "description": "Additional pg_ident.conf entries for this particular node, one mapping per array element. Prepended to the database-level pg_ident_conf entries.", + "example": [ + "ssl_users CN=alice,O=example alice" + ] + }, "port": { "type": "integer", "description": "The port used by the Postgres database for this node. Overrides the Postgres port set in the DatabaseSpec.", @@ -10679,6 +10917,7 @@ }, "cpus": "500m", "host_ids": [ + "76f9b8c0-4958-11f0-a489-3bb29577c696", "76f9b8c0-4958-11f0-a489-3bb29577c696", "76f9b8c0-4958-11f0-a489-3bb29577c696" ], @@ -10739,6 +10978,12 @@ } }, "patroni_port": 8888, + "pg_hba_conf": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], "port": 5432, "postgres_version": "17.6", "postgresql_conf": { @@ -10803,6 +11048,7 @@ }, "description": "The IDs of the hosts that should run this node. When multiple hosts are specified, one host will chosen as a primary, and the others will be read replicas.", "example": [ + "76f9b8c0-4958-11f0-a489-3bb29577c696", "76f9b8c0-4958-11f0-a489-3bb29577c696", "76f9b8c0-4958-11f0-a489-3bb29577c696" ], @@ -10831,6 +11077,28 @@ "minimum": 0, "maximum": 65535 }, + "pg_hba_conf": { + "type": "array", + "items": { + "type": "string", + "example": "Occaecati et et consequuntur." + }, + "description": "Additional pg_hba.conf entries for this particular node, one rule per array element. Prepended to the database-level pg_hba_conf entries, so node entries take first-match priority. Entries are inserted between control-plane's system-user rules and its catch-all, and cannot affect control-plane-internal connectivity.", + "example": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ] + }, + "pg_ident_conf": { + "type": "array", + "items": { + "type": "string", + "example": "Qui et nulla omnis nobis dolor." + }, + "description": "Additional pg_ident.conf entries for this particular node, one mapping per array element. Prepended to the database-level pg_ident_conf entries.", + "example": [ + "ssl_users CN=alice,O=example alice" + ] + }, "port": { "type": "integer", "description": "The port used by the Postgres database for this node. Overrides the Postgres port set in the DatabaseSpec.", @@ -10955,7 +11223,6 @@ }, "cpus": "500m", "host_ids": [ - "76f9b8c0-4958-11f0-a489-3bb29577c696", "76f9b8c0-4958-11f0-a489-3bb29577c696" ], "memory": "500M", @@ -11015,6 +11282,12 @@ } }, "patroni_port": 8888, + "pg_hba_conf": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], "port": 5432, "postgres_version": "17.6", "postgresql_conf": { @@ -11106,6 +11379,28 @@ "minimum": 0, "maximum": 65535 }, + "pg_hba_conf": { + "type": "array", + "items": { + "type": "string", + "example": "Ducimus deserunt quis commodi officiis libero mollitia." + }, + "description": "Additional pg_hba.conf entries for this particular node, one rule per array element. Prepended to the database-level pg_hba_conf entries, so node entries take first-match priority. Entries are inserted between control-plane's system-user rules and its catch-all, and cannot affect control-plane-internal connectivity.", + "example": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ] + }, + "pg_ident_conf": { + "type": "array", + "items": { + "type": "string", + "example": "Impedit ab." + }, + "description": "Additional pg_ident.conf entries for this particular node, one mapping per array element. Prepended to the database-level pg_ident_conf entries.", + "example": [ + "ssl_users CN=alice,O=example alice" + ] + }, "port": { "type": "integer", "description": "The port used by the Postgres database for this node. Overrides the Postgres port set in the DatabaseSpec.", @@ -11230,7 +11525,6 @@ }, "cpus": "500m", "host_ids": [ - "76f9b8c0-4958-11f0-a489-3bb29577c696", "76f9b8c0-4958-11f0-a489-3bb29577c696" ], "memory": "500M", @@ -11290,6 +11584,12 @@ } }, "patroni_port": 8888, + "pg_hba_conf": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], "port": 5432, "postgres_version": "17.6", "postgresql_conf": { @@ -11563,6 +11863,12 @@ } }, "patroni_port": 8888, + "pg_hba_conf": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], "port": 5432, "postgres_version": "17.6", "postgresql_conf": { @@ -11615,6 +11921,29 @@ "minimum": 0, "maximum": 65535 }, + "pg_hba_conf": { + "type": "array", + "items": { + "type": "string", + "example": "Reprehenderit harum sapiente qui ullam qui." + }, + "description": "Additional pg_hba.conf entries, one rule per array element. Inserted between control-plane's system-user rules and its catch-all, so they cannot affect control-plane-internal connectivity (Patroni, replication, health checks). Node-level pg_hba_conf entries are prepended to these.", + "example": [ + "hostssl all myapp_user 203.0.113.0/24 scram-sha-256", + "hostssl all alice 0.0.0.0/0 cert clientcert=verify-full map=ssl_users" + ] + }, + "pg_ident_conf": { + "type": "array", + "items": { + "type": "string", + "example": "Sint iure eum ducimus quia deserunt animi." + }, + "description": "Additional pg_ident.conf entries, one mapping per array element. Purely additive; control-plane writes no pg_ident entries of its own. The primary use case is cert auth with map= translating certificate CNs to PostgreSQL usernames.", + "example": [ + "ssl_users CN=alice,O=example alice" + ] + }, "port": { "type": "integer", "description": "The port used by the Postgres database. If the port is 0, each instance will be assigned a random port. If the port is unspecified, the database will not be exposed on any port, dependent on orchestrator support for that feature.", @@ -11667,7 +11996,6 @@ "target_session_attrs": "primary" }, "host_ids": [ - "de3b1388-1f0c-42f1-a86c-59ab72f255ec", "de3b1388-1f0c-42f1-a86c-59ab72f255ec", "de3b1388-1f0c-42f1-a86c-59ab72f255ec" ], @@ -11747,7 +12075,6 @@ "target_session_attrs": "primary" }, "host_ids": [ - "de3b1388-1f0c-42f1-a86c-59ab72f255ec", "de3b1388-1f0c-42f1-a86c-59ab72f255ec", "de3b1388-1f0c-42f1-a86c-59ab72f255ec" ], @@ -12062,6 +12389,12 @@ } }, "patroni_port": 8888, + "pg_hba_conf": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], "port": 5432, "postgres_version": "17.6", "postgresql_conf": { @@ -12098,130 +12431,81 @@ "source_node_name": "n1" }, "source_node": "n1" - } - ], - "orchestrator_opts": { - "swarm": { - "extra_labels": { - "traefik.enable": "true", - "traefik.tcp.routers.mydb.rule": "HostSNI(`mydb.example.com`)" - }, - "extra_networks": [ - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" + }, + { + "backup_config": { + "repositories": [ + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "f6b84a99-5e91-4203-be1e-131fe82e5984", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" }, - "id": "traefik-public" - }, - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "f6b84a99-5e91-4203-be1e-131fe82e5984", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + } + ], + "schedules": [ + { + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" }, - "id": "traefik-public" - }, - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" + { + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" }, - "id": "traefik-public" - } + { + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" + } + ] + }, + "cpus": "500m", + "host_ids": [ + "de3b1388-1f0c-42f1-a86c-59ab72f255ec" ], - "extra_volumes": [ - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - }, - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - }, - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - } - ] - } - }, - "patroni_port": 8888, - "port": 5432, - "postgres_version": "17.6", - "postgresql_conf": { - "max_connections": 1000 - }, - "restore_config": { - "repository": { - "azure_account": "pgedge-backups", - "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "azure_endpoint": "blob.core.usgovcloudapi.net", - "azure_key": "YXpLZXk=", - "base_path": "/backups", - "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab" - }, - "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "gcs_endpoint": "localhost", - "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", - "id": "f6b84a99-5e91-4203-be1e-131fe82e5984", - "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "s3_endpoint": "s3.us-east-1.amazonaws.com", - "s3_key": "AKIAIOSFODNN7EXAMPLE", - "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - "s3_region": "us-east-1", - "type": "s3" - }, - "restore_options": { - "set": "20250505-153628F", - "target": "123456", - "type": "xid" - }, - "source_database_id": "02f1a7db-fca8-4521-b57a-2a375c1ced51", - "source_database_name": "northwind", - "source_node_name": "n1" - }, - "scripts": { - "post_database_create": [ - "ALTER DEFAULT PRIVILEGES FOR ROLE admin GRANT USAGE ON SCHEMAS TO app", - "ALTER DEFAULT PRIVILEGES FOR ROLE admin GRANT ALL PRIVILEGES ON TABLES TO app", - "ALTER DEFAULT PRIVILEGES FOR ROLE admin GRANT ALL PRIVILEGES ON SEQUENCES TO app" - ], - "post_init": [ - "CREATE ROLE accounting_admin NOLOGIN" - ] - }, - "services": [ - { - "config": { - "llm_model": "gpt-4", - "llm_provider": "openai", - "openai_api_key": "sk-..." - }, - "connect_as": "app", - "cpus": "500m", - "database_connection": { - "target_nodes": [ - "n1", - "n2" - ], - "target_session_attrs": "primary" - }, - "host_ids": [ - "de3b1388-1f0c-42f1-a86c-59ab72f255ec", - "de3b1388-1f0c-42f1-a86c-59ab72f255ec", - "de3b1388-1f0c-42f1-a86c-59ab72f255ec" - ], - "memory": "512M", + "memory": "500M", + "name": "n1", "orchestrator_opts": { "swarm": { "extra_labels": { @@ -12276,32 +12560,124 @@ ] } }, - "port": 0, - "service_id": "analytics-service", - "service_type": "rag", - "version": "latest" + "patroni_port": 8888, + "pg_hba_conf": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], + "port": 5432, + "postgres_version": "17.6", + "postgresql_conf": { + "max_connections": 1000 + }, + "restore_config": { + "repository": { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "f6b84a99-5e91-4203-be1e-131fe82e5984", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + }, + "restore_options": { + "set": "20250505-153628F", + "target": "123456", + "type": "xid" + }, + "source_database_id": "02f1a7db-fca8-4521-b57a-2a375c1ced51", + "source_database_name": "northwind", + "source_node_name": "n1" + }, + "source_node": "n1" }, { - "config": { - "llm_model": "gpt-4", - "llm_provider": "openai", - "openai_api_key": "sk-..." - }, - "connect_as": "app", - "cpus": "500m", - "database_connection": { - "target_nodes": [ - "n1", - "n2" + "backup_config": { + "repositories": [ + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "f6b84a99-5e91-4203-be1e-131fe82e5984", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + }, + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "f6b84a99-5e91-4203-be1e-131fe82e5984", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + } ], - "target_session_attrs": "primary" + "schedules": [ + { + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" + }, + { + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" + }, + { + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" + } + ] }, + "cpus": "500m", "host_ids": [ - "de3b1388-1f0c-42f1-a86c-59ab72f255ec", - "de3b1388-1f0c-42f1-a86c-59ab72f255ec", "de3b1388-1f0c-42f1-a86c-59ab72f255ec" ], - "memory": "512M", + "memory": "500M", + "name": "n1", "orchestrator_opts": { "swarm": { "extra_labels": { @@ -12356,55 +12732,202 @@ ] } }, - "port": 0, - "service_id": "analytics-service", - "service_type": "rag", - "version": "latest" - }, - { - "config": { - "llm_model": "gpt-4", - "llm_provider": "openai", - "openai_api_key": "sk-..." - }, - "connect_as": "app", - "cpus": "500m", - "database_connection": { - "target_nodes": [ - "n1", - "n2" - ], - "target_session_attrs": "primary" - }, - "host_ids": [ - "de3b1388-1f0c-42f1-a86c-59ab72f255ec", - "de3b1388-1f0c-42f1-a86c-59ab72f255ec", - "de3b1388-1f0c-42f1-a86c-59ab72f255ec" + "patroni_port": 8888, + "pg_hba_conf": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" ], - "memory": "512M", - "orchestrator_opts": { - "swarm": { - "extra_labels": { - "traefik.enable": "true", - "traefik.tcp.routers.mydb.rule": "HostSNI(`mydb.example.com`)" + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], + "port": 5432, + "postgres_version": "17.6", + "postgresql_conf": { + "max_connections": 1000 + }, + "restore_config": { + "repository": { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab" }, - "extra_networks": [ - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - }, - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "f6b84a99-5e91-4203-be1e-131fe82e5984", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + }, + "restore_options": { + "set": "20250505-153628F", + "target": "123456", + "type": "xid" + }, + "source_database_id": "02f1a7db-fca8-4521-b57a-2a375c1ced51", + "source_database_name": "northwind", + "source_node_name": "n1" + }, + "source_node": "n1" + } + ], + "orchestrator_opts": { + "swarm": { + "extra_labels": { + "traefik.enable": "true", + "traefik.tcp.routers.mydb.rule": "HostSNI(`mydb.example.com`)" + }, + "extra_networks": [ + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + }, + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + }, + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + } + ], + "extra_volumes": [ + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + }, + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + }, + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + } + ] + } + }, + "patroni_port": 8888, + "pg_hba_conf": [ + "hostssl all myapp_user 203.0.113.0/24 scram-sha-256", + "hostssl all alice 0.0.0.0/0 cert clientcert=verify-full map=ssl_users" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], + "port": 5432, + "postgres_version": "17.6", + "postgresql_conf": { + "max_connections": 1000 + }, + "restore_config": { + "repository": { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "f6b84a99-5e91-4203-be1e-131fe82e5984", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + }, + "restore_options": { + "set": "20250505-153628F", + "target": "123456", + "type": "xid" + }, + "source_database_id": "02f1a7db-fca8-4521-b57a-2a375c1ced51", + "source_database_name": "northwind", + "source_node_name": "n1" + }, + "scripts": { + "post_database_create": [ + "ALTER DEFAULT PRIVILEGES FOR ROLE admin GRANT USAGE ON SCHEMAS TO app", + "ALTER DEFAULT PRIVILEGES FOR ROLE admin GRANT ALL PRIVILEGES ON TABLES TO app", + "ALTER DEFAULT PRIVILEGES FOR ROLE admin GRANT ALL PRIVILEGES ON SEQUENCES TO app" + ], + "post_init": [ + "CREATE ROLE accounting_admin NOLOGIN" + ] + }, + "services": [ + { + "config": { + "llm_model": "gpt-4", + "llm_provider": "openai", + "openai_api_key": "sk-..." + }, + "connect_as": "app", + "cpus": "500m", + "database_connection": { + "target_nodes": [ + "n1", + "n2" + ], + "target_session_attrs": "primary" + }, + "host_ids": [ + "de3b1388-1f0c-42f1-a86c-59ab72f255ec", + "de3b1388-1f0c-42f1-a86c-59ab72f255ec" + ], + "memory": "512M", + "orchestrator_opts": { + "swarm": { + "extra_labels": { + "traefik.enable": "true", + "traefik.tcp.routers.mydb.rule": "HostSNI(`mydb.example.com`)" + }, + "extra_networks": [ + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + }, + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { "com.docker.network.endpoint.expose": "true" }, "id": "traefik-public" @@ -12457,7 +12980,6 @@ "target_session_attrs": "primary" }, "host_ids": [ - "de3b1388-1f0c-42f1-a86c-59ab72f255ec", "de3b1388-1f0c-42f1-a86c-59ab72f255ec", "de3b1388-1f0c-42f1-a86c-59ab72f255ec" ], @@ -12520,84 +13042,242 @@ "service_id": "analytics-service", "service_type": "rag", "version": "latest" - } - ], - "spock_version": "5" - }, - "required": [ - "database_name", - "nodes" - ] - }, - "DatabaseSpec2": { - "type": "object", - "properties": { - "backup_config": { - "$ref": "#/components/schemas/BackupConfigSpec" - }, - "cpus": { - "type": "string", - "description": "The number of CPUs to allocate for the database and to use for tuning Postgres. Defaults to the number of available CPUs on the host. Can include an SI suffix, e.g. '500m' for 500 millicpus. Whether this limit is enforced depends on the orchestrator.", - "example": "500m", - "pattern": "^[0-9]+(\\.[0-9]{1,3}|m)?$" - }, - "database_name": { - "type": "string", - "description": "The name of the Postgres database.", - "example": "northwind", - "minLength": 1, - "maxLength": 31 - }, - "database_users": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DatabaseUserSpec" }, - "description": "The users to create for this database.", - "example": [ - { - "attributes": [ - "LOGIN", - "CREATEDB", - "CREATEROLE" - ], - "db_owner": true, - "password": "secret", - "roles": [ - "pgedge_superuser" - ], - "username": "admin" + { + "config": { + "llm_model": "gpt-4", + "llm_provider": "openai", + "openai_api_key": "sk-..." }, - { - "attributes": [ - "LOGIN", - "CREATEDB", - "CREATEROLE" - ], - "db_owner": true, - "password": "secret", - "roles": [ - "pgedge_superuser" + "connect_as": "app", + "cpus": "500m", + "database_connection": { + "target_nodes": [ + "n1", + "n2" ], - "username": "admin" + "target_session_attrs": "primary" }, - { - "attributes": [ - "LOGIN", - "CREATEDB", - "CREATEROLE" - ], - "db_owner": true, - "password": "secret", - "roles": [ - "pgedge_superuser" - ], - "username": "admin" - } - ], - "maxItems": 16 - }, - "memory": { + "host_ids": [ + "de3b1388-1f0c-42f1-a86c-59ab72f255ec", + "de3b1388-1f0c-42f1-a86c-59ab72f255ec" + ], + "memory": "512M", + "orchestrator_opts": { + "swarm": { + "extra_labels": { + "traefik.enable": "true", + "traefik.tcp.routers.mydb.rule": "HostSNI(`mydb.example.com`)" + }, + "extra_networks": [ + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + }, + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + }, + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + } + ], + "extra_volumes": [ + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + }, + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + }, + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + } + ] + } + }, + "port": 0, + "service_id": "analytics-service", + "service_type": "rag", + "version": "latest" + }, + { + "config": { + "llm_model": "gpt-4", + "llm_provider": "openai", + "openai_api_key": "sk-..." + }, + "connect_as": "app", + "cpus": "500m", + "database_connection": { + "target_nodes": [ + "n1", + "n2" + ], + "target_session_attrs": "primary" + }, + "host_ids": [ + "de3b1388-1f0c-42f1-a86c-59ab72f255ec", + "de3b1388-1f0c-42f1-a86c-59ab72f255ec" + ], + "memory": "512M", + "orchestrator_opts": { + "swarm": { + "extra_labels": { + "traefik.enable": "true", + "traefik.tcp.routers.mydb.rule": "HostSNI(`mydb.example.com`)" + }, + "extra_networks": [ + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + }, + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + }, + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + } + ], + "extra_volumes": [ + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + }, + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + }, + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + } + ] + } + }, + "port": 0, + "service_id": "analytics-service", + "service_type": "rag", + "version": "latest" + } + ], + "spock_version": "5" + }, + "required": [ + "database_name", + "nodes" + ] + }, + "DatabaseSpec2": { + "type": "object", + "properties": { + "backup_config": { + "$ref": "#/components/schemas/BackupConfigSpec" + }, + "cpus": { + "type": "string", + "description": "The number of CPUs to allocate for the database and to use for tuning Postgres. Defaults to the number of available CPUs on the host. Can include an SI suffix, e.g. '500m' for 500 millicpus. Whether this limit is enforced depends on the orchestrator.", + "example": "500m", + "pattern": "^[0-9]+(\\.[0-9]{1,3}|m)?$" + }, + "database_name": { + "type": "string", + "description": "The name of the Postgres database.", + "example": "northwind", + "minLength": 1, + "maxLength": 31 + }, + "database_users": { + "type": "array", + "items": { + "$ref": "#/components/schemas/DatabaseUserSpec" + }, + "description": "The users to create for this database.", + "example": [ + { + "attributes": [ + "LOGIN", + "CREATEDB", + "CREATEROLE" + ], + "db_owner": true, + "password": "secret", + "roles": [ + "pgedge_superuser" + ], + "username": "admin" + }, + { + "attributes": [ + "LOGIN", + "CREATEDB", + "CREATEROLE" + ], + "db_owner": true, + "password": "secret", + "roles": [ + "pgedge_superuser" + ], + "username": "admin" + }, + { + "attributes": [ + "LOGIN", + "CREATEDB", + "CREATEROLE" + ], + "db_owner": true, + "password": "secret", + "roles": [ + "pgedge_superuser" + ], + "username": "admin" + } + ], + "maxItems": 16 + }, + "memory": { "type": "string", "description": "The amount of memory in SI or IEC notation to allocate for the database and to use for tuning Postgres. Defaults to the total available memory on the host. Whether this limit is enforced depends on the orchestrator.", "example": "500M", @@ -12764,6 +13444,12 @@ } }, "patroni_port": 8888, + "pg_hba_conf": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], "port": 5432, "postgres_version": "17.6", "postgresql_conf": { @@ -12955,6 +13641,12 @@ } }, "patroni_port": 8888, + "pg_hba_conf": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], "port": 5432, "postgres_version": "17.6", "postgresql_conf": { @@ -12991,38 +13683,258 @@ "source_node_name": "n1" }, "source_node": "n1" - } - ], - "minItems": 1, - "maxItems": 9 - }, - "orchestrator_opts": { - "$ref": "#/components/schemas/OrchestratorOpts" - }, - "patroni_port": { - "type": "integer", - "description": "The port used by Patroni for this database. If the port is 0, each instance will be assigned a random port. NOTE: This field is not currently supported for Docker Swarm.", - "example": 8888, - "format": "int64", - "minimum": 0, - "maximum": 65535 - }, - "port": { - "type": "integer", - "description": "The port used by the Postgres database. If the port is 0, each instance will be assigned a random port. If the port is unspecified, the database will not be exposed on any port, dependent on orchestrator support for that feature.", - "example": 5432, - "format": "int64", - "minimum": 0, - "maximum": 65535 - }, - "postgres_version": { - "type": "string", - "description": "The Postgres version in 'major.minor' format.", - "example": "17.6", - "pattern": "^\\d{2}\\.\\d{1,2}$" - }, - "postgresql_conf": { - "type": "object", + }, + { + "backup_config": { + "repositories": [ + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + }, + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + }, + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + } + ], + "schedules": [ + { + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" + }, + { + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" + }, + { + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" + } + ] + }, + "cpus": "500m", + "host_ids": [ + "76f9b8c0-4958-11f0-a489-3bb29577c696", + "76f9b8c0-4958-11f0-a489-3bb29577c696", + "76f9b8c0-4958-11f0-a489-3bb29577c696" + ], + "memory": "500M", + "name": "n1", + "orchestrator_opts": { + "swarm": { + "extra_labels": { + "traefik.enable": "true", + "traefik.tcp.routers.mydb.rule": "HostSNI(`mydb.example.com`)" + }, + "extra_networks": [ + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + }, + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + }, + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + } + ], + "extra_volumes": [ + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + }, + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + }, + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + } + ] + } + }, + "patroni_port": 8888, + "pg_hba_conf": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], + "port": 5432, + "postgres_version": "17.6", + "postgresql_conf": { + "max_connections": 1000 + }, + "restore_config": { + "repository": { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + }, + "restore_options": { + "set": "20250505-153628F", + "target": "123456", + "type": "xid" + }, + "source_database_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "source_database_name": "northwind", + "source_node_name": "n1" + }, + "source_node": "n1" + } + ], + "minItems": 1, + "maxItems": 9 + }, + "orchestrator_opts": { + "$ref": "#/components/schemas/OrchestratorOpts" + }, + "patroni_port": { + "type": "integer", + "description": "The port used by Patroni for this database. If the port is 0, each instance will be assigned a random port. NOTE: This field is not currently supported for Docker Swarm.", + "example": 8888, + "format": "int64", + "minimum": 0, + "maximum": 65535 + }, + "pg_hba_conf": { + "type": "array", + "items": { + "type": "string", + "example": "Est asperiores quis in sunt dignissimos." + }, + "description": "Additional pg_hba.conf entries, one rule per array element. Inserted between control-plane's system-user rules and its catch-all, so they cannot affect control-plane-internal connectivity (Patroni, replication, health checks). Node-level pg_hba_conf entries are prepended to these.", + "example": [ + "hostssl all myapp_user 203.0.113.0/24 scram-sha-256", + "hostssl all alice 0.0.0.0/0 cert clientcert=verify-full map=ssl_users" + ] + }, + "pg_ident_conf": { + "type": "array", + "items": { + "type": "string", + "example": "Cupiditate molestiae." + }, + "description": "Additional pg_ident.conf entries, one mapping per array element. Purely additive; control-plane writes no pg_ident entries of its own. The primary use case is cert auth with map= translating certificate CNs to PostgreSQL usernames.", + "example": [ + "ssl_users CN=alice,O=example alice" + ] + }, + "port": { + "type": "integer", + "description": "The port used by the Postgres database. If the port is 0, each instance will be assigned a random port. If the port is unspecified, the database will not be exposed on any port, dependent on orchestrator support for that feature.", + "example": 5432, + "format": "int64", + "minimum": 0, + "maximum": 65535 + }, + "postgres_version": { + "type": "string", + "description": "The Postgres version in 'major.minor' format.", + "example": "17.6", + "pattern": "^\\d{2}\\.\\d{1,2}$" + }, + "postgresql_conf": { + "type": "object", "description": "Additional postgresql.conf settings. Will be merged with the settings provided by control-plane.", "example": { "max_connections": 1000 @@ -13658,197 +14570,12 @@ } }, "patroni_port": 8888, - "port": 5432, - "postgres_version": "17.6", - "postgresql_conf": { - "max_connections": 1000 - }, - "restore_config": { - "repository": { - "azure_account": "pgedge-backups", - "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "azure_endpoint": "blob.core.usgovcloudapi.net", - "azure_key": "YXpLZXk=", - "base_path": "/backups", - "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab" - }, - "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "gcs_endpoint": "localhost", - "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", - "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "s3_endpoint": "s3.us-east-1.amazonaws.com", - "s3_key": "AKIAIOSFODNN7EXAMPLE", - "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - "s3_region": "us-east-1", - "type": "s3" - }, - "restore_options": { - "set": "20250505-153628F", - "target": "123456", - "type": "xid" - }, - "source_database_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "source_database_name": "northwind", - "source_node_name": "n1" - }, - "source_node": "n1" - }, - { - "backup_config": { - "repositories": [ - { - "azure_account": "pgedge-backups", - "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "azure_endpoint": "blob.core.usgovcloudapi.net", - "azure_key": "YXpLZXk=", - "base_path": "/backups", - "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", - "storage-upload-chunk-size": "5MiB" - }, - "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "gcs_endpoint": "localhost", - "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", - "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "retention_full": 2, - "retention_full_type": "count", - "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "s3_endpoint": "s3.us-east-1.amazonaws.com", - "s3_key": "AKIAIOSFODNN7EXAMPLE", - "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - "s3_region": "us-east-1", - "type": "s3" - }, - { - "azure_account": "pgedge-backups", - "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "azure_endpoint": "blob.core.usgovcloudapi.net", - "azure_key": "YXpLZXk=", - "base_path": "/backups", - "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", - "storage-upload-chunk-size": "5MiB" - }, - "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "gcs_endpoint": "localhost", - "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", - "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "retention_full": 2, - "retention_full_type": "count", - "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "s3_endpoint": "s3.us-east-1.amazonaws.com", - "s3_key": "AKIAIOSFODNN7EXAMPLE", - "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - "s3_region": "us-east-1", - "type": "s3" - }, - { - "azure_account": "pgedge-backups", - "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "azure_endpoint": "blob.core.usgovcloudapi.net", - "azure_key": "YXpLZXk=", - "base_path": "/backups", - "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", - "storage-upload-chunk-size": "5MiB" - }, - "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "gcs_endpoint": "localhost", - "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", - "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "retention_full": 2, - "retention_full_type": "count", - "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "s3_endpoint": "s3.us-east-1.amazonaws.com", - "s3_key": "AKIAIOSFODNN7EXAMPLE", - "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - "s3_region": "us-east-1", - "type": "s3" - } - ], - "schedules": [ - { - "cron_expression": "0 6 * * ?", - "id": "daily-full-backup", - "type": "full" - }, - { - "cron_expression": "0 6 * * ?", - "id": "daily-full-backup", - "type": "full" - }, - { - "cron_expression": "0 6 * * ?", - "id": "daily-full-backup", - "type": "full" - } - ] - }, - "cpus": "500m", - "host_ids": [ - "76f9b8c0-4958-11f0-a489-3bb29577c696", - "76f9b8c0-4958-11f0-a489-3bb29577c696", - "76f9b8c0-4958-11f0-a489-3bb29577c696" - ], - "memory": "500M", - "name": "n1", - "orchestrator_opts": { - "swarm": { - "extra_labels": { - "traefik.enable": "true", - "traefik.tcp.routers.mydb.rule": "HostSNI(`mydb.example.com`)" - }, - "extra_networks": [ - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - }, - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - }, - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - } - ], - "extra_volumes": [ - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - }, - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - }, - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - } - ] - } - }, - "patroni_port": 8888, + "pg_hba_conf": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], "port": 5432, "postgres_version": "17.6", "postgresql_conf": { @@ -13942,6 +14669,13 @@ } }, "patroni_port": 8888, + "pg_hba_conf": [ + "hostssl all myapp_user 203.0.113.0/24 scram-sha-256", + "hostssl all alice 0.0.0.0/0 cert clientcert=verify-full map=ssl_users" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], "port": 5432, "postgres_version": "17.6", "postgresql_conf": { @@ -14548,6 +15282,12 @@ } }, "patroni_port": 8888, + "pg_hba_conf": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], "port": 5432, "postgres_version": "17.6", "postgresql_conf": { @@ -14584,248 +15324,81 @@ "source_node_name": "n1" }, "source_node": "n1" - }, - { - "backup_config": { - "repositories": [ - { - "azure_account": "pgedge-backups", - "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "azure_endpoint": "blob.core.usgovcloudapi.net", - "azure_key": "YXpLZXk=", - "base_path": "/backups", - "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", - "storage-upload-chunk-size": "5MiB" - }, - "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "gcs_endpoint": "localhost", - "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", - "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "retention_full": 2, - "retention_full_type": "count", - "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "s3_endpoint": "s3.us-east-1.amazonaws.com", - "s3_key": "AKIAIOSFODNN7EXAMPLE", - "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - "s3_region": "us-east-1", - "type": "s3" - }, - { - "azure_account": "pgedge-backups", - "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "azure_endpoint": "blob.core.usgovcloudapi.net", - "azure_key": "YXpLZXk=", - "base_path": "/backups", - "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", - "storage-upload-chunk-size": "5MiB" - }, - "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "gcs_endpoint": "localhost", - "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", - "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "retention_full": 2, - "retention_full_type": "count", - "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "s3_endpoint": "s3.us-east-1.amazonaws.com", - "s3_key": "AKIAIOSFODNN7EXAMPLE", - "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - "s3_region": "us-east-1", - "type": "s3" - }, - { - "azure_account": "pgedge-backups", - "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "azure_endpoint": "blob.core.usgovcloudapi.net", - "azure_key": "YXpLZXk=", - "base_path": "/backups", - "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", - "storage-upload-chunk-size": "5MiB" - }, - "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "gcs_endpoint": "localhost", - "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", - "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "retention_full": 2, - "retention_full_type": "count", - "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "s3_endpoint": "s3.us-east-1.amazonaws.com", - "s3_key": "AKIAIOSFODNN7EXAMPLE", - "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - "s3_region": "us-east-1", - "type": "s3" - } - ], - "schedules": [ - { - "cron_expression": "0 6 * * ?", - "id": "daily-full-backup", - "type": "full" - }, - { - "cron_expression": "0 6 * * ?", - "id": "daily-full-backup", - "type": "full" - }, - { - "cron_expression": "0 6 * * ?", - "id": "daily-full-backup", - "type": "full" - } - ] - }, - "cpus": "500m", - "host_ids": [ - "76f9b8c0-4958-11f0-a489-3bb29577c696", - "76f9b8c0-4958-11f0-a489-3bb29577c696" - ], - "memory": "500M", - "name": "n1", - "orchestrator_opts": { - "swarm": { - "extra_labels": { - "traefik.enable": "true", - "traefik.tcp.routers.mydb.rule": "HostSNI(`mydb.example.com`)" - }, - "extra_networks": [ - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - }, - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - }, - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - } - ], - "extra_volumes": [ - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - }, - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - }, - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - } - ] - } - }, - "patroni_port": 8888, - "port": 5432, - "postgres_version": "17.6", - "postgresql_conf": { - "max_connections": 1000 - }, - "restore_config": { - "repository": { - "azure_account": "pgedge-backups", - "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "azure_endpoint": "blob.core.usgovcloudapi.net", - "azure_key": "YXpLZXk=", - "base_path": "/backups", - "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab" - }, - "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "gcs_endpoint": "localhost", - "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", - "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "s3_endpoint": "s3.us-east-1.amazonaws.com", - "s3_key": "AKIAIOSFODNN7EXAMPLE", - "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - "s3_region": "us-east-1", - "type": "s3" - }, - "restore_options": { - "set": "20250505-153628F", - "target": "123456", - "type": "xid" - }, - "source_database_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "source_database_name": "northwind", - "source_node_name": "n1" - }, - "source_node": "n1" - } - ], - "minItems": 1, - "maxItems": 9 - }, - "orchestrator_opts": { - "$ref": "#/components/schemas/OrchestratorOpts" - }, - "patroni_port": { - "type": "integer", - "description": "The port used by Patroni for this database. If the port is 0, each instance will be assigned a random port. NOTE: This field is not currently supported for Docker Swarm.", - "example": 8888, - "format": "int64", - "minimum": 0, - "maximum": 65535 - }, - "port": { - "type": "integer", - "description": "The port used by the Postgres database. If the port is 0, each instance will be assigned a random port. If the port is unspecified, the database will not be exposed on any port, dependent on orchestrator support for that feature.", - "example": 5432, - "format": "int64", - "minimum": 0, - "maximum": 65535 - }, - "postgres_version": { - "type": "string", - "description": "The Postgres version in 'major.minor' format.", - "example": "17.6", - "pattern": "^\\d{2}\\.\\d{1,2}$" - }, - "postgresql_conf": { - "type": "object", - "description": "Additional postgresql.conf settings. Will be merged with the settings provided by control-plane.", - "example": { - "max_connections": 1000 - }, - "maxLength": 64, - "additionalProperties": true - }, - "restore_config": { - "$ref": "#/components/schemas/RestoreConfigSpec" - }, - "scripts": { - "$ref": "#/components/schemas/DatabaseScripts" - }, - "services": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ServiceSpec3" - }, - "description": "Service instances to run alongside the database (e.g., MCP servers).", - "example": [ + } + ], + "minItems": 1, + "maxItems": 9 + }, + "orchestrator_opts": { + "$ref": "#/components/schemas/OrchestratorOpts" + }, + "patroni_port": { + "type": "integer", + "description": "The port used by Patroni for this database. If the port is 0, each instance will be assigned a random port. NOTE: This field is not currently supported for Docker Swarm.", + "example": 8888, + "format": "int64", + "minimum": 0, + "maximum": 65535 + }, + "pg_hba_conf": { + "type": "array", + "items": { + "type": "string", + "example": "Nisi nihil corporis perspiciatis et." + }, + "description": "Additional pg_hba.conf entries, one rule per array element. Inserted between control-plane's system-user rules and its catch-all, so they cannot affect control-plane-internal connectivity (Patroni, replication, health checks). Node-level pg_hba_conf entries are prepended to these.", + "example": [ + "hostssl all myapp_user 203.0.113.0/24 scram-sha-256", + "hostssl all alice 0.0.0.0/0 cert clientcert=verify-full map=ssl_users" + ] + }, + "pg_ident_conf": { + "type": "array", + "items": { + "type": "string", + "example": "Blanditiis et accusamus repellat fuga occaecati." + }, + "description": "Additional pg_ident.conf entries, one mapping per array element. Purely additive; control-plane writes no pg_ident entries of its own. The primary use case is cert auth with map= translating certificate CNs to PostgreSQL usernames.", + "example": [ + "ssl_users CN=alice,O=example alice" + ] + }, + "port": { + "type": "integer", + "description": "The port used by the Postgres database. If the port is 0, each instance will be assigned a random port. If the port is unspecified, the database will not be exposed on any port, dependent on orchestrator support for that feature.", + "example": 5432, + "format": "int64", + "minimum": 0, + "maximum": 65535 + }, + "postgres_version": { + "type": "string", + "description": "The Postgres version in 'major.minor' format.", + "example": "17.6", + "pattern": "^\\d{2}\\.\\d{1,2}$" + }, + "postgresql_conf": { + "type": "object", + "description": "Additional postgresql.conf settings. Will be merged with the settings provided by control-plane.", + "example": { + "max_connections": 1000 + }, + "maxLength": 64, + "additionalProperties": true + }, + "restore_config": { + "$ref": "#/components/schemas/RestoreConfigSpec" + }, + "scripts": { + "$ref": "#/components/schemas/DatabaseScripts" + }, + "services": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ServiceSpec3" + }, + "description": "Service instances to run alongside the database (e.g., MCP servers).", + "example": [ { "config": { "llm_model": "gpt-4", @@ -15361,6 +15934,12 @@ } }, "patroni_port": 8888, + "pg_hba_conf": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], "port": 5432, "postgres_version": "17.6", "postgresql_conf": { @@ -15551,196 +16130,12 @@ } }, "patroni_port": 8888, - "port": 5432, - "postgres_version": "17.6", - "postgresql_conf": { - "max_connections": 1000 - }, - "restore_config": { - "repository": { - "azure_account": "pgedge-backups", - "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "azure_endpoint": "blob.core.usgovcloudapi.net", - "azure_key": "YXpLZXk=", - "base_path": "/backups", - "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab" - }, - "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "gcs_endpoint": "localhost", - "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", - "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "s3_endpoint": "s3.us-east-1.amazonaws.com", - "s3_key": "AKIAIOSFODNN7EXAMPLE", - "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - "s3_region": "us-east-1", - "type": "s3" - }, - "restore_options": { - "set": "20250505-153628F", - "target": "123456", - "type": "xid" - }, - "source_database_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "source_database_name": "northwind", - "source_node_name": "n1" - }, - "source_node": "n1" - }, - { - "backup_config": { - "repositories": [ - { - "azure_account": "pgedge-backups", - "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "azure_endpoint": "blob.core.usgovcloudapi.net", - "azure_key": "YXpLZXk=", - "base_path": "/backups", - "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", - "storage-upload-chunk-size": "5MiB" - }, - "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "gcs_endpoint": "localhost", - "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", - "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "retention_full": 2, - "retention_full_type": "count", - "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "s3_endpoint": "s3.us-east-1.amazonaws.com", - "s3_key": "AKIAIOSFODNN7EXAMPLE", - "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - "s3_region": "us-east-1", - "type": "s3" - }, - { - "azure_account": "pgedge-backups", - "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "azure_endpoint": "blob.core.usgovcloudapi.net", - "azure_key": "YXpLZXk=", - "base_path": "/backups", - "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", - "storage-upload-chunk-size": "5MiB" - }, - "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "gcs_endpoint": "localhost", - "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", - "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "retention_full": 2, - "retention_full_type": "count", - "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "s3_endpoint": "s3.us-east-1.amazonaws.com", - "s3_key": "AKIAIOSFODNN7EXAMPLE", - "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - "s3_region": "us-east-1", - "type": "s3" - }, - { - "azure_account": "pgedge-backups", - "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "azure_endpoint": "blob.core.usgovcloudapi.net", - "azure_key": "YXpLZXk=", - "base_path": "/backups", - "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", - "storage-upload-chunk-size": "5MiB" - }, - "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "gcs_endpoint": "localhost", - "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", - "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "retention_full": 2, - "retention_full_type": "count", - "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "s3_endpoint": "s3.us-east-1.amazonaws.com", - "s3_key": "AKIAIOSFODNN7EXAMPLE", - "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - "s3_region": "us-east-1", - "type": "s3" - } - ], - "schedules": [ - { - "cron_expression": "0 6 * * ?", - "id": "daily-full-backup", - "type": "full" - }, - { - "cron_expression": "0 6 * * ?", - "id": "daily-full-backup", - "type": "full" - }, - { - "cron_expression": "0 6 * * ?", - "id": "daily-full-backup", - "type": "full" - } - ] - }, - "cpus": "500m", - "host_ids": [ - "76f9b8c0-4958-11f0-a489-3bb29577c696", - "76f9b8c0-4958-11f0-a489-3bb29577c696" - ], - "memory": "500M", - "name": "n1", - "orchestrator_opts": { - "swarm": { - "extra_labels": { - "traefik.enable": "true", - "traefik.tcp.routers.mydb.rule": "HostSNI(`mydb.example.com`)" - }, - "extra_networks": [ - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - }, - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - }, - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - } - ], - "extra_volumes": [ - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - }, - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - }, - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - } - ] - } - }, - "patroni_port": 8888, + "pg_hba_conf": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], "port": 5432, "postgres_version": "17.6", "postgresql_conf": { @@ -15834,6 +16229,13 @@ } }, "patroni_port": 8888, + "pg_hba_conf": [ + "hostssl all myapp_user 203.0.113.0/24 scram-sha-256", + "hostssl all alice 0.0.0.0/0 cert clientcert=verify-full map=ssl_users" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], "port": 5432, "postgres_version": "17.6", "postgresql_conf": { @@ -15961,85 +16363,6 @@ "service_type": "rag", "version": "latest" }, - { - "config": { - "llm_model": "gpt-4", - "llm_provider": "openai", - "openai_api_key": "sk-..." - }, - "connect_as": "app", - "cpus": "500m", - "database_connection": { - "target_nodes": [ - "n1", - "n2" - ], - "target_session_attrs": "primary" - }, - "host_ids": [ - "76f9b8c0-4958-11f0-a489-3bb29577c696", - "76f9b8c0-4958-11f0-a489-3bb29577c696" - ], - "memory": "512M", - "orchestrator_opts": { - "swarm": { - "extra_labels": { - "traefik.enable": "true", - "traefik.tcp.routers.mydb.rule": "HostSNI(`mydb.example.com`)" - }, - "extra_networks": [ - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - }, - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - }, - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - } - ], - "extra_volumes": [ - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - }, - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - }, - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - } - ] - } - }, - "port": 0, - "service_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "service_type": "rag", - "version": "latest" - }, { "config": { "llm_model": "gpt-4", @@ -16361,196 +16684,12 @@ } }, "patroni_port": 8888, - "port": 5432, - "postgres_version": "17.6", - "postgresql_conf": { - "max_connections": 1000 - }, - "restore_config": { - "repository": { - "azure_account": "pgedge-backups", - "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "azure_endpoint": "blob.core.usgovcloudapi.net", - "azure_key": "YXpLZXk=", - "base_path": "/backups", - "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab" - }, - "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "gcs_endpoint": "localhost", - "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", - "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "s3_endpoint": "s3.us-east-1.amazonaws.com", - "s3_key": "AKIAIOSFODNN7EXAMPLE", - "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - "s3_region": "us-east-1", - "type": "s3" - }, - "restore_options": { - "set": "20250505-153628F", - "target": "123456", - "type": "xid" - }, - "source_database_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "source_database_name": "northwind", - "source_node_name": "n1" - }, - "source_node": "n1" - }, - { - "backup_config": { - "repositories": [ - { - "azure_account": "pgedge-backups", - "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "azure_endpoint": "blob.core.usgovcloudapi.net", - "azure_key": "YXpLZXk=", - "base_path": "/backups", - "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", - "storage-upload-chunk-size": "5MiB" - }, - "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "gcs_endpoint": "localhost", - "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", - "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "retention_full": 2, - "retention_full_type": "count", - "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "s3_endpoint": "s3.us-east-1.amazonaws.com", - "s3_key": "AKIAIOSFODNN7EXAMPLE", - "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - "s3_region": "us-east-1", - "type": "s3" - }, - { - "azure_account": "pgedge-backups", - "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "azure_endpoint": "blob.core.usgovcloudapi.net", - "azure_key": "YXpLZXk=", - "base_path": "/backups", - "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", - "storage-upload-chunk-size": "5MiB" - }, - "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "gcs_endpoint": "localhost", - "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", - "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "retention_full": 2, - "retention_full_type": "count", - "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "s3_endpoint": "s3.us-east-1.amazonaws.com", - "s3_key": "AKIAIOSFODNN7EXAMPLE", - "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - "s3_region": "us-east-1", - "type": "s3" - }, - { - "azure_account": "pgedge-backups", - "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "azure_endpoint": "blob.core.usgovcloudapi.net", - "azure_key": "YXpLZXk=", - "base_path": "/backups", - "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", - "storage-upload-chunk-size": "5MiB" - }, - "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "gcs_endpoint": "localhost", - "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", - "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "retention_full": 2, - "retention_full_type": "count", - "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "s3_endpoint": "s3.us-east-1.amazonaws.com", - "s3_key": "AKIAIOSFODNN7EXAMPLE", - "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - "s3_region": "us-east-1", - "type": "s3" - } - ], - "schedules": [ - { - "cron_expression": "0 6 * * ?", - "id": "daily-full-backup", - "type": "full" - }, - { - "cron_expression": "0 6 * * ?", - "id": "daily-full-backup", - "type": "full" - }, - { - "cron_expression": "0 6 * * ?", - "id": "daily-full-backup", - "type": "full" - } - ] - }, - "cpus": "500m", - "host_ids": [ - "76f9b8c0-4958-11f0-a489-3bb29577c696", - "76f9b8c0-4958-11f0-a489-3bb29577c696" - ], - "memory": "500M", - "name": "n1", - "orchestrator_opts": { - "swarm": { - "extra_labels": { - "traefik.enable": "true", - "traefik.tcp.routers.mydb.rule": "HostSNI(`mydb.example.com`)" - }, - "extra_networks": [ - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - }, - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - }, - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - } - ], - "extra_volumes": [ - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - }, - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - }, - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - } - ] - } - }, - "patroni_port": 8888, + "pg_hba_conf": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], "port": 5432, "postgres_version": "17.6", "postgresql_conf": { @@ -16603,6 +16742,29 @@ "minimum": 0, "maximum": 65535 }, + "pg_hba_conf": { + "type": "array", + "items": { + "type": "string", + "example": "Dignissimos voluptas vel earum eaque." + }, + "description": "Additional pg_hba.conf entries, one rule per array element. Inserted between control-plane's system-user rules and its catch-all, so they cannot affect control-plane-internal connectivity (Patroni, replication, health checks). Node-level pg_hba_conf entries are prepended to these.", + "example": [ + "hostssl all myapp_user 203.0.113.0/24 scram-sha-256", + "hostssl all alice 0.0.0.0/0 cert clientcert=verify-full map=ssl_users" + ] + }, + "pg_ident_conf": { + "type": "array", + "items": { + "type": "string", + "example": "Et minima ipsum ut impedit." + }, + "description": "Additional pg_ident.conf entries, one mapping per array element. Purely additive; control-plane writes no pg_ident entries of its own. The primary use case is cert auth with map= translating certificate CNs to PostgreSQL usernames.", + "example": [ + "ssl_users CN=alice,O=example alice" + ] + }, "port": { "type": "integer", "description": "The port used by the Postgres database. If the port is 0, each instance will be assigned a random port. If the port is unspecified, the database will not be exposed on any port, dependent on orchestrator support for that feature.", @@ -17253,6 +17415,12 @@ } }, "patroni_port": 8888, + "pg_hba_conf": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], "port": 5432, "postgres_version": "17.6", "postgresql_conf": { @@ -17443,6 +17611,12 @@ } }, "patroni_port": 8888, + "pg_hba_conf": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], "port": 5432, "postgres_version": "17.6", "postgresql_conf": { @@ -17479,32 +17653,228 @@ "source_node_name": "n1" }, "source_node": "n1" - } - ], - "orchestrator_opts": { - "swarm": { - "extra_labels": { - "traefik.enable": "true", - "traefik.tcp.routers.mydb.rule": "HostSNI(`mydb.example.com`)" - }, - "extra_networks": [ - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" + }, + { + "backup_config": { + "repositories": [ + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" }, - "id": "traefik-public" - }, - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + }, + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + } + ], + "schedules": [ + { + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" + }, + { + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" + }, + { + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" + } + ] + }, + "cpus": "500m", + "host_ids": [ + "76f9b8c0-4958-11f0-a489-3bb29577c696", + "76f9b8c0-4958-11f0-a489-3bb29577c696" + ], + "memory": "500M", + "name": "n1", + "orchestrator_opts": { + "swarm": { + "extra_labels": { + "traefik.enable": "true", + "traefik.tcp.routers.mydb.rule": "HostSNI(`mydb.example.com`)" + }, + "extra_networks": [ + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + }, + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + }, + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + } + ], + "extra_volumes": [ + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + }, + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + }, + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + } + ] + } + }, + "patroni_port": 8888, + "pg_hba_conf": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], + "port": 5432, + "postgres_version": "17.6", + "postgresql_conf": { + "max_connections": 1000 + }, + "restore_config": { + "repository": { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + }, + "restore_options": { + "set": "20250505-153628F", + "target": "123456", + "type": "xid" + }, + "source_database_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "source_database_name": "northwind", + "source_node_name": "n1" + }, + "source_node": "n1" + } + ], + "orchestrator_opts": { + "swarm": { + "extra_labels": { + "traefik.enable": "true", + "traefik.tcp.routers.mydb.rule": "HostSNI(`mydb.example.com`)" + }, + "extra_networks": [ + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + }, + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" }, "id": "traefik-public" }, @@ -17536,6 +17906,13 @@ } }, "patroni_port": 8888, + "pg_hba_conf": [ + "hostssl all myapp_user 203.0.113.0/24 scram-sha-256", + "hostssl all alice 0.0.0.0/0 cert clientcert=verify-full map=ssl_users" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], "port": 5432, "postgres_version": "17.6", "postgresql_conf": { @@ -18142,6 +18519,12 @@ } }, "patroni_port": 8888, + "pg_hba_conf": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], "port": 5432, "postgres_version": "17.6", "postgresql_conf": { @@ -18194,6 +18577,29 @@ "minimum": 0, "maximum": 65535 }, + "pg_hba_conf": { + "type": "array", + "items": { + "type": "string", + "example": "Nobis quam sequi." + }, + "description": "Additional pg_hba.conf entries, one rule per array element. Inserted between control-plane's system-user rules and its catch-all, so they cannot affect control-plane-internal connectivity (Patroni, replication, health checks). Node-level pg_hba_conf entries are prepended to these.", + "example": [ + "hostssl all myapp_user 203.0.113.0/24 scram-sha-256", + "hostssl all alice 0.0.0.0/0 cert clientcert=verify-full map=ssl_users" + ] + }, + "pg_ident_conf": { + "type": "array", + "items": { + "type": "string", + "example": "Aliquid porro dolorum natus sunt harum magnam." + }, + "description": "Additional pg_ident.conf entries, one mapping per array element. Purely additive; control-plane writes no pg_ident entries of its own. The primary use case is cert auth with map= translating certificate CNs to PostgreSQL usernames.", + "example": [ + "ssl_users CN=alice,O=example alice" + ] + }, "port": { "type": "integer", "description": "The port used by the Postgres database. If the port is 0, each instance will be assigned a random port. If the port is unspecified, the database will not be exposed on any port, dependent on orchestrator support for that feature.", @@ -18463,51 +18869,129 @@ "service_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", "service_type": "rag", "version": "latest" - } - ] - }, - "spock_version": { - "type": "string", - "description": "The major version of the Spock extension.", - "example": "5", - "pattern": "^\\d{1}$" - } - }, - "example": { - "backup_config": { - "repositories": [ - { - "azure_account": "pgedge-backups", - "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "azure_endpoint": "blob.core.usgovcloudapi.net", - "azure_key": "YXpLZXk=", - "base_path": "/backups", - "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", - "storage-upload-chunk-size": "5MiB" - }, - "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "gcs_endpoint": "localhost", - "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", - "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "retention_full": 2, - "retention_full_type": "count", - "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "s3_endpoint": "s3.us-east-1.amazonaws.com", - "s3_key": "AKIAIOSFODNN7EXAMPLE", - "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - "s3_region": "us-east-1", - "type": "s3" }, { - "azure_account": "pgedge-backups", - "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "azure_endpoint": "blob.core.usgovcloudapi.net", - "azure_key": "YXpLZXk=", - "base_path": "/backups", - "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", - "storage-upload-chunk-size": "5MiB" + "config": { + "llm_model": "gpt-4", + "llm_provider": "openai", + "openai_api_key": "sk-..." + }, + "connect_as": "app", + "cpus": "500m", + "database_connection": { + "target_nodes": [ + "n1", + "n2" + ], + "target_session_attrs": "primary" + }, + "host_ids": [ + "76f9b8c0-4958-11f0-a489-3bb29577c696" + ], + "memory": "512M", + "orchestrator_opts": { + "swarm": { + "extra_labels": { + "traefik.enable": "true", + "traefik.tcp.routers.mydb.rule": "HostSNI(`mydb.example.com`)" + }, + "extra_networks": [ + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + }, + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + }, + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + } + ], + "extra_volumes": [ + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + }, + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + }, + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + } + ] + } + }, + "port": 0, + "service_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "service_type": "rag", + "version": "latest" + } + ] + }, + "spock_version": { + "type": "string", + "description": "The major version of the Spock extension.", + "example": "5", + "pattern": "^\\d{1}$" + } + }, + "example": { + "backup_config": { + "repositories": [ + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + }, + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" }, "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", "gcs_endpoint": "localhost", @@ -18762,6 +19246,12 @@ } }, "patroni_port": 8888, + "pg_hba_conf": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], "port": 5432, "postgres_version": "17.6", "postgresql_conf": { @@ -18855,6 +19345,13 @@ } }, "patroni_port": 8888, + "pg_hba_conf": [ + "hostssl all myapp_user 203.0.113.0/24 scram-sha-256", + "hostssl all alice 0.0.0.0/0 cert clientcert=verify-full map=ssl_users" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], "port": 5432, "postgres_version": "17.6", "postgresql_conf": { @@ -18981,84 +19478,6 @@ "service_type": "rag", "version": "latest" }, - { - "config": { - "llm_model": "gpt-4", - "llm_provider": "openai", - "openai_api_key": "sk-..." - }, - "connect_as": "app", - "cpus": "500m", - "database_connection": { - "target_nodes": [ - "n1", - "n2" - ], - "target_session_attrs": "primary" - }, - "host_ids": [ - "76f9b8c0-4958-11f0-a489-3bb29577c696" - ], - "memory": "512M", - "orchestrator_opts": { - "swarm": { - "extra_labels": { - "traefik.enable": "true", - "traefik.tcp.routers.mydb.rule": "HostSNI(`mydb.example.com`)" - }, - "extra_networks": [ - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - }, - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - }, - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - } - ], - "extra_volumes": [ - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - }, - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - }, - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - } - ] - } - }, - "port": 0, - "service_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "service_type": "rag", - "version": "latest" - }, { "config": { "llm_model": "gpt-4", @@ -19379,6 +19798,12 @@ } }, "patroni_port": 8888, + "pg_hba_conf": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], "port": 5432, "postgres_version": "17.6", "postgresql_conf": { @@ -19431,6 +19856,29 @@ "minimum": 0, "maximum": 65535 }, + "pg_hba_conf": { + "type": "array", + "items": { + "type": "string", + "example": "Nisi eveniet sit dignissimos ducimus." + }, + "description": "Additional pg_hba.conf entries, one rule per array element. Inserted between control-plane's system-user rules and its catch-all, so they cannot affect control-plane-internal connectivity (Patroni, replication, health checks). Node-level pg_hba_conf entries are prepended to these.", + "example": [ + "hostssl all myapp_user 203.0.113.0/24 scram-sha-256", + "hostssl all alice 0.0.0.0/0 cert clientcert=verify-full map=ssl_users" + ] + }, + "pg_ident_conf": { + "type": "array", + "items": { + "type": "string", + "example": "Asperiores explicabo." + }, + "description": "Additional pg_ident.conf entries, one mapping per array element. Purely additive; control-plane writes no pg_ident entries of its own. The primary use case is cert auth with map= translating certificate CNs to PostgreSQL usernames.", + "example": [ + "ssl_users CN=alice,O=example alice" + ] + }, "port": { "type": "integer", "description": "The port used by the Postgres database. If the port is 0, each instance will be assigned a random port. If the port is unspecified, the database will not be exposed on any port, dependent on orchestrator support for that feature.", @@ -19624,49 +20072,207 @@ "service_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", "service_type": "rag", "version": "latest" - } - ] - }, - "spock_version": { - "type": "string", - "description": "The major version of the Spock extension.", - "example": "5", - "pattern": "^\\d{1}$" - } - }, - "example": { - "backup_config": { - "repositories": [ - { - "azure_account": "pgedge-backups", - "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "azure_endpoint": "blob.core.usgovcloudapi.net", - "azure_key": "YXpLZXk=", - "base_path": "/backups", - "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", - "storage-upload-chunk-size": "5MiB" - }, - "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "gcs_endpoint": "localhost", - "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", - "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "retention_full": 2, - "retention_full_type": "count", - "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "s3_endpoint": "s3.us-east-1.amazonaws.com", - "s3_key": "AKIAIOSFODNN7EXAMPLE", - "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - "s3_region": "us-east-1", - "type": "s3" }, { - "azure_account": "pgedge-backups", - "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "azure_endpoint": "blob.core.usgovcloudapi.net", - "azure_key": "YXpLZXk=", - "base_path": "/backups", - "custom_options": { + "config": { + "llm_model": "gpt-4", + "llm_provider": "openai", + "openai_api_key": "sk-..." + }, + "connect_as": "app", + "cpus": "500m", + "database_connection": { + "target_nodes": [ + "n1", + "n2" + ], + "target_session_attrs": "primary" + }, + "host_ids": [ + "76f9b8c0-4958-11f0-a489-3bb29577c696", + "76f9b8c0-4958-11f0-a489-3bb29577c696" + ], + "memory": "512M", + "orchestrator_opts": { + "swarm": { + "extra_labels": { + "traefik.enable": "true", + "traefik.tcp.routers.mydb.rule": "HostSNI(`mydb.example.com`)" + }, + "extra_networks": [ + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + }, + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + }, + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + } + ], + "extra_volumes": [ + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + }, + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + }, + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + } + ] + } + }, + "port": 0, + "service_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "service_type": "rag", + "version": "latest" + }, + { + "config": { + "llm_model": "gpt-4", + "llm_provider": "openai", + "openai_api_key": "sk-..." + }, + "connect_as": "app", + "cpus": "500m", + "database_connection": { + "target_nodes": [ + "n1", + "n2" + ], + "target_session_attrs": "primary" + }, + "host_ids": [ + "76f9b8c0-4958-11f0-a489-3bb29577c696", + "76f9b8c0-4958-11f0-a489-3bb29577c696" + ], + "memory": "512M", + "orchestrator_opts": { + "swarm": { + "extra_labels": { + "traefik.enable": "true", + "traefik.tcp.routers.mydb.rule": "HostSNI(`mydb.example.com`)" + }, + "extra_networks": [ + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + }, + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + }, + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + } + ], + "extra_volumes": [ + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + }, + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + }, + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + } + ] + } + }, + "port": 0, + "service_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "service_type": "rag", + "version": "latest" + } + ] + }, + "spock_version": { + "type": "string", + "description": "The major version of the Spock extension.", + "example": "5", + "pattern": "^\\d{1}$" + } + }, + "example": { + "backup_config": { + "repositories": [ + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + }, + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", "storage-upload-chunk-size": "5MiB" }, @@ -19923,6 +20529,12 @@ } }, "patroni_port": 8888, + "pg_hba_conf": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], "port": 5432, "postgres_version": "17.6", "postgresql_conf": { @@ -19959,36 +20571,232 @@ "source_node_name": "n1" }, "source_node": "n1" - } - ], - "orchestrator_opts": { - "swarm": { - "extra_labels": { - "traefik.enable": "true", - "traefik.tcp.routers.mydb.rule": "HostSNI(`mydb.example.com`)" - }, - "extra_networks": [ - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - }, - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" + }, + { + "backup_config": { + "repositories": [ + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" }, - "id": "traefik-public" - }, - { + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + }, + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + } + ], + "schedules": [ + { + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" + }, + { + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" + }, + { + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" + } + ] + }, + "cpus": "500m", + "host_ids": [ + "76f9b8c0-4958-11f0-a489-3bb29577c696", + "76f9b8c0-4958-11f0-a489-3bb29577c696" + ], + "memory": "500M", + "name": "n1", + "orchestrator_opts": { + "swarm": { + "extra_labels": { + "traefik.enable": "true", + "traefik.tcp.routers.mydb.rule": "HostSNI(`mydb.example.com`)" + }, + "extra_networks": [ + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + }, + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + }, + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + } + ], + "extra_volumes": [ + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + }, + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + }, + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + } + ] + } + }, + "patroni_port": 8888, + "pg_hba_conf": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], + "port": 5432, + "postgres_version": "17.6", + "postgresql_conf": { + "max_connections": 1000 + }, + "restore_config": { + "repository": { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + }, + "restore_options": { + "set": "20250505-153628F", + "target": "123456", + "type": "xid" + }, + "source_database_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "source_database_name": "northwind", + "source_node_name": "n1" + }, + "source_node": "n1" + } + ], + "orchestrator_opts": { + "swarm": { + "extra_labels": { + "traefik.enable": "true", + "traefik.tcp.routers.mydb.rule": "HostSNI(`mydb.example.com`)" + }, + "extra_networks": [ + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + }, + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + }, + { "aliases": [ "pg-db", "db-alias" @@ -20016,6 +20824,13 @@ } }, "patroni_port": 8888, + "pg_hba_conf": [ + "hostssl all myapp_user 203.0.113.0/24 scram-sha-256", + "hostssl all alice 0.0.0.0/0 cert clientcert=verify-full map=ssl_users" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], "port": 5432, "postgres_version": "17.6", "postgresql_conf": { @@ -20300,132 +21115,53 @@ "service_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", "service_type": "rag", "version": "latest" + } + ], + "spock_version": "5" + }, + "required": [ + "database_name", + "nodes" + ] + }, + "DatabaseSpec7": { + "type": "object", + "properties": { + "backup_config": { + "$ref": "#/components/schemas/BackupConfigSpec" + }, + "cpus": { + "type": "string", + "description": "The number of CPUs to allocate for the database and to use for tuning Postgres. Defaults to the number of available CPUs on the host. Can include an SI suffix, e.g. '500m' for 500 millicpus. Whether this limit is enforced depends on the orchestrator.", + "example": "500m", + "pattern": "^[0-9]+(\\.[0-9]{1,3}|m)?$" + }, + "database_name": { + "type": "string", + "description": "The name of the Postgres database.", + "example": "northwind", + "minLength": 1, + "maxLength": 31 + }, + "database_users": { + "type": "array", + "items": { + "$ref": "#/components/schemas/DatabaseUserSpec" }, - { - "config": { - "llm_model": "gpt-4", - "llm_provider": "openai", - "openai_api_key": "sk-..." - }, - "connect_as": "app", - "cpus": "500m", - "database_connection": { - "target_nodes": [ - "n1", - "n2" + "description": "The users to create for this database.", + "example": [ + { + "attributes": [ + "LOGIN", + "CREATEDB", + "CREATEROLE" ], - "target_session_attrs": "primary" - }, - "host_ids": [ - "76f9b8c0-4958-11f0-a489-3bb29577c696", - "76f9b8c0-4958-11f0-a489-3bb29577c696" - ], - "memory": "512M", - "orchestrator_opts": { - "swarm": { - "extra_labels": { - "traefik.enable": "true", - "traefik.tcp.routers.mydb.rule": "HostSNI(`mydb.example.com`)" - }, - "extra_networks": [ - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - }, - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - }, - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - } - ], - "extra_volumes": [ - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - }, - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - }, - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - } - ] - } - }, - "port": 0, - "service_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "service_type": "rag", - "version": "latest" - } - ], - "spock_version": "5" - }, - "required": [ - "database_name", - "nodes" - ] - }, - "DatabaseSpec7": { - "type": "object", - "properties": { - "backup_config": { - "$ref": "#/components/schemas/BackupConfigSpec" - }, - "cpus": { - "type": "string", - "description": "The number of CPUs to allocate for the database and to use for tuning Postgres. Defaults to the number of available CPUs on the host. Can include an SI suffix, e.g. '500m' for 500 millicpus. Whether this limit is enforced depends on the orchestrator.", - "example": "500m", - "pattern": "^[0-9]+(\\.[0-9]{1,3}|m)?$" - }, - "database_name": { - "type": "string", - "description": "The name of the Postgres database.", - "example": "northwind", - "minLength": 1, - "maxLength": 31 - }, - "database_users": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DatabaseUserSpec" - }, - "description": "The users to create for this database.", - "example": [ - { - "attributes": [ - "LOGIN", - "CREATEDB", - "CREATEROLE" - ], - "db_owner": false, - "password": "secret", - "roles": [ - "pgedge_superuser" - ], - "username": "admin" + "db_owner": false, + "password": "secret", + "roles": [ + "pgedge_superuser" + ], + "username": "admin" }, { "attributes": [ @@ -20622,6 +21358,12 @@ } }, "patroni_port": 8888, + "pg_hba_conf": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], "port": 5432, "postgres_version": "17.6", "postgresql_conf": { @@ -20812,6 +21554,12 @@ } }, "patroni_port": 8888, + "pg_hba_conf": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], "port": 5432, "postgres_version": "17.6", "postgresql_conf": { @@ -20848,117 +21596,144 @@ "source_node_name": "n1" }, "source_node": "n1" - } - ], - "minItems": 1, - "maxItems": 9 - }, - "orchestrator_opts": { - "$ref": "#/components/schemas/OrchestratorOpts" - }, - "patroni_port": { - "type": "integer", - "description": "The port used by Patroni for this database. If the port is 0, each instance will be assigned a random port. NOTE: This field is not currently supported for Docker Swarm.", - "example": 8888, - "format": "int64", - "minimum": 0, - "maximum": 65535 - }, - "port": { - "type": "integer", - "description": "The port used by the Postgres database. If the port is 0, each instance will be assigned a random port. If the port is unspecified, the database will not be exposed on any port, dependent on orchestrator support for that feature.", - "example": 5432, - "format": "int64", - "minimum": 0, - "maximum": 65535 - }, - "postgres_version": { - "type": "string", - "description": "The Postgres version in 'major.minor' format.", - "example": "17.6", - "pattern": "^\\d{2}\\.\\d{1,2}$" - }, - "postgresql_conf": { - "type": "object", - "description": "Additional postgresql.conf settings. Will be merged with the settings provided by control-plane.", - "example": { - "max_connections": 1000 - }, - "maxLength": 64, - "additionalProperties": true - }, - "restore_config": { - "$ref": "#/components/schemas/RestoreConfigSpec" - }, - "scripts": { - "$ref": "#/components/schemas/DatabaseScripts" - }, - "services": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ServiceSpec7" - }, - "description": "Service instances to run alongside the database (e.g., MCP servers).", - "example": [ + }, { - "config": { - "llm_model": "gpt-4", - "llm_provider": "openai", - "openai_api_key": "sk-..." - }, - "connect_as": "app", - "cpus": "500m", - "database_connection": { - "target_nodes": [ - "n1", - "n2" - ], - "target_session_attrs": "primary" - }, - "host_ids": [ - "76f9b8c0-4958-11f0-a489-3bb29577c696", - "76f9b8c0-4958-11f0-a489-3bb29577c696" - ], - "memory": "512M", - "orchestrator_opts": { - "swarm": { - "extra_labels": { - "traefik.enable": "true", - "traefik.tcp.routers.mydb.rule": "HostSNI(`mydb.example.com`)" - }, - "extra_networks": [ - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" + "backup_config": { + "repositories": [ + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" }, - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + }, + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" }, - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - } - ], - "extra_volumes": [ + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + }, + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + } + ], + "schedules": [ + { + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" + }, + { + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" + }, + { + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" + } + ] + }, + "cpus": "500m", + "host_ids": [ + "76f9b8c0-4958-11f0-a489-3bb29577c696", + "76f9b8c0-4958-11f0-a489-3bb29577c696" + ], + "memory": "500M", + "name": "n1", + "orchestrator_opts": { + "swarm": { + "extra_labels": { + "traefik.enable": "true", + "traefik.tcp.routers.mydb.rule": "HostSNI(`mydb.example.com`)" + }, + "extra_networks": [ + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + }, + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + }, + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + } + ], + "extra_volumes": [ { "destination_path": "/backups/container", "host_path": "/Users/user/backups/host" @@ -20974,11 +21749,124 @@ ] } }, - "port": 0, - "service_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "service_type": "rag", - "version": "latest" - }, + "patroni_port": 8888, + "pg_hba_conf": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], + "port": 5432, + "postgres_version": "17.6", + "postgresql_conf": { + "max_connections": 1000 + }, + "restore_config": { + "repository": { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + }, + "restore_options": { + "set": "20250505-153628F", + "target": "123456", + "type": "xid" + }, + "source_database_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "source_database_name": "northwind", + "source_node_name": "n1" + }, + "source_node": "n1" + } + ], + "minItems": 1, + "maxItems": 9 + }, + "orchestrator_opts": { + "$ref": "#/components/schemas/OrchestratorOpts" + }, + "patroni_port": { + "type": "integer", + "description": "The port used by Patroni for this database. If the port is 0, each instance will be assigned a random port. NOTE: This field is not currently supported for Docker Swarm.", + "example": 8888, + "format": "int64", + "minimum": 0, + "maximum": 65535 + }, + "pg_hba_conf": { + "type": "array", + "items": { + "type": "string", + "example": "Et vero dolorem aut." + }, + "description": "Additional pg_hba.conf entries, one rule per array element. Inserted between control-plane's system-user rules and its catch-all, so they cannot affect control-plane-internal connectivity (Patroni, replication, health checks). Node-level pg_hba_conf entries are prepended to these.", + "example": [ + "hostssl all myapp_user 203.0.113.0/24 scram-sha-256", + "hostssl all alice 0.0.0.0/0 cert clientcert=verify-full map=ssl_users" + ] + }, + "pg_ident_conf": { + "type": "array", + "items": { + "type": "string", + "example": "Omnis quisquam officiis." + }, + "description": "Additional pg_ident.conf entries, one mapping per array element. Purely additive; control-plane writes no pg_ident entries of its own. The primary use case is cert auth with map= translating certificate CNs to PostgreSQL usernames.", + "example": [ + "ssl_users CN=alice,O=example alice" + ] + }, + "port": { + "type": "integer", + "description": "The port used by the Postgres database. If the port is 0, each instance will be assigned a random port. If the port is unspecified, the database will not be exposed on any port, dependent on orchestrator support for that feature.", + "example": 5432, + "format": "int64", + "minimum": 0, + "maximum": 65535 + }, + "postgres_version": { + "type": "string", + "description": "The Postgres version in 'major.minor' format.", + "example": "17.6", + "pattern": "^\\d{2}\\.\\d{1,2}$" + }, + "postgresql_conf": { + "type": "object", + "description": "Additional postgresql.conf settings. Will be merged with the settings provided by control-plane.", + "example": { + "max_connections": 1000 + }, + "maxLength": 64, + "additionalProperties": true + }, + "restore_config": { + "$ref": "#/components/schemas/RestoreConfigSpec" + }, + "scripts": { + "$ref": "#/components/schemas/DatabaseScripts" + }, + "services": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ServiceSpec7" + }, + "description": "Service instances to run alongside the database (e.g., MCP servers).", + "example": [ { "config": { "llm_model": "gpt-4", @@ -21057,53 +21945,132 @@ "service_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", "service_type": "rag", "version": "latest" - } - ] - }, - "spock_version": { - "type": "string", - "description": "The major version of the Spock extension.", - "example": "5", - "pattern": "^\\d{1}$" - } - }, - "example": { - "backup_config": { - "repositories": [ - { - "azure_account": "pgedge-backups", - "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "azure_endpoint": "blob.core.usgovcloudapi.net", - "azure_key": "YXpLZXk=", - "base_path": "/backups", - "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", - "storage-upload-chunk-size": "5MiB" - }, - "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "gcs_endpoint": "localhost", - "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", - "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "retention_full": 2, - "retention_full_type": "count", - "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "s3_endpoint": "s3.us-east-1.amazonaws.com", - "s3_key": "AKIAIOSFODNN7EXAMPLE", - "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - "s3_region": "us-east-1", - "type": "s3" }, { - "azure_account": "pgedge-backups", - "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "azure_endpoint": "blob.core.usgovcloudapi.net", - "azure_key": "YXpLZXk=", - "base_path": "/backups", - "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", - "storage-upload-chunk-size": "5MiB" - }, - "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "config": { + "llm_model": "gpt-4", + "llm_provider": "openai", + "openai_api_key": "sk-..." + }, + "connect_as": "app", + "cpus": "500m", + "database_connection": { + "target_nodes": [ + "n1", + "n2" + ], + "target_session_attrs": "primary" + }, + "host_ids": [ + "76f9b8c0-4958-11f0-a489-3bb29577c696", + "76f9b8c0-4958-11f0-a489-3bb29577c696" + ], + "memory": "512M", + "orchestrator_opts": { + "swarm": { + "extra_labels": { + "traefik.enable": "true", + "traefik.tcp.routers.mydb.rule": "HostSNI(`mydb.example.com`)" + }, + "extra_networks": [ + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + }, + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + }, + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + } + ], + "extra_volumes": [ + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + }, + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + }, + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + } + ] + } + }, + "port": 0, + "service_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "service_type": "rag", + "version": "latest" + } + ] + }, + "spock_version": { + "type": "string", + "description": "The major version of the Spock extension.", + "example": "5", + "pattern": "^\\d{1}$" + } + }, + "example": { + "backup_config": { + "repositories": [ + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + }, + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", "gcs_endpoint": "localhost", "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", @@ -21180,29 +22147,421 @@ "CREATEDB", "CREATEROLE" ], - "db_owner": false, - "password": "secret", - "roles": [ - "pgedge_superuser" + "db_owner": false, + "password": "secret", + "roles": [ + "pgedge_superuser" + ], + "username": "admin" + }, + { + "attributes": [ + "LOGIN", + "CREATEDB", + "CREATEROLE" + ], + "db_owner": false, + "password": "secret", + "roles": [ + "pgedge_superuser" + ], + "username": "admin" + } + ], + "memory": "500M", + "nodes": [ + { + "backup_config": { + "repositories": [ + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + }, + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + }, + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + } + ], + "schedules": [ + { + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" + }, + { + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" + }, + { + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" + } + ] + }, + "cpus": "500m", + "host_ids": [ + "76f9b8c0-4958-11f0-a489-3bb29577c696", + "76f9b8c0-4958-11f0-a489-3bb29577c696" + ], + "memory": "500M", + "name": "n1", + "orchestrator_opts": { + "swarm": { + "extra_labels": { + "traefik.enable": "true", + "traefik.tcp.routers.mydb.rule": "HostSNI(`mydb.example.com`)" + }, + "extra_networks": [ + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + }, + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + }, + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + } + ], + "extra_volumes": [ + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + }, + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + }, + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + } + ] + } + }, + "patroni_port": 8888, + "pg_hba_conf": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], + "port": 5432, + "postgres_version": "17.6", + "postgresql_conf": { + "max_connections": 1000 + }, + "restore_config": { + "repository": { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + }, + "restore_options": { + "set": "20250505-153628F", + "target": "123456", + "type": "xid" + }, + "source_database_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "source_database_name": "northwind", + "source_node_name": "n1" + }, + "source_node": "n1" + }, + { + "backup_config": { + "repositories": [ + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + }, + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + }, + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + } + ], + "schedules": [ + { + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" + }, + { + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" + }, + { + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" + } + ] + }, + "cpus": "500m", + "host_ids": [ + "76f9b8c0-4958-11f0-a489-3bb29577c696", + "76f9b8c0-4958-11f0-a489-3bb29577c696" + ], + "memory": "500M", + "name": "n1", + "orchestrator_opts": { + "swarm": { + "extra_labels": { + "traefik.enable": "true", + "traefik.tcp.routers.mydb.rule": "HostSNI(`mydb.example.com`)" + }, + "extra_networks": [ + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + }, + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + }, + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + } + ], + "extra_volumes": [ + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + }, + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + }, + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + } + ] + } + }, + "patroni_port": 8888, + "pg_hba_conf": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" ], - "username": "admin" + "port": 5432, + "postgres_version": "17.6", + "postgresql_conf": { + "max_connections": 1000 + }, + "restore_config": { + "repository": { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + }, + "restore_options": { + "set": "20250505-153628F", + "target": "123456", + "type": "xid" + }, + "source_database_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "source_database_name": "northwind", + "source_node_name": "n1" + }, + "source_node": "n1" }, - { - "attributes": [ - "LOGIN", - "CREATEDB", - "CREATEROLE" - ], - "db_owner": false, - "password": "secret", - "roles": [ - "pgedge_superuser" - ], - "username": "admin" - } - ], - "memory": "500M", - "nodes": [ { "backup_config": { "repositories": [ @@ -21356,6 +22715,12 @@ } }, "patroni_port": 8888, + "pg_hba_conf": [ + "host example myapp_user 10.0.0.0/8 scram-sha-256" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], "port": 5432, "postgres_version": "17.6", "postgresql_conf": { @@ -21449,6 +22814,13 @@ } }, "patroni_port": 8888, + "pg_hba_conf": [ + "hostssl all myapp_user 203.0.113.0/24 scram-sha-256", + "hostssl all alice 0.0.0.0/0 cert clientcert=verify-full map=ssl_users" + ], + "pg_ident_conf": [ + "ssl_users CN=alice,O=example alice" + ], "port": 5432, "postgres_version": "17.6", "postgresql_conf": { @@ -21472,189 +22844,31 @@ "s3_endpoint": "s3.us-east-1.amazonaws.com", "s3_key": "AKIAIOSFODNN7EXAMPLE", "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - "s3_region": "us-east-1", - "type": "s3" - }, - "restore_options": { - "set": "20250505-153628F", - "target": "123456", - "type": "xid" - }, - "source_database_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "source_database_name": "northwind", - "source_node_name": "n1" - }, - "scripts": { - "post_database_create": [ - "ALTER DEFAULT PRIVILEGES FOR ROLE admin GRANT USAGE ON SCHEMAS TO app", - "ALTER DEFAULT PRIVILEGES FOR ROLE admin GRANT ALL PRIVILEGES ON TABLES TO app", - "ALTER DEFAULT PRIVILEGES FOR ROLE admin GRANT ALL PRIVILEGES ON SEQUENCES TO app" - ], - "post_init": [ - "ALTER DEFAULT PRIVILEGES FOR ROLE admin GRANT USAGE ON SCHEMAS TO app", - "ALTER DEFAULT PRIVILEGES FOR ROLE admin GRANT ALL PRIVILEGES ON TABLES TO app", - "ALTER DEFAULT PRIVILEGES FOR ROLE admin GRANT ALL PRIVILEGES ON SEQUENCES TO app" - ] - }, - "services": [ - { - "config": { - "llm_model": "gpt-4", - "llm_provider": "openai", - "openai_api_key": "sk-..." - }, - "connect_as": "app", - "cpus": "500m", - "database_connection": { - "target_nodes": [ - "n1", - "n2" - ], - "target_session_attrs": "primary" - }, - "host_ids": [ - "76f9b8c0-4958-11f0-a489-3bb29577c696", - "76f9b8c0-4958-11f0-a489-3bb29577c696" - ], - "memory": "512M", - "orchestrator_opts": { - "swarm": { - "extra_labels": { - "traefik.enable": "true", - "traefik.tcp.routers.mydb.rule": "HostSNI(`mydb.example.com`)" - }, - "extra_networks": [ - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - }, - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - }, - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - } - ], - "extra_volumes": [ - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - }, - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - }, - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - } - ] - } - }, - "port": 0, - "service_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "service_type": "rag", - "version": "latest" - }, - { - "config": { - "llm_model": "gpt-4", - "llm_provider": "openai", - "openai_api_key": "sk-..." - }, - "connect_as": "app", - "cpus": "500m", - "database_connection": { - "target_nodes": [ - "n1", - "n2" - ], - "target_session_attrs": "primary" - }, - "host_ids": [ - "76f9b8c0-4958-11f0-a489-3bb29577c696", - "76f9b8c0-4958-11f0-a489-3bb29577c696" - ], - "memory": "512M", - "orchestrator_opts": { - "swarm": { - "extra_labels": { - "traefik.enable": "true", - "traefik.tcp.routers.mydb.rule": "HostSNI(`mydb.example.com`)" - }, - "extra_networks": [ - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - }, - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - }, - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - } - ], - "extra_volumes": [ - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - }, - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - }, - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - } - ] - } - }, - "port": 0, - "service_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "service_type": "rag", - "version": "latest" + "s3_region": "us-east-1", + "type": "s3" + }, + "restore_options": { + "set": "20250505-153628F", + "target": "123456", + "type": "xid" }, + "source_database_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "source_database_name": "northwind", + "source_node_name": "n1" + }, + "scripts": { + "post_database_create": [ + "ALTER DEFAULT PRIVILEGES FOR ROLE admin GRANT USAGE ON SCHEMAS TO app", + "ALTER DEFAULT PRIVILEGES FOR ROLE admin GRANT ALL PRIVILEGES ON TABLES TO app", + "ALTER DEFAULT PRIVILEGES FOR ROLE admin GRANT ALL PRIVILEGES ON SEQUENCES TO app" + ], + "post_init": [ + "ALTER DEFAULT PRIVILEGES FOR ROLE admin GRANT USAGE ON SCHEMAS TO app", + "ALTER DEFAULT PRIVILEGES FOR ROLE admin GRANT ALL PRIVILEGES ON TABLES TO app", + "ALTER DEFAULT PRIVILEGES FOR ROLE admin GRANT ALL PRIVILEGES ON SEQUENCES TO app" + ] + }, + "services": [ { "config": { "llm_model": "gpt-4", @@ -21852,7 +23066,7 @@ ], "port": 5432 }, - "created_at": "1970-12-24T01:48:39Z", + "created_at": "2001-11-21T07:07:15Z", "error": "failed to get patroni status: connection refused", "host_id": "de3b1388-1f0c-42f1-a86c-59ab72f255ec", "id": "a67cbb36-c3c3-49c9-8aac-f4a0438a883d", @@ -21860,7 +23074,7 @@ "postgres": { "patroni_paused": true, "patroni_state": "unknown", - "pending_restart": true, + "pending_restart": false, "role": "primary", "version": "18.1" }, @@ -21872,6 +23086,11 @@ "provider_node": "n2", "status": "down" }, + { + "name": "sub_n1n2", + "provider_node": "n2", + "status": "down" + }, { "name": "sub_n1n2", "provider_node": "n2", @@ -21880,9 +23099,9 @@ ], "version": "4.10.0" }, - "state": "unknown", - "status_updated_at": "1978-12-17T01:14:06Z", - "updated_at": "2010-08-13T18:38:44Z" + "state": "degraded", + "status_updated_at": "1990-07-23T01:22:30Z", + "updated_at": "2013-01-29T23:51:44Z" }, { "connection_info": { @@ -21892,7 +23111,7 @@ ], "port": 5432 }, - "created_at": "1970-12-24T01:48:39Z", + "created_at": "2001-11-21T07:07:15Z", "error": "failed to get patroni status: connection refused", "host_id": "de3b1388-1f0c-42f1-a86c-59ab72f255ec", "id": "a67cbb36-c3c3-49c9-8aac-f4a0438a883d", @@ -21900,7 +23119,7 @@ "postgres": { "patroni_paused": true, "patroni_state": "unknown", - "pending_restart": true, + "pending_restart": false, "role": "primary", "version": "18.1" }, @@ -21912,6 +23131,11 @@ "provider_node": "n2", "status": "down" }, + { + "name": "sub_n1n2", + "provider_node": "n2", + "status": "down" + }, { "name": "sub_n1n2", "provider_node": "n2", @@ -21920,9 +23144,9 @@ ], "version": "4.10.0" }, - "state": "unknown", - "status_updated_at": "1978-12-17T01:14:06Z", - "updated_at": "2010-08-13T18:38:44Z" + "state": "degraded", + "status_updated_at": "1990-07-23T01:22:30Z", + "updated_at": "2013-01-29T23:51:44Z" }, { "connection_info": { @@ -21932,7 +23156,7 @@ ], "port": 5432 }, - "created_at": "1970-12-24T01:48:39Z", + "created_at": "2001-11-21T07:07:15Z", "error": "failed to get patroni status: connection refused", "host_id": "de3b1388-1f0c-42f1-a86c-59ab72f255ec", "id": "a67cbb36-c3c3-49c9-8aac-f4a0438a883d", @@ -21940,7 +23164,52 @@ "postgres": { "patroni_paused": true, "patroni_state": "unknown", - "pending_restart": true, + "pending_restart": false, + "role": "primary", + "version": "18.1" + }, + "spock": { + "read_only": "off", + "subscriptions": [ + { + "name": "sub_n1n2", + "provider_node": "n2", + "status": "down" + }, + { + "name": "sub_n1n2", + "provider_node": "n2", + "status": "down" + }, + { + "name": "sub_n1n2", + "provider_node": "n2", + "status": "down" + } + ], + "version": "4.10.0" + }, + "state": "degraded", + "status_updated_at": "1990-07-23T01:22:30Z", + "updated_at": "2013-01-29T23:51:44Z" + }, + { + "connection_info": { + "addresses": [ + "10.24.34.2", + "i-0123456789abcdef.ec2.internal" + ], + "port": 5432 + }, + "created_at": "2001-11-21T07:07:15Z", + "error": "failed to get patroni status: connection refused", + "host_id": "de3b1388-1f0c-42f1-a86c-59ab72f255ec", + "id": "a67cbb36-c3c3-49c9-8aac-f4a0438a883d", + "node_name": "n1", + "postgres": { + "patroni_paused": true, + "patroni_state": "unknown", + "pending_restart": false, "role": "primary", "version": "18.1" }, @@ -21952,6 +23221,11 @@ "provider_node": "n2", "status": "down" }, + { + "name": "sub_n1n2", + "provider_node": "n2", + "status": "down" + }, { "name": "sub_n1n2", "provider_node": "n2", @@ -21960,16 +23234,16 @@ ], "version": "4.10.0" }, - "state": "unknown", - "status_updated_at": "1978-12-17T01:14:06Z", - "updated_at": "2010-08-13T18:38:44Z" + "state": "degraded", + "status_updated_at": "1990-07-23T01:22:30Z", + "updated_at": "2013-01-29T23:51:44Z" } ] }, "state": { "type": "string", "description": "Current state of the database.", - "example": "backing_up", + "example": "degraded", "enum": [ "creating", "modifying", @@ -22008,7 +23282,7 @@ ], "port": 5432 }, - "created_at": "1970-12-24T01:48:39Z", + "created_at": "2001-11-21T07:07:15Z", "error": "failed to get patroni status: connection refused", "host_id": "de3b1388-1f0c-42f1-a86c-59ab72f255ec", "id": "a67cbb36-c3c3-49c9-8aac-f4a0438a883d", @@ -22016,7 +23290,7 @@ "postgres": { "patroni_paused": true, "patroni_state": "unknown", - "pending_restart": true, + "pending_restart": false, "role": "primary", "version": "18.1" }, @@ -22028,41 +23302,6 @@ "provider_node": "n2", "status": "down" }, - { - "name": "sub_n1n2", - "provider_node": "n2", - "status": "down" - } - ], - "version": "4.10.0" - }, - "state": "unknown", - "status_updated_at": "1978-12-17T01:14:06Z", - "updated_at": "2010-08-13T18:38:44Z" - }, - { - "connection_info": { - "addresses": [ - "10.24.34.2", - "i-0123456789abcdef.ec2.internal" - ], - "port": 5432 - }, - "created_at": "1970-12-24T01:48:39Z", - "error": "failed to get patroni status: connection refused", - "host_id": "de3b1388-1f0c-42f1-a86c-59ab72f255ec", - "id": "a67cbb36-c3c3-49c9-8aac-f4a0438a883d", - "node_name": "n1", - "postgres": { - "patroni_paused": true, - "patroni_state": "unknown", - "pending_restart": true, - "role": "primary", - "version": "18.1" - }, - "spock": { - "read_only": "off", - "subscriptions": [ { "name": "sub_n1n2", "provider_node": "n2", @@ -22076,9 +23315,9 @@ ], "version": "4.10.0" }, - "state": "unknown", - "status_updated_at": "1978-12-17T01:14:06Z", - "updated_at": "2010-08-13T18:38:44Z" + "state": "degraded", + "status_updated_at": "1990-07-23T01:22:30Z", + "updated_at": "2013-01-29T23:51:44Z" }, { "connection_info": { @@ -22088,7 +23327,7 @@ ], "port": 5432 }, - "created_at": "1970-12-24T01:48:39Z", + "created_at": "2001-11-21T07:07:15Z", "error": "failed to get patroni status: connection refused", "host_id": "de3b1388-1f0c-42f1-a86c-59ab72f255ec", "id": "a67cbb36-c3c3-49c9-8aac-f4a0438a883d", @@ -22096,7 +23335,7 @@ "postgres": { "patroni_paused": true, "patroni_state": "unknown", - "pending_restart": true, + "pending_restart": false, "role": "primary", "version": "18.1" }, @@ -22108,41 +23347,6 @@ "provider_node": "n2", "status": "down" }, - { - "name": "sub_n1n2", - "provider_node": "n2", - "status": "down" - } - ], - "version": "4.10.0" - }, - "state": "unknown", - "status_updated_at": "1978-12-17T01:14:06Z", - "updated_at": "2010-08-13T18:38:44Z" - }, - { - "connection_info": { - "addresses": [ - "10.24.34.2", - "i-0123456789abcdef.ec2.internal" - ], - "port": 5432 - }, - "created_at": "1970-12-24T01:48:39Z", - "error": "failed to get patroni status: connection refused", - "host_id": "de3b1388-1f0c-42f1-a86c-59ab72f255ec", - "id": "a67cbb36-c3c3-49c9-8aac-f4a0438a883d", - "node_name": "n1", - "postgres": { - "patroni_paused": true, - "patroni_state": "unknown", - "pending_restart": true, - "role": "primary", - "version": "18.1" - }, - "spock": { - "read_only": "off", - "subscriptions": [ { "name": "sub_n1n2", "provider_node": "n2", @@ -22156,9 +23360,9 @@ ], "version": "4.10.0" }, - "state": "unknown", - "status_updated_at": "1978-12-17T01:14:06Z", - "updated_at": "2010-08-13T18:38:44Z" + "state": "degraded", + "status_updated_at": "1990-07-23T01:22:30Z", + "updated_at": "2013-01-29T23:51:44Z" } ], "state": "failed", @@ -22179,7 +23383,7 @@ "type": "array", "items": { "type": "string", - "example": "Et nam quo qui qui natus." + "example": "Aut omnis magnam aspernatur occaecati itaque dolores." }, "description": "The attributes to assign to this database user.", "example": [ @@ -22192,7 +23396,7 @@ "db_owner": { "type": "boolean", "description": "If true, this user will be granted database ownership.", - "example": false + "example": true }, "password": { "type": "string", @@ -22204,7 +23408,7 @@ "type": "array", "items": { "type": "string", - "example": "Veniam exercitationem placeat temporibus aut." + "example": "Dolor autem eum." }, "description": "The roles to assign to this database user.", "example": [ @@ -22225,7 +23429,7 @@ "CREATEDB", "CREATEROLE" ], - "db_owner": false, + "db_owner": true, "password": "secret", "roles": [ "pgedge_superuser" @@ -22263,7 +23467,7 @@ "type": "array", "items": { "type": "string", - "example": "Accusantium ut aperiam qui sed quis architecto." + "example": "Rerum animi et itaque placeat placeat." }, "description": "The Etcd client endpoint for this cluster member.", "example": [ @@ -22279,7 +23483,7 @@ "type": "array", "items": { "type": "string", - "example": "Labore explicabo culpa eos natus aperiam excepturi." + "example": "Repudiandae ab sed." }, "description": "The Etcd peer endpoint for this cluster member.", "example": [ @@ -22309,7 +23513,7 @@ "type": "array", "items": { "type": "string", - "example": "Totam accusamus alias." + "example": "Aliquid cupiditate sapiente eos aut dignissimos cum." }, "description": "Optional network-scoped aliases for the container.", "example": [ @@ -22326,7 +23530,7 @@ }, "additionalProperties": { "type": "string", - "example": "Qui ut et." + "example": "Modi consequatur non at." } }, "id": { @@ -22401,7 +23605,7 @@ "type": "boolean", "description": "If true, skip the health validations that prevent running failover on a healthy cluster.", "default": false, - "example": true + "example": false } }, "example": { @@ -22432,7 +23636,7 @@ }, "example": { "candidate_instance_id": "68f50878-44d2-4524-a823-e31bd478706d-n1-689qacsi", - "skip_validation": true + "skip_validation": false } }, "FailoverDatabaseNodeResponse": { @@ -22498,7 +23702,7 @@ "type": "array", "items": { "type": "string", - "example": "Animi recusandae." + "example": "Illo aut et corporis harum." }, "description": "The addresses that this host advertises to client applications.", "example": [ @@ -22553,7 +23757,7 @@ "type": "array", "items": { "type": "string", - "example": "Qui quam sint iure eum ducimus quia." + "example": "Eos molestiae voluptates laborum." }, "description": "The addresses that this host advertises to other hosts.", "example": [ @@ -22639,14 +23843,6 @@ "updated_at": "2021-07-01T12:34:56Z" }, "supported_pgedge_versions": [ - { - "postgres_version": "17.6", - "spock_version": "5" - }, - { - "postgres_version": "17.6", - "spock_version": "5" - }, { "postgres_version": "17.6", "spock_version": "5" @@ -22703,25 +23899,7 @@ "type": "object", "description": "The status of each component of the host.", "example": { - "At esse ut possimus error eligendi.": { - "details": { - "alarms": [ - "3: NOSPACE" - ] - }, - "error": "failed to connect to etcd", - "healthy": false - }, - "Atque facilis non modi explicabo illum.": { - "details": { - "alarms": [ - "3: NOSPACE" - ] - }, - "error": "failed to connect to etcd", - "healthy": false - }, - "Similique sed neque eos rerum quia.": { + "Sint ea omnis ut.": { "details": { "alarms": [ "3: NOSPACE" @@ -22754,7 +23932,7 @@ }, "example": { "components": { - "Et eius reiciendis accusamus veritatis quo recusandae.": { + "Impedit laudantium et quia commodi consequatur.": { "details": { "alarms": [ "3: NOSPACE" @@ -22763,7 +23941,7 @@ "error": "failed to connect to etcd", "healthy": false }, - "Fuga molestiae.": { + "Possimus magni quaerat qui quam id.": { "details": { "alarms": [ "3: NOSPACE" @@ -22772,7 +23950,7 @@ "error": "failed to connect to etcd", "healthy": false }, - "Quas nostrum eos reprehenderit harum sapiente qui.": { + "Velit et labore in dolor quisquam placeat.": { "details": { "alarms": [ "3: NOSPACE" @@ -22816,7 +23994,7 @@ "created_at": { "type": "string", "description": "The time that the instance was created.", - "example": "1993-02-25T18:38:10Z", + "example": "1985-10-05T07:39:21Z", "format": "date-time" }, "error": { @@ -22847,7 +24025,7 @@ }, "state": { "type": "string", - "example": "available", + "example": "creating", "enum": [ "creating", "modifying", @@ -22863,13 +24041,13 @@ "status_updated_at": { "type": "string", "description": "The time that the instance status information was last updated.", - "example": "1983-10-23T08:18:23Z", + "example": "1980-07-23T10:57:18Z", "format": "date-time" }, "updated_at": { "type": "string", "description": "The time that the instance was last modified.", - "example": "1971-02-20T15:20:44Z", + "example": "2012-09-29T21:49:40Z", "format": "date-time" } }, @@ -22882,7 +24060,7 @@ ], "port": 5432 }, - "created_at": "1994-07-03T05:16:56Z", + "created_at": "1978-04-27T14:09:21Z", "error": "failed to get patroni status: connection refused", "host_id": "de3b1388-1f0c-42f1-a86c-59ab72f255ec", "id": "a67cbb36-c3c3-49c9-8aac-f4a0438a883d", @@ -22890,7 +24068,7 @@ "postgres": { "patroni_paused": true, "patroni_state": "unknown", - "pending_restart": true, + "pending_restart": false, "role": "primary", "version": "18.1" }, @@ -22902,6 +24080,11 @@ "provider_node": "n2", "status": "down" }, + { + "name": "sub_n1n2", + "provider_node": "n2", + "status": "down" + }, { "name": "sub_n1n2", "provider_node": "n2", @@ -22910,9 +24093,9 @@ ], "version": "4.10.0" }, - "state": "modifying", - "status_updated_at": "1994-09-09T06:25:01Z", - "updated_at": "2014-04-20T04:34:11Z" + "state": "degraded", + "status_updated_at": "1976-06-24T23:38:37Z", + "updated_at": "2015-04-11T16:50:06Z" }, "required": [ "id", @@ -22930,7 +24113,7 @@ "type": "array", "items": { "type": "string", - "example": "Ea omnis ut dolor dolorem impedit laudantium." + "example": "Facere eius totam." }, "description": "The addresses of the host that's running this instance.", "example": [ @@ -22969,7 +24152,7 @@ "pending_restart": { "type": "boolean", "description": "True if this instance has a pending restart from a configuration change.", - "example": false + "example": true }, "role": { "type": "string", @@ -22983,7 +24166,7 @@ }, "description": "Postgres status information for a pgEdge instance.", "example": { - "patroni_paused": false, + "patroni_paused": true, "patroni_state": "unknown", "pending_restart": false, "role": "primary", @@ -23015,6 +24198,11 @@ "provider_node": "n2", "status": "down" }, + { + "name": "sub_n1n2", + "provider_node": "n2", + "status": "down" + }, { "name": "sub_n1n2", "provider_node": "n2", @@ -23207,7 +24395,97 @@ ], "port": 5432 }, - "created_at": "1970-12-24T01:48:39Z", + "created_at": "2001-11-21T07:07:15Z", + "error": "failed to get patroni status: connection refused", + "host_id": "de3b1388-1f0c-42f1-a86c-59ab72f255ec", + "id": "a67cbb36-c3c3-49c9-8aac-f4a0438a883d", + "node_name": "n1", + "postgres": { + "patroni_paused": true, + "patroni_state": "unknown", + "pending_restart": false, + "role": "primary", + "version": "18.1" + }, + "spock": { + "read_only": "off", + "subscriptions": [ + { + "name": "sub_n1n2", + "provider_node": "n2", + "status": "down" + }, + { + "name": "sub_n1n2", + "provider_node": "n2", + "status": "down" + }, + { + "name": "sub_n1n2", + "provider_node": "n2", + "status": "down" + } + ], + "version": "4.10.0" + }, + "state": "degraded", + "status_updated_at": "1990-07-23T01:22:30Z", + "updated_at": "2013-01-29T23:51:44Z" + }, + { + "connection_info": { + "addresses": [ + "10.24.34.2", + "i-0123456789abcdef.ec2.internal" + ], + "port": 5432 + }, + "created_at": "2001-11-21T07:07:15Z", + "error": "failed to get patroni status: connection refused", + "host_id": "de3b1388-1f0c-42f1-a86c-59ab72f255ec", + "id": "a67cbb36-c3c3-49c9-8aac-f4a0438a883d", + "node_name": "n1", + "postgres": { + "patroni_paused": true, + "patroni_state": "unknown", + "pending_restart": false, + "role": "primary", + "version": "18.1" + }, + "spock": { + "read_only": "off", + "subscriptions": [ + { + "name": "sub_n1n2", + "provider_node": "n2", + "status": "down" + }, + { + "name": "sub_n1n2", + "provider_node": "n2", + "status": "down" + }, + { + "name": "sub_n1n2", + "provider_node": "n2", + "status": "down" + } + ], + "version": "4.10.0" + }, + "state": "degraded", + "status_updated_at": "1990-07-23T01:22:30Z", + "updated_at": "2013-01-29T23:51:44Z" + }, + { + "connection_info": { + "addresses": [ + "10.24.34.2", + "i-0123456789abcdef.ec2.internal" + ], + "port": 5432 + }, + "created_at": "2001-11-21T07:07:15Z", "error": "failed to get patroni status: connection refused", "host_id": "de3b1388-1f0c-42f1-a86c-59ab72f255ec", "id": "a67cbb36-c3c3-49c9-8aac-f4a0438a883d", @@ -23215,7 +24493,7 @@ "postgres": { "patroni_paused": true, "patroni_state": "unknown", - "pending_restart": true, + "pending_restart": false, "role": "primary", "version": "18.1" }, @@ -23227,6 +24505,11 @@ "provider_node": "n2", "status": "down" }, + { + "name": "sub_n1n2", + "provider_node": "n2", + "status": "down" + }, { "name": "sub_n1n2", "provider_node": "n2", @@ -23235,9 +24518,9 @@ ], "version": "4.10.0" }, - "state": "unknown", - "status_updated_at": "1978-12-17T01:14:06Z", - "updated_at": "2010-08-13T18:38:44Z" + "state": "degraded", + "status_updated_at": "1990-07-23T01:22:30Z", + "updated_at": "2013-01-29T23:51:44Z" }, { "connection_info": { @@ -23247,7 +24530,7 @@ ], "port": 5432 }, - "created_at": "1970-12-24T01:48:39Z", + "created_at": "2001-11-21T07:07:15Z", "error": "failed to get patroni status: connection refused", "host_id": "de3b1388-1f0c-42f1-a86c-59ab72f255ec", "id": "a67cbb36-c3c3-49c9-8aac-f4a0438a883d", @@ -23255,7 +24538,7 @@ "postgres": { "patroni_paused": true, "patroni_state": "unknown", - "pending_restart": true, + "pending_restart": false, "role": "primary", "version": "18.1" }, @@ -23267,6 +24550,11 @@ "provider_node": "n2", "status": "down" }, + { + "name": "sub_n1n2", + "provider_node": "n2", + "status": "down" + }, { "name": "sub_n1n2", "provider_node": "n2", @@ -23275,10 +24563,19 @@ ], "version": "4.10.0" }, - "state": "unknown", - "status_updated_at": "1978-12-17T01:14:06Z", - "updated_at": "2010-08-13T18:38:44Z" - }, + "state": "degraded", + "status_updated_at": "1990-07-23T01:22:30Z", + "updated_at": "2013-01-29T23:51:44Z" + } + ], + "state": "failed", + "tenant_id": "8210ec10-2dca-406c-ac4a-0661d2189954", + "updated_at": "2025-01-01T02:30:00Z" + }, + { + "created_at": "2025-01-01T01:30:00Z", + "id": "02f1a7db-fca8-4521-b57a-2a375c1ced51", + "instances": [ { "connection_info": { "addresses": [ @@ -23287,7 +24584,7 @@ ], "port": 5432 }, - "created_at": "1970-12-24T01:48:39Z", + "created_at": "2001-11-21T07:07:15Z", "error": "failed to get patroni status: connection refused", "host_id": "de3b1388-1f0c-42f1-a86c-59ab72f255ec", "id": "a67cbb36-c3c3-49c9-8aac-f4a0438a883d", @@ -23295,7 +24592,7 @@ "postgres": { "patroni_paused": true, "patroni_state": "unknown", - "pending_restart": true, + "pending_restart": false, "role": "primary", "version": "18.1" }, @@ -23307,6 +24604,11 @@ "provider_node": "n2", "status": "down" }, + { + "name": "sub_n1n2", + "provider_node": "n2", + "status": "down" + }, { "name": "sub_n1n2", "provider_node": "n2", @@ -23315,19 +24617,10 @@ ], "version": "4.10.0" }, - "state": "unknown", - "status_updated_at": "1978-12-17T01:14:06Z", - "updated_at": "2010-08-13T18:38:44Z" - } - ], - "state": "failed", - "tenant_id": "8210ec10-2dca-406c-ac4a-0661d2189954", - "updated_at": "2025-01-01T02:30:00Z" - }, - { - "created_at": "2025-01-01T01:30:00Z", - "id": "02f1a7db-fca8-4521-b57a-2a375c1ced51", - "instances": [ + "state": "degraded", + "status_updated_at": "1990-07-23T01:22:30Z", + "updated_at": "2013-01-29T23:51:44Z" + }, { "connection_info": { "addresses": [ @@ -23336,7 +24629,7 @@ ], "port": 5432 }, - "created_at": "1970-12-24T01:48:39Z", + "created_at": "2001-11-21T07:07:15Z", "error": "failed to get patroni status: connection refused", "host_id": "de3b1388-1f0c-42f1-a86c-59ab72f255ec", "id": "a67cbb36-c3c3-49c9-8aac-f4a0438a883d", @@ -23344,7 +24637,7 @@ "postgres": { "patroni_paused": true, "patroni_state": "unknown", - "pending_restart": true, + "pending_restart": false, "role": "primary", "version": "18.1" }, @@ -23356,6 +24649,11 @@ "provider_node": "n2", "status": "down" }, + { + "name": "sub_n1n2", + "provider_node": "n2", + "status": "down" + }, { "name": "sub_n1n2", "provider_node": "n2", @@ -23364,9 +24662,9 @@ ], "version": "4.10.0" }, - "state": "unknown", - "status_updated_at": "1978-12-17T01:14:06Z", - "updated_at": "2010-08-13T18:38:44Z" + "state": "degraded", + "status_updated_at": "1990-07-23T01:22:30Z", + "updated_at": "2013-01-29T23:51:44Z" }, { "connection_info": { @@ -23376,7 +24674,7 @@ ], "port": 5432 }, - "created_at": "1970-12-24T01:48:39Z", + "created_at": "2001-11-21T07:07:15Z", "error": "failed to get patroni status: connection refused", "host_id": "de3b1388-1f0c-42f1-a86c-59ab72f255ec", "id": "a67cbb36-c3c3-49c9-8aac-f4a0438a883d", @@ -23384,7 +24682,7 @@ "postgres": { "patroni_paused": true, "patroni_state": "unknown", - "pending_restart": true, + "pending_restart": false, "role": "primary", "version": "18.1" }, @@ -23396,6 +24694,11 @@ "provider_node": "n2", "status": "down" }, + { + "name": "sub_n1n2", + "provider_node": "n2", + "status": "down" + }, { "name": "sub_n1n2", "provider_node": "n2", @@ -23404,9 +24707,9 @@ ], "version": "4.10.0" }, - "state": "unknown", - "status_updated_at": "1978-12-17T01:14:06Z", - "updated_at": "2010-08-13T18:38:44Z" + "state": "degraded", + "status_updated_at": "1990-07-23T01:22:30Z", + "updated_at": "2013-01-29T23:51:44Z" }, { "connection_info": { @@ -23416,7 +24719,7 @@ ], "port": 5432 }, - "created_at": "1970-12-24T01:48:39Z", + "created_at": "2001-11-21T07:07:15Z", "error": "failed to get patroni status: connection refused", "host_id": "de3b1388-1f0c-42f1-a86c-59ab72f255ec", "id": "a67cbb36-c3c3-49c9-8aac-f4a0438a883d", @@ -23424,7 +24727,7 @@ "postgres": { "patroni_paused": true, "patroni_state": "unknown", - "pending_restart": true, + "pending_restart": false, "role": "primary", "version": "18.1" }, @@ -23436,6 +24739,11 @@ "provider_node": "n2", "status": "down" }, + { + "name": "sub_n1n2", + "provider_node": "n2", + "status": "down" + }, { "name": "sub_n1n2", "provider_node": "n2", @@ -23444,9 +24752,9 @@ ], "version": "4.10.0" }, - "state": "unknown", - "status_updated_at": "1978-12-17T01:14:06Z", - "updated_at": "2010-08-13T18:38:44Z" + "state": "degraded", + "status_updated_at": "1990-07-23T01:22:30Z", + "updated_at": "2013-01-29T23:51:44Z" } ], "state": "failed", @@ -23465,7 +24773,7 @@ ], "port": 5432 }, - "created_at": "1970-12-24T01:48:39Z", + "created_at": "2001-11-21T07:07:15Z", "error": "failed to get patroni status: connection refused", "host_id": "de3b1388-1f0c-42f1-a86c-59ab72f255ec", "id": "a67cbb36-c3c3-49c9-8aac-f4a0438a883d", @@ -23473,13 +24781,63 @@ "postgres": { "patroni_paused": true, "patroni_state": "unknown", - "pending_restart": true, + "pending_restart": false, "role": "primary", "version": "18.1" }, "spock": { "read_only": "off", "subscriptions": [ + { + "name": "sub_n1n2", + "provider_node": "n2", + "status": "down" + }, + { + "name": "sub_n1n2", + "provider_node": "n2", + "status": "down" + }, + { + "name": "sub_n1n2", + "provider_node": "n2", + "status": "down" + } + ], + "version": "4.10.0" + }, + "state": "degraded", + "status_updated_at": "1990-07-23T01:22:30Z", + "updated_at": "2013-01-29T23:51:44Z" + }, + { + "connection_info": { + "addresses": [ + "10.24.34.2", + "i-0123456789abcdef.ec2.internal" + ], + "port": 5432 + }, + "created_at": "2001-11-21T07:07:15Z", + "error": "failed to get patroni status: connection refused", + "host_id": "de3b1388-1f0c-42f1-a86c-59ab72f255ec", + "id": "a67cbb36-c3c3-49c9-8aac-f4a0438a883d", + "node_name": "n1", + "postgres": { + "patroni_paused": true, + "patroni_state": "unknown", + "pending_restart": false, + "role": "primary", + "version": "18.1" + }, + "spock": { + "read_only": "off", + "subscriptions": [ + { + "name": "sub_n1n2", + "provider_node": "n2", + "status": "down" + }, { "name": "sub_n1n2", "provider_node": "n2", @@ -23493,9 +24851,9 @@ ], "version": "4.10.0" }, - "state": "unknown", - "status_updated_at": "1978-12-17T01:14:06Z", - "updated_at": "2010-08-13T18:38:44Z" + "state": "degraded", + "status_updated_at": "1990-07-23T01:22:30Z", + "updated_at": "2013-01-29T23:51:44Z" }, { "connection_info": { @@ -23505,7 +24863,7 @@ ], "port": 5432 }, - "created_at": "1970-12-24T01:48:39Z", + "created_at": "2001-11-21T07:07:15Z", "error": "failed to get patroni status: connection refused", "host_id": "de3b1388-1f0c-42f1-a86c-59ab72f255ec", "id": "a67cbb36-c3c3-49c9-8aac-f4a0438a883d", @@ -23513,7 +24871,7 @@ "postgres": { "patroni_paused": true, "patroni_state": "unknown", - "pending_restart": true, + "pending_restart": false, "role": "primary", "version": "18.1" }, @@ -23525,6 +24883,11 @@ "provider_node": "n2", "status": "down" }, + { + "name": "sub_n1n2", + "provider_node": "n2", + "status": "down" + }, { "name": "sub_n1n2", "provider_node": "n2", @@ -23533,9 +24896,9 @@ ], "version": "4.10.0" }, - "state": "unknown", - "status_updated_at": "1978-12-17T01:14:06Z", - "updated_at": "2010-08-13T18:38:44Z" + "state": "degraded", + "status_updated_at": "1990-07-23T01:22:30Z", + "updated_at": "2013-01-29T23:51:44Z" }, { "connection_info": { @@ -23545,7 +24908,7 @@ ], "port": 5432 }, - "created_at": "1970-12-24T01:48:39Z", + "created_at": "2001-11-21T07:07:15Z", "error": "failed to get patroni status: connection refused", "host_id": "de3b1388-1f0c-42f1-a86c-59ab72f255ec", "id": "a67cbb36-c3c3-49c9-8aac-f4a0438a883d", @@ -23553,7 +24916,7 @@ "postgres": { "patroni_paused": true, "patroni_state": "unknown", - "pending_restart": true, + "pending_restart": false, "role": "primary", "version": "18.1" }, @@ -23565,6 +24928,11 @@ "provider_node": "n2", "status": "down" }, + { + "name": "sub_n1n2", + "provider_node": "n2", + "status": "down" + }, { "name": "sub_n1n2", "provider_node": "n2", @@ -23573,9 +24941,9 @@ ], "version": "4.10.0" }, - "state": "unknown", - "status_updated_at": "1978-12-17T01:14:06Z", - "updated_at": "2010-08-13T18:38:44Z" + "state": "degraded", + "status_updated_at": "1990-07-23T01:22:30Z", + "updated_at": "2013-01-29T23:51:44Z" } ], "state": "failed", @@ -23861,16 +25229,6 @@ "task_id": "019783f4-75f4-71e7-85a3-c9b96b345d77", "type": "create" }, - { - "completed_at": "2025-06-18T16:52:35Z", - "created_at": "2025-06-18T16:52:05Z", - "database_id": "storefront", - "entity_id": "storefront", - "scope": "database", - "status": "completed", - "task_id": "019783f4-75f4-71e7-85a3-c9b96b345d77", - "type": "create" - }, { "completed_at": "2025-06-18T16:52:35Z", "created_at": "2025-06-18T16:52:05Z", @@ -24107,69 +25465,6 @@ } ] }, - { - "client_addresses": [ - "10.24.34.2", - "i-0123456789abcdef.ec2.internal" - ], - "cohort": { - "control_available": true, - "member_id": "lah4bsznw6kc0hp7biylmmmll", - "type": "swarm" - }, - "cpus": 4, - "data_dir": "/data", - "default_pgedge_version": { - "postgres_version": "17.6", - "spock_version": "5" - }, - "etcd_mode": "server", - "id": "de3b1388-1f0c-42f1-a86c-59ab72f255ec", - "memory": "16GiB", - "orchestrator": "swarm", - "peer_addresses": [ - "10.24.34.2", - "i-0123456789abcdef.ec2.internal" - ], - "status": { - "components": { - "Enim et voluptatum ex ea dolore.": { - "details": { - "alarms": [ - "3: NOSPACE" - ] - }, - "error": "failed to connect to etcd", - "healthy": false - }, - "Tenetur nostrum repellendus sint qui.": { - "details": { - "alarms": [ - "3: NOSPACE" - ] - }, - "error": "failed to connect to etcd", - "healthy": false - } - }, - "state": "available", - "updated_at": "2021-07-01T12:34:56Z" - }, - "supported_pgedge_versions": [ - { - "postgres_version": "17.6", - "spock_version": "5" - }, - { - "postgres_version": "17.6", - "spock_version": "5" - }, - { - "postgres_version": "17.6", - "spock_version": "5" - } - ] - }, { "client_addresses": [ "10.24.34.2", @@ -24269,6 +25564,16 @@ "task_id": "019783f4-75f4-71e7-85a3-c9b96b345d77", "type": "create" }, + { + "completed_at": "2025-06-18T16:52:35Z", + "created_at": "2025-06-18T16:52:05Z", + "database_id": "storefront", + "entity_id": "storefront", + "scope": "database", + "status": "completed", + "task_id": "019783f4-75f4-71e7-85a3-c9b96b345d77", + "type": "create" + }, { "completed_at": "2025-06-18T16:52:35Z", "created_at": "2025-06-18T16:52:05Z", @@ -24445,26 +25750,6 @@ }, "description": "The tasks that will update databases affected by the host removal.", "example": [ - { - "completed_at": "2025-06-18T16:52:35Z", - "created_at": "2025-06-18T16:52:05Z", - "database_id": "storefront", - "entity_id": "storefront", - "scope": "database", - "status": "completed", - "task_id": "019783f4-75f4-71e7-85a3-c9b96b345d77", - "type": "create" - }, - { - "completed_at": "2025-06-18T16:52:35Z", - "created_at": "2025-06-18T16:52:05Z", - "database_id": "storefront", - "entity_id": "storefront", - "scope": "database", - "status": "completed", - "task_id": "019783f4-75f4-71e7-85a3-c9b96b345d77", - "type": "create" - }, { "completed_at": "2025-06-18T16:52:35Z", "created_at": "2025-06-18T16:52:05Z", @@ -24578,7 +25863,7 @@ "maxLength": 32, "additionalProperties": { "type": "string", - "example": "Dolor autem eum." + "example": "Et aut aut." } }, "source_database_id": { @@ -24649,7 +25934,7 @@ "type": "array", "items": { "type": "string", - "example": "Sapiente placeat illo." + "example": "Dolore eos et sunt culpa animi dolor." }, "description": "The nodes to restore. Defaults to all nodes if empty or unspecified.", "example": [ @@ -24957,16 +26242,6 @@ "task_id": "019783f4-75f4-71e7-85a3-c9b96b345d77", "type": "create" }, - { - "completed_at": "2025-06-18T16:52:35Z", - "created_at": "2025-06-18T16:52:05Z", - "database_id": "storefront", - "entity_id": "storefront", - "scope": "database", - "status": "completed", - "task_id": "019783f4-75f4-71e7-85a3-c9b96b345d77", - "type": "create" - }, { "completed_at": "2025-06-18T16:52:35Z", "created_at": "2025-06-18T16:52:05Z", @@ -25226,7 +26501,7 @@ }, "additionalProperties": { "type": "string", - "example": "Aut omnis magnam aspernatur occaecati itaque dolores." + "example": "Accusamus alias ipsa qui." } }, "gcs_bucket": { @@ -25330,7 +26605,7 @@ "type": "array", "items": { "type": "string", - "example": "i3l", + "example": "i", "minLength": 1, "maxLength": 1024 }, @@ -25460,7 +26735,7 @@ "type": "array", "items": { "type": "string", - "example": "Eos et error vel nihil." + "example": "Et animi magnam velit vitae praesentium ad." }, "description": "The addresses of the host that's running this service instance.", "example": [ @@ -25532,16 +26807,6 @@ "image_version": "1.0.0", "last_health_at": "2025-01-28T10:00:00Z", "ports": [ - { - "container_port": 8080, - "host_port": 8080, - "name": "web-client" - }, - { - "container_port": 8080, - "host_port": 8080, - "name": "web-client" - }, { "container_port": 8080, "host_port": 8080, @@ -25594,7 +26859,6 @@ }, "description": "The IDs of the hosts that should run this service. One service instance will be created per host.", "example": [ - "de3b1388-1f0c-42f1-a86c-59ab72f255ec", "de3b1388-1f0c-42f1-a86c-59ab72f255ec" ], "minItems": 1 @@ -25763,6 +27027,7 @@ }, "description": "The IDs of the hosts that should run this service. One service instance will be created per host.", "example": [ + "76f9b8c0-4958-11f0-a489-3bb29577c696", "76f9b8c0-4958-11f0-a489-3bb29577c696" ], "minItems": 1 @@ -25824,6 +27089,7 @@ "target_session_attrs": "primary" }, "host_ids": [ + "76f9b8c0-4958-11f0-a489-3bb29577c696", "76f9b8c0-4958-11f0-a489-3bb29577c696", "76f9b8c0-4958-11f0-a489-3bb29577c696" ], @@ -25932,6 +27198,7 @@ }, "description": "The IDs of the hosts that should run this service. One service instance will be created per host.", "example": [ + "76f9b8c0-4958-11f0-a489-3bb29577c696", "76f9b8c0-4958-11f0-a489-3bb29577c696" ], "minItems": 1 @@ -25993,7 +27260,6 @@ "target_session_attrs": "primary" }, "host_ids": [ - "76f9b8c0-4958-11f0-a489-3bb29577c696", "76f9b8c0-4958-11f0-a489-3bb29577c696", "76f9b8c0-4958-11f0-a489-3bb29577c696" ], @@ -26102,7 +27368,6 @@ }, "description": "The IDs of the hosts that should run this service. One service instance will be created per host.", "example": [ - "76f9b8c0-4958-11f0-a489-3bb29577c696", "76f9b8c0-4958-11f0-a489-3bb29577c696" ], "minItems": 1 @@ -26273,8 +27538,6 @@ }, "description": "The IDs of the hosts that should run this service. One service instance will be created per host.", "example": [ - "76f9b8c0-4958-11f0-a489-3bb29577c696", - "76f9b8c0-4958-11f0-a489-3bb29577c696", "76f9b8c0-4958-11f0-a489-3bb29577c696" ], "minItems": 1 @@ -26336,8 +27599,6 @@ "target_session_attrs": "primary" }, "host_ids": [ - "76f9b8c0-4958-11f0-a489-3bb29577c696", - "76f9b8c0-4958-11f0-a489-3bb29577c696", "76f9b8c0-4958-11f0-a489-3bb29577c696" ], "memory": "512M", @@ -26445,7 +27706,6 @@ }, "description": "The IDs of the hosts that should run this service. One service instance will be created per host.", "example": [ - "76f9b8c0-4958-11f0-a489-3bb29577c696", "76f9b8c0-4958-11f0-a489-3bb29577c696", "76f9b8c0-4958-11f0-a489-3bb29577c696" ], @@ -26678,6 +27938,7 @@ "target_session_attrs": "primary" }, "host_ids": [ + "76f9b8c0-4958-11f0-a489-3bb29577c696", "76f9b8c0-4958-11f0-a489-3bb29577c696" ], "memory": "512M", @@ -26808,7 +28069,7 @@ }, "additionalProperties": { "type": "string", - "example": "Rem culpa." + "example": "Error eligendi recusandae similique sed neque eos." } }, "extra_networks": { diff --git a/api/apiv1/gen/http/openapi3.yaml b/api/apiv1/gen/http/openapi3.yaml index f95e0f5a..7e7c8e6f 100644 --- a/api/apiv1/gen/http/openapi3.yaml +++ b/api/apiv1/gen/http/openapi3.yaml @@ -1142,17 +1142,18 @@ paths: type: array items: type: string - example: Doloribus consequatur voluptatibus sed et nisi. + example: Qui excepturi debitis aperiam rerum at. description: Host IDs to treat as removed during this update. Events targeting these hosts will be skipped. example: - - Perspiciatis et veniam blanditiis et. - - Repellat fuga occaecati optio accusantium. - - Voluptatibus sunt deserunt sapiente doloribus est. + - Facilis autem molestiae voluptatem. + - Dolorem sed alias est mollitia. + - Possimus id laudantium sed delectus. + - Ut distinctio expedita. example: - - Officiis sint. - - Ad aut velit distinctio sed. - - Rem voluptas qui. - - Voluptatem nesciunt dignissimos voluptas vel earum. + - Esse odit placeat quod facere. + - Sit commodi in dolor unde optio illo. + - Sint cumque quia non. + - Perferendis doloremque nam cumque. - name: database_id in: path description: ID of the database to update. @@ -3896,7 +3897,7 @@ components: key: value additionalProperties: type: string - example: Quibusdam veniam. + example: Ipsa et et. backup_options: type: object description: Options for the backup. @@ -3904,7 +3905,7 @@ components: archive-check: "n" additionalProperties: type: string - example: Non expedita sequi eligendi delectus sit quas. + example: Et nam quo qui qui natus. type: type: string description: The type of backup. @@ -3960,7 +3961,7 @@ components: storage-upload-chunk-size: 5MiB additionalProperties: type: string - example: Placeat a. + example: Ut dolorem. gcs_bucket: type: string description: The GCS bucket name for this repository. Only applies when type = 'gcs'. @@ -4399,7 +4400,7 @@ components: type: array items: type: string - example: 76l + example: k0t minLength: 3 maxLength: 128 description: The peer addresses of the host that's joining the cluster. @@ -4440,7 +4441,7 @@ components: type: array items: type: string - example: Quasi ipsum officiis et est et. + example: Placeat temporibus aut. description: Existing server to join example: - http://192.168.1.1:3000 @@ -4461,7 +4462,7 @@ components: state: type: string description: The current state of the cluster. - example: available + example: error enum: - available - error @@ -4692,7 +4693,7 @@ components: - 10.24.34.2 - i-0123456789abcdef.ec2.internal port: 5432 - created_at: "1970-12-24T01:48:39Z" + created_at: "2001-11-21T07:07:15Z" error: 'failed to get patroni status: connection refused' host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d @@ -4700,7 +4701,7 @@ components: postgres: patroni_paused: true patroni_state: unknown - pending_restart: true + pending_restart: false role: primary version: "18.1" spock: @@ -4712,16 +4713,19 @@ components: - name: sub_n1n2 provider_node: n2 status: down + - name: sub_n1n2 + provider_node: n2 + status: down version: 4.10.0 - state: unknown - status_updated_at: "1978-12-17T01:14:06Z" - updated_at: "2010-08-13T18:38:44Z" + state: degraded + status_updated_at: "1990-07-23T01:22:30Z" + updated_at: "2013-01-29T23:51:44Z" - connection_info: addresses: - 10.24.34.2 - i-0123456789abcdef.ec2.internal port: 5432 - created_at: "1970-12-24T01:48:39Z" + created_at: "2001-11-21T07:07:15Z" error: 'failed to get patroni status: connection refused' host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d @@ -4729,7 +4733,7 @@ components: postgres: patroni_paused: true patroni_state: unknown - pending_restart: true + pending_restart: false role: primary version: "18.1" spock: @@ -4741,16 +4745,19 @@ components: - name: sub_n1n2 provider_node: n2 status: down + - name: sub_n1n2 + provider_node: n2 + status: down version: 4.10.0 - state: unknown - status_updated_at: "1978-12-17T01:14:06Z" - updated_at: "2010-08-13T18:38:44Z" + state: degraded + status_updated_at: "1990-07-23T01:22:30Z" + updated_at: "2013-01-29T23:51:44Z" - connection_info: addresses: - 10.24.34.2 - i-0123456789abcdef.ec2.internal port: 5432 - created_at: "1970-12-24T01:48:39Z" + created_at: "2001-11-21T07:07:15Z" error: 'failed to get patroni status: connection refused' host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d @@ -4758,7 +4765,39 @@ components: postgres: patroni_paused: true patroni_state: unknown - pending_restart: true + pending_restart: false + role: primary + version: "18.1" + spock: + read_only: "off" + subscriptions: + - name: sub_n1n2 + provider_node: n2 + status: down + - name: sub_n1n2 + provider_node: n2 + status: down + - name: sub_n1n2 + provider_node: n2 + status: down + version: 4.10.0 + state: degraded + status_updated_at: "1990-07-23T01:22:30Z" + updated_at: "2013-01-29T23:51:44Z" + - connection_info: + addresses: + - 10.24.34.2 + - i-0123456789abcdef.ec2.internal + port: 5432 + created_at: "2001-11-21T07:07:15Z" + error: 'failed to get patroni status: connection refused' + host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec + id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d + node_name: n1 + postgres: + patroni_paused: true + patroni_state: unknown + pending_restart: false role: primary version: "18.1" spock: @@ -4770,10 +4809,13 @@ components: - name: sub_n1n2 provider_node: n2 status: down + - name: sub_n1n2 + provider_node: n2 + status: down version: 4.10.0 - state: unknown - status_updated_at: "1978-12-17T01:14:06Z" - updated_at: "2010-08-13T18:38:44Z" + state: degraded + status_updated_at: "1990-07-23T01:22:30Z" + updated_at: "2013-01-29T23:51:44Z" service_instances: type: array items: @@ -4845,7 +4887,7 @@ components: state: type: string description: Current state of the database. - example: available + example: creating enum: - creating - modifying @@ -5092,6 +5134,38 @@ components: state: available status_updated_at: "1993-04-25T23:06:28Z" updated_at: "1981-08-22T23:20:01Z" + - connection_info: + addresses: + - 10.24.34.2 + - i-0123456789abcdef.ec2.internal + port: 5432 + created_at: "2011-03-15T17:48:48Z" + error: 'failed to get patroni status: connection refused' + host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec + id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d + node_name: n1 + postgres: + patroni_paused: false + patroni_state: unknown + pending_restart: true + role: primary + version: "18.1" + spock: + read_only: "off" + subscriptions: + - name: sub_n1n2 + provider_node: n2 + status: down + - name: sub_n1n2 + provider_node: n2 + status: down + - name: sub_n1n2 + provider_node: n2 + status: down + version: 4.10.0 + state: available + status_updated_at: "1993-04-25T23:06:28Z" + updated_at: "1981-08-22T23:20:01Z" service_instances: type: array items: @@ -5164,78 +5238,12 @@ components: name: web-client service_ready: true updated_at: "2025-01-28T10:05:00Z" - - created_at: "2025-01-28T10:00:00Z" - database_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - error: 'failed to start container: image not found' - host_id: host-1 - service_id: mcp-server - service_instance_id: mcp-server-host-1 - state: running - status: - addresses: - - 10.24.34.2 - - i-0123456789abcdef.ec2.internal - container_id: a1b2c3d4e5f6 - health_check: - checked_at: "2025-01-28T10:00:00Z" - message: Connection refused - status: healthy - image_version: 1.0.0 - last_health_at: "2025-01-28T10:00:00Z" - ports: - - container_port: 8080 - host_port: 8080 - name: web-client - - container_port: 8080 - host_port: 8080 - name: web-client - - container_port: 8080 - host_port: 8080 - name: web-client - - container_port: 8080 - host_port: 8080 - name: web-client - service_ready: true - updated_at: "2025-01-28T10:05:00Z" - - created_at: "2025-01-28T10:00:00Z" - database_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - error: 'failed to start container: image not found' - host_id: host-1 - service_id: mcp-server - service_instance_id: mcp-server-host-1 - state: running - status: - addresses: - - 10.24.34.2 - - i-0123456789abcdef.ec2.internal - container_id: a1b2c3d4e5f6 - health_check: - checked_at: "2025-01-28T10:00:00Z" - message: Connection refused - status: healthy - image_version: 1.0.0 - last_health_at: "2025-01-28T10:00:00Z" - ports: - - container_port: 8080 - host_port: 8080 - name: web-client - - container_port: 8080 - host_port: 8080 - name: web-client - - container_port: 8080 - host_port: 8080 - name: web-client - - container_port: 8080 - host_port: 8080 - name: web-client - service_ready: true - updated_at: "2025-01-28T10:05:00Z" spec: $ref: '#/components/schemas/DatabaseSpec3' state: type: string description: Current state of the database. - example: modifying + example: unknown enum: - creating - modifying @@ -5482,6 +5490,38 @@ components: state: available status_updated_at: "1993-04-25T23:06:28Z" updated_at: "1981-08-22T23:20:01Z" + - connection_info: + addresses: + - 10.24.34.2 + - i-0123456789abcdef.ec2.internal + port: 5432 + created_at: "2011-03-15T17:48:48Z" + error: 'failed to get patroni status: connection refused' + host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec + id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d + node_name: n1 + postgres: + patroni_paused: false + patroni_state: unknown + pending_restart: true + role: primary + version: "18.1" + spock: + read_only: "off" + subscriptions: + - name: sub_n1n2 + provider_node: n2 + status: down + - name: sub_n1n2 + provider_node: n2 + status: down + - name: sub_n1n2 + provider_node: n2 + status: down + version: 4.10.0 + state: available + status_updated_at: "1993-04-25T23:06:28Z" + updated_at: "1981-08-22T23:20:01Z" service_instances: type: array items: @@ -5554,12 +5594,78 @@ components: name: web-client service_ready: true updated_at: "2025-01-28T10:05:00Z" + - created_at: "2025-01-28T10:00:00Z" + database_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + error: 'failed to start container: image not found' + host_id: host-1 + service_id: mcp-server + service_instance_id: mcp-server-host-1 + state: running + status: + addresses: + - 10.24.34.2 + - i-0123456789abcdef.ec2.internal + container_id: a1b2c3d4e5f6 + health_check: + checked_at: "2025-01-28T10:00:00Z" + message: Connection refused + status: healthy + image_version: 1.0.0 + last_health_at: "2025-01-28T10:00:00Z" + ports: + - container_port: 8080 + host_port: 8080 + name: web-client + - container_port: 8080 + host_port: 8080 + name: web-client + - container_port: 8080 + host_port: 8080 + name: web-client + - container_port: 8080 + host_port: 8080 + name: web-client + service_ready: true + updated_at: "2025-01-28T10:05:00Z" + - created_at: "2025-01-28T10:00:00Z" + database_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + error: 'failed to start container: image not found' + host_id: host-1 + service_id: mcp-server + service_instance_id: mcp-server-host-1 + state: running + status: + addresses: + - 10.24.34.2 + - i-0123456789abcdef.ec2.internal + container_id: a1b2c3d4e5f6 + health_check: + checked_at: "2025-01-28T10:00:00Z" + message: Connection refused + status: healthy + image_version: 1.0.0 + last_health_at: "2025-01-28T10:00:00Z" + ports: + - container_port: 8080 + host_port: 8080 + name: web-client + - container_port: 8080 + host_port: 8080 + name: web-client + - container_port: 8080 + host_port: 8080 + name: web-client + - container_port: 8080 + host_port: 8080 + name: web-client + service_ready: true + updated_at: "2025-01-28T10:05:00Z" spec: $ref: '#/components/schemas/DatabaseSpec4' state: type: string description: Current state of the database. - example: degraded + example: deleting enum: - creating - modifying @@ -6196,76 +6302,45 @@ components: state: available status_updated_at: "1993-04-25T23:06:28Z" updated_at: "1981-08-22T23:20:01Z" - - connection_info: + service_instances: + type: array + items: + $ref: '#/components/schemas/ServiceInstance' + description: Service instances running alongside this database. + example: + - created_at: "2025-01-28T10:00:00Z" + database_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + error: 'failed to start container: image not found' + host_id: host-1 + service_id: mcp-server + service_instance_id: mcp-server-host-1 + state: running + status: addresses: - 10.24.34.2 - i-0123456789abcdef.ec2.internal - port: 5432 - created_at: "2011-03-15T17:48:48Z" - error: 'failed to get patroni status: connection refused' - host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec - id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d - node_name: n1 - postgres: - patroni_paused: false - patroni_state: unknown - pending_restart: true - role: primary - version: "18.1" - spock: - read_only: "off" - subscriptions: - - name: sub_n1n2 - provider_node: n2 - status: down - - name: sub_n1n2 - provider_node: n2 - status: down - - name: sub_n1n2 - provider_node: n2 - status: down - version: 4.10.0 - state: available - status_updated_at: "1993-04-25T23:06:28Z" - updated_at: "1981-08-22T23:20:01Z" - - connection_info: - addresses: - - 10.24.34.2 - - i-0123456789abcdef.ec2.internal - port: 5432 - created_at: "2011-03-15T17:48:48Z" - error: 'failed to get patroni status: connection refused' - host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec - id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d - node_name: n1 - postgres: - patroni_paused: false - patroni_state: unknown - pending_restart: true - role: primary - version: "18.1" - spock: - read_only: "off" - subscriptions: - - name: sub_n1n2 - provider_node: n2 - status: down - - name: sub_n1n2 - provider_node: n2 - status: down - - name: sub_n1n2 - provider_node: n2 - status: down - version: 4.10.0 - state: available - status_updated_at: "1993-04-25T23:06:28Z" - updated_at: "1981-08-22T23:20:01Z" - service_instances: - type: array - items: - $ref: '#/components/schemas/ServiceInstance' - description: Service instances running alongside this database. - example: + container_id: a1b2c3d4e5f6 + health_check: + checked_at: "2025-01-28T10:00:00Z" + message: Connection refused + status: healthy + image_version: 1.0.0 + last_health_at: "2025-01-28T10:00:00Z" + ports: + - container_port: 8080 + host_port: 8080 + name: web-client + - container_port: 8080 + host_port: 8080 + name: web-client + - container_port: 8080 + host_port: 8080 + name: web-client + - container_port: 8080 + host_port: 8080 + name: web-client + service_ready: true + updated_at: "2025-01-28T10:05:00Z" - created_at: "2025-01-28T10:00:00Z" database_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 error: 'failed to start container: image not found' @@ -6337,7 +6412,7 @@ components: state: type: string description: Current state of the database. - example: unknown + example: failed enum: - creating - modifying @@ -6475,7 +6550,7 @@ components: type: array items: type: string - example: Ab sed exercitationem rerum animi et itaque. + example: Eius at. description: Optional ordered list of database node names. When set, the service's database connection includes only the listed nodes in the specified order. example: - n1 @@ -6517,6 +6592,8 @@ components: description: The IDs of the hosts that should run this node. When multiple hosts are specified, one host will chosen as a primary, and the others will be read replicas. example: - de3b1388-1f0c-42f1-a86c-59ab72f255ec + - de3b1388-1f0c-42f1-a86c-59ab72f255ec + - de3b1388-1f0c-42f1-a86c-59ab72f255ec minItems: 1 memory: type: string @@ -6537,6 +6614,22 @@ components: format: int64 minimum: 0 maximum: 65535 + pg_hba_conf: + type: array + items: + type: string + example: Modi explicabo. + description: Additional pg_hba.conf entries for this particular node, one rule per array element. Prepended to the database-level pg_hba_conf entries, so node entries take first-match priority. Entries are inserted between control-plane's system-user rules and its catch-all, and cannot affect control-plane-internal connectivity. + example: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + type: array + items: + type: string + example: Alias qui et eius. + description: Additional pg_ident.conf entries for this particular node, one mapping per array element. Prepended to the database-level pg_ident_conf entries. + example: + - ssl_users CN=alice,O=example alice port: type: integer description: The port used by the Postgres database for this node. Overrides the Postgres port set in the DatabaseSpec. @@ -6618,6 +6711,7 @@ components: host_ids: - de3b1388-1f0c-42f1-a86c-59ab72f255ec - de3b1388-1f0c-42f1-a86c-59ab72f255ec + - de3b1388-1f0c-42f1-a86c-59ab72f255ec memory: 500M name: n1 orchestrator_opts: @@ -6652,6 +6746,10 @@ components: - destination_path: /backups/container host_path: /Users/user/backups/host patroni_port: 8888 + pg_hba_conf: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + - ssl_users CN=alice,O=example alice port: 5432 postgres_version: "17.6" postgresql_conf: @@ -6707,6 +6805,7 @@ components: example: - 76f9b8c0-4958-11f0-a489-3bb29577c696 - 76f9b8c0-4958-11f0-a489-3bb29577c696 + - 76f9b8c0-4958-11f0-a489-3bb29577c696 minItems: 1 memory: type: string @@ -6727,6 +6826,22 @@ components: format: int64 minimum: 0 maximum: 65535 + pg_hba_conf: + type: array + items: + type: string + example: Ut quae eos. + description: Additional pg_hba.conf entries for this particular node, one rule per array element. Prepended to the database-level pg_hba_conf entries, so node entries take first-match priority. Entries are inserted between control-plane's system-user rules and its catch-all, and cannot affect control-plane-internal connectivity. + example: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + type: array + items: + type: string + example: Voluptates quo. + description: Additional pg_ident.conf entries for this particular node, one mapping per array element. Prepended to the database-level pg_ident_conf entries. + example: + - ssl_users CN=alice,O=example alice port: type: integer description: The port used by the Postgres database for this node. Overrides the Postgres port set in the DatabaseSpec. @@ -6827,8 +6942,6 @@ components: cpus: 500m host_ids: - 76f9b8c0-4958-11f0-a489-3bb29577c696 - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - - 76f9b8c0-4958-11f0-a489-3bb29577c696 memory: 500M name: n1 orchestrator_opts: @@ -6863,6 +6976,10 @@ components: - destination_path: /backups/container host_path: /Users/user/backups/host patroni_port: 8888 + pg_hba_conf: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + - ssl_users CN=alice,O=example alice port: 5432 postgres_version: "17.6" postgresql_conf: @@ -6917,8 +7034,6 @@ components: description: The IDs of the hosts that should run this node. When multiple hosts are specified, one host will chosen as a primary, and the others will be read replicas. example: - 76f9b8c0-4958-11f0-a489-3bb29577c696 - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - - 76f9b8c0-4958-11f0-a489-3bb29577c696 minItems: 1 memory: type: string @@ -6939,6 +7054,22 @@ components: format: int64 minimum: 0 maximum: 65535 + pg_hba_conf: + type: array + items: + type: string + example: Distinctio atque. + description: Additional pg_hba.conf entries for this particular node, one rule per array element. Prepended to the database-level pg_hba_conf entries, so node entries take first-match priority. Entries are inserted between control-plane's system-user rules and its catch-all, and cannot affect control-plane-internal connectivity. + example: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + type: array + items: + type: string + example: Autem doloremque et excepturi. + description: Additional pg_ident.conf entries for this particular node, one mapping per array element. Prepended to the database-level pg_ident_conf entries. + example: + - ssl_users CN=alice,O=example alice port: type: integer description: The port used by the Postgres database for this node. Overrides the Postgres port set in the DatabaseSpec. @@ -7075,6 +7206,10 @@ components: - destination_path: /backups/container host_path: /Users/user/backups/host patroni_port: 8888 + pg_hba_conf: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + - ssl_users CN=alice,O=example alice port: 5432 postgres_version: "17.6" postgresql_conf: @@ -7129,8 +7264,6 @@ components: description: The IDs of the hosts that should run this node. When multiple hosts are specified, one host will chosen as a primary, and the others will be read replicas. example: - 76f9b8c0-4958-11f0-a489-3bb29577c696 - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - - 76f9b8c0-4958-11f0-a489-3bb29577c696 minItems: 1 memory: type: string @@ -7151,6 +7284,22 @@ components: format: int64 minimum: 0 maximum: 65535 + pg_hba_conf: + type: array + items: + type: string + example: Est temporibus molestias officiis sint. + description: Additional pg_hba.conf entries for this particular node, one rule per array element. Prepended to the database-level pg_hba_conf entries, so node entries take first-match priority. Entries are inserted between control-plane's system-user rules and its catch-all, and cannot affect control-plane-internal connectivity. + example: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + type: array + items: + type: string + example: Ad aut velit distinctio sed. + description: Additional pg_ident.conf entries for this particular node, one mapping per array element. Prepended to the database-level pg_ident_conf entries. + example: + - ssl_users CN=alice,O=example alice port: type: integer description: The port used by the Postgres database for this node. Overrides the Postgres port set in the DatabaseSpec. @@ -7285,6 +7434,10 @@ components: - destination_path: /backups/container host_path: /Users/user/backups/host patroni_port: 8888 + pg_hba_conf: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + - ssl_users CN=alice,O=example alice port: 5432 postgres_version: "17.6" postgresql_conf: @@ -7339,8 +7492,6 @@ components: description: The IDs of the hosts that should run this node. When multiple hosts are specified, one host will chosen as a primary, and the others will be read replicas. example: - 76f9b8c0-4958-11f0-a489-3bb29577c696 - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - - 76f9b8c0-4958-11f0-a489-3bb29577c696 minItems: 1 memory: type: string @@ -7361,6 +7512,22 @@ components: format: int64 minimum: 0 maximum: 65535 + pg_hba_conf: + type: array + items: + type: string + example: Quaerat rem. + description: Additional pg_hba.conf entries for this particular node, one rule per array element. Prepended to the database-level pg_hba_conf entries, so node entries take first-match priority. Entries are inserted between control-plane's system-user rules and its catch-all, and cannot affect control-plane-internal connectivity. + example: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + type: array + items: + type: string + example: Qui numquam incidunt eaque totam at. + description: Additional pg_ident.conf entries for this particular node, one mapping per array element. Prepended to the database-level pg_ident_conf entries. + example: + - ssl_users CN=alice,O=example alice port: type: integer description: The port used by the Postgres database for this node. Overrides the Postgres port set in the DatabaseSpec. @@ -7462,6 +7629,7 @@ components: host_ids: - 76f9b8c0-4958-11f0-a489-3bb29577c696 - 76f9b8c0-4958-11f0-a489-3bb29577c696 + - 76f9b8c0-4958-11f0-a489-3bb29577c696 memory: 500M name: n1 orchestrator_opts: @@ -7496,6 +7664,10 @@ components: - destination_path: /backups/container host_path: /Users/user/backups/host patroni_port: 8888 + pg_hba_conf: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + - ssl_users CN=alice,O=example alice port: 5432 postgres_version: "17.6" postgresql_conf: @@ -7551,6 +7723,7 @@ components: example: - 76f9b8c0-4958-11f0-a489-3bb29577c696 - 76f9b8c0-4958-11f0-a489-3bb29577c696 + - 76f9b8c0-4958-11f0-a489-3bb29577c696 minItems: 1 memory: type: string @@ -7571,6 +7744,22 @@ components: format: int64 minimum: 0 maximum: 65535 + pg_hba_conf: + type: array + items: + type: string + example: Occaecati et et consequuntur. + description: Additional pg_hba.conf entries for this particular node, one rule per array element. Prepended to the database-level pg_hba_conf entries, so node entries take first-match priority. Entries are inserted between control-plane's system-user rules and its catch-all, and cannot affect control-plane-internal connectivity. + example: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + type: array + items: + type: string + example: Qui et nulla omnis nobis dolor. + description: Additional pg_ident.conf entries for this particular node, one mapping per array element. Prepended to the database-level pg_ident_conf entries. + example: + - ssl_users CN=alice,O=example alice port: type: integer description: The port used by the Postgres database for this node. Overrides the Postgres port set in the DatabaseSpec. @@ -7671,7 +7860,6 @@ components: cpus: 500m host_ids: - 76f9b8c0-4958-11f0-a489-3bb29577c696 - - 76f9b8c0-4958-11f0-a489-3bb29577c696 memory: 500M name: n1 orchestrator_opts: @@ -7706,6 +7894,10 @@ components: - destination_path: /backups/container host_path: /Users/user/backups/host patroni_port: 8888 + pg_hba_conf: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + - ssl_users CN=alice,O=example alice port: 5432 postgres_version: "17.6" postgresql_conf: @@ -7780,6 +7972,22 @@ components: format: int64 minimum: 0 maximum: 65535 + pg_hba_conf: + type: array + items: + type: string + example: Ducimus deserunt quis commodi officiis libero mollitia. + description: Additional pg_hba.conf entries for this particular node, one rule per array element. Prepended to the database-level pg_hba_conf entries, so node entries take first-match priority. Entries are inserted between control-plane's system-user rules and its catch-all, and cannot affect control-plane-internal connectivity. + example: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + type: array + items: + type: string + example: Impedit ab. + description: Additional pg_ident.conf entries for this particular node, one mapping per array element. Prepended to the database-level pg_ident_conf entries. + example: + - ssl_users CN=alice,O=example alice port: type: integer description: The port used by the Postgres database for this node. Overrides the Postgres port set in the DatabaseSpec. @@ -7880,7 +8088,6 @@ components: cpus: 500m host_ids: - 76f9b8c0-4958-11f0-a489-3bb29577c696 - - 76f9b8c0-4958-11f0-a489-3bb29577c696 memory: 500M name: n1 orchestrator_opts: @@ -7915,6 +8122,10 @@ components: - destination_path: /backups/container host_path: /Users/user/backups/host patroni_port: 8888 + pg_hba_conf: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + - ssl_users CN=alice,O=example alice port: 5432 postgres_version: "17.6" postgresql_conf: @@ -8113,6 +8324,10 @@ components: - destination_path: /backups/container host_path: /Users/user/backups/host patroni_port: 8888 + pg_hba_conf: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + - ssl_users CN=alice,O=example alice port: 5432 postgres_version: "17.6" postgresql_conf: @@ -8155,6 +8370,23 @@ components: format: int64 minimum: 0 maximum: 65535 + pg_hba_conf: + type: array + items: + type: string + example: Reprehenderit harum sapiente qui ullam qui. + description: Additional pg_hba.conf entries, one rule per array element. Inserted between control-plane's system-user rules and its catch-all, so they cannot affect control-plane-internal connectivity (Patroni, replication, health checks). Node-level pg_hba_conf entries are prepended to these. + example: + - hostssl all myapp_user 203.0.113.0/24 scram-sha-256 + - hostssl all alice 0.0.0.0/0 cert clientcert=verify-full map=ssl_users + pg_ident_conf: + type: array + items: + type: string + example: Sint iure eum ducimus quia deserunt animi. + description: Additional pg_ident.conf entries, one mapping per array element. Purely additive; control-plane writes no pg_ident entries of its own. The primary use case is cert auth with map= translating certificate CNs to PostgreSQL usernames. + example: + - ssl_users CN=alice,O=example alice port: type: integer description: The port used by the Postgres database. If the port is 0, each instance will be assigned a random port. If the port is unspecified, the database will not be exposed on any port, dependent on orchestrator support for that feature. @@ -8198,7 +8430,6 @@ components: host_ids: - de3b1388-1f0c-42f1-a86c-59ab72f255ec - de3b1388-1f0c-42f1-a86c-59ab72f255ec - - de3b1388-1f0c-42f1-a86c-59ab72f255ec memory: 512M orchestrator_opts: swarm: @@ -8249,7 +8480,6 @@ components: host_ids: - de3b1388-1f0c-42f1-a86c-59ab72f255ec - de3b1388-1f0c-42f1-a86c-59ab72f255ec - - de3b1388-1f0c-42f1-a86c-59ab72f255ec memory: 512M orchestrator_opts: swarm: @@ -8465,6 +8695,10 @@ components: - destination_path: /backups/container host_path: /Users/user/backups/host patroni_port: 8888 + pg_hba_conf: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + - ssl_users CN=alice,O=example alice port: 5432 postgres_version: "17.6" postgresql_conf: @@ -8496,143 +8730,63 @@ components: source_database_name: northwind source_node_name: n1 source_node: n1 - orchestrator_opts: - swarm: - extra_labels: - traefik.enable: "true" - traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) - extra_networks: - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - extra_volumes: - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - patroni_port: 8888 - port: 5432 - postgres_version: "17.6" - postgresql_conf: - max_connections: 1000 - restore_config: - repository: - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: f6b84a99-5e91-4203-be1e-131fe82e5984 - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - restore_options: - set: 20250505-153628F - target: "123456" - type: xid - source_database_id: 02f1a7db-fca8-4521-b57a-2a375c1ced51 - source_database_name: northwind - source_node_name: n1 - scripts: - post_database_create: - - ALTER DEFAULT PRIVILEGES FOR ROLE admin GRANT USAGE ON SCHEMAS TO app - - ALTER DEFAULT PRIVILEGES FOR ROLE admin GRANT ALL PRIVILEGES ON TABLES TO app - - ALTER DEFAULT PRIVILEGES FOR ROLE admin GRANT ALL PRIVILEGES ON SEQUENCES TO app - post_init: - - CREATE ROLE accounting_admin NOLOGIN - services: - - config: - llm_model: gpt-4 - llm_provider: openai - openai_api_key: sk-... - connect_as: app - cpus: 500m - database_connection: - target_nodes: - - n1 - - n2 - target_session_attrs: primary - host_ids: - - de3b1388-1f0c-42f1-a86c-59ab72f255ec - - de3b1388-1f0c-42f1-a86c-59ab72f255ec - - de3b1388-1f0c-42f1-a86c-59ab72f255ec - memory: 512M - orchestrator_opts: - swarm: - extra_labels: - traefik.enable: "true" - traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) - extra_networks: - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - extra_volumes: - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - port: 0 - service_id: analytics-service - service_type: rag - version: latest - - config: - llm_model: gpt-4 - llm_provider: openai - openai_api_key: sk-... - connect_as: app + - backup_config: + repositories: + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: f6b84a99-5e91-4203-be1e-131fe82e5984 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: f6b84a99-5e91-4203-be1e-131fe82e5984 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + schedules: + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full cpus: 500m - database_connection: - target_nodes: - - n1 - - n2 - target_session_attrs: primary host_ids: - de3b1388-1f0c-42f1-a86c-59ab72f255ec - - de3b1388-1f0c-42f1-a86c-59ab72f255ec - - de3b1388-1f0c-42f1-a86c-59ab72f255ec - memory: 512M + memory: 500M + name: n1 orchestrator_opts: swarm: extra_labels: @@ -8664,26 +8818,99 @@ components: host_path: /Users/user/backups/host - destination_path: /backups/container host_path: /Users/user/backups/host - port: 0 - service_id: analytics-service - service_type: rag - version: latest - - config: - llm_model: gpt-4 - llm_provider: openai - openai_api_key: sk-... - connect_as: app + patroni_port: 8888 + pg_hba_conf: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + - ssl_users CN=alice,O=example alice + port: 5432 + postgres_version: "17.6" + postgresql_conf: + max_connections: 1000 + restore_config: + repository: + azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: f6b84a99-5e91-4203-be1e-131fe82e5984 + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + restore_options: + set: 20250505-153628F + target: "123456" + type: xid + source_database_id: 02f1a7db-fca8-4521-b57a-2a375c1ced51 + source_database_name: northwind + source_node_name: n1 + source_node: n1 + - backup_config: + repositories: + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: f6b84a99-5e91-4203-be1e-131fe82e5984 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: f6b84a99-5e91-4203-be1e-131fe82e5984 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + schedules: + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full cpus: 500m - database_connection: - target_nodes: - - n1 - - n2 - target_session_attrs: primary host_ids: - de3b1388-1f0c-42f1-a86c-59ab72f255ec - - de3b1388-1f0c-42f1-a86c-59ab72f255ec - - de3b1388-1f0c-42f1-a86c-59ab72f255ec - memory: 512M + memory: 500M + name: n1 orchestrator_opts: swarm: extra_labels: @@ -8715,56 +8942,312 @@ components: host_path: /Users/user/backups/host - destination_path: /backups/container host_path: /Users/user/backups/host - port: 0 - service_id: analytics-service - service_type: rag - version: latest - - config: - llm_model: gpt-4 - llm_provider: openai - openai_api_key: sk-... - connect_as: app - cpus: 500m - database_connection: - target_nodes: - - n1 - - n2 - target_session_attrs: primary - host_ids: - - de3b1388-1f0c-42f1-a86c-59ab72f255ec - - de3b1388-1f0c-42f1-a86c-59ab72f255ec - - de3b1388-1f0c-42f1-a86c-59ab72f255ec - memory: 512M - orchestrator_opts: - swarm: - extra_labels: - traefik.enable: "true" - traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) - extra_networks: - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - extra_volumes: - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container + patroni_port: 8888 + pg_hba_conf: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + - ssl_users CN=alice,O=example alice + port: 5432 + postgres_version: "17.6" + postgresql_conf: + max_connections: 1000 + restore_config: + repository: + azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: f6b84a99-5e91-4203-be1e-131fe82e5984 + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + restore_options: + set: 20250505-153628F + target: "123456" + type: xid + source_database_id: 02f1a7db-fca8-4521-b57a-2a375c1ced51 + source_database_name: northwind + source_node_name: n1 + source_node: n1 + orchestrator_opts: + swarm: + extra_labels: + traefik.enable: "true" + traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) + extra_networks: + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + extra_volumes: + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + patroni_port: 8888 + pg_hba_conf: + - hostssl all myapp_user 203.0.113.0/24 scram-sha-256 + - hostssl all alice 0.0.0.0/0 cert clientcert=verify-full map=ssl_users + pg_ident_conf: + - ssl_users CN=alice,O=example alice + port: 5432 + postgres_version: "17.6" + postgresql_conf: + max_connections: 1000 + restore_config: + repository: + azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: f6b84a99-5e91-4203-be1e-131fe82e5984 + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + restore_options: + set: 20250505-153628F + target: "123456" + type: xid + source_database_id: 02f1a7db-fca8-4521-b57a-2a375c1ced51 + source_database_name: northwind + source_node_name: n1 + scripts: + post_database_create: + - ALTER DEFAULT PRIVILEGES FOR ROLE admin GRANT USAGE ON SCHEMAS TO app + - ALTER DEFAULT PRIVILEGES FOR ROLE admin GRANT ALL PRIVILEGES ON TABLES TO app + - ALTER DEFAULT PRIVILEGES FOR ROLE admin GRANT ALL PRIVILEGES ON SEQUENCES TO app + post_init: + - CREATE ROLE accounting_admin NOLOGIN + services: + - config: + llm_model: gpt-4 + llm_provider: openai + openai_api_key: sk-... + connect_as: app + cpus: 500m + database_connection: + target_nodes: + - n1 + - n2 + target_session_attrs: primary + host_ids: + - de3b1388-1f0c-42f1-a86c-59ab72f255ec + - de3b1388-1f0c-42f1-a86c-59ab72f255ec + memory: 512M + orchestrator_opts: + swarm: + extra_labels: + traefik.enable: "true" + traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) + extra_networks: + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + extra_volumes: + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + port: 0 + service_id: analytics-service + service_type: rag + version: latest + - config: + llm_model: gpt-4 + llm_provider: openai + openai_api_key: sk-... + connect_as: app + cpus: 500m + database_connection: + target_nodes: + - n1 + - n2 + target_session_attrs: primary + host_ids: + - de3b1388-1f0c-42f1-a86c-59ab72f255ec + - de3b1388-1f0c-42f1-a86c-59ab72f255ec + memory: 512M + orchestrator_opts: + swarm: + extra_labels: + traefik.enable: "true" + traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) + extra_networks: + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + extra_volumes: + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + port: 0 + service_id: analytics-service + service_type: rag + version: latest + - config: + llm_model: gpt-4 + llm_provider: openai + openai_api_key: sk-... + connect_as: app + cpus: 500m + database_connection: + target_nodes: + - n1 + - n2 + target_session_attrs: primary + host_ids: + - de3b1388-1f0c-42f1-a86c-59ab72f255ec + - de3b1388-1f0c-42f1-a86c-59ab72f255ec + memory: 512M + orchestrator_opts: + swarm: + extra_labels: + traefik.enable: "true" + traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) + extra_networks: + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + extra_volumes: + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + port: 0 + service_id: analytics-service + service_type: rag + version: latest + - config: + llm_model: gpt-4 + llm_provider: openai + openai_api_key: sk-... + connect_as: app + cpus: 500m + database_connection: + target_nodes: + - n1 + - n2 + target_session_attrs: primary + host_ids: + - de3b1388-1f0c-42f1-a86c-59ab72f255ec + - de3b1388-1f0c-42f1-a86c-59ab72f255ec + memory: 512M + orchestrator_opts: + swarm: + extra_labels: + traefik.enable: "true" + traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) + extra_networks: + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + extra_volumes: + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container host_path: /Users/user/backups/host port: 0 service_id: analytics-service @@ -8946,6 +9429,156 @@ components: - destination_path: /backups/container host_path: /Users/user/backups/host patroni_port: 8888 + pg_hba_conf: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + - ssl_users CN=alice,O=example alice + port: 5432 + postgres_version: "17.6" + postgresql_conf: + max_connections: 1000 + restore_config: + repository: + azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + restore_options: + set: 20250505-153628F + target: "123456" + type: xid + source_database_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + source_database_name: northwind + source_node_name: n1 + source_node: n1 + - backup_config: + repositories: + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + schedules: + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + cpus: 500m + host_ids: + - 76f9b8c0-4958-11f0-a489-3bb29577c696 + - 76f9b8c0-4958-11f0-a489-3bb29577c696 + - 76f9b8c0-4958-11f0-a489-3bb29577c696 + memory: 500M + name: n1 + orchestrator_opts: + swarm: + extra_labels: + traefik.enable: "true" + traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) + extra_networks: + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + extra_volumes: + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + patroni_port: 8888 + pg_hba_conf: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + - ssl_users CN=alice,O=example alice port: 5432 postgres_version: "17.6" postgresql_conf: @@ -9088,6 +9721,10 @@ components: - destination_path: /backups/container host_path: /Users/user/backups/host patroni_port: 8888 + pg_hba_conf: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + - ssl_users CN=alice,O=example alice port: 5432 postgres_version: "17.6" postgresql_conf: @@ -9130,6 +9767,23 @@ components: format: int64 minimum: 0 maximum: 65535 + pg_hba_conf: + type: array + items: + type: string + example: Est asperiores quis in sunt dignissimos. + description: Additional pg_hba.conf entries, one rule per array element. Inserted between control-plane's system-user rules and its catch-all, so they cannot affect control-plane-internal connectivity (Patroni, replication, health checks). Node-level pg_hba_conf entries are prepended to these. + example: + - hostssl all myapp_user 203.0.113.0/24 scram-sha-256 + - hostssl all alice 0.0.0.0/0 cert clientcert=verify-full map=ssl_users + pg_ident_conf: + type: array + items: + type: string + example: Cupiditate molestiae. + description: Additional pg_ident.conf entries, one mapping per array element. Purely additive; control-plane writes no pg_ident entries of its own. The primary use case is cert auth with map= translating certificate CNs to PostgreSQL usernames. + example: + - ssl_users CN=alice,O=example alice port: type: integer description: The port used by the Postgres database. If the port is 0, each instance will be assigned a random port. If the port is unspecified, the database will not be exposed on any port, dependent on orchestrator support for that feature. @@ -9394,223 +10048,81 @@ components: base_path: /backups custom_options: s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - schedules: - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - cpus: 500m - database_name: northwind - database_users: - - attributes: - - LOGIN - - CREATEDB - - CREATEROLE - db_owner: true - password: secret - roles: - - pgedge_superuser - username: admin - - attributes: - - LOGIN - - CREATEDB - - CREATEROLE - db_owner: true - password: secret - roles: - - pgedge_superuser - username: admin - - attributes: - - LOGIN - - CREATEDB - - CREATEROLE - db_owner: true - password: secret - roles: - - pgedge_superuser - username: admin - memory: 500M - nodes: - - backup_config: - repositories: - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - schedules: - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - cpus: 500m - host_ids: - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - memory: 500M - name: n1 - orchestrator_opts: - swarm: - extra_labels: - traefik.enable: "true" - traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) - extra_networks: - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - extra_volumes: - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - patroni_port: 8888 - port: 5432 - postgres_version: "17.6" - postgresql_conf: - max_connections: 1000 - restore_config: - repository: - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - restore_options: - set: 20250505-153628F - target: "123456" - type: xid - source_database_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - source_database_name: northwind - source_node_name: n1 - source_node: n1 + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + schedules: + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + cpus: 500m + database_name: northwind + database_users: + - attributes: + - LOGIN + - CREATEDB + - CREATEROLE + db_owner: true + password: secret + roles: + - pgedge_superuser + username: admin + - attributes: + - LOGIN + - CREATEDB + - CREATEROLE + db_owner: true + password: secret + roles: + - pgedge_superuser + username: admin + - attributes: + - LOGIN + - CREATEDB + - CREATEROLE + db_owner: true + password: secret + roles: + - pgedge_superuser + username: admin + memory: 500M + nodes: - backup_config: repositories: - azure_account: pgedge-backups @@ -9722,6 +10234,10 @@ components: - destination_path: /backups/container host_path: /Users/user/backups/host patroni_port: 8888 + pg_hba_conf: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + - ssl_users CN=alice,O=example alice port: 5432 postgres_version: "17.6" postgresql_conf: @@ -9785,6 +10301,11 @@ components: - destination_path: /backups/container host_path: /Users/user/backups/host patroni_port: 8888 + pg_hba_conf: + - hostssl all myapp_user 203.0.113.0/24 scram-sha-256 + - hostssl all alice 0.0.0.0/0 cert clientcert=verify-full map=ssl_users + pg_ident_conf: + - ssl_users CN=alice,O=example alice port: 5432 postgres_version: "17.6" postgresql_conf: @@ -10050,187 +10571,46 @@ components: items: $ref: '#/components/schemas/DatabaseUserSpec' description: The users to create for this database. - example: - - attributes: - - LOGIN - - CREATEDB - - CREATEROLE - db_owner: false - password: secret - roles: - - pgedge_superuser - username: admin - - attributes: - - LOGIN - - CREATEDB - - CREATEROLE - db_owner: false - password: secret - roles: - - pgedge_superuser - username: admin - - attributes: - - LOGIN - - CREATEDB - - CREATEROLE - db_owner: false - password: secret - roles: - - pgedge_superuser - username: admin - maxItems: 16 - memory: - type: string - description: The amount of memory in SI or IEC notation to allocate for the database and to use for tuning Postgres. Defaults to the total available memory on the host. Whether this limit is enforced depends on the orchestrator. - example: 500M - maxLength: 16 - nodes: - type: array - items: - $ref: '#/components/schemas/DatabaseNodeSpec3' - description: The Spock nodes for this database. - example: - - backup_config: - repositories: - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - schedules: - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - cpus: 500m - host_ids: - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - memory: 500M - name: n1 - orchestrator_opts: - swarm: - extra_labels: - traefik.enable: "true" - traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) - extra_networks: - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - extra_volumes: - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - patroni_port: 8888 - port: 5432 - postgres_version: "17.6" - postgresql_conf: - max_connections: 1000 - restore_config: - repository: - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - restore_options: - set: 20250505-153628F - target: "123456" - type: xid - source_database_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - source_database_name: northwind - source_node_name: n1 - source_node: n1 + example: + - attributes: + - LOGIN + - CREATEDB + - CREATEROLE + db_owner: false + password: secret + roles: + - pgedge_superuser + username: admin + - attributes: + - LOGIN + - CREATEDB + - CREATEROLE + db_owner: false + password: secret + roles: + - pgedge_superuser + username: admin + - attributes: + - LOGIN + - CREATEDB + - CREATEROLE + db_owner: false + password: secret + roles: + - pgedge_superuser + username: admin + maxItems: 16 + memory: + type: string + description: The amount of memory in SI or IEC notation to allocate for the database and to use for tuning Postgres. Defaults to the total available memory on the host. Whether this limit is enforced depends on the orchestrator. + example: 500M + maxLength: 16 + nodes: + type: array + items: + $ref: '#/components/schemas/DatabaseNodeSpec3' + description: The Spock nodes for this database. + example: - backup_config: repositories: - azure_account: pgedge-backups @@ -10341,6 +10721,10 @@ components: - destination_path: /backups/container host_path: /Users/user/backups/host patroni_port: 8888 + pg_hba_conf: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + - ssl_users CN=alice,O=example alice port: 5432 postgres_version: "17.6" postgresql_conf: @@ -10383,6 +10767,23 @@ components: format: int64 minimum: 0 maximum: 65535 + pg_hba_conf: + type: array + items: + type: string + example: Nisi nihil corporis perspiciatis et. + description: Additional pg_hba.conf entries, one rule per array element. Inserted between control-plane's system-user rules and its catch-all, so they cannot affect control-plane-internal connectivity (Patroni, replication, health checks). Node-level pg_hba_conf entries are prepended to these. + example: + - hostssl all myapp_user 203.0.113.0/24 scram-sha-256 + - hostssl all alice 0.0.0.0/0 cert clientcert=verify-full map=ssl_users + pg_ident_conf: + type: array + items: + type: string + example: Blanditiis et accusamus repellat fuga occaecati. + description: Additional pg_ident.conf entries, one mapping per array element. Purely additive; control-plane writes no pg_ident entries of its own. The primary use case is cert auth with map= translating certificate CNs to PostgreSQL usernames. + example: + - ssl_users CN=alice,O=example alice port: type: integer description: The port used by the Postgres database. If the port is 0, each instance will be assigned a random port. If the port is unspecified, the database will not be exposed on any port, dependent on orchestrator support for that feature. @@ -10782,6 +11183,10 @@ components: - destination_path: /backups/container host_path: /Users/user/backups/host patroni_port: 8888 + pg_hba_conf: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + - ssl_users CN=alice,O=example alice port: 5432 postgres_version: "17.6" postgresql_conf: @@ -10923,147 +11328,10 @@ components: - destination_path: /backups/container host_path: /Users/user/backups/host patroni_port: 8888 - port: 5432 - postgres_version: "17.6" - postgresql_conf: - max_connections: 1000 - restore_config: - repository: - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - restore_options: - set: 20250505-153628F - target: "123456" - type: xid - source_database_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - source_database_name: northwind - source_node_name: n1 - source_node: n1 - - backup_config: - repositories: - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - schedules: - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - cpus: 500m - host_ids: - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - memory: 500M - name: n1 - orchestrator_opts: - swarm: - extra_labels: - traefik.enable: "true" - traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) - extra_networks: - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - extra_volumes: - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - patroni_port: 8888 + pg_hba_conf: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + - ssl_users CN=alice,O=example alice port: 5432 postgres_version: "17.6" postgresql_conf: @@ -11127,6 +11395,11 @@ components: - destination_path: /backups/container host_path: /Users/user/backups/host patroni_port: 8888 + pg_hba_conf: + - hostssl all myapp_user 203.0.113.0/24 scram-sha-256 + - hostssl all alice 0.0.0.0/0 cert clientcert=verify-full map=ssl_users + pg_ident_conf: + - ssl_users CN=alice,O=example alice port: 5432 postgres_version: "17.6" postgresql_conf: @@ -11150,73 +11423,23 @@ components: s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY s3_region: us-east-1 type: s3 - restore_options: - set: 20250505-153628F - target: "123456" - type: xid - source_database_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - source_database_name: northwind - source_node_name: n1 - scripts: - post_database_create: - - ALTER DEFAULT PRIVILEGES FOR ROLE admin GRANT USAGE ON SCHEMAS TO app - - ALTER DEFAULT PRIVILEGES FOR ROLE admin GRANT ALL PRIVILEGES ON TABLES TO app - - ALTER DEFAULT PRIVILEGES FOR ROLE admin GRANT ALL PRIVILEGES ON SEQUENCES TO app - post_init: - - ALTER DEFAULT PRIVILEGES FOR ROLE admin GRANT USAGE ON SCHEMAS TO app - - ALTER DEFAULT PRIVILEGES FOR ROLE admin GRANT ALL PRIVILEGES ON TABLES TO app - - ALTER DEFAULT PRIVILEGES FOR ROLE admin GRANT ALL PRIVILEGES ON SEQUENCES TO app - services: - - config: - llm_model: gpt-4 - llm_provider: openai - openai_api_key: sk-... - connect_as: app - cpus: 500m - database_connection: - target_nodes: - - n1 - - n2 - target_session_attrs: primary - host_ids: - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - memory: 512M - orchestrator_opts: - swarm: - extra_labels: - traefik.enable: "true" - traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) - extra_networks: - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - extra_volumes: - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - port: 0 - service_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - service_type: rag - version: latest + restore_options: + set: 20250505-153628F + target: "123456" + type: xid + source_database_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + source_database_name: northwind + source_node_name: n1 + scripts: + post_database_create: + - ALTER DEFAULT PRIVILEGES FOR ROLE admin GRANT USAGE ON SCHEMAS TO app + - ALTER DEFAULT PRIVILEGES FOR ROLE admin GRANT ALL PRIVILEGES ON TABLES TO app + - ALTER DEFAULT PRIVILEGES FOR ROLE admin GRANT ALL PRIVILEGES ON SEQUENCES TO app + post_init: + - ALTER DEFAULT PRIVILEGES FOR ROLE admin GRANT USAGE ON SCHEMAS TO app + - ALTER DEFAULT PRIVILEGES FOR ROLE admin GRANT ALL PRIVILEGES ON TABLES TO app + - ALTER DEFAULT PRIVILEGES FOR ROLE admin GRANT ALL PRIVILEGES ON SEQUENCES TO app + services: - config: llm_model: gpt-4 llm_provider: openai @@ -11284,245 +11507,104 @@ components: memory: 512M orchestrator_opts: swarm: - extra_labels: - traefik.enable: "true" - traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) - extra_networks: - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - extra_volumes: - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - port: 0 - service_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - service_type: rag - version: latest - spock_version: "5" - required: - - database_name - - nodes - DatabaseSpec4: - type: object - properties: - backup_config: - $ref: '#/components/schemas/BackupConfigSpec' - cpus: - type: string - description: The number of CPUs to allocate for the database and to use for tuning Postgres. Defaults to the number of available CPUs on the host. Can include an SI suffix, e.g. '500m' for 500 millicpus. Whether this limit is enforced depends on the orchestrator. - example: 500m - pattern: ^[0-9]+(\.[0-9]{1,3}|m)?$ - database_name: - type: string - description: The name of the Postgres database. - example: northwind - minLength: 1 - maxLength: 31 - database_users: - type: array - items: - $ref: '#/components/schemas/DatabaseUserSpec' - description: The users to create for this database. - example: - - attributes: - - LOGIN - - CREATEDB - - CREATEROLE - db_owner: false - password: secret - roles: - - pgedge_superuser - username: admin - - attributes: - - LOGIN - - CREATEDB - - CREATEROLE - db_owner: false - password: secret - roles: - - pgedge_superuser - username: admin - - attributes: - - LOGIN - - CREATEDB - - CREATEROLE - db_owner: false - password: secret - roles: - - pgedge_superuser - username: admin - maxItems: 16 - memory: - type: string - description: The amount of memory in SI or IEC notation to allocate for the database and to use for tuning Postgres. Defaults to the total available memory on the host. Whether this limit is enforced depends on the orchestrator. - example: 500M - maxLength: 16 - nodes: - type: array - items: - $ref: '#/components/schemas/DatabaseNodeSpec4' - description: The Spock nodes for this database. - example: - - backup_config: - repositories: - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - schedules: - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - cpus: 500m - host_ids: - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - memory: 500M - name: n1 - orchestrator_opts: - swarm: - extra_labels: - traefik.enable: "true" - traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) - extra_networks: - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - extra_volumes: - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - patroni_port: 8888 - port: 5432 - postgres_version: "17.6" - postgresql_conf: - max_connections: 1000 - restore_config: - repository: - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - restore_options: - set: 20250505-153628F - target: "123456" - type: xid - source_database_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - source_database_name: northwind - source_node_name: n1 - source_node: n1 + extra_labels: + traefik.enable: "true" + traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) + extra_networks: + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + extra_volumes: + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + port: 0 + service_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + service_type: rag + version: latest + spock_version: "5" + required: + - database_name + - nodes + DatabaseSpec4: + type: object + properties: + backup_config: + $ref: '#/components/schemas/BackupConfigSpec' + cpus: + type: string + description: The number of CPUs to allocate for the database and to use for tuning Postgres. Defaults to the number of available CPUs on the host. Can include an SI suffix, e.g. '500m' for 500 millicpus. Whether this limit is enforced depends on the orchestrator. + example: 500m + pattern: ^[0-9]+(\.[0-9]{1,3}|m)?$ + database_name: + type: string + description: The name of the Postgres database. + example: northwind + minLength: 1 + maxLength: 31 + database_users: + type: array + items: + $ref: '#/components/schemas/DatabaseUserSpec' + description: The users to create for this database. + example: + - attributes: + - LOGIN + - CREATEDB + - CREATEROLE + db_owner: false + password: secret + roles: + - pgedge_superuser + username: admin + - attributes: + - LOGIN + - CREATEDB + - CREATEROLE + db_owner: false + password: secret + roles: + - pgedge_superuser + username: admin + - attributes: + - LOGIN + - CREATEDB + - CREATEROLE + db_owner: false + password: secret + roles: + - pgedge_superuser + username: admin + maxItems: 16 + memory: + type: string + description: The amount of memory in SI or IEC notation to allocate for the database and to use for tuning Postgres. Defaults to the total available memory on the host. Whether this limit is enforced depends on the orchestrator. + example: 500M + maxLength: 16 + nodes: + type: array + items: + $ref: '#/components/schemas/DatabaseNodeSpec4' + description: The Spock nodes for this database. + example: - backup_config: repositories: - azure_account: pgedge-backups @@ -11633,6 +11715,10 @@ components: - destination_path: /backups/container host_path: /Users/user/backups/host patroni_port: 8888 + pg_hba_conf: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + - ssl_users CN=alice,O=example alice port: 5432 postgres_version: "17.6" postgresql_conf: @@ -11675,6 +11761,23 @@ components: format: int64 minimum: 0 maximum: 65535 + pg_hba_conf: + type: array + items: + type: string + example: Dignissimos voluptas vel earum eaque. + description: Additional pg_hba.conf entries, one rule per array element. Inserted between control-plane's system-user rules and its catch-all, so they cannot affect control-plane-internal connectivity (Patroni, replication, health checks). Node-level pg_hba_conf entries are prepended to these. + example: + - hostssl all myapp_user 203.0.113.0/24 scram-sha-256 + - hostssl all alice 0.0.0.0/0 cert clientcert=verify-full map=ssl_users + pg_ident_conf: + type: array + items: + type: string + example: Et minima ipsum ut impedit. + description: Additional pg_ident.conf entries, one mapping per array element. Purely additive; control-plane writes no pg_ident entries of its own. The primary use case is cert auth with map= translating certificate CNs to PostgreSQL usernames. + example: + - ssl_users CN=alice,O=example alice port: type: integer description: The port used by the Postgres database. If the port is 0, each instance will be assigned a random port. If the port is unspecified, the database will not be exposed on any port, dependent on orchestrator support for that feature. @@ -12124,6 +12227,155 @@ components: - destination_path: /backups/container host_path: /Users/user/backups/host patroni_port: 8888 + pg_hba_conf: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + - ssl_users CN=alice,O=example alice + port: 5432 + postgres_version: "17.6" + postgresql_conf: + max_connections: 1000 + restore_config: + repository: + azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + restore_options: + set: 20250505-153628F + target: "123456" + type: xid + source_database_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + source_database_name: northwind + source_node_name: n1 + source_node: n1 + - backup_config: + repositories: + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + schedules: + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + cpus: 500m + host_ids: + - 76f9b8c0-4958-11f0-a489-3bb29577c696 + - 76f9b8c0-4958-11f0-a489-3bb29577c696 + memory: 500M + name: n1 + orchestrator_opts: + swarm: + extra_labels: + traefik.enable: "true" + traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) + extra_networks: + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + extra_volumes: + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + patroni_port: 8888 + pg_hba_conf: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + - ssl_users CN=alice,O=example alice port: 5432 postgres_version: "17.6" postgresql_conf: @@ -12265,6 +12517,10 @@ components: - destination_path: /backups/container host_path: /Users/user/backups/host patroni_port: 8888 + pg_hba_conf: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + - ssl_users CN=alice,O=example alice port: 5432 postgres_version: "17.6" postgresql_conf: @@ -12328,6 +12584,11 @@ components: - destination_path: /backups/container host_path: /Users/user/backups/host patroni_port: 8888 + pg_hba_conf: + - hostssl all myapp_user 203.0.113.0/24 scram-sha-256 + - hostssl all alice 0.0.0.0/0 cert clientcert=verify-full map=ssl_users + pg_ident_conf: + - ssl_users CN=alice,O=example alice port: 5432 postgres_version: "17.6" postgresql_conf: @@ -12743,6 +13004,10 @@ components: - destination_path: /backups/container host_path: /Users/user/backups/host patroni_port: 8888 + pg_hba_conf: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + - ssl_users CN=alice,O=example alice port: 5432 postgres_version: "17.6" postgresql_conf: @@ -12785,6 +13050,23 @@ components: format: int64 minimum: 0 maximum: 65535 + pg_hba_conf: + type: array + items: + type: string + example: Nobis quam sequi. + description: Additional pg_hba.conf entries, one rule per array element. Inserted between control-plane's system-user rules and its catch-all, so they cannot affect control-plane-internal connectivity (Patroni, replication, health checks). Node-level pg_hba_conf entries are prepended to these. + example: + - hostssl all myapp_user 203.0.113.0/24 scram-sha-256 + - hostssl all alice 0.0.0.0/0 cert clientcert=verify-full map=ssl_users + pg_ident_conf: + type: array + items: + type: string + example: Aliquid porro dolorum natus sunt harum magnam. + description: Additional pg_ident.conf entries, one mapping per array element. Purely additive; control-plane writes no pg_ident entries of its own. The primary use case is cert auth with map= translating certificate CNs to PostgreSQL usernames. + example: + - ssl_users CN=alice,O=example alice port: type: integer description: The port used by the Postgres database. If the port is 0, each instance will be assigned a random port. If the port is unspecified, the database will not be exposed on any port, dependent on orchestrator support for that feature. @@ -12961,6 +13243,55 @@ components: service_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 service_type: rag version: latest + - config: + llm_model: gpt-4 + llm_provider: openai + openai_api_key: sk-... + connect_as: app + cpus: 500m + database_connection: + target_nodes: + - n1 + - n2 + target_session_attrs: primary + host_ids: + - 76f9b8c0-4958-11f0-a489-3bb29577c696 + memory: 512M + orchestrator_opts: + swarm: + extra_labels: + traefik.enable: "true" + traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) + extra_networks: + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + extra_volumes: + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + port: 0 + service_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + service_type: rag + version: latest spock_version: type: string description: The major version of the Spock extension. @@ -13181,6 +13512,10 @@ components: - destination_path: /backups/container host_path: /Users/user/backups/host patroni_port: 8888 + pg_hba_conf: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + - ssl_users CN=alice,O=example alice port: 5432 postgres_version: "17.6" postgresql_conf: @@ -13244,6 +13579,11 @@ components: - destination_path: /backups/container host_path: /Users/user/backups/host patroni_port: 8888 + pg_hba_conf: + - hostssl all myapp_user 203.0.113.0/24 scram-sha-256 + - hostssl all alice 0.0.0.0/0 cert clientcert=verify-full map=ssl_users + pg_ident_conf: + - ssl_users CN=alice,O=example alice port: 5432 postgres_version: "17.6" postgresql_conf: @@ -13382,55 +13722,6 @@ components: service_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 service_type: rag version: latest - - config: - llm_model: gpt-4 - llm_provider: openai - openai_api_key: sk-... - connect_as: app - cpus: 500m - database_connection: - target_nodes: - - n1 - - n2 - target_session_attrs: primary - host_ids: - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - memory: 512M - orchestrator_opts: - swarm: - extra_labels: - traefik.enable: "true" - traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) - extra_networks: - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - extra_volumes: - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - port: 0 - service_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - service_type: rag - version: latest spock_version: "5" required: - database_name @@ -13606,6 +13897,10 @@ components: - destination_path: /backups/container host_path: /Users/user/backups/host patroni_port: 8888 + pg_hba_conf: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + - ssl_users CN=alice,O=example alice port: 5432 postgres_version: "17.6" postgresql_conf: @@ -13648,6 +13943,23 @@ components: format: int64 minimum: 0 maximum: 65535 + pg_hba_conf: + type: array + items: + type: string + example: Nisi eveniet sit dignissimos ducimus. + description: Additional pg_hba.conf entries, one rule per array element. Inserted between control-plane's system-user rules and its catch-all, so they cannot affect control-plane-internal connectivity (Patroni, replication, health checks). Node-level pg_hba_conf entries are prepended to these. + example: + - hostssl all myapp_user 203.0.113.0/24 scram-sha-256 + - hostssl all alice 0.0.0.0/0 cert clientcert=verify-full map=ssl_users + pg_ident_conf: + type: array + items: + type: string + example: Asperiores explicabo. + description: Additional pg_ident.conf entries, one mapping per array element. Purely additive; control-plane writes no pg_ident entries of its own. The primary use case is cert auth with map= translating certificate CNs to PostgreSQL usernames. + example: + - ssl_users CN=alice,O=example alice port: type: integer description: The port used by the Postgres database. If the port is 0, each instance will be assigned a random port. If the port is unspecified, the database will not be exposed on any port, dependent on orchestrator support for that feature. @@ -13777,6 +14089,106 @@ components: service_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 service_type: rag version: latest + - config: + llm_model: gpt-4 + llm_provider: openai + openai_api_key: sk-... + connect_as: app + cpus: 500m + database_connection: + target_nodes: + - n1 + - n2 + target_session_attrs: primary + host_ids: + - 76f9b8c0-4958-11f0-a489-3bb29577c696 + - 76f9b8c0-4958-11f0-a489-3bb29577c696 + memory: 512M + orchestrator_opts: + swarm: + extra_labels: + traefik.enable: "true" + traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) + extra_networks: + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + extra_volumes: + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + port: 0 + service_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + service_type: rag + version: latest + - config: + llm_model: gpt-4 + llm_provider: openai + openai_api_key: sk-... + connect_as: app + cpus: 500m + database_connection: + target_nodes: + - n1 + - n2 + target_session_attrs: primary + host_ids: + - 76f9b8c0-4958-11f0-a489-3bb29577c696 + - 76f9b8c0-4958-11f0-a489-3bb29577c696 + memory: 512M + orchestrator_opts: + swarm: + extra_labels: + traefik.enable: "true" + traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) + extra_networks: + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + extra_volumes: + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + port: 0 + service_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + service_type: rag + version: latest spock_version: type: string description: The major version of the Spock extension. @@ -13997,6 +14409,155 @@ components: - destination_path: /backups/container host_path: /Users/user/backups/host patroni_port: 8888 + pg_hba_conf: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + - ssl_users CN=alice,O=example alice + port: 5432 + postgres_version: "17.6" + postgresql_conf: + max_connections: 1000 + restore_config: + repository: + azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + restore_options: + set: 20250505-153628F + target: "123456" + type: xid + source_database_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + source_database_name: northwind + source_node_name: n1 + source_node: n1 + - backup_config: + repositories: + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + schedules: + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + cpus: 500m + host_ids: + - 76f9b8c0-4958-11f0-a489-3bb29577c696 + - 76f9b8c0-4958-11f0-a489-3bb29577c696 + memory: 500M + name: n1 + orchestrator_opts: + swarm: + extra_labels: + traefik.enable: "true" + traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) + extra_networks: + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + extra_volumes: + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + patroni_port: 8888 + pg_hba_conf: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + - ssl_users CN=alice,O=example alice port: 5432 postgres_version: "17.6" postgresql_conf: @@ -14060,6 +14621,11 @@ components: - destination_path: /backups/container host_path: /Users/user/backups/host patroni_port: 8888 + pg_hba_conf: + - hostssl all myapp_user 203.0.113.0/24 scram-sha-256 + - hostssl all alice 0.0.0.0/0 cert clientcert=verify-full map=ssl_users + pg_ident_conf: + - ssl_users CN=alice,O=example alice port: 5432 postgres_version: "17.6" postgresql_conf: @@ -14250,56 +14816,6 @@ components: service_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 service_type: rag version: latest - - config: - llm_model: gpt-4 - llm_provider: openai - openai_api_key: sk-... - connect_as: app - cpus: 500m - database_connection: - target_nodes: - - n1 - - n2 - target_session_attrs: primary - host_ids: - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - memory: 512M - orchestrator_opts: - swarm: - extra_labels: - traefik.enable: "true" - traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) - extra_networks: - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - extra_volumes: - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - port: 0 - service_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - service_type: rag - version: latest spock_version: "5" required: - database_name @@ -14475,6 +14991,155 @@ components: - destination_path: /backups/container host_path: /Users/user/backups/host patroni_port: 8888 + pg_hba_conf: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + - ssl_users CN=alice,O=example alice + port: 5432 + postgres_version: "17.6" + postgresql_conf: + max_connections: 1000 + restore_config: + repository: + azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + restore_options: + set: 20250505-153628F + target: "123456" + type: xid + source_database_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + source_database_name: northwind + source_node_name: n1 + source_node: n1 + - backup_config: + repositories: + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + schedules: + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + cpus: 500m + host_ids: + - 76f9b8c0-4958-11f0-a489-3bb29577c696 + - 76f9b8c0-4958-11f0-a489-3bb29577c696 + memory: 500M + name: n1 + orchestrator_opts: + swarm: + extra_labels: + traefik.enable: "true" + traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) + extra_networks: + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + extra_volumes: + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + patroni_port: 8888 + pg_hba_conf: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + - ssl_users CN=alice,O=example alice port: 5432 postgres_version: "17.6" postgresql_conf: @@ -14616,6 +15281,10 @@ components: - destination_path: /backups/container host_path: /Users/user/backups/host patroni_port: 8888 + pg_hba_conf: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + - ssl_users CN=alice,O=example alice port: 5432 postgres_version: "17.6" postgresql_conf: @@ -14658,6 +15327,23 @@ components: format: int64 minimum: 0 maximum: 65535 + pg_hba_conf: + type: array + items: + type: string + example: Et vero dolorem aut. + description: Additional pg_hba.conf entries, one rule per array element. Inserted between control-plane's system-user rules and its catch-all, so they cannot affect control-plane-internal connectivity (Patroni, replication, health checks). Node-level pg_hba_conf entries are prepended to these. + example: + - hostssl all myapp_user 203.0.113.0/24 scram-sha-256 + - hostssl all alice 0.0.0.0/0 cert clientcert=verify-full map=ssl_users + pg_ident_conf: + type: array + items: + type: string + example: Omnis quisquam officiis. + description: Additional pg_ident.conf entries, one mapping per array element. Purely additive; control-plane writes no pg_ident entries of its own. The primary use case is cert auth with map= translating certificate CNs to PostgreSQL usernames. + example: + - ssl_users CN=alice,O=example alice port: type: integer description: The port used by the Postgres database. If the port is 0, each instance will be assigned a random port. If the port is unspecified, the database will not be exposed on any port, dependent on orchestrator support for that feature. @@ -15007,6 +15693,300 @@ components: - destination_path: /backups/container host_path: /Users/user/backups/host patroni_port: 8888 + pg_hba_conf: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + - ssl_users CN=alice,O=example alice + port: 5432 + postgres_version: "17.6" + postgresql_conf: + max_connections: 1000 + restore_config: + repository: + azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + restore_options: + set: 20250505-153628F + target: "123456" + type: xid + source_database_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + source_database_name: northwind + source_node_name: n1 + source_node: n1 + - backup_config: + repositories: + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + schedules: + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + cpus: 500m + host_ids: + - 76f9b8c0-4958-11f0-a489-3bb29577c696 + - 76f9b8c0-4958-11f0-a489-3bb29577c696 + memory: 500M + name: n1 + orchestrator_opts: + swarm: + extra_labels: + traefik.enable: "true" + traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) + extra_networks: + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + extra_volumes: + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + patroni_port: 8888 + pg_hba_conf: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + - ssl_users CN=alice,O=example alice + port: 5432 + postgres_version: "17.6" + postgresql_conf: + max_connections: 1000 + restore_config: + repository: + azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + restore_options: + set: 20250505-153628F + target: "123456" + type: xid + source_database_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + source_database_name: northwind + source_node_name: n1 + source_node: n1 + - backup_config: + repositories: + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + schedules: + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + cpus: 500m + host_ids: + - 76f9b8c0-4958-11f0-a489-3bb29577c696 + - 76f9b8c0-4958-11f0-a489-3bb29577c696 + memory: 500M + name: n1 + orchestrator_opts: + swarm: + extra_labels: + traefik.enable: "true" + traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) + extra_networks: + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + extra_volumes: + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + patroni_port: 8888 + pg_hba_conf: + - host example myapp_user 10.0.0.0/8 scram-sha-256 + pg_ident_conf: + - ssl_users CN=alice,O=example alice port: 5432 postgres_version: "17.6" postgresql_conf: @@ -15070,6 +16050,11 @@ components: - destination_path: /backups/container host_path: /Users/user/backups/host patroni_port: 8888 + pg_hba_conf: + - hostssl all myapp_user 203.0.113.0/24 scram-sha-256 + - hostssl all alice 0.0.0.0/0 cert clientcert=verify-full map=ssl_users + pg_ident_conf: + - ssl_users CN=alice,O=example alice port: 5432 postgres_version: "17.6" postgresql_conf: @@ -15210,106 +16195,6 @@ components: service_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 service_type: rag version: latest - - config: - llm_model: gpt-4 - llm_provider: openai - openai_api_key: sk-... - connect_as: app - cpus: 500m - database_connection: - target_nodes: - - n1 - - n2 - target_session_attrs: primary - host_ids: - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - memory: 512M - orchestrator_opts: - swarm: - extra_labels: - traefik.enable: "true" - traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) - extra_networks: - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - extra_volumes: - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - port: 0 - service_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - service_type: rag - version: latest - - config: - llm_model: gpt-4 - llm_provider: openai - openai_api_key: sk-... - connect_as: app - cpus: 500m - database_connection: - target_nodes: - - n1 - - n2 - target_session_attrs: primary - host_ids: - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - memory: 512M - orchestrator_opts: - swarm: - extra_labels: - traefik.enable: "true" - traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) - extra_networks: - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - extra_volumes: - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - port: 0 - service_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - service_type: rag - version: latest spock_version: "5" required: - database_name @@ -15339,7 +16224,7 @@ components: - 10.24.34.2 - i-0123456789abcdef.ec2.internal port: 5432 - created_at: "1970-12-24T01:48:39Z" + created_at: "2001-11-21T07:07:15Z" error: 'failed to get patroni status: connection refused' host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d @@ -15347,7 +16232,7 @@ components: postgres: patroni_paused: true patroni_state: unknown - pending_restart: true + pending_restart: false role: primary version: "18.1" spock: @@ -15359,16 +16244,19 @@ components: - name: sub_n1n2 provider_node: n2 status: down + - name: sub_n1n2 + provider_node: n2 + status: down version: 4.10.0 - state: unknown - status_updated_at: "1978-12-17T01:14:06Z" - updated_at: "2010-08-13T18:38:44Z" + state: degraded + status_updated_at: "1990-07-23T01:22:30Z" + updated_at: "2013-01-29T23:51:44Z" - connection_info: addresses: - 10.24.34.2 - i-0123456789abcdef.ec2.internal port: 5432 - created_at: "1970-12-24T01:48:39Z" + created_at: "2001-11-21T07:07:15Z" error: 'failed to get patroni status: connection refused' host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d @@ -15376,7 +16264,7 @@ components: postgres: patroni_paused: true patroni_state: unknown - pending_restart: true + pending_restart: false role: primary version: "18.1" spock: @@ -15388,16 +16276,19 @@ components: - name: sub_n1n2 provider_node: n2 status: down + - name: sub_n1n2 + provider_node: n2 + status: down version: 4.10.0 - state: unknown - status_updated_at: "1978-12-17T01:14:06Z" - updated_at: "2010-08-13T18:38:44Z" + state: degraded + status_updated_at: "1990-07-23T01:22:30Z" + updated_at: "2013-01-29T23:51:44Z" - connection_info: addresses: - 10.24.34.2 - i-0123456789abcdef.ec2.internal port: 5432 - created_at: "1970-12-24T01:48:39Z" + created_at: "2001-11-21T07:07:15Z" error: 'failed to get patroni status: connection refused' host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d @@ -15405,7 +16296,39 @@ components: postgres: patroni_paused: true patroni_state: unknown - pending_restart: true + pending_restart: false + role: primary + version: "18.1" + spock: + read_only: "off" + subscriptions: + - name: sub_n1n2 + provider_node: n2 + status: down + - name: sub_n1n2 + provider_node: n2 + status: down + - name: sub_n1n2 + provider_node: n2 + status: down + version: 4.10.0 + state: degraded + status_updated_at: "1990-07-23T01:22:30Z" + updated_at: "2013-01-29T23:51:44Z" + - connection_info: + addresses: + - 10.24.34.2 + - i-0123456789abcdef.ec2.internal + port: 5432 + created_at: "2001-11-21T07:07:15Z" + error: 'failed to get patroni status: connection refused' + host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec + id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d + node_name: n1 + postgres: + patroni_paused: true + patroni_state: unknown + pending_restart: false role: primary version: "18.1" spock: @@ -15417,14 +16340,17 @@ components: - name: sub_n1n2 provider_node: n2 status: down + - name: sub_n1n2 + provider_node: n2 + status: down version: 4.10.0 - state: unknown - status_updated_at: "1978-12-17T01:14:06Z" - updated_at: "2010-08-13T18:38:44Z" + state: degraded + status_updated_at: "1990-07-23T01:22:30Z" + updated_at: "2013-01-29T23:51:44Z" state: type: string description: Current state of the database. - example: backing_up + example: degraded enum: - creating - modifying @@ -15441,79 +16367,21 @@ components: example: 76f9b8c0-4958-11f0-a489-3bb29577c696 minLength: 1 maxLength: 36 - updated_at: - type: string - description: The time that the database was last updated. - example: "2025-01-01T02:30:00Z" - format: date-time - example: - created_at: "2025-01-01T01:30:00Z" - id: 02f1a7db-fca8-4521-b57a-2a375c1ced51 - instances: - - connection_info: - addresses: - - 10.24.34.2 - - i-0123456789abcdef.ec2.internal - port: 5432 - created_at: "1970-12-24T01:48:39Z" - error: 'failed to get patroni status: connection refused' - host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec - id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d - node_name: n1 - postgres: - patroni_paused: true - patroni_state: unknown - pending_restart: true - role: primary - version: "18.1" - spock: - read_only: "off" - subscriptions: - - name: sub_n1n2 - provider_node: n2 - status: down - - name: sub_n1n2 - provider_node: n2 - status: down - version: 4.10.0 - state: unknown - status_updated_at: "1978-12-17T01:14:06Z" - updated_at: "2010-08-13T18:38:44Z" - - connection_info: - addresses: - - 10.24.34.2 - - i-0123456789abcdef.ec2.internal - port: 5432 - created_at: "1970-12-24T01:48:39Z" - error: 'failed to get patroni status: connection refused' - host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec - id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d - node_name: n1 - postgres: - patroni_paused: true - patroni_state: unknown - pending_restart: true - role: primary - version: "18.1" - spock: - read_only: "off" - subscriptions: - - name: sub_n1n2 - provider_node: n2 - status: down - - name: sub_n1n2 - provider_node: n2 - status: down - version: 4.10.0 - state: unknown - status_updated_at: "1978-12-17T01:14:06Z" - updated_at: "2010-08-13T18:38:44Z" + updated_at: + type: string + description: The time that the database was last updated. + example: "2025-01-01T02:30:00Z" + format: date-time + example: + created_at: "2025-01-01T01:30:00Z" + id: 02f1a7db-fca8-4521-b57a-2a375c1ced51 + instances: - connection_info: addresses: - 10.24.34.2 - i-0123456789abcdef.ec2.internal port: 5432 - created_at: "1970-12-24T01:48:39Z" + created_at: "2001-11-21T07:07:15Z" error: 'failed to get patroni status: connection refused' host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d @@ -15521,7 +16389,7 @@ components: postgres: patroni_paused: true patroni_state: unknown - pending_restart: true + pending_restart: false role: primary version: "18.1" spock: @@ -15533,16 +16401,19 @@ components: - name: sub_n1n2 provider_node: n2 status: down + - name: sub_n1n2 + provider_node: n2 + status: down version: 4.10.0 - state: unknown - status_updated_at: "1978-12-17T01:14:06Z" - updated_at: "2010-08-13T18:38:44Z" + state: degraded + status_updated_at: "1990-07-23T01:22:30Z" + updated_at: "2013-01-29T23:51:44Z" - connection_info: addresses: - 10.24.34.2 - i-0123456789abcdef.ec2.internal port: 5432 - created_at: "1970-12-24T01:48:39Z" + created_at: "2001-11-21T07:07:15Z" error: 'failed to get patroni status: connection refused' host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d @@ -15550,7 +16421,7 @@ components: postgres: patroni_paused: true patroni_state: unknown - pending_restart: true + pending_restart: false role: primary version: "18.1" spock: @@ -15562,10 +16433,13 @@ components: - name: sub_n1n2 provider_node: n2 status: down + - name: sub_n1n2 + provider_node: n2 + status: down version: 4.10.0 - state: unknown - status_updated_at: "1978-12-17T01:14:06Z" - updated_at: "2010-08-13T18:38:44Z" + state: degraded + status_updated_at: "1990-07-23T01:22:30Z" + updated_at: "2013-01-29T23:51:44Z" state: failed tenant_id: 8210ec10-2dca-406c-ac4a-0661d2189954 updated_at: "2025-01-01T02:30:00Z" @@ -15581,7 +16455,7 @@ components: type: array items: type: string - example: Et nam quo qui qui natus. + example: Aut omnis magnam aspernatur occaecati itaque dolores. description: The attributes to assign to this database user. example: - LOGIN @@ -15591,7 +16465,7 @@ components: db_owner: type: boolean description: If true, this user will be granted database ownership. - example: false + example: true password: type: string description: The password for this database user. This field will be excluded from the response of all endpoints. It can also be omitted from update requests to keep the current value. @@ -15601,7 +16475,7 @@ components: type: array items: type: string - example: Veniam exercitationem placeat temporibus aut. + example: Dolor autem eum. description: The roles to assign to this database user. example: - pgedge_superuser @@ -15616,7 +16490,7 @@ components: - LOGIN - CREATEDB - CREATEROLE - db_owner: false + db_owner: true password: secret roles: - pgedge_superuser @@ -15644,7 +16518,7 @@ components: type: array items: type: string - example: Accusantium ut aperiam qui sed quis architecto. + example: Rerum animi et itaque placeat placeat. description: The Etcd client endpoint for this cluster member. example: - http://192.168.1.1:2379 @@ -15656,7 +16530,7 @@ components: type: array items: type: string - example: Labore explicabo culpa eos natus aperiam excepturi. + example: Repudiandae ab sed. description: The Etcd peer endpoint for this cluster member. example: - http://192.168.1.1:2380 @@ -15677,7 +16551,7 @@ components: type: array items: type: string - example: Totam accusamus alias. + example: Aliquid cupiditate sapiente eos aut dignissimos cum. description: Optional network-scoped aliases for the container. example: - pg-db @@ -15690,7 +16564,7 @@ components: com.docker.network.endpoint.expose: "true" additionalProperties: type: string - example: Qui ut et. + example: Modi consequatur non at. id: type: string description: The name or ID of the network to connect to. @@ -15747,7 +16621,7 @@ components: type: boolean description: If true, skip the health validations that prevent running failover on a healthy cluster. default: false - example: true + example: false example: candidate_instance_id: 68f50878-44d2-4524-a823-e31bd478706d-n1-689qacsi database_id: my-app @@ -15770,7 +16644,7 @@ components: example: false example: candidate_instance_id: 68f50878-44d2-4524-a823-e31bd478706d-n1-689qacsi - skip_validation: true + skip_validation: false FailoverDatabaseNodeResponse: type: object properties: @@ -15820,7 +16694,7 @@ components: type: array items: type: string - example: Animi recusandae. + example: Illo aut et corporis harum. description: The addresses that this host advertises to client applications. example: - 10.24.34.2 @@ -15863,7 +16737,7 @@ components: type: array items: type: string - example: Qui quam sint iure eum ducimus quia. + example: Eos molestiae voluptates laborum. description: The addresses that this host advertises to other hosts. example: - 10.24.34.2 @@ -15925,10 +16799,6 @@ components: spock_version: "5" - postgres_version: "17.6" spock_version: "5" - - postgres_version: "17.6" - spock_version: "5" - - postgres_version: "17.6" - spock_version: "5" required: - id - orchestrator @@ -15966,19 +16836,7 @@ components: type: object description: The status of each component of the host. example: - At esse ut possimus error eligendi.: - details: - alarms: - - '3: NOSPACE' - error: failed to connect to etcd - healthy: false - Atque facilis non modi explicabo illum.: - details: - alarms: - - '3: NOSPACE' - error: failed to connect to etcd - healthy: false - Similique sed neque eos rerum quia.: + Sint ea omnis ut.: details: alarms: - '3: NOSPACE' @@ -16001,19 +16859,19 @@ components: format: date-time example: components: - Et eius reiciendis accusamus veritatis quo recusandae.: + Impedit laudantium et quia commodi consequatur.: details: alarms: - '3: NOSPACE' error: failed to connect to etcd healthy: false - Fuga molestiae.: + Possimus magni quaerat qui quam id.: details: alarms: - '3: NOSPACE' error: failed to connect to etcd healthy: false - Quas nostrum eos reprehenderit harum sapiente qui.: + Velit et labore in dolor quisquam placeat.: details: alarms: - '3: NOSPACE' @@ -16045,7 +16903,7 @@ components: created_at: type: string description: The time that the instance was created. - example: "1993-02-25T18:38:10Z" + example: "1985-10-05T07:39:21Z" format: date-time error: type: string @@ -16069,7 +16927,7 @@ components: $ref: '#/components/schemas/InstanceSpockStatus' state: type: string - example: available + example: creating enum: - creating - modifying @@ -16083,12 +16941,12 @@ components: status_updated_at: type: string description: The time that the instance status information was last updated. - example: "1983-10-23T08:18:23Z" + example: "1980-07-23T10:57:18Z" format: date-time updated_at: type: string description: The time that the instance was last modified. - example: "1971-02-20T15:20:44Z" + example: "2012-09-29T21:49:40Z" format: date-time description: An instance of pgEdge Postgres running on a host. example: @@ -16097,7 +16955,7 @@ components: - 10.24.34.2 - i-0123456789abcdef.ec2.internal port: 5432 - created_at: "1994-07-03T05:16:56Z" + created_at: "1978-04-27T14:09:21Z" error: 'failed to get patroni status: connection refused' host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d @@ -16105,7 +16963,7 @@ components: postgres: patroni_paused: true patroni_state: unknown - pending_restart: true + pending_restart: false role: primary version: "18.1" spock: @@ -16117,10 +16975,13 @@ components: - name: sub_n1n2 provider_node: n2 status: down + - name: sub_n1n2 + provider_node: n2 + status: down version: 4.10.0 - state: modifying - status_updated_at: "1994-09-09T06:25:01Z" - updated_at: "2014-04-20T04:34:11Z" + state: degraded + status_updated_at: "1976-06-24T23:38:37Z" + updated_at: "2015-04-11T16:50:06Z" required: - id - host_id @@ -16135,7 +16996,7 @@ components: type: array items: type: string - example: Ea omnis ut dolor dolorem impedit laudantium. + example: Facere eius totam. description: The addresses of the host that's running this instance. example: - 10.24.34.2 @@ -16164,7 +17025,7 @@ components: pending_restart: type: boolean description: True if this instance has a pending restart from a configuration change. - example: false + example: true role: type: string example: primary @@ -16174,7 +17035,7 @@ components: example: "18.1" description: Postgres status information for a pgEdge instance. example: - patroni_paused: false + patroni_paused: true patroni_state: unknown pending_restart: false role: primary @@ -16201,6 +17062,9 @@ components: - name: sub_n1n2 provider_node: n2 status: down + - name: sub_n1n2 + provider_node: n2 + status: down version: type: string description: The version of Spock for this instance. @@ -16339,7 +17203,39 @@ components: - 10.24.34.2 - i-0123456789abcdef.ec2.internal port: 5432 - created_at: "1970-12-24T01:48:39Z" + created_at: "2001-11-21T07:07:15Z" + error: 'failed to get patroni status: connection refused' + host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec + id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d + node_name: n1 + postgres: + patroni_paused: true + patroni_state: unknown + pending_restart: false + role: primary + version: "18.1" + spock: + read_only: "off" + subscriptions: + - name: sub_n1n2 + provider_node: n2 + status: down + - name: sub_n1n2 + provider_node: n2 + status: down + - name: sub_n1n2 + provider_node: n2 + status: down + version: 4.10.0 + state: degraded + status_updated_at: "1990-07-23T01:22:30Z" + updated_at: "2013-01-29T23:51:44Z" + - connection_info: + addresses: + - 10.24.34.2 + - i-0123456789abcdef.ec2.internal + port: 5432 + created_at: "2001-11-21T07:07:15Z" error: 'failed to get patroni status: connection refused' host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d @@ -16347,7 +17243,7 @@ components: postgres: patroni_paused: true patroni_state: unknown - pending_restart: true + pending_restart: false role: primary version: "18.1" spock: @@ -16359,16 +17255,19 @@ components: - name: sub_n1n2 provider_node: n2 status: down + - name: sub_n1n2 + provider_node: n2 + status: down version: 4.10.0 - state: unknown - status_updated_at: "1978-12-17T01:14:06Z" - updated_at: "2010-08-13T18:38:44Z" + state: degraded + status_updated_at: "1990-07-23T01:22:30Z" + updated_at: "2013-01-29T23:51:44Z" - connection_info: addresses: - 10.24.34.2 - i-0123456789abcdef.ec2.internal port: 5432 - created_at: "1970-12-24T01:48:39Z" + created_at: "2001-11-21T07:07:15Z" error: 'failed to get patroni status: connection refused' host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d @@ -16376,7 +17275,7 @@ components: postgres: patroni_paused: true patroni_state: unknown - pending_restart: true + pending_restart: false role: primary version: "18.1" spock: @@ -16388,16 +17287,19 @@ components: - name: sub_n1n2 provider_node: n2 status: down + - name: sub_n1n2 + provider_node: n2 + status: down version: 4.10.0 - state: unknown - status_updated_at: "1978-12-17T01:14:06Z" - updated_at: "2010-08-13T18:38:44Z" + state: degraded + status_updated_at: "1990-07-23T01:22:30Z" + updated_at: "2013-01-29T23:51:44Z" - connection_info: addresses: - 10.24.34.2 - i-0123456789abcdef.ec2.internal port: 5432 - created_at: "1970-12-24T01:48:39Z" + created_at: "2001-11-21T07:07:15Z" error: 'failed to get patroni status: connection refused' host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d @@ -16405,7 +17307,7 @@ components: postgres: patroni_paused: true patroni_state: unknown - pending_restart: true + pending_restart: false role: primary version: "18.1" spock: @@ -16417,10 +17319,13 @@ components: - name: sub_n1n2 provider_node: n2 status: down + - name: sub_n1n2 + provider_node: n2 + status: down version: 4.10.0 - state: unknown - status_updated_at: "1978-12-17T01:14:06Z" - updated_at: "2010-08-13T18:38:44Z" + state: degraded + status_updated_at: "1990-07-23T01:22:30Z" + updated_at: "2013-01-29T23:51:44Z" state: failed tenant_id: 8210ec10-2dca-406c-ac4a-0661d2189954 updated_at: "2025-01-01T02:30:00Z" @@ -16432,7 +17337,39 @@ components: - 10.24.34.2 - i-0123456789abcdef.ec2.internal port: 5432 - created_at: "1970-12-24T01:48:39Z" + created_at: "2001-11-21T07:07:15Z" + error: 'failed to get patroni status: connection refused' + host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec + id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d + node_name: n1 + postgres: + patroni_paused: true + patroni_state: unknown + pending_restart: false + role: primary + version: "18.1" + spock: + read_only: "off" + subscriptions: + - name: sub_n1n2 + provider_node: n2 + status: down + - name: sub_n1n2 + provider_node: n2 + status: down + - name: sub_n1n2 + provider_node: n2 + status: down + version: 4.10.0 + state: degraded + status_updated_at: "1990-07-23T01:22:30Z" + updated_at: "2013-01-29T23:51:44Z" + - connection_info: + addresses: + - 10.24.34.2 + - i-0123456789abcdef.ec2.internal + port: 5432 + created_at: "2001-11-21T07:07:15Z" error: 'failed to get patroni status: connection refused' host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d @@ -16440,7 +17377,7 @@ components: postgres: patroni_paused: true patroni_state: unknown - pending_restart: true + pending_restart: false role: primary version: "18.1" spock: @@ -16452,16 +17389,19 @@ components: - name: sub_n1n2 provider_node: n2 status: down + - name: sub_n1n2 + provider_node: n2 + status: down version: 4.10.0 - state: unknown - status_updated_at: "1978-12-17T01:14:06Z" - updated_at: "2010-08-13T18:38:44Z" + state: degraded + status_updated_at: "1990-07-23T01:22:30Z" + updated_at: "2013-01-29T23:51:44Z" - connection_info: addresses: - 10.24.34.2 - i-0123456789abcdef.ec2.internal port: 5432 - created_at: "1970-12-24T01:48:39Z" + created_at: "2001-11-21T07:07:15Z" error: 'failed to get patroni status: connection refused' host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d @@ -16469,7 +17409,7 @@ components: postgres: patroni_paused: true patroni_state: unknown - pending_restart: true + pending_restart: false role: primary version: "18.1" spock: @@ -16481,16 +17421,19 @@ components: - name: sub_n1n2 provider_node: n2 status: down + - name: sub_n1n2 + provider_node: n2 + status: down version: 4.10.0 - state: unknown - status_updated_at: "1978-12-17T01:14:06Z" - updated_at: "2010-08-13T18:38:44Z" + state: degraded + status_updated_at: "1990-07-23T01:22:30Z" + updated_at: "2013-01-29T23:51:44Z" - connection_info: addresses: - 10.24.34.2 - i-0123456789abcdef.ec2.internal port: 5432 - created_at: "1970-12-24T01:48:39Z" + created_at: "2001-11-21T07:07:15Z" error: 'failed to get patroni status: connection refused' host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d @@ -16498,7 +17441,7 @@ components: postgres: patroni_paused: true patroni_state: unknown - pending_restart: true + pending_restart: false role: primary version: "18.1" spock: @@ -16510,10 +17453,13 @@ components: - name: sub_n1n2 provider_node: n2 status: down + - name: sub_n1n2 + provider_node: n2 + status: down version: 4.10.0 - state: unknown - status_updated_at: "1978-12-17T01:14:06Z" - updated_at: "2010-08-13T18:38:44Z" + state: degraded + status_updated_at: "1990-07-23T01:22:30Z" + updated_at: "2013-01-29T23:51:44Z" state: failed tenant_id: 8210ec10-2dca-406c-ac4a-0661d2189954 updated_at: "2025-01-01T02:30:00Z" @@ -16525,7 +17471,39 @@ components: - 10.24.34.2 - i-0123456789abcdef.ec2.internal port: 5432 - created_at: "1970-12-24T01:48:39Z" + created_at: "2001-11-21T07:07:15Z" + error: 'failed to get patroni status: connection refused' + host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec + id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d + node_name: n1 + postgres: + patroni_paused: true + patroni_state: unknown + pending_restart: false + role: primary + version: "18.1" + spock: + read_only: "off" + subscriptions: + - name: sub_n1n2 + provider_node: n2 + status: down + - name: sub_n1n2 + provider_node: n2 + status: down + - name: sub_n1n2 + provider_node: n2 + status: down + version: 4.10.0 + state: degraded + status_updated_at: "1990-07-23T01:22:30Z" + updated_at: "2013-01-29T23:51:44Z" + - connection_info: + addresses: + - 10.24.34.2 + - i-0123456789abcdef.ec2.internal + port: 5432 + created_at: "2001-11-21T07:07:15Z" error: 'failed to get patroni status: connection refused' host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d @@ -16533,7 +17511,7 @@ components: postgres: patroni_paused: true patroni_state: unknown - pending_restart: true + pending_restart: false role: primary version: "18.1" spock: @@ -16545,16 +17523,19 @@ components: - name: sub_n1n2 provider_node: n2 status: down + - name: sub_n1n2 + provider_node: n2 + status: down version: 4.10.0 - state: unknown - status_updated_at: "1978-12-17T01:14:06Z" - updated_at: "2010-08-13T18:38:44Z" + state: degraded + status_updated_at: "1990-07-23T01:22:30Z" + updated_at: "2013-01-29T23:51:44Z" - connection_info: addresses: - 10.24.34.2 - i-0123456789abcdef.ec2.internal port: 5432 - created_at: "1970-12-24T01:48:39Z" + created_at: "2001-11-21T07:07:15Z" error: 'failed to get patroni status: connection refused' host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d @@ -16562,7 +17543,7 @@ components: postgres: patroni_paused: true patroni_state: unknown - pending_restart: true + pending_restart: false role: primary version: "18.1" spock: @@ -16574,16 +17555,19 @@ components: - name: sub_n1n2 provider_node: n2 status: down + - name: sub_n1n2 + provider_node: n2 + status: down version: 4.10.0 - state: unknown - status_updated_at: "1978-12-17T01:14:06Z" - updated_at: "2010-08-13T18:38:44Z" + state: degraded + status_updated_at: "1990-07-23T01:22:30Z" + updated_at: "2013-01-29T23:51:44Z" - connection_info: addresses: - 10.24.34.2 - i-0123456789abcdef.ec2.internal port: 5432 - created_at: "1970-12-24T01:48:39Z" + created_at: "2001-11-21T07:07:15Z" error: 'failed to get patroni status: connection refused' host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d @@ -16591,7 +17575,7 @@ components: postgres: patroni_paused: true patroni_state: unknown - pending_restart: true + pending_restart: false role: primary version: "18.1" spock: @@ -16603,10 +17587,13 @@ components: - name: sub_n1n2 provider_node: n2 status: down + - name: sub_n1n2 + provider_node: n2 + status: down version: 4.10.0 - state: unknown - status_updated_at: "1978-12-17T01:14:06Z" - updated_at: "2010-08-13T18:38:44Z" + state: degraded + status_updated_at: "1990-07-23T01:22:30Z" + updated_at: "2013-01-29T23:51:44Z" state: failed tenant_id: 8210ec10-2dca-406c-ac4a-0661d2189954 updated_at: "2025-01-01T02:30:00Z" @@ -16813,14 +17800,6 @@ components: status: completed task_id: 019783f4-75f4-71e7-85a3-c9b96b345d77 type: create - - completed_at: "2025-06-18T16:52:35Z" - created_at: "2025-06-18T16:52:05Z" - database_id: storefront - entity_id: storefront - scope: database - status: completed - task_id: 019783f4-75f4-71e7-85a3-c9b96b345d77 - type: create example: tasks: - completed_at: "2025-06-18T17:54:36Z" @@ -17013,48 +17992,6 @@ components: spock_version: "5" - postgres_version: "17.6" spock_version: "5" - - client_addresses: - - 10.24.34.2 - - i-0123456789abcdef.ec2.internal - cohort: - control_available: true - member_id: lah4bsznw6kc0hp7biylmmmll - type: swarm - cpus: 4 - data_dir: /data - default_pgedge_version: - postgres_version: "17.6" - spock_version: "5" - etcd_mode: server - id: de3b1388-1f0c-42f1-a86c-59ab72f255ec - memory: 16GiB - orchestrator: swarm - peer_addresses: - - 10.24.34.2 - - i-0123456789abcdef.ec2.internal - status: - components: - Enim et voluptatum ex ea dolore.: - details: - alarms: - - '3: NOSPACE' - error: failed to connect to etcd - healthy: false - Tenetur nostrum repellendus sint qui.: - details: - alarms: - - '3: NOSPACE' - error: failed to connect to etcd - healthy: false - state: available - updated_at: "2021-07-01T12:34:56Z" - supported_pgedge_versions: - - postgres_version: "17.6" - spock_version: "5" - - postgres_version: "17.6" - spock_version: "5" - - postgres_version: "17.6" - spock_version: "5" required: - hosts ListTasksResponse: @@ -17090,6 +18027,14 @@ components: status: completed task_id: 019783f4-75f4-71e7-85a3-c9b96b345d77 type: create + - completed_at: "2025-06-18T16:52:35Z" + created_at: "2025-06-18T16:52:05Z" + database_id: storefront + entity_id: storefront + scope: database + status: completed + task_id: 019783f4-75f4-71e7-85a3-c9b96b345d77 + type: create example: tasks: - completed_at: "2025-06-18T17:54:36Z" @@ -17220,22 +18165,6 @@ components: status: completed task_id: 019783f4-75f4-71e7-85a3-c9b96b345d77 type: create - - completed_at: "2025-06-18T16:52:35Z" - created_at: "2025-06-18T16:52:05Z" - database_id: storefront - entity_id: storefront - scope: database - status: completed - task_id: 019783f4-75f4-71e7-85a3-c9b96b345d77 - type: create - - completed_at: "2025-06-18T16:52:35Z" - created_at: "2025-06-18T16:52:05Z" - database_id: storefront - entity_id: storefront - scope: database - status: completed - task_id: 019783f4-75f4-71e7-85a3-c9b96b345d77 - type: create example: task: completed_at: "2025-06-18T16:52:35Z" @@ -17307,7 +18236,7 @@ components: maxLength: 32 additionalProperties: type: string - example: Dolor autem eum. + example: Et aut aut. source_database_id: type: string description: A user-specified identifier. Must be 1-36 characters, contain only lower-cased letters and hyphens, start and end with a letter or number, and not contain consecutive hyphens. @@ -17365,7 +18294,7 @@ components: type: array items: type: string - example: Sapiente placeat illo. + example: Dolore eos et sunt culpa animi dolor. description: The nodes to restore. Defaults to all nodes if empty or unspecified. example: - n1 @@ -17592,14 +18521,6 @@ components: status: completed task_id: 019783f4-75f4-71e7-85a3-c9b96b345d77 type: create - - completed_at: "2025-06-18T16:52:35Z" - created_at: "2025-06-18T16:52:05Z" - database_id: storefront - entity_id: storefront - scope: database - status: completed - task_id: 019783f4-75f4-71e7-85a3-c9b96b345d77 - type: create task: $ref: '#/components/schemas/Task' example: @@ -17778,7 +18699,7 @@ components: s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab additionalProperties: type: string - example: Aut omnis magnam aspernatur occaecati itaque dolores. + example: Accusamus alias ipsa qui. gcs_bucket: type: string description: The GCS bucket name for this repository. Only applies when type = 'gcs'. @@ -17864,7 +18785,7 @@ components: type: array items: type: string - example: i3l + example: i minLength: 1 maxLength: 1024 description: Each element of this array is an individual SQL statement. @@ -17967,7 +18888,7 @@ components: type: array items: type: string - example: Eos et error vel nihil. + example: Et animi magnam velit vitae praesentium ad. description: The addresses of the host that's running this service instance. example: - 10.24.34.2 @@ -18025,12 +18946,6 @@ components: - container_port: 8080 host_port: 8080 name: web-client - - container_port: 8080 - host_port: 8080 - name: web-client - - container_port: 8080 - host_port: 8080 - name: web-client service_ready: true ServiceSpec: type: object @@ -18065,7 +18980,6 @@ components: description: The IDs of the hosts that should run this service. One service instance will be created per host. example: - de3b1388-1f0c-42f1-a86c-59ab72f255ec - - de3b1388-1f0c-42f1-a86c-59ab72f255ec minItems: 1 memory: type: string @@ -18188,6 +19102,7 @@ components: description: The IDs of the hosts that should run this service. One service instance will be created per host. example: - 76f9b8c0-4958-11f0-a489-3bb29577c696 + - 76f9b8c0-4958-11f0-a489-3bb29577c696 minItems: 1 memory: type: string @@ -18237,6 +19152,7 @@ components: host_ids: - 76f9b8c0-4958-11f0-a489-3bb29577c696 - 76f9b8c0-4958-11f0-a489-3bb29577c696 + - 76f9b8c0-4958-11f0-a489-3bb29577c696 memory: 512M orchestrator_opts: swarm: @@ -18311,6 +19227,7 @@ components: description: The IDs of the hosts that should run this service. One service instance will be created per host. example: - 76f9b8c0-4958-11f0-a489-3bb29577c696 + - 76f9b8c0-4958-11f0-a489-3bb29577c696 minItems: 1 memory: type: string @@ -18360,7 +19277,6 @@ components: host_ids: - 76f9b8c0-4958-11f0-a489-3bb29577c696 - 76f9b8c0-4958-11f0-a489-3bb29577c696 - - 76f9b8c0-4958-11f0-a489-3bb29577c696 memory: 512M orchestrator_opts: swarm: @@ -18435,7 +19351,6 @@ components: description: The IDs of the hosts that should run this service. One service instance will be created per host. example: - 76f9b8c0-4958-11f0-a489-3bb29577c696 - - 76f9b8c0-4958-11f0-a489-3bb29577c696 minItems: 1 memory: type: string @@ -18560,8 +19475,6 @@ components: description: The IDs of the hosts that should run this service. One service instance will be created per host. example: - 76f9b8c0-4958-11f0-a489-3bb29577c696 - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - - 76f9b8c0-4958-11f0-a489-3bb29577c696 minItems: 1 memory: type: string @@ -18610,8 +19523,6 @@ components: target_session_attrs: primary host_ids: - 76f9b8c0-4958-11f0-a489-3bb29577c696 - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - - 76f9b8c0-4958-11f0-a489-3bb29577c696 memory: 512M orchestrator_opts: swarm: @@ -18687,7 +19598,6 @@ components: example: - 76f9b8c0-4958-11f0-a489-3bb29577c696 - 76f9b8c0-4958-11f0-a489-3bb29577c696 - - 76f9b8c0-4958-11f0-a489-3bb29577c696 minItems: 1 memory: type: string @@ -18860,6 +19770,7 @@ components: target_session_attrs: primary host_ids: - 76f9b8c0-4958-11f0-a489-3bb29577c696 + - 76f9b8c0-4958-11f0-a489-3bb29577c696 memory: 512M orchestrator_opts: swarm: @@ -18949,7 +19860,7 @@ components: traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) additionalProperties: type: string - example: Rem culpa. + example: Error eligendi recusandae similique sed neque eos. extra_networks: type: array items: diff --git a/server/internal/api/apiv1/convert.go b/server/internal/api/apiv1/convert.go index 2865a7ce..e1372fdb 100644 --- a/server/internal/api/apiv1/convert.go +++ b/server/internal/api/apiv1/convert.go @@ -145,6 +145,8 @@ func databaseNodesToAPI(nodes []*database.Node) []*api.DatabaseNodeSpec { Cpus: utils.NillablePointerTo(humanizeCPUs(node.CPUs)), Memory: utils.NillablePointerTo(humanizeBytes(node.MemoryBytes)), PostgresqlConf: node.PostgreSQLConf, + PgHbaConf: node.PgHbaConf, + PgIdentConf: node.PgIdentConf, BackupConfig: backupConfigToAPI(node.BackupConfig), RestoreConfig: restoreConfigToAPI(node.RestoreConfig), OrchestratorOpts: orchestratorOptsToAPI(node.OrchestratorOpts), @@ -314,6 +316,8 @@ func databaseSpecToAPI(d *database.Spec) *api.DatabaseSpec { BackupConfig: backupConfigToAPI(d.BackupConfig), RestoreConfig: restoreConfigToAPI(d.RestoreConfig), PostgresqlConf: d.PostgreSQLConf, + PgHbaConf: d.PgHbaConf, + PgIdentConf: d.PgIdentConf, OrchestratorOpts: orchestratorOptsToAPI(d.OrchestratorOpts), Scripts: scriptsToAPI(d.Scripts), } @@ -565,6 +569,8 @@ func apiToDatabaseNodes(apiNodes []*api.DatabaseNodeSpec) ([]*database.Node, err CPUs: cpus, MemoryBytes: memory, PostgreSQLConf: apiNode.PostgresqlConf, + PgHbaConf: apiNode.PgHbaConf, + PgIdentConf: apiNode.PgIdentConf, BackupConfig: backupConfig, RestoreConfig: restoreConfig, OrchestratorOpts: orchestratorOptsToDatabase(apiNode.OrchestratorOpts), @@ -819,6 +825,8 @@ func apiToDatabaseSpec( Services: services, BackupConfig: backupConfig, PostgreSQLConf: apiSpec.PostgresqlConf, + PgHbaConf: apiSpec.PgHbaConf, + PgIdentConf: apiSpec.PgIdentConf, RestoreConfig: restoreConfig, OrchestratorOpts: orchestratorOptsToDatabase(apiSpec.OrchestratorOpts), Scripts: apiToScripts(apiSpec.Scripts), diff --git a/server/internal/api/apiv1/validate.go b/server/internal/api/apiv1/validate.go index 85be21b6..585b41b5 100644 --- a/server/internal/api/apiv1/validate.go +++ b/server/internal/api/apiv1/validate.go @@ -17,6 +17,7 @@ import ( "github.com/pgEdge/control-plane/server/internal/ds" "github.com/pgEdge/control-plane/server/internal/host" "github.com/pgEdge/control-plane/server/internal/pgbackrest" + "github.com/pgEdge/control-plane/server/internal/postgres/hba" "github.com/pgEdge/control-plane/server/internal/storage" "github.com/pgEdge/control-plane/server/internal/utils" ) @@ -64,6 +65,55 @@ func appendPath(path []string, new ...string) []string { return append(slices.Clone(path), new...) } +// validateAuthFileGUCs rejects postgresql_conf settings that would make +// user-supplied pg_hba_conf/pg_ident_conf entries ineffective. When hba_file +// or ident_file is set, Patroni ignores the pg_hba/pg_ident arrays it manages, +// so the control-plane-generated file (including user entries) would never be +// written. GUC names are case-insensitive in PostgreSQL, so we compare lower. +func validateAuthFileGUCs(conf map[string]any, path []string) []error { + var errs []error + for key := range conf { + switch strings.ToLower(strings.TrimSpace(key)) { + case "hba_file", "ident_file": + err := fmt.Errorf("%q is not allowed: it overrides the control-plane-managed pg_hba.conf/pg_ident.conf and would make pg_hba_conf/pg_ident_conf entries ineffective", key) + errs = append(errs, newValidationError(err, appendPath(path, mapKeyPath(key)))) + } + } + return errs +} + +// validatePgHbaConf checks that every non-comment pg_hba_conf entry parses. +// Blank and comment lines are allowed and skipped. Validation is intentionally +// minimal — see server/internal/postgres/hba/parse.go. +func validatePgHbaConf(lines []string, path []string) []error { + var errs []error + for i, line := range lines { + if hba.IsComment(line) { + continue + } + if _, err := hba.ParseEntry(line); err != nil { + wrapped := fmt.Errorf("invalid pg_hba entry %q: %w", line, err) + errs = append(errs, newValidationError(wrapped, appendPath(path, arrayIndexPath(i)))) + } + } + return errs +} + +// validatePgIdentConf checks that every non-comment pg_ident_conf entry parses. +func validatePgIdentConf(lines []string, path []string) []error { + var errs []error + for i, line := range lines { + if hba.IsComment(line) { + continue + } + if _, err := hba.ParseIdent(line); err != nil { + wrapped := fmt.Errorf("invalid pg_ident entry %q: %w", line, err) + errs = append(errs, newValidationError(wrapped, appendPath(path, arrayIndexPath(i)))) + } + } + return errs +} + func validateDatabaseSpec(orchestrator config.Orchestrator, databaseID string, spec *api.DatabaseSpec) error { var errs []error @@ -123,6 +173,12 @@ func validateDatabaseSpec(orchestrator config.Orchestrator, databaseID string, s } } + // Reject postgresql_conf GUCs that would make user-supplied pg_hba/pg_ident + // entries ineffective, then validate the entries themselves. + errs = append(errs, validateAuthFileGUCs(spec.PostgresqlConf, []string{"postgresql_conf"})...) + errs = append(errs, validatePgHbaConf(spec.PgHbaConf, []string{"pg_hba_conf"})...) + errs = append(errs, validatePgIdentConf(spec.PgIdentConf, []string{"pg_ident_conf"})...) + if spec.BackupConfig != nil { errs = append(errs, validateBackupConfig(spec.BackupConfig, []string{"backup_config"})...) } @@ -285,6 +341,10 @@ func validateNode( } } + errs = append(errs, validateAuthFileGUCs(node.PostgresqlConf, appendPath(path, "postgresql_conf"))...) + errs = append(errs, validatePgHbaConf(node.PgHbaConf, appendPath(path, "pg_hba_conf"))...) + errs = append(errs, validatePgIdentConf(node.PgIdentConf, appendPath(path, "pg_ident_conf"))...) + if node.BackupConfig != nil { backupConfigPath := appendPath(path, "backup_config") errs = append(errs, validateBackupConfig(node.BackupConfig, backupConfigPath)...) diff --git a/server/internal/api/apiv1/validate_test.go b/server/internal/api/apiv1/validate_test.go index 04786269..97f1a84e 100644 --- a/server/internal/api/apiv1/validate_test.go +++ b/server/internal/api/apiv1/validate_test.go @@ -1268,6 +1268,65 @@ func TestValidateDatabaseSpec(t *testing.T) { "scripts.post_database_create[3]: failed to parse SQL statement", }, }, + { + name: "valid pg_hba_conf and pg_ident_conf at database and node level", + spec: &api.DatabaseSpec{ + PgHbaConf: []string{ + "hostssl all myapp_user 203.0.113.0/24 scram-sha-256", + "hostssl all alice 0.0.0.0/0 cert clientcert=verify-full map=ssl_users", + "# a comment is allowed", + "", + }, + PgIdentConf: []string{"ssl_users CN=alice,O=example alice"}, + Nodes: []*api.DatabaseNodeSpec{ + { + Name: "n1", + HostIds: []api.Identifier{api.Identifier("host-1")}, + PgHbaConf: []string{"host example myapp_user 10.0.0.0/8 scram-sha-256"}, + }, + }, + }, + }, + { + name: "unparseable pg_hba_conf/pg_ident_conf lines are rejected with the offending line", + spec: &api.DatabaseSpec{ + PgHbaConf: []string{"tcp all all 0.0.0.0/0 md5"}, + PgIdentConf: []string{"ssl_users alice"}, + Nodes: []*api.DatabaseNodeSpec{ + { + Name: "n1", + HostIds: []api.Identifier{api.Identifier("host-1")}, + PgHbaConf: []string{"nonsense line"}, + }, + }, + }, + expected: []string{ + `pg_hba_conf[0]: invalid pg_hba entry "tcp all all 0.0.0.0/0 md5": unknown connection type "tcp"`, + `pg_ident_conf[0]: invalid pg_ident entry "ssl_users alice": pg_ident entry requires map-name`, + `nodes[0].pg_hba_conf[0]: invalid pg_hba entry "nonsense line": unknown connection type "nonsense"`, + }, + }, + { + name: "hba_file and ident_file GUCs are rejected", + spec: &api.DatabaseSpec{ + PostgresqlConf: map[string]any{ + "hba_file": "/custom/pg_hba.conf", + "ident_file": "/custom/pg_ident.conf", + }, + Nodes: []*api.DatabaseNodeSpec{ + { + Name: "n1", + HostIds: []api.Identifier{api.Identifier("host-1")}, + PostgresqlConf: map[string]any{"HBA_FILE": "/x"}, + }, + }, + }, + expected: []string{ + `postgresql_conf[hba_file]: "hba_file" is not allowed`, + `postgresql_conf[ident_file]: "ident_file" is not allowed`, + `nodes[0].postgresql_conf[HBA_FILE]: "HBA_FILE" is not allowed`, + }, + }, } { t.Run(tc.name, func(t *testing.T) { err := validateDatabaseSpec(config.OrchestratorSwarm, "test-db", tc.spec) @@ -1895,13 +1954,13 @@ func TestValidateServiceSpec_NameBudget(t *testing.T) { } // 26-char DB ID + 27-char service ID = 53 (at the limit, valid) - dbID26 := "abcdefghijklmnopqrstuvwxyz" // 26 chars - svcID27 := "svc-aaaaaaaaaaaaaaaaaaaaaaa" // 27 chars + dbID26 := "abcdefghijklmnopqrstuvwxyz" // 26 chars + svcID27 := "svc-aaaaaaaaaaaaaaaaaaaaaaa" // 27 chars err := errors.Join(validateServiceSpec(baseSvc(svcID27), nil, false, dbID26, testDBUsers)...) assert.NoError(t, err, "combined length of 53 should be valid") // 27-char DB ID + 27-char service ID = 54 (one over the limit, invalid) - dbID27 := "abcdefghijklmnopqrstuvwxyz1" // 27 chars + dbID27 := "abcdefghijklmnopqrstuvwxyz1" // 27 chars err = errors.Join(validateServiceSpec(baseSvc(svcID27), nil, false, dbID27, testDBUsers)...) assert.ErrorContains(t, err, "database ID and service ID combined must not exceed 53 characters (got 54)") diff --git a/server/internal/database/spec.go b/server/internal/database/spec.go index eb921b87..e4410dd7 100644 --- a/server/internal/database/spec.go +++ b/server/internal/database/spec.go @@ -45,6 +45,8 @@ type Node struct { CPUs float64 `json:"cpus"` MemoryBytes uint64 `json:"memory"` PostgreSQLConf map[string]any `json:"postgresql_conf"` + PgHbaConf []string `json:"pg_hba_conf,omitempty"` + PgIdentConf []string `json:"pg_ident_conf,omitempty"` BackupConfig *BackupConfig `json:"backup_config"` RestoreConfig *RestoreConfig `json:"restore_config"` OrchestratorOpts *OrchestratorOpts `json:"orchestrator_opts,omitempty"` @@ -64,6 +66,8 @@ func (n *Node) Clone() *Node { CPUs: n.CPUs, MemoryBytes: n.MemoryBytes, PostgreSQLConf: maps.Clone(n.PostgreSQLConf), + PgHbaConf: slices.Clone(n.PgHbaConf), + PgIdentConf: slices.Clone(n.PgIdentConf), BackupConfig: n.BackupConfig.Clone(), RestoreConfig: n.RestoreConfig.Clone(), OrchestratorOpts: n.OrchestratorOpts.Clone(), @@ -331,6 +335,8 @@ type Spec struct { BackupConfig *BackupConfig `json:"backup_config"` RestoreConfig *RestoreConfig `json:"restore_config"` PostgreSQLConf map[string]any `json:"postgresql_conf"` + PgHbaConf []string `json:"pg_hba_conf,omitempty"` + PgIdentConf []string `json:"pg_ident_conf,omitempty"` OrchestratorOpts *OrchestratorOpts `json:"orchestrator_opts,omitempty"` Scripts *ScriptStatements `json:"scripts,omitempty"` } @@ -414,6 +420,8 @@ func (s *Spec) Clone() *Spec { CPUs: s.CPUs, MemoryBytes: s.MemoryBytes, PostgreSQLConf: maps.Clone(s.PostgreSQLConf), + PgHbaConf: slices.Clone(s.PgHbaConf), + PgIdentConf: slices.Clone(s.PgIdentConf), Nodes: nodes, DatabaseUsers: users, Services: services, @@ -564,6 +572,8 @@ type InstanceSpec struct { BackupConfig *BackupConfig `json:"backup_config"` RestoreConfig *RestoreConfig `json:"restore_config"` PostgreSQLConf map[string]any `json:"postgresql_conf"` + PgHbaConf []string `json:"pg_hba_conf,omitempty"` + PgIdentConf []string `json:"pg_ident_conf,omitempty"` ClusterSize int `json:"cluster_size"` NodeSize int `json:"node_size"` OrchestratorOpts *OrchestratorOpts `json:"orchestrator_opts,omitempty"` @@ -618,6 +628,8 @@ func (s *InstanceSpec) Clone() *InstanceSpec { BackupConfig: s.BackupConfig.Clone(), RestoreConfig: s.RestoreConfig.Clone(), PostgreSQLConf: maps.Clone(s.PostgreSQLConf), + PgHbaConf: slices.Clone(s.PgHbaConf), + PgIdentConf: slices.Clone(s.PgIdentConf), ClusterSize: s.ClusterSize, NodeSize: s.NodeSize, OrchestratorOpts: s.OrchestratorOpts.Clone(), @@ -716,6 +728,8 @@ func (s *Spec) NodeInstances() ([]*NodeInstances, error) { BackupConfig: overridableValue(s.BackupConfig, node.BackupConfig), RestoreConfig: effectiveRestore, PostgreSQLConf: overridableMapValue(s.PostgreSQLConf, node.PostgreSQLConf), + PgHbaConf: prependEntries(s.PgHbaConf, node.PgHbaConf), + PgIdentConf: prependEntries(s.PgIdentConf, node.PgIdentConf), ClusterSize: clusterSize, NodeSize: nodeSize, OrchestratorOpts: overridableValue(s.OrchestratorOpts, node.OrchestratorOpts), @@ -762,3 +776,18 @@ func overridableMapValue[T ~map[V]any, V comparable](base, override T) T { } return base } + +// prependEntries merges node-level entries (override) ahead of database-level +// entries (base). pg_hba/pg_ident are ordered lists evaluated first-match, so +// node entries are given priority by placing them first; the database-level +// entries act as the baseline. Returns nil when both are empty so the field is +// omitted, identical to today's behavior. +func prependEntries(base, override []string) []string { + if len(base) == 0 && len(override) == 0 { + return nil + } + merged := make([]string, 0, len(override)+len(base)) + merged = append(merged, override...) + merged = append(merged, base...) + return merged +} diff --git a/server/internal/database/spec_test.go b/server/internal/database/spec_test.go index 4b7a2692..9acdbf23 100644 --- a/server/internal/database/spec_test.go +++ b/server/internal/database/spec_test.go @@ -566,3 +566,59 @@ func TestSpec_NodeInstances_DBOwner(t *testing.T) { assert.Equal(t, "app", nodes[1].DatabaseOwner) }) } + +func TestSpec_NodeInstances_PgHbaIdentMerge(t *testing.T) { + dbHba := []string{"host all myapp_user 203.0.113.0/24 scram-sha-256"} + dbIdent := []string{"ssl_users CN=alice alice"} + + spec := func(n1, n2 *database.Node) *database.Spec { + return &database.Spec{ + DatabaseID: "test-db", + DatabaseName: "testdb", + PostgresVersion: "17.6", + SpockVersion: "5", + PgHbaConf: dbHba, + PgIdentConf: dbIdent, + Nodes: []*database.Node{n1, n2}, + } + } + + t.Run("node with no entries inherits database-level list", func(t *testing.T) { + s := spec( + &database.Node{Name: "n1", HostIDs: []string{"host-1"}}, + &database.Node{Name: "n2", HostIDs: []string{"host-2"}}, + ) + nodes, err := s.NodeInstances() + assert.NoError(t, err) + assert.Equal(t, dbHba, nodes[0].Instances[0].PgHbaConf) + assert.Equal(t, dbIdent, nodes[0].Instances[0].PgIdentConf) + }) + + t.Run("node entries are prepended ahead of database-level entries", func(t *testing.T) { + nodeHba := "host example myapp_user 10.0.0.0/8 scram-sha-256" + s := spec( + &database.Node{Name: "n1", HostIDs: []string{"host-1"}, PgHbaConf: []string{nodeHba}}, + &database.Node{Name: "n2", HostIDs: []string{"host-2"}}, + ) + nodes, err := s.NodeInstances() + assert.NoError(t, err) + // n1: node entry first, then database-level entry (first-match priority). + assert.Equal(t, append([]string{nodeHba}, dbHba...), nodes[0].Instances[0].PgHbaConf) + // n2: unchanged, inherits database-level list only. + assert.Equal(t, dbHba, nodes[1].Instances[0].PgHbaConf) + }) + + t.Run("empty everywhere yields nil", func(t *testing.T) { + s := &database.Spec{ + DatabaseID: "test-db", + DatabaseName: "testdb", + PostgresVersion: "17.6", + SpockVersion: "5", + Nodes: []*database.Node{{Name: "n1", HostIDs: []string{"host-1"}}}, + } + nodes, err := s.NodeInstances() + assert.NoError(t, err) + assert.Nil(t, nodes[0].Instances[0].PgHbaConf) + assert.Nil(t, nodes[0].Instances[0].PgIdentConf) + }) +} diff --git a/server/internal/postgres/hba/parse.go b/server/internal/postgres/hba/parse.go new file mode 100644 index 00000000..754553e7 --- /dev/null +++ b/server/internal/postgres/hba/parse.go @@ -0,0 +1,201 @@ +package hba + +import ( + "errors" + "fmt" + "net" + "strings" + "unicode" +) + +// This file provides lightweight parsers for pg_hba.conf and pg_ident.conf +// lines. They are used to validate user-supplied entries at spec-acceptance +// time. +// +// Validation is intentionally minimal. Per the design, the control plane does +// not second-guess the operator: there are NO enum-style restrictions on the +// auth method, no blocking of trust on broad CIDRs, no duplicate detection, and +// no map= cross-reference checks. We only reject lines that are not +// recognizable pg_hba/pg_ident entries at all (unknown connection type, too few +// fields, unterminated quotes). PostgreSQL surfaces deeper configuration errors +// (bad auth methods, addresses, options) at reload time via the task logs. + +var entryTypes = map[EntryType]struct{}{ + EntryTypeLocal: {}, + EntryTypeHost: {}, + EntryTypeHostSSL: {}, + EntryTypeHostNoSSL: {}, + EntryTypeHostGSSEnc: {}, + EntryTypeHostNoGSSEnc: {}, + EntryTypeInclude: {}, + EntryTypeIncludeIfExists: {}, + EntryTypeIncludeDir: {}, +} + +func isIncludeType(t EntryType) bool { + return t == EntryTypeInclude || t == EntryTypeIncludeIfExists || t == EntryTypeIncludeDir +} + +// isBareIP reports whether s is a plain IP address with no CIDR suffix. It is +// used only to disambiguate the optional separate IP-mask form of a host entry +// ("ADDRESS MASK METHOD"); it is not a validity check on the address. +func isBareIP(s string) bool { + return !strings.Contains(s, "/") && net.ParseIP(s) != nil +} + +// IsComment reports whether a line is blank or a comment and therefore carries +// no rule to parse. Callers should skip such lines. +func IsComment(line string) bool { + trimmed := strings.TrimSpace(line) + return trimmed == "" || strings.HasPrefix(trimmed, "#") +} + +// tokenize splits a configuration line into whitespace-separated fields, +// honoring double-quoted strings (which may contain spaces) and stopping at an +// unquoted '#' comment. It returns an error for an unterminated quote. +func tokenize(line string) ([]string, error) { + var ( + tokens []string + buf strings.Builder + inQuote bool + hasToken bool + ) + flush := func() { + if hasToken { + tokens = append(tokens, buf.String()) + buf.Reset() + hasToken = false + } + } + for _, r := range line { + switch { + case r == '"': + inQuote = !inQuote + hasToken = true + case r == '#' && !inQuote: + flush() + return tokens, nil + case unicode.IsSpace(r) && !inQuote: + flush() + default: + buf.WriteRune(r) + hasToken = true + } + } + if inQuote { + return nil, errors.New("unterminated quoted string") + } + flush() + return tokens, nil +} + +// ParseEntry parses a single pg_hba.conf rule line into an Entry. The line must +// contain a rule; callers should skip blank and comment lines (see IsComment). +// The auth method is captured verbatim and NOT validated against a known set. +func ParseEntry(line string) (Entry, error) { + tokens, err := tokenize(line) + if err != nil { + return Entry{}, err + } + if len(tokens) == 0 { + return Entry{}, errors.New("empty entry") + } + + typ := EntryType(tokens[0]) + if _, ok := entryTypes[typ]; !ok { + return Entry{}, fmt.Errorf("unknown connection type %q", tokens[0]) + } + + switch { + case isIncludeType(typ): + if len(tokens) != 2 { + return Entry{}, fmt.Errorf("%s requires exactly one path argument", typ) + } + return Entry{Type: typ, IncludePath: tokens[1]}, nil + + case typ == EntryTypeLocal: + // local DATABASE USER METHOD [options] + if len(tokens) < 4 { + return Entry{}, errors.New("local entry requires database, user, and an auth method") + } + return Entry{ + Type: typ, + Database: tokens[1], + User: tokens[2], + AuthMethod: AuthMethod(tokens[3]), + AuthOptions: strings.Join(tokens[4:], " "), + }, nil + + default: + // host-based: TYPE DATABASE USER ADDRESS [MASK] METHOD [options] + if len(tokens) < 5 { + return Entry{}, fmt.Errorf("%s entry requires database, user, address, and an auth method", typ) + } + entry := Entry{ + Type: typ, + Database: tokens[1], + User: tokens[2], + Address: tokens[3], + } + rest := tokens[4:] + if len(rest) >= 2 && isBareIP(rest[0]) { + // Separate IP-mask form: ADDRESS MASK METHOD [options]. + entry.Mask = rest[0] + entry.AuthMethod = AuthMethod(rest[1]) + entry.AuthOptions = strings.Join(rest[2:], " ") + } else { + entry.AuthMethod = AuthMethod(rest[0]) + entry.AuthOptions = strings.Join(rest[1:], " ") + } + return entry, nil + } +} + +// IdentEntry is a single pg_ident.conf user-name-map line: a mapping of +// map-name + system-username to a PostgreSQL username, or an include directive. +type IdentEntry struct { + MapName string + SystemUsername string + PostgresUsername string + + // Include and IncludePath are set instead of the mapping fields when the + // line is an include directive. + Include EntryType + IncludePath string +} + +func (e IdentEntry) String() string { + if e.Include != "" { + return fmt.Sprintf("%-17s %s", e.Include, e.IncludePath) + } + return fmt.Sprintf("%-15s %-23s %s", e.MapName, e.SystemUsername, e.PostgresUsername) +} + +// ParseIdent parses a single pg_ident.conf line. The line must contain a +// mapping or an include directive; callers should skip blank and comment lines +// (see IsComment). A mapping is always exactly three fields. +func ParseIdent(line string) (IdentEntry, error) { + tokens, err := tokenize(line) + if err != nil { + return IdentEntry{}, err + } + if len(tokens) == 0 { + return IdentEntry{}, errors.New("empty entry") + } + + if typ := EntryType(tokens[0]); isIncludeType(typ) { + if len(tokens) != 2 { + return IdentEntry{}, fmt.Errorf("%s requires exactly one path argument", typ) + } + return IdentEntry{Include: typ, IncludePath: tokens[1]}, nil + } + + if len(tokens) != 3 { + return IdentEntry{}, errors.New("pg_ident entry requires map-name, system-username, and postgres-username") + } + return IdentEntry{ + MapName: tokens[0], + SystemUsername: tokens[1], + PostgresUsername: tokens[2], + }, nil +} diff --git a/server/internal/postgres/hba/parse_test.go b/server/internal/postgres/hba/parse_test.go new file mode 100644 index 00000000..3abab8df --- /dev/null +++ b/server/internal/postgres/hba/parse_test.go @@ -0,0 +1,151 @@ +package hba + +import "testing" + +func TestParseEntry(t *testing.T) { + tests := []struct { + name string + line string + want Entry + }{ + { + name: "host with cidr and md5", + line: "host all all 0.0.0.0/0 md5", + want: Entry{Type: EntryTypeHost, Database: "all", User: "all", Address: "0.0.0.0/0", AuthMethod: AuthMethodMD5}, + }, + { + name: "hostssl scram for specific user and cidr", + line: "hostssl all myapp_user 203.0.113.0/24 scram-sha-256", + want: Entry{Type: EntryTypeHostSSL, Database: "all", User: "myapp_user", Address: "203.0.113.0/24", AuthMethod: AuthMethodScramSHA256}, + }, + { + name: "cert with options and map", + line: "hostssl all alice 0.0.0.0/0 cert clientcert=verify-full map=ssl_users", + want: Entry{Type: EntryTypeHostSSL, Database: "all", User: "alice", Address: "0.0.0.0/0", AuthMethod: AuthMethodCert, AuthOptions: "clientcert=verify-full map=ssl_users"}, + }, + { + name: "separate ip mask form", + line: "host all all 192.168.0.0 255.255.0.0 md5", + want: Entry{Type: EntryTypeHost, Database: "all", User: "all", Address: "192.168.0.0", Mask: "255.255.0.0", AuthMethod: AuthMethodMD5}, + }, + { + name: "local trust", + line: "local all all trust", + want: Entry{Type: EntryTypeLocal, Database: "all", User: "all", AuthMethod: AuthMethodTrust}, + }, + { + name: "comma-separated users", + line: "host all pgedge,patroni_replicator 0.0.0.0/0 reject", + want: Entry{Type: EntryTypeHost, Database: "all", User: "pgedge,patroni_replicator", Address: "0.0.0.0/0", AuthMethod: AuthMethodReject}, + }, + { + name: "quoted database with space", + line: `host "my db" all 10.0.0.0/8 md5`, + want: Entry{Type: EntryTypeHost, Database: "my db", User: "all", Address: "10.0.0.0/8", AuthMethod: AuthMethodMD5}, + }, + { + name: "trailing comment is ignored", + line: "host all all 0.0.0.0/0 md5 # allow everyone", + want: Entry{Type: EntryTypeHost, Database: "all", User: "all", Address: "0.0.0.0/0", AuthMethod: AuthMethodMD5}, + }, + { + name: "include directive", + line: "include /etc/pg_hba_extra.conf", + want: Entry{Type: EntryTypeInclude, IncludePath: "/etc/pg_hba_extra.conf"}, + }, + { + // The auth method is captured verbatim and not validated against a + // known set (design: no enum-style restrictions on auth_method). + name: "unrecognized auth method is accepted verbatim", + line: "host all all 0.0.0.0/0 ldap2", + want: Entry{Type: EntryTypeHost, Database: "all", User: "all", Address: "0.0.0.0/0", AuthMethod: AuthMethod("ldap2")}, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + got, err := ParseEntry(tc.line) + if err != nil { + t.Fatalf("ParseEntry(%q) returned error: %v", tc.line, err) + } + if got != tc.want { + t.Errorf("ParseEntry(%q)\n got: %#v\n want: %#v", tc.line, got, tc.want) + } + }) + } +} + +func TestParseEntryErrors(t *testing.T) { + tests := []struct { + name string + line string + }{ + {"unknown connection type", "tcp all all 0.0.0.0/0 md5"}, + {"missing auth method", "host all all 0.0.0.0/0"}, + {"local missing method", "local all all"}, + {"include without path", "include"}, + {"include with too many args", "include a b"}, + {"empty", ""}, + {"unterminated quote", `host "all all 0.0.0.0/0 md5`}, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + if _, err := ParseEntry(tc.line); err == nil { + t.Errorf("ParseEntry(%q) expected an error, got nil", tc.line) + } + }) + } +} + +func TestParseIdent(t *testing.T) { + tests := []struct { + name string + line string + want IdentEntry + }{ + { + name: "basic mapping", + line: "ssl_users CN=alice,O=example alice", + want: IdentEntry{MapName: "ssl_users", SystemUsername: "CN=alice,O=example", PostgresUsername: "alice"}, + }, + { + name: "quoted system username with spaces", + line: `ssl_users "CN=alice smith,O=example" alice`, + want: IdentEntry{MapName: "ssl_users", SystemUsername: "CN=alice smith,O=example", PostgresUsername: "alice"}, + }, + { + name: "include directive", + line: "include_if_exists /etc/pg_ident_extra.conf", + want: IdentEntry{Include: EntryTypeIncludeIfExists, IncludePath: "/etc/pg_ident_extra.conf"}, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + got, err := ParseIdent(tc.line) + if err != nil { + t.Fatalf("ParseIdent(%q) returned error: %v", tc.line, err) + } + if got != tc.want { + t.Errorf("ParseIdent(%q)\n got: %#v\n want: %#v", tc.line, got, tc.want) + } + }) + } +} + +func TestParseIdentErrors(t *testing.T) { + tests := []struct { + name string + line string + }{ + {"too few fields", "ssl_users alice"}, + {"too many fields", "ssl_users CN=alice alice extra"}, + {"empty", ""}, + {"unterminated quote", `ssl_users "CN=alice alice`}, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + if _, err := ParseIdent(tc.line); err == nil { + t.Errorf("ParseIdent(%q) expected an error, got nil", tc.line) + } + }) + } +} From 498491a30c34b0bdab136465423243cfc05ef078 Mon Sep 17 00:00:00 2001 From: moizpgedge Date: Thu, 4 Jun 2026 19:17:56 +0500 Subject: [PATCH 2/2] refactor: address pg_hba/pg_ident review feedback Code-review cleanups for the pg_hba_conf/pg_ident_conf spec work. No behavior change. - Merge node-level and database-level entries with `slices.Concat` instead of a custom helper. Node entries come first to keep first-match priority. - Use `ds.Set` for the pg_hba connection-type set instead of a plain `map[EntryType]struct{}`. - Drop the redundant `strings.Contains` guard in `isBareIP`; `net.ParseIP` already returns nil for CIDR strings. - Simplify the tokenizer to flush on `buf.Len() > 0` instead of a separate `hasToken` flag. - Convert the parser tests to testify, asserting specific error messages via `require.ErrorContains`. PLAT-615 --- server/internal/database/spec.go | 53 ++++++++------------ server/internal/postgres/hba/parse.go | 40 ++++++++-------- server/internal/postgres/hba/parse_test.go | 56 ++++++++++------------ 3 files changed, 65 insertions(+), 84 deletions(-) diff --git a/server/internal/database/spec.go b/server/internal/database/spec.go index e4410dd7..42d9aed7 100644 --- a/server/internal/database/spec.go +++ b/server/internal/database/spec.go @@ -712,24 +712,26 @@ func (s *Spec) NodeInstances() ([]*NodeInstances, error) { instances := make([]*InstanceSpec, len(node.HostIDs)) for hostIdx, hostID := range node.HostIDs { instances[hostIdx] = &InstanceSpec{ - InstanceID: InstanceIDFor(hostID, s.DatabaseID, node.Name), - TenantID: s.TenantID, - DatabaseID: s.DatabaseID, - HostID: hostID, - DatabaseName: s.DatabaseName, - NodeName: node.Name, - NodeOrdinal: nodeOrdinal, - PgEdgeVersion: nodeVersion, - Port: overridableValue(s.Port, node.Port), - PatroniPort: overridableValue(s.PatroniPort, node.PatroniPort), - CPUs: overridableValue(s.CPUs, node.CPUs), - MemoryBytes: overridableValue(s.MemoryBytes, node.MemoryBytes), - DatabaseUsers: s.DatabaseUsers, - BackupConfig: overridableValue(s.BackupConfig, node.BackupConfig), - RestoreConfig: effectiveRestore, - PostgreSQLConf: overridableMapValue(s.PostgreSQLConf, node.PostgreSQLConf), - PgHbaConf: prependEntries(s.PgHbaConf, node.PgHbaConf), - PgIdentConf: prependEntries(s.PgIdentConf, node.PgIdentConf), + InstanceID: InstanceIDFor(hostID, s.DatabaseID, node.Name), + TenantID: s.TenantID, + DatabaseID: s.DatabaseID, + HostID: hostID, + DatabaseName: s.DatabaseName, + NodeName: node.Name, + NodeOrdinal: nodeOrdinal, + PgEdgeVersion: nodeVersion, + Port: overridableValue(s.Port, node.Port), + PatroniPort: overridableValue(s.PatroniPort, node.PatroniPort), + CPUs: overridableValue(s.CPUs, node.CPUs), + MemoryBytes: overridableValue(s.MemoryBytes, node.MemoryBytes), + DatabaseUsers: s.DatabaseUsers, + BackupConfig: overridableValue(s.BackupConfig, node.BackupConfig), + RestoreConfig: effectiveRestore, + PostgreSQLConf: overridableMapValue(s.PostgreSQLConf, node.PostgreSQLConf), + // Node entries come first so they take first-match priority; + // database-level entries follow as the baseline. + PgHbaConf: slices.Concat(node.PgHbaConf, s.PgHbaConf), + PgIdentConf: slices.Concat(node.PgIdentConf, s.PgIdentConf), ClusterSize: clusterSize, NodeSize: nodeSize, OrchestratorOpts: overridableValue(s.OrchestratorOpts, node.OrchestratorOpts), @@ -776,18 +778,3 @@ func overridableMapValue[T ~map[V]any, V comparable](base, override T) T { } return base } - -// prependEntries merges node-level entries (override) ahead of database-level -// entries (base). pg_hba/pg_ident are ordered lists evaluated first-match, so -// node entries are given priority by placing them first; the database-level -// entries act as the baseline. Returns nil when both are empty so the field is -// omitted, identical to today's behavior. -func prependEntries(base, override []string) []string { - if len(base) == 0 && len(override) == 0 { - return nil - } - merged := make([]string, 0, len(override)+len(base)) - merged = append(merged, override...) - merged = append(merged, base...) - return merged -} diff --git a/server/internal/postgres/hba/parse.go b/server/internal/postgres/hba/parse.go index 754553e7..11b2c76a 100644 --- a/server/internal/postgres/hba/parse.go +++ b/server/internal/postgres/hba/parse.go @@ -6,6 +6,8 @@ import ( "net" "strings" "unicode" + + "github.com/pgEdge/control-plane/server/internal/ds" ) // This file provides lightweight parsers for pg_hba.conf and pg_ident.conf @@ -20,17 +22,17 @@ import ( // fields, unterminated quotes). PostgreSQL surfaces deeper configuration errors // (bad auth methods, addresses, options) at reload time via the task logs. -var entryTypes = map[EntryType]struct{}{ - EntryTypeLocal: {}, - EntryTypeHost: {}, - EntryTypeHostSSL: {}, - EntryTypeHostNoSSL: {}, - EntryTypeHostGSSEnc: {}, - EntryTypeHostNoGSSEnc: {}, - EntryTypeInclude: {}, - EntryTypeIncludeIfExists: {}, - EntryTypeIncludeDir: {}, -} +var entryTypes = ds.NewSet( + EntryTypeLocal, + EntryTypeHost, + EntryTypeHostSSL, + EntryTypeHostNoSSL, + EntryTypeHostGSSEnc, + EntryTypeHostNoGSSEnc, + EntryTypeInclude, + EntryTypeIncludeIfExists, + EntryTypeIncludeDir, +) func isIncludeType(t EntryType) bool { return t == EntryTypeInclude || t == EntryTypeIncludeIfExists || t == EntryTypeIncludeDir @@ -40,7 +42,7 @@ func isIncludeType(t EntryType) bool { // used only to disambiguate the optional separate IP-mask form of a host entry // ("ADDRESS MASK METHOD"); it is not a validity check on the address. func isBareIP(s string) bool { - return !strings.Contains(s, "/") && net.ParseIP(s) != nil + return net.ParseIP(s) != nil } // IsComment reports whether a line is blank or a comment and therefore carries @@ -55,23 +57,20 @@ func IsComment(line string) bool { // unquoted '#' comment. It returns an error for an unterminated quote. func tokenize(line string) ([]string, error) { var ( - tokens []string - buf strings.Builder - inQuote bool - hasToken bool + tokens []string + buf strings.Builder + inQuote bool ) flush := func() { - if hasToken { + if buf.Len() > 0 { tokens = append(tokens, buf.String()) buf.Reset() - hasToken = false } } for _, r := range line { switch { case r == '"': inQuote = !inQuote - hasToken = true case r == '#' && !inQuote: flush() return tokens, nil @@ -79,7 +78,6 @@ func tokenize(line string) ([]string, error) { flush() default: buf.WriteRune(r) - hasToken = true } } if inQuote { @@ -102,7 +100,7 @@ func ParseEntry(line string) (Entry, error) { } typ := EntryType(tokens[0]) - if _, ok := entryTypes[typ]; !ok { + if !entryTypes.Has(typ) { return Entry{}, fmt.Errorf("unknown connection type %q", tokens[0]) } diff --git a/server/internal/postgres/hba/parse_test.go b/server/internal/postgres/hba/parse_test.go index 3abab8df..c874ab83 100644 --- a/server/internal/postgres/hba/parse_test.go +++ b/server/internal/postgres/hba/parse_test.go @@ -1,6 +1,10 @@ package hba -import "testing" +import ( + "testing" + + "github.com/stretchr/testify/require" +) func TestParseEntry(t *testing.T) { tests := []struct { @@ -64,12 +68,8 @@ func TestParseEntry(t *testing.T) { for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { got, err := ParseEntry(tc.line) - if err != nil { - t.Fatalf("ParseEntry(%q) returned error: %v", tc.line, err) - } - if got != tc.want { - t.Errorf("ParseEntry(%q)\n got: %#v\n want: %#v", tc.line, got, tc.want) - } + require.NoError(t, err) + require.Equal(t, tc.want, got) }) } } @@ -78,20 +78,20 @@ func TestParseEntryErrors(t *testing.T) { tests := []struct { name string line string + err string }{ - {"unknown connection type", "tcp all all 0.0.0.0/0 md5"}, - {"missing auth method", "host all all 0.0.0.0/0"}, - {"local missing method", "local all all"}, - {"include without path", "include"}, - {"include with too many args", "include a b"}, - {"empty", ""}, - {"unterminated quote", `host "all all 0.0.0.0/0 md5`}, + {"unknown connection type", "tcp all all 0.0.0.0/0 md5", `unknown connection type "tcp"`}, + {"missing auth method", "host all all 0.0.0.0/0", "requires database, user, address, and an auth method"}, + {"local missing method", "local all all", "local entry requires database, user, and an auth method"}, + {"include without path", "include", "requires exactly one path argument"}, + {"include with too many args", "include a b", "requires exactly one path argument"}, + {"empty", "", "empty entry"}, + {"unterminated quote", `host "all all 0.0.0.0/0 md5`, "unterminated quoted string"}, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - if _, err := ParseEntry(tc.line); err == nil { - t.Errorf("ParseEntry(%q) expected an error, got nil", tc.line) - } + _, err := ParseEntry(tc.line) + require.ErrorContains(t, err, tc.err) }) } } @@ -121,12 +121,8 @@ func TestParseIdent(t *testing.T) { for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { got, err := ParseIdent(tc.line) - if err != nil { - t.Fatalf("ParseIdent(%q) returned error: %v", tc.line, err) - } - if got != tc.want { - t.Errorf("ParseIdent(%q)\n got: %#v\n want: %#v", tc.line, got, tc.want) - } + require.NoError(t, err) + require.Equal(t, tc.want, got) }) } } @@ -135,17 +131,17 @@ func TestParseIdentErrors(t *testing.T) { tests := []struct { name string line string + err string }{ - {"too few fields", "ssl_users alice"}, - {"too many fields", "ssl_users CN=alice alice extra"}, - {"empty", ""}, - {"unterminated quote", `ssl_users "CN=alice alice`}, + {"too few fields", "ssl_users alice", "pg_ident entry requires map-name, system-username, and postgres-username"}, + {"too many fields", "ssl_users CN=alice alice extra", "pg_ident entry requires map-name, system-username, and postgres-username"}, + {"empty", "", "empty entry"}, + {"unterminated quote", `ssl_users "CN=alice alice`, "unterminated quoted string"}, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - if _, err := ParseIdent(tc.line); err == nil { - t.Errorf("ParseIdent(%q) expected an error, got nil", tc.line) - } + _, err := ParseIdent(tc.line) + require.ErrorContains(t, err, tc.err) }) } }