@@ -6,7 +6,9 @@ package postgrescluster
66
77import (
88 "context"
9+ "strings"
910
11+ "github.com/pkg/errors"
1012 corev1 "k8s.io/api/core/v1"
1113 "k8s.io/apimachinery/pkg/api/resource"
1214
@@ -19,7 +21,7 @@ import (
1921// status. If the value has grown, create an Event.
2022func (r * Reconciler ) storeDesiredRequest (
2123 ctx context.Context , cluster * v1beta1.PostgresCluster ,
22- volumeType , instanceSetName , desiredRequest , desiredRequestBackup string ,
24+ volumeType , host , desiredRequest , desiredRequestBackup string ,
2325) string {
2426 var current resource.Quantity
2527 var previous resource.Quantity
@@ -31,7 +33,7 @@ func (r *Reconciler) storeDesiredRequest(
3133 current , err = resource .ParseQuantity (desiredRequest )
3234 if err != nil {
3335 log .Error (err , "Unable to parse " + volumeType + " volume request from status (" +
34- desiredRequest + ") for " + cluster .Name + "/" + instanceSetName )
36+ desiredRequest + ") for " + cluster .Name + "/" + host )
3537 // If there was an error parsing the value, treat as unset (equivalent to zero).
3638 desiredRequest = ""
3739 current , _ = resource .ParseQuantity ("" )
@@ -44,7 +46,7 @@ func (r *Reconciler) storeDesiredRequest(
4446 previous , err = resource .ParseQuantity (desiredRequestBackup )
4547 if err != nil {
4648 log .Error (err , "Unable to parse " + volumeType + " volume request from status backup (" +
47- desiredRequestBackup + ") for " + cluster .Name + "/" + instanceSetName )
49+ desiredRequestBackup + ") for " + cluster .Name + "/" + host )
4850 // If there was an error parsing the value, treat as unset (equivalent to zero).
4951 desiredRequestBackup = ""
5052 previous , _ = resource .ParseQuantity ("" )
@@ -53,12 +55,12 @@ func (r *Reconciler) storeDesiredRequest(
5355 }
5456
5557 // determine if the appropriate volume limit is set
56- limitSet := limitIsSet (cluster , volumeType , instanceSetName )
58+ limitSet := limitIsSet (cluster , volumeType , host )
5759
5860 if limitSet && current .Value () > previous .Value () {
5961 r .Recorder .Eventf (cluster , corev1 .EventTypeNormal , "VolumeAutoGrow" ,
6062 "%s volume expansion to %v requested for %s/%s." ,
61- volumeType , current .String (), cluster .Name , instanceSetName )
63+ volumeType , current .String (), cluster .Name , host )
6264 }
6365
6466 // If the desired size was not observed, update with previously stored value.
@@ -77,34 +79,44 @@ func limitIsSet(cluster *v1beta1.PostgresCluster, volumeType, instanceSetName st
7779
7880 var limitSet bool
7981
80- switch volumeType {
82+ switch {
8183
8284 // Cycle through the instance sets to ensure the correct limit is identified.
83- case "pgData" :
85+ case volumeType == "pgData" :
8486 for _ , specInstance := range cluster .Spec .InstanceSets {
8587 if specInstance .Name == instanceSetName {
8688 limitSet = ! specInstance .DataVolumeClaimSpec .Resources .Limits .Storage ().IsZero ()
8789 }
8890 }
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+ }
89101 }
90- // TODO: Add cases for pgWAL and repo volumes
102+ // TODO: Add case for pgWAL
91103
92104 return limitSet
93105
94106}
95107
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.
98110func (r * Reconciler ) setVolumeSize (ctx context.Context , cluster * v1beta1.PostgresCluster ,
99- pvc * corev1.PersistentVolumeClaim , volumeType , instanceSpecName string ) {
111+ spec * corev1.PersistentVolumeClaimSpec , volumeType , host string ) {
100112
101113 log := logging .FromContext (ctx )
102114
103115 // 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 ()
105117
106118 // This value will capture our desired update.
107- volumeRequestSize := pvc . Spec .Resources .Requests .Storage ()
119+ volumeRequestSize := spec .Resources .Requests .Storage ()
108120
109121 // A limit of 0 is ignorned, so the volume request is used.
110122 if volumeLimitFromSpec .IsZero () {
@@ -116,19 +128,19 @@ func (r *Reconciler) setVolumeSize(ctx context.Context, cluster *v1beta1.Postgre
116128 if volumeRequestSize .Value () > volumeLimitFromSpec .Value () {
117129 r .Recorder .Eventf (cluster , corev1 .EventTypeWarning , "VolumeRequestOverLimit" ,
118130 "%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 )
120132
121- pvc . Spec .Resources .Requests = corev1.ResourceList {
133+ spec .Resources .Requests = corev1.ResourceList {
122134 corev1 .ResourceStorage : * resource .NewQuantity (volumeLimitFromSpec .Value (), resource .BinarySI ),
123135 }
124136 // Otherwise, if the feature gate is not enabled, do not autogrow.
125137 } else if feature .Enabled (ctx , feature .AutoGrowVolumes ) {
126138
127139 // determine the appropriate volume request based on what's set in the status
128140 if dpv , err := getDesiredVolumeSize (
129- cluster , volumeType , instanceSpecName , volumeRequestSize ,
141+ cluster , volumeType , host , volumeRequestSize ,
130142 ); err != nil {
131- log .Error (err , "For " + cluster .Name + "/" + instanceSpecName +
143+ log .Error (err , "For " + cluster .Name + "/" + host +
132144 ": Unable to parse " + volumeType + " volume request: " + dpv )
133145 }
134146
@@ -140,19 +152,19 @@ func (r *Reconciler) setVolumeSize(ctx context.Context, cluster *v1beta1.Postgre
140152
141153 r .Recorder .Eventf (cluster , corev1 .EventTypeNormal , "VolumeLimitReached" ,
142154 "%s volume(s) for %s/%s are at size limit (%v)." , volumeType ,
143- cluster .Name , instanceSpecName , volumeLimitFromSpec )
155+ cluster .Name , host , volumeLimitFromSpec )
144156
145157 // If the volume size request is greater than the limit, issue an
146158 // additional event warning.
147159 if volumeRequestSize .Value () > volumeLimitFromSpec .Value () {
148160 r .Recorder .Eventf (cluster , corev1 .EventTypeWarning , "DesiredVolumeAboveLimit" ,
149161 "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 )
151163 }
152164
153165 volumeRequestSize = volumeLimitFromSpec
154166 }
155- pvc . Spec .Resources .Requests = corev1.ResourceList {
167+ spec .Resources .Requests = corev1.ResourceList {
156168 corev1 .ResourceStorage : * resource .NewQuantity (volumeRequestSize .Value (), resource .BinarySI ),
157169 }
158170 }
@@ -164,8 +176,8 @@ func getDesiredVolumeSize(cluster *v1beta1.PostgresCluster,
164176 volumeType , instanceSpecName string ,
165177 volumeRequestSize * resource.Quantity ) (string , error ) {
166178
167- switch volumeType {
168- case "pgData" :
179+ switch {
180+ case volumeType == "pgData" :
169181 for i := range cluster .Status .InstanceSets {
170182 if instanceSpecName == cluster .Status .InstanceSets [i ].Name {
171183 for _ , dpv := range cluster .Status .InstanceSets [i ].DesiredPGDataVolume {
@@ -182,7 +194,30 @@ func getDesiredVolumeSize(cluster *v1beta1.PostgresCluster,
182194 }
183195 }
184196 }
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+ }
186220 }
221+ // TODO: Add case for pgWAL
187222 return "" , nil
188223}
0 commit comments