@@ -6,7 +6,9 @@ package postgrescluster
6
6
7
7
import (
8
8
"context"
9
+ "strings"
9
10
11
+ "github.com/pkg/errors"
10
12
corev1 "k8s.io/api/core/v1"
11
13
"k8s.io/apimachinery/pkg/api/resource"
12
14
@@ -19,7 +21,7 @@ import (
19
21
// status. If the value has grown, create an Event.
20
22
func (r * Reconciler ) storeDesiredRequest (
21
23
ctx context.Context , cluster * v1beta1.PostgresCluster ,
22
- volumeType , instanceSetName , desiredRequest , desiredRequestBackup string ,
24
+ volumeType , host , desiredRequest , desiredRequestBackup string ,
23
25
) string {
24
26
var current resource.Quantity
25
27
var previous resource.Quantity
@@ -31,7 +33,7 @@ func (r *Reconciler) storeDesiredRequest(
31
33
current , err = resource .ParseQuantity (desiredRequest )
32
34
if err != nil {
33
35
log .Error (err , "Unable to parse " + volumeType + " volume request from status (" +
34
- desiredRequest + ") for " + cluster .Name + "/" + instanceSetName )
36
+ desiredRequest + ") for " + cluster .Name + "/" + host )
35
37
// If there was an error parsing the value, treat as unset (equivalent to zero).
36
38
desiredRequest = ""
37
39
current , _ = resource .ParseQuantity ("" )
@@ -44,7 +46,7 @@ func (r *Reconciler) storeDesiredRequest(
44
46
previous , err = resource .ParseQuantity (desiredRequestBackup )
45
47
if err != nil {
46
48
log .Error (err , "Unable to parse " + volumeType + " volume request from status backup (" +
47
- desiredRequestBackup + ") for " + cluster .Name + "/" + instanceSetName )
49
+ desiredRequestBackup + ") for " + cluster .Name + "/" + host )
48
50
// If there was an error parsing the value, treat as unset (equivalent to zero).
49
51
desiredRequestBackup = ""
50
52
previous , _ = resource .ParseQuantity ("" )
@@ -53,12 +55,12 @@ func (r *Reconciler) storeDesiredRequest(
53
55
}
54
56
55
57
// determine if the appropriate volume limit is set
56
- limitSet := limitIsSet (cluster , volumeType , instanceSetName )
58
+ limitSet := limitIsSet (cluster , volumeType , host )
57
59
58
60
if limitSet && current .Value () > previous .Value () {
59
61
r .Recorder .Eventf (cluster , corev1 .EventTypeNormal , "VolumeAutoGrow" ,
60
62
"%s volume expansion to %v requested for %s/%s." ,
61
- volumeType , current .String (), cluster .Name , instanceSetName )
63
+ volumeType , current .String (), cluster .Name , host )
62
64
}
63
65
64
66
// If the desired size was not observed, update with previously stored value.
@@ -77,34 +79,44 @@ func limitIsSet(cluster *v1beta1.PostgresCluster, volumeType, instanceSetName st
77
79
78
80
var limitSet bool
79
81
80
- switch volumeType {
82
+ switch {
81
83
82
84
// Cycle through the instance sets to ensure the correct limit is identified.
83
- case "pgData" :
85
+ case volumeType == "pgData" :
84
86
for _ , specInstance := range cluster .Spec .InstanceSets {
85
87
if specInstance .Name == instanceSetName {
86
88
limitSet = ! specInstance .DataVolumeClaimSpec .Resources .Limits .Storage ().IsZero ()
87
89
}
88
90
}
91
+
92
+ // VolumeType for the repository host volumes should be in the form 'repoN'
93
+ // where N is 1-4. As above, cycle through any defined repositories and ensure
94
+ // the correct limit is identified.
95
+ case strings .HasPrefix (volumeType , "repo" ):
96
+ for _ , specRepo := range cluster .Spec .Backups .PGBackRest .Repos {
97
+ if specRepo .Name == volumeType && specRepo .Volume != nil {
98
+ limitSet = ! specRepo .Volume .VolumeClaimSpec .Resources .Limits .Storage ().IsZero ()
99
+ }
100
+ }
89
101
}
90
- // TODO: Add cases for pgWAL and repo volumes
102
+ // TODO: Add case for pgWAL
91
103
92
104
return limitSet
93
105
94
106
}
95
107
96
- // setVolumeSize compares the potential sizes from the instance spec, status
97
- // and limit and sets the appropriate current value.
108
+ // setVolumeSize compares the potential sizes from the cluster status, volume request
109
+ // and volume limit and sets the appropriate current value.
98
110
func (r * Reconciler ) setVolumeSize (ctx context.Context , cluster * v1beta1.PostgresCluster ,
99
- pvc * corev1.PersistentVolumeClaim , volumeType , instanceSpecName string ) {
111
+ spec * corev1.PersistentVolumeClaimSpec , volumeType , host string ) {
100
112
101
113
log := logging .FromContext (ctx )
102
114
103
115
// Store the limit for this instance set. This value will not change below.
104
- volumeLimitFromSpec := pvc . Spec .Resources .Limits .Storage ()
116
+ volumeLimitFromSpec := spec .Resources .Limits .Storage ()
105
117
106
118
// This value will capture our desired update.
107
- volumeRequestSize := pvc . Spec .Resources .Requests .Storage ()
119
+ volumeRequestSize := spec .Resources .Requests .Storage ()
108
120
109
121
// A limit of 0 is ignorned, so the volume request is used.
110
122
if volumeLimitFromSpec .IsZero () {
@@ -116,19 +128,19 @@ func (r *Reconciler) setVolumeSize(ctx context.Context, cluster *v1beta1.Postgre
116
128
if volumeRequestSize .Value () > volumeLimitFromSpec .Value () {
117
129
r .Recorder .Eventf (cluster , corev1 .EventTypeWarning , "VolumeRequestOverLimit" ,
118
130
"%s volume request (%v) for %s/%s is greater than set limit (%v). Limit value will be used." ,
119
- volumeType , volumeRequestSize , cluster .Name , instanceSpecName , volumeLimitFromSpec )
131
+ volumeType , volumeRequestSize , cluster .Name , host , volumeLimitFromSpec )
120
132
121
- pvc . Spec .Resources .Requests = corev1.ResourceList {
133
+ spec .Resources .Requests = corev1.ResourceList {
122
134
corev1 .ResourceStorage : * resource .NewQuantity (volumeLimitFromSpec .Value (), resource .BinarySI ),
123
135
}
124
136
// Otherwise, if the feature gate is not enabled, do not autogrow.
125
137
} else if feature .Enabled (ctx , feature .AutoGrowVolumes ) {
126
138
127
139
// determine the appropriate volume request based on what's set in the status
128
140
if dpv , err := getDesiredVolumeSize (
129
- cluster , volumeType , instanceSpecName , volumeRequestSize ,
141
+ cluster , volumeType , host , volumeRequestSize ,
130
142
); err != nil {
131
- log .Error (err , "For " + cluster .Name + "/" + instanceSpecName +
143
+ log .Error (err , "For " + cluster .Name + "/" + host +
132
144
": Unable to parse " + volumeType + " volume request: " + dpv )
133
145
}
134
146
@@ -140,19 +152,19 @@ func (r *Reconciler) setVolumeSize(ctx context.Context, cluster *v1beta1.Postgre
140
152
141
153
r .Recorder .Eventf (cluster , corev1 .EventTypeNormal , "VolumeLimitReached" ,
142
154
"%s volume(s) for %s/%s are at size limit (%v)." , volumeType ,
143
- cluster .Name , instanceSpecName , volumeLimitFromSpec )
155
+ cluster .Name , host , volumeLimitFromSpec )
144
156
145
157
// If the volume size request is greater than the limit, issue an
146
158
// additional event warning.
147
159
if volumeRequestSize .Value () > volumeLimitFromSpec .Value () {
148
160
r .Recorder .Eventf (cluster , corev1 .EventTypeWarning , "DesiredVolumeAboveLimit" ,
149
161
"The desired size (%v) for the %s/%s %s volume(s) is greater than the size limit (%v)." ,
150
- volumeRequestSize , cluster .Name , instanceSpecName , volumeType , volumeLimitFromSpec )
162
+ volumeRequestSize , cluster .Name , host , volumeType , volumeLimitFromSpec )
151
163
}
152
164
153
165
volumeRequestSize = volumeLimitFromSpec
154
166
}
155
- pvc . Spec .Resources .Requests = corev1.ResourceList {
167
+ spec .Resources .Requests = corev1.ResourceList {
156
168
corev1 .ResourceStorage : * resource .NewQuantity (volumeRequestSize .Value (), resource .BinarySI ),
157
169
}
158
170
}
@@ -164,8 +176,8 @@ func getDesiredVolumeSize(cluster *v1beta1.PostgresCluster,
164
176
volumeType , instanceSpecName string ,
165
177
volumeRequestSize * resource.Quantity ) (string , error ) {
166
178
167
- switch volumeType {
168
- case "pgData" :
179
+ switch {
180
+ case volumeType == "pgData" :
169
181
for i := range cluster .Status .InstanceSets {
170
182
if instanceSpecName == cluster .Status .InstanceSets [i ].Name {
171
183
for _ , dpv := range cluster .Status .InstanceSets [i ].DesiredPGDataVolume {
@@ -182,7 +194,30 @@ func getDesiredVolumeSize(cluster *v1beta1.PostgresCluster,
182
194
}
183
195
}
184
196
}
185
- // TODO: Add cases for pgWAL and repo volumes (requires relevant status sections)
197
+
198
+ // VolumeType for the repository host volumes should be in the form 'repoN'
199
+ // where N is 1-4. As above, cycle through any defined repositories and ensure
200
+ // the correct limit is identified.
201
+ case strings .HasPrefix (volumeType , "repo" ):
202
+ if cluster .Status .PGBackRest == nil {
203
+ return "" , errors .New ("PostgresCluster.Status.PGBackRest is nil" )
204
+ }
205
+ for i := range cluster .Status .PGBackRest .Repos {
206
+ if volumeType == cluster .Status .PGBackRest .Repos [i ].Name {
207
+ dpv := cluster .Status .PGBackRest .Repos [i ].DesiredRepoVolume
208
+ if dpv != "" {
209
+ desiredRequest , err := resource .ParseQuantity (dpv )
210
+ if err == nil {
211
+ if desiredRequest .Value () > volumeRequestSize .Value () {
212
+ * volumeRequestSize = desiredRequest
213
+ }
214
+ } else {
215
+ return dpv , err
216
+ }
217
+ }
218
+ }
219
+ }
186
220
}
221
+ // TODO: Add case for pgWAL
187
222
return "" , nil
188
223
}
0 commit comments