From 0bf18378a614d775b72ac6ef8465243d9622e5a0 Mon Sep 17 00:00:00 2001 From: Mark Haley Date: Mon, 18 Apr 2022 15:32:45 -0400 Subject: [PATCH] allow ability to adjust patroni log setting (#1203) * Update postgresql CRD to include patroni log configuration * Have operator include log config (if available) in the `SPILO_CONFIGURATION` environment variable. --- manifests/postgresql.crd.yaml | 23 +++++++++++ pkg/apis/acid.zalan.do/v1/postgresql_type.go | 14 +++++++ pkg/cluster/k8sres.go | 43 ++++++++++++++++++++ pkg/cluster/k8sres_test.go | 13 ++++++ 4 files changed, 93 insertions(+) diff --git a/manifests/postgresql.crd.yaml b/manifests/postgresql.crd.yaml index 34a4298dd..cd76cf4cd 100644 --- a/manifests/postgresql.crd.yaml +++ b/manifests/postgresql.crd.yaml @@ -322,6 +322,29 @@ spec: type: object additionalProperties: type: string + log: + type: object + properties: + level: + type: string + traceback_level: + type: string + format: + type: string + dateformat: + type: string + max_queue_size: + type: string + dir: + type: string + file_num: + type: string + file_size: + type: string + loggers: + type: array + items: + type: string loop_wait: type: integer maximum_lag_on_failover: diff --git a/pkg/apis/acid.zalan.do/v1/postgresql_type.go b/pkg/apis/acid.zalan.do/v1/postgresql_type.go index 3d37dacfb..1eb89103f 100644 --- a/pkg/apis/acid.zalan.do/v1/postgresql_type.go +++ b/pkg/apis/acid.zalan.do/v1/postgresql_type.go @@ -157,6 +157,19 @@ type Resources struct { ResourceLimits ResourceDescription `json:"limits,omitempty"` } +// PatroniLog contains Patroni-specific log configuration +type PatroniLog struct { + Level *string `json:"level,omitempty"` + TracebackLevel *string `json:"traceback_level,omitempty"` + Format *string `json:"format,omitempty"` + Dateformat *string `json:"dateformat,omitempty"` + MaxQueueSize *string `json:"max_queue_size,omitempty"` + Dir *string `json:"dir,omitempty"` + FileNum *string `json:"file_num,omitempty"` + FileSize *string `json:"file_size,omitempty"` + Loggers []string `json:"loggers,omitempty"` +} + // Patroni contains Patroni-specific configuration type Patroni struct { InitDB map[string]string `json:"initdb,omitempty"` @@ -169,6 +182,7 @@ type Patroni struct { SynchronousMode bool `json:"synchronous_mode,omitempty"` SynchronousModeStrict bool `json:"synchronous_mode_strict,omitempty"` SynchronousNodeCount uint32 `json:"synchronous_node_count,omitempty" defaults:"1"` + Log *PatroniLog `json:"log,omitempty"` } // StandbyDescription contains remote primary config or s3/gs wal path diff --git a/pkg/cluster/k8sres.go b/pkg/cluster/k8sres.go index 6cdf379bd..541fe89f3 100644 --- a/pkg/cluster/k8sres.go +++ b/pkg/cluster/k8sres.go @@ -67,9 +67,22 @@ type pgBootstrap struct { DCS patroniDCS `json:"dcs,omitempty"` } +type patroniLog struct { + Level string `json:"level,omitempty"` + TracebackLevel string `json:"traceback_level,omitempty"` + Format string `json:"format,omitempty"` + Dateformat string `json:"dateformat,omitempty"` + MaxQueueSize string `json:"max_queue_size,omitempty"` + Dir string `json:"dir,omitempty"` + FileNum string `json:"file_num,omitempty"` + FileSize string `json:"file_size,omitempty"` + Loggers []string `json:"loggers,omitempty"` +} + type spiloConfiguration struct { PgLocalConfiguration map[string]interface{} `json:"postgresql"` Bootstrap pgBootstrap `json:"bootstrap"` + Log *patroniLog `json:"log,omitempty"` } func (c *Cluster) statefulSetName() string { @@ -344,6 +357,36 @@ PatroniInitDBParams: if patroni.SynchronousNodeCount >= 1 { config.Bootstrap.DCS.SynchronousNodeCount = patroni.SynchronousNodeCount } + if patroni.Log != nil { + config.Log = &patroniLog{} + if patroni.Log.Level != nil { + config.Log.Level = *patroni.Log.Level + } + if patroni.Log.TracebackLevel != nil { + config.Log.TracebackLevel = *patroni.Log.TracebackLevel + } + if patroni.Log.Format != nil { + config.Log.Format = *patroni.Log.Format + } + if patroni.Log.Dateformat != nil { + config.Log.Dateformat = *patroni.Log.Dateformat + } + if patroni.Log.MaxQueueSize != nil { + config.Log.MaxQueueSize = *patroni.Log.MaxQueueSize + } + if patroni.Log.Dir != nil { + config.Log.Dir = *patroni.Log.Dir + } + if patroni.Log.FileNum != nil { + config.Log.FileNum = *patroni.Log.FileNum + } + if patroni.Log.FileSize != nil { + config.Log.FileSize = *patroni.Log.FileSize + } + if patroni.Log.Loggers != nil { + config.Log.Loggers = patroni.Log.Loggers + } + } config.PgLocalConfiguration = make(map[string]interface{}) diff --git a/pkg/cluster/k8sres_test.go b/pkg/cluster/k8sres_test.go index 7a1bdeaf9..a31e3e82d 100644 --- a/pkg/cluster/k8sres_test.go +++ b/pkg/cluster/k8sres_test.go @@ -65,6 +65,7 @@ func TestGenerateSpiloJSONConfiguration(t *testing.T) { }, k8sutil.KubernetesClient{}, acidv1.Postgresql{}, logger, eventRecorder) testName := "TestGenerateSpiloConfig" + testLogDirectory := "/path/to/logs" tests := []struct { subtest string pgParam *acidv1.PostgresqlParam @@ -104,6 +105,18 @@ func TestGenerateSpiloJSONConfiguration(t *testing.T) { opConfig: config.Config{}, result: `{"postgresql":{"bin_dir":"/usr/lib/postgresql/11/bin","pg_hba":["hostssl all all 0.0.0.0/0 md5","host all all 0.0.0.0/0 md5"]},"bootstrap":{"initdb":[{"auth-host":"md5"},{"auth-local":"trust"},"data-checksums",{"encoding":"UTF8"},{"locale":"en_US.UTF-8"}],"users":{"zalandos":{"password":"","options":["CREATEDB","NOLOGIN"]}},"dcs":{"ttl":30,"loop_wait":10,"retry_timeout":10,"maximum_lag_on_failover":33554432,"synchronous_mode":true,"synchronous_mode_strict":true,"synchronous_node_count":1,"slots":{"permanent_logical_1":{"database":"foo","plugin":"pgoutput","type":"logical"}}}}}`, }, + { + subtest: "Patroni log configuration", + pgParam: &acidv1.PostgresqlParam{PgVersion: "9.6"}, + patroni: &acidv1.Patroni{ + Log: &acidv1.PatroniLog{ + Dir: &testLogDirectory, + }, + }, + role: "zalandos", + opConfig: config.Config{}, + result: `{"postgresql":{"bin_dir":"/usr/lib/postgresql/9.6/bin"},"bootstrap":{"initdb":[{"auth-host":"md5"},{"auth-local":"trust"}],"users":{"zalandos":{"password":"","options":["CREATEDB","NOLOGIN"]}},"dcs":{}},"log":{"dir":"/path/to/logs"}}`, + }, } for _, tt := range tests { cluster.OpConfig = tt.opConfig