Skip to content

Commit 46ae3da

Browse files
committed
refactor, add tests
1 parent b076535 commit 46ae3da

File tree

6 files changed

+187
-35
lines changed

6 files changed

+187
-35
lines changed

internal/controller/postgrescluster/cluster.go

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"github.com/pkg/errors"
1313
corev1 "k8s.io/api/core/v1"
1414
"k8s.io/apimachinery/pkg/api/meta"
15+
"k8s.io/apimachinery/pkg/api/resource"
1516
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1617
"k8s.io/apimachinery/pkg/util/intstr"
1718

@@ -44,7 +45,7 @@ func (r *Reconciler) reconcileClusterConfigMap(
4445

4546
if err == nil {
4647
err = patroni.ClusterConfigMap(ctx, cluster, pgHBAs, pgParameters,
47-
clusterConfigMap)
48+
clusterConfigMap, r.patroniLogSize(ctx, cluster))
4849
}
4950
if err == nil {
5051
err = errors.WithStack(r.apply(ctx, clusterConfigMap))
@@ -53,6 +54,32 @@ func (r *Reconciler) reconcileClusterConfigMap(
5354
return clusterConfigMap, err
5455
}
5556

57+
// patroniLogSize attemps to parse the defined log file size, if configured.
58+
// If a value is set, this enables volume based log storage and triggers the
59+
// relevant Patroni configuration. If the value given cannot be parsed, the log
60+
// file size defaults to 25M and a warning event is triggered.
61+
func (r *Reconciler) patroniLogSize(ctx context.Context, cluster *v1beta1.PostgresCluster) int64 {
62+
63+
if cluster.Spec.Patroni != nil {
64+
if cluster.Spec.Patroni.Log != nil {
65+
if cluster.Spec.Patroni.Log.FileSize != nil {
66+
67+
fileSize, err := resource.ParseQuantity(*cluster.Spec.Patroni.Log.FileSize)
68+
sizeInBytes := fileSize.Value()
69+
70+
if err != nil {
71+
r.Recorder.Eventf(cluster, corev1.EventTypeWarning, "InvalidPatroniLogFileSize",
72+
"Error when parsing spec.patroni.log.fileSize. File size will default to 25M.")
73+
74+
sizeInBytes = 25000000
75+
}
76+
return sizeInBytes
77+
}
78+
}
79+
}
80+
return 0
81+
}
82+
5683
// +kubebuilder:rbac:groups="",resources="services",verbs={create,patch}
5784

5885
// reconcileClusterPodService writes the Service that can provide stable DNS

internal/controller/postgrescluster/cluster_test.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/crunchydata/postgres-operator/internal/initialize"
2424
"github.com/crunchydata/postgres-operator/internal/naming"
2525
"github.com/crunchydata/postgres-operator/internal/testing/cmp"
26+
"github.com/crunchydata/postgres-operator/internal/testing/events"
2627
"github.com/crunchydata/postgres-operator/internal/testing/require"
2728
"github.com/crunchydata/postgres-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1"
2829
)
@@ -783,3 +784,73 @@ postgres-operator.crunchydata.com/role: replica
783784
`))
784785
})
785786
}
787+
788+
func TestPatroniLogSize(t *testing.T) {
789+
ctx := context.Background()
790+
791+
oneMeg := "1M"
792+
badSize := "notASize"
793+
794+
cluster := v1beta1.PostgresCluster{
795+
ObjectMeta: metav1.ObjectMeta{
796+
Name: "sometest",
797+
Namespace: "test-namespace",
798+
},
799+
Spec: v1beta1.PostgresClusterSpec{}}
800+
801+
t.Run("Default", func(t *testing.T) {
802+
recorder := events.NewRecorder(t, runtime.Scheme)
803+
reconciler := &Reconciler{Recorder: recorder}
804+
805+
size := reconciler.patroniLogSize(ctx, &cluster)
806+
807+
assert.Equal(t, size, int64(0))
808+
assert.Equal(t, len(recorder.Events), 0)
809+
})
810+
811+
t.Run("NoSize", func(t *testing.T) {
812+
recorder := events.NewRecorder(t, runtime.Scheme)
813+
reconciler := &Reconciler{Recorder: recorder}
814+
815+
cluster.Spec.Patroni = &v1beta1.PatroniSpec{
816+
Log: &v1beta1.PatroniLogConfig{}}
817+
818+
size := reconciler.patroniLogSize(ctx, &cluster)
819+
820+
assert.Equal(t, size, int64(0))
821+
assert.Equal(t, len(recorder.Events), 0)
822+
})
823+
824+
t.Run("ValidSize", func(t *testing.T) {
825+
recorder := events.NewRecorder(t, runtime.Scheme)
826+
reconciler := &Reconciler{Recorder: recorder}
827+
828+
cluster.Spec.Patroni = &v1beta1.PatroniSpec{
829+
Log: &v1beta1.PatroniLogConfig{
830+
FileSize: &oneMeg,
831+
}}
832+
833+
size := reconciler.patroniLogSize(ctx, &cluster)
834+
835+
assert.Equal(t, size, int64(1000000))
836+
assert.Equal(t, len(recorder.Events), 0)
837+
})
838+
839+
t.Run("BadSize", func(t *testing.T) {
840+
recorder := events.NewRecorder(t, runtime.Scheme)
841+
reconciler := &Reconciler{Recorder: recorder}
842+
843+
cluster.Spec.Patroni = &v1beta1.PatroniSpec{
844+
Log: &v1beta1.PatroniLogConfig{
845+
FileSize: &badSize,
846+
}}
847+
848+
size := reconciler.patroniLogSize(ctx, &cluster)
849+
850+
assert.Equal(t, size, int64(25000000))
851+
assert.Equal(t, len(recorder.Events), 1)
852+
assert.Equal(t, recorder.Events[0].Regarding.Name, cluster.Name)
853+
assert.Equal(t, recorder.Events[0].Reason, "InvalidPatroniLogFileSize")
854+
assert.Equal(t, recorder.Events[0].Note, "Error when parsing spec.patroni.log.fileSize. File size will default to 25M.")
855+
})
856+
}

internal/patroni/config.go

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010
"strings"
1111

1212
corev1 "k8s.io/api/core/v1"
13-
"k8s.io/apimachinery/pkg/api/resource"
1413
"sigs.k8s.io/yaml"
1514

1615
"github.com/crunchydata/postgres-operator/internal/config"
@@ -44,7 +43,7 @@ func quoteShellWord(s string) string {
4443
// clusterYAML returns Patroni settings that apply to the entire cluster.
4544
func clusterYAML(
4645
cluster *v1beta1.PostgresCluster,
47-
pgHBAs postgres.HBAs, pgParameters postgres.Parameters,
46+
pgHBAs postgres.HBAs, pgParameters postgres.Parameters, patroniLogFileSize int64,
4847
) (string, error) {
4948
root := map[string]any{
5049
// The cluster identifier. This value cannot change during the cluster's
@@ -153,28 +152,17 @@ func clusterYAML(
153152
},
154153
}
155154

156-
if cluster.Spec.Patroni != nil {
157-
if cluster.Spec.Patroni.Log != nil {
158-
159-
fileSize, err := resource.ParseQuantity(*cluster.Spec.Patroni.Log.FileSize)
160-
sizeInBytes := fileSize.Value()
161-
162-
// TODO: This isn't how I want to handle this, figure something better out...
163-
if err != nil {
164-
fmt.Printf("Bad Patroni log file size given, using 25MB instead, error: %v\n", err)
165-
sizeInBytes = 25000000 // Patroni's default size
166-
}
167-
168-
root["log"] = map[string]any{
169-
// Configure the Patroni log settings
170-
// - https://patroni.readthedocs.io/en/latest/yaml_configuration.html#log
171-
"dir": naming.PatroniPGDataLogPath,
172-
"file_num": 1,
173-
"file_size": sizeInBytes,
174-
"type": "json",
175-
"level": cluster.Spec.Patroni.Log.LogLevel, // defaults to "INFO"
176-
}
177-
155+
// if a Patroni log file size is configured, configure volume file storage
156+
if patroniLogFileSize != 0 {
157+
158+
root["log"] = map[string]any{
159+
// Configure the Patroni log settings
160+
// - https://patroni.readthedocs.io/en/latest/yaml_configuration.html#log
161+
"dir": naming.PatroniPGDataLogPath,
162+
"file_num": 1,
163+
"file_size": patroniLogFileSize,
164+
"type": "json",
165+
"level": cluster.Spec.Patroni.Log.LogLevel, // defaults to "INFO"
178166
}
179167
}
180168

internal/patroni/config_test.go

Lines changed: 71 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ func TestClusterYAML(t *testing.T) {
3232
cluster.Namespace = "some-namespace"
3333
cluster.Name = "cluster-name"
3434

35-
data, err := clusterYAML(cluster, postgres.HBAs{}, postgres.Parameters{})
35+
data, err := clusterYAML(cluster, postgres.HBAs{}, postgres.Parameters{}, 0)
3636
assert.NilError(t, err)
3737
assert.Equal(t, data, strings.TrimSpace(`
3838
# Generated by postgres-operator. DO NOT EDIT.
@@ -58,9 +58,6 @@ kubernetes:
5858
role_label: postgres-operator.crunchydata.com/role
5959
scope_label: postgres-operator.crunchydata.com/patroni
6060
use_endpoints: true
61-
log:
62-
dir: /pgdata/patroni/log
63-
file_size: 0
6461
postgresql:
6562
authentication:
6663
replication:
@@ -93,7 +90,72 @@ watchdog:
9390
cluster.Name = "cluster-name"
9491
cluster.Spec.PostgresVersion = 14
9592

96-
data, err := clusterYAML(cluster, postgres.HBAs{}, postgres.Parameters{})
93+
data, err := clusterYAML(cluster, postgres.HBAs{}, postgres.Parameters{}, 0)
94+
assert.NilError(t, err)
95+
assert.Equal(t, data, strings.TrimSpace(`
96+
# Generated by postgres-operator. DO NOT EDIT.
97+
# Your changes will not be saved.
98+
bootstrap:
99+
dcs:
100+
loop_wait: 10
101+
postgresql:
102+
parameters: {}
103+
pg_hba: []
104+
use_pg_rewind: true
105+
use_slots: false
106+
ttl: 30
107+
ctl:
108+
cacert: /etc/patroni/~postgres-operator/patroni.ca-roots
109+
certfile: /etc/patroni/~postgres-operator/patroni.crt+key
110+
insecure: false
111+
keyfile: null
112+
kubernetes:
113+
labels:
114+
postgres-operator.crunchydata.com/cluster: cluster-name
115+
namespace: some-namespace
116+
role_label: postgres-operator.crunchydata.com/role
117+
scope_label: postgres-operator.crunchydata.com/patroni
118+
use_endpoints: true
119+
postgresql:
120+
authentication:
121+
replication:
122+
sslcert: /tmp/replication/tls.crt
123+
sslkey: /tmp/replication/tls.key
124+
sslmode: verify-ca
125+
sslrootcert: /tmp/replication/ca.crt
126+
username: _crunchyrepl
127+
rewind:
128+
sslcert: /tmp/replication/tls.crt
129+
sslkey: /tmp/replication/tls.key
130+
sslmode: verify-ca
131+
sslrootcert: /tmp/replication/ca.crt
132+
username: _crunchyrepl
133+
restapi:
134+
cafile: /etc/patroni/~postgres-operator/patroni.ca-roots
135+
certfile: /etc/patroni/~postgres-operator/patroni.crt+key
136+
keyfile: null
137+
verify_client: optional
138+
scope: cluster-name-ha
139+
watchdog:
140+
mode: "off"
141+
`)+"\n")
142+
})
143+
144+
t.Run("PatroniLogSizeConfigured", func(t *testing.T) {
145+
cluster := new(v1beta1.PostgresCluster)
146+
cluster.Default()
147+
cluster.Namespace = "some-namespace"
148+
cluster.Name = "cluster-name"
149+
cluster.Spec.PostgresVersion = 14
150+
151+
fileSize := "1k"
152+
logLevel := "DEBUG"
153+
cluster.Spec.Patroni.Log = &v1beta1.PatroniLogConfig{
154+
FileSize: &fileSize,
155+
LogLevel: &logLevel,
156+
}
157+
158+
data, err := clusterYAML(cluster, postgres.HBAs{}, postgres.Parameters{}, 1000)
97159
assert.NilError(t, err)
98160
assert.Equal(t, data, strings.TrimSpace(`
99161
# Generated by postgres-operator. DO NOT EDIT.
@@ -121,7 +183,10 @@ kubernetes:
121183
use_endpoints: true
122184
log:
123185
dir: /pgdata/patroni/log
124-
file_size: 0
186+
file_num: 1
187+
file_size: 1000
188+
level: DEBUG
189+
type: json
125190
postgresql:
126191
authentication:
127192
replication:

internal/patroni/reconcile.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,14 @@ func ClusterConfigMap(ctx context.Context,
3232
inHBAs postgres.HBAs,
3333
inParameters postgres.Parameters,
3434
outClusterConfigMap *corev1.ConfigMap,
35+
patroniLogFileSize int64,
3536
) error {
3637
var err error
3738

3839
initialize.Map(&outClusterConfigMap.Data)
3940

4041
outClusterConfigMap.Data[configMapFileKey], err = clusterYAML(inCluster, inHBAs,
41-
inParameters)
42+
inParameters, patroniLogFileSize)
4243

4344
return err
4445
}

internal/patroni/reconcile_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,15 @@ func TestClusterConfigMap(t *testing.T) {
2929

3030
cluster.Default()
3131
config := new(corev1.ConfigMap)
32-
assert.NilError(t, ClusterConfigMap(ctx, cluster, pgHBAs, pgParameters, config))
32+
assert.NilError(t, ClusterConfigMap(ctx, cluster, pgHBAs, pgParameters, config, 0))
3333

3434
// The output of clusterYAML should go into config.
35-
data, _ := clusterYAML(cluster, pgHBAs, pgParameters)
35+
data, _ := clusterYAML(cluster, pgHBAs, pgParameters, 0)
3636
assert.DeepEqual(t, config.Data["patroni.yaml"], data)
3737

3838
// No change when called again.
3939
before := config.DeepCopy()
40-
assert.NilError(t, ClusterConfigMap(ctx, cluster, pgHBAs, pgParameters, config))
40+
assert.NilError(t, ClusterConfigMap(ctx, cluster, pgHBAs, pgParameters, config, 0))
4141
assert.DeepEqual(t, config, before)
4242
}
4343

0 commit comments

Comments
 (0)