Skip to content

Commit afc7512

Browse files
authored
fix(cluster): failed to update volume size. (#567)
add support for resizing volume add unit test for sfsUpdated()
1 parent 5e05677 commit afc7512

File tree

2 files changed

+154
-1
lines changed

2 files changed

+154
-1
lines changed

mysqlcluster/syncer/statefulset.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -590,9 +590,15 @@ func (s *StatefulSetSyncer) backupIsRunning(ctx context.Context) (bool, error) {
590590

591591
// Updates to statefulset spec for fields other than 'replicas', 'template', and 'updateStrategy' are forbidden.
592592
func (s *StatefulSetSyncer) sfsUpdated(existing *appsv1.StatefulSet) bool {
593+
var resizeVolume = false
594+
// TODO: this is a temporary workaround until we figure out a better way to do this.
595+
if len(existing.Spec.VolumeClaimTemplates) > 0 && len(s.sfs.Spec.VolumeClaimTemplates) > 0 {
596+
resizeVolume = existing.Spec.VolumeClaimTemplates[0].Spec.Resources.Requests.Storage().Cmp(*s.sfs.Spec.VolumeClaimTemplates[0].Spec.Resources.Requests.Storage()) != 0
597+
}
593598
return *existing.Spec.Replicas != *s.sfs.Spec.Replicas ||
594599
!equality.Semantic.DeepEqual(existing.Spec.Template, s.sfs.Spec.Template) ||
595-
existing.Spec.UpdateStrategy != s.sfs.Spec.UpdateStrategy
600+
existing.Spec.UpdateStrategy != s.sfs.Spec.UpdateStrategy ||
601+
resizeVolume
596602
}
597603

598604
func (s *StatefulSetSyncer) podsAllUpdated(ctx context.Context) bool {
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
/*
2+
Copyright 2021 RadonDB.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package syncer
18+
19+
import (
20+
"testing"
21+
22+
appsv1 "k8s.io/api/apps/v1"
23+
v1 "k8s.io/api/core/v1"
24+
"k8s.io/apimachinery/pkg/api/resource"
25+
)
26+
27+
func TestStatefulSetSyncer_sfsUpdated(t *testing.T) {
28+
mockSfs := &appsv1.StatefulSet{
29+
Spec: appsv1.StatefulSetSpec{
30+
Replicas: &[]int32{1}[0],
31+
Template: v1.PodTemplateSpec{
32+
Spec: v1.PodSpec{
33+
Containers: []v1.Container{
34+
{
35+
Name: "test1",
36+
},
37+
},
38+
},
39+
},
40+
VolumeClaimTemplates: []v1.PersistentVolumeClaim{
41+
{
42+
Spec: v1.PersistentVolumeClaimSpec{
43+
Resources: v1.ResourceRequirements{
44+
Requests: v1.ResourceList{
45+
v1.ResourceStorage: resource.MustParse("1Gi"),
46+
},
47+
},
48+
},
49+
},
50+
},
51+
},
52+
}
53+
updateReplicas := func() *appsv1.StatefulSet {
54+
sfs := mockSfs.DeepCopy()
55+
sfs.Spec.Replicas = &[]int32{2}[0]
56+
return sfs
57+
}
58+
updateTemplate := func() *appsv1.StatefulSet {
59+
sfs := mockSfs.DeepCopy()
60+
sfs.Spec.Template.Spec.Containers[0].Name = "test2"
61+
return sfs
62+
}
63+
updateVolume := func() *appsv1.StatefulSet {
64+
sfs := mockSfs.DeepCopy()
65+
sfs.Spec.VolumeClaimTemplates[0].Spec.Resources.Requests[v1.ResourceStorage] = resource.MustParse("2Gi")
66+
return sfs
67+
}
68+
volumeNotExist := func() *appsv1.StatefulSet {
69+
sfs := mockSfs.DeepCopy()
70+
sfs.Spec.VolumeClaimTemplates = nil
71+
return sfs
72+
}
73+
74+
type fields struct {
75+
sfs *appsv1.StatefulSet
76+
}
77+
type args struct {
78+
existing *appsv1.StatefulSet
79+
}
80+
tests := []struct {
81+
name string
82+
fields fields
83+
args args
84+
want bool
85+
}{
86+
{
87+
name: "update replicas",
88+
fields: fields{
89+
sfs: updateReplicas(),
90+
},
91+
args: args{
92+
existing: mockSfs,
93+
},
94+
want: true,
95+
},
96+
{
97+
name: "update template",
98+
fields: fields{
99+
sfs: updateTemplate(),
100+
},
101+
args: args{
102+
existing: mockSfs,
103+
},
104+
want: true,
105+
},
106+
{
107+
name: "update volume size",
108+
fields: fields{
109+
sfs: updateVolume(),
110+
},
111+
args: args{
112+
existing: mockSfs,
113+
},
114+
want: true,
115+
},
116+
{
117+
name: "no change",
118+
fields: fields{
119+
sfs: mockSfs,
120+
},
121+
args: args{
122+
existing: mockSfs,
123+
},
124+
want: false,
125+
},
126+
{
127+
name: "volume not exist",
128+
fields: fields{
129+
sfs: mockSfs,
130+
},
131+
args: args{
132+
existing: volumeNotExist(),
133+
},
134+
want: false,
135+
},
136+
}
137+
for _, tt := range tests {
138+
t.Run(tt.name, func(t *testing.T) {
139+
s := &StatefulSetSyncer{
140+
sfs: tt.fields.sfs,
141+
}
142+
if got := s.sfsUpdated(tt.args.existing); got != tt.want {
143+
t.Errorf("StatefulSetSyncer.sfsUpdated() = %v, want %v", got, tt.want)
144+
}
145+
})
146+
}
147+
}

0 commit comments

Comments
 (0)