66 "testing"
77 "time"
88
9+ "github.com/stretchr/testify/require"
10+
911 "github.com/dchest/uniuri"
1012 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1113
@@ -26,7 +28,7 @@ func TestResiliencePod(t *testing.T) {
2628 //fmt.Printf("There are %d pods in the cluster\n", len(pods.Items))
2729
2830 // Prepare deployment config
29- depl := newDeployment ("test-pod-resilience" + uniuri .NewLen (4 ))
31+ depl := newDeployment ("test-pod-resilience- " + uniuri .NewLen (4 ))
3032 depl .Spec .Mode = api .NewMode (api .DeploymentModeCluster )
3133 depl .Spec .SetDefaults (depl .GetName ()) // this must be last
3234
@@ -106,7 +108,7 @@ func TestResiliencePVC(t *testing.T) {
106108 ns := getNamespace (t )
107109
108110 // Prepare deployment config
109- depl := newDeployment ("test-pvc-resilience" + uniuri .NewLen (4 ))
111+ depl := newDeployment ("test-pvc-resilience- " + uniuri .NewLen (4 ))
110112 depl .Spec .Mode = api .NewMode (api .DeploymentModeCluster )
111113 depl .Spec .SetDefaults (depl .GetName ()) // this must be last
112114
@@ -181,6 +183,109 @@ func TestResiliencePVC(t *testing.T) {
181183 removeDeployment (c , depl .GetName (), ns )
182184}
183185
186+ // TestResiliencePVDBServer
187+ // Tests handling of entire PVs of dbservers being removed.
188+ func TestResiliencePVDBServer (t * testing.T ) {
189+ longOrSkip (t )
190+ c := client .MustNewInCluster ()
191+ kubecli := mustNewKubeClient (t )
192+ ns := getNamespace (t )
193+
194+ // Prepare deployment config
195+ depl := newDeployment ("test-pv-prmr-resi-" + uniuri .NewLen (4 ))
196+ depl .Spec .Mode = api .NewMode (api .DeploymentModeCluster )
197+ depl .Spec .SetDefaults (depl .GetName ()) // this must be last
198+
199+ // Create deployment
200+ apiObject , err := c .DatabaseV1alpha ().ArangoDeployments (ns ).Create (depl )
201+ if err != nil {
202+ t .Fatalf ("Create deployment failed: %v" , err )
203+ }
204+
205+ // Wait for deployment to be ready
206+ if _ , err = waitUntilDeployment (c , depl .GetName (), ns , deploymentIsReady ()); err != nil {
207+ t .Fatalf ("Deployment not running in time: %v" , err )
208+ }
209+
210+ // Create a database client
211+ ctx := context .Background ()
212+ client := mustNewArangodDatabaseClient (ctx , kubecli , apiObject , t )
213+
214+ // Wait for cluster to be completely ready
215+ if err := waitUntilClusterHealth (client , func (h driver.ClusterHealth ) error {
216+ return clusterHealthEqualsSpec (h , apiObject .Spec )
217+ }); err != nil {
218+ t .Fatalf ("Cluster not running in expected health in time: %v" , err )
219+ }
220+
221+ // Fetch latest status so we know all member details
222+ apiObject , err = c .DatabaseV1alpha ().ArangoDeployments (ns ).Get (depl .GetName (), metav1.GetOptions {})
223+ if err != nil {
224+ t .Fatalf ("Failed to get deployment: %v" , err )
225+ }
226+
227+ // Delete one pv, pvc & pod after the other
228+ apiObject .ForeachServerGroup (func (group api.ServerGroup , spec api.ServerGroupSpec , status * api.MemberStatusList ) error {
229+ if group != api .ServerGroupDBServers {
230+ // Agents cannot be replaced with a new ID
231+ // Coordinators, Sync masters/workers have no persistent storage
232+ return nil
233+ }
234+ for i , m := range * status {
235+ // Only test first 2
236+ if i >= 2 {
237+ continue
238+ }
239+ // Get current pvc so we can compare UID later
240+ originalPVC , err := kubecli .CoreV1 ().PersistentVolumeClaims (ns ).Get (m .PersistentVolumeClaimName , metav1.GetOptions {})
241+ if err != nil {
242+ t .Fatalf ("Failed to get pvc %s: %v" , m .PersistentVolumeClaimName , err )
243+ }
244+ // Get current pv
245+ pvName := originalPVC .Spec .VolumeName
246+ require .NotEmpty (t , pvName , "VolumeName of %s must be non-empty" , originalPVC .GetName ())
247+ // Delete PV
248+ if err := kubecli .CoreV1 ().PersistentVolumes ().Delete (pvName , & metav1.DeleteOptions {}); err != nil {
249+ t .Fatalf ("Failed to delete pv %s: %v" , pvName , err )
250+ }
251+ // Delete PVC
252+ if err := kubecli .CoreV1 ().PersistentVolumeClaims (ns ).Delete (m .PersistentVolumeClaimName , & metav1.DeleteOptions {}); err != nil {
253+ t .Fatalf ("Failed to delete pvc %s: %v" , m .PersistentVolumeClaimName , err )
254+ }
255+ // Delete Pod
256+ if err := kubecli .CoreV1 ().Pods (ns ).Delete (m .PodName , & metav1.DeleteOptions {}); err != nil {
257+ t .Fatalf ("Failed to delete pod %s: %v" , m .PodName , err )
258+ }
259+ // Wait for cluster to be healthy again with the same number of
260+ // dbservers, but the current dbserver being replaced.
261+ expectedDBServerCount := apiObject .Spec .DBServers .GetCount ()
262+ unexpectedID := m .ID
263+ pred := func (depl * api.ArangoDeployment ) error {
264+ if len (depl .Status .Members .DBServers ) != expectedDBServerCount {
265+ return maskAny (fmt .Errorf ("Expected %d dbservers, got %d" , expectedDBServerCount , len (depl .Status .Members .DBServers )))
266+ }
267+ if depl .Status .Members .ContainsID (unexpectedID ) {
268+ return maskAny (fmt .Errorf ("Member %s should be gone" , unexpectedID ))
269+ }
270+ return nil
271+ }
272+ if _ , err := waitUntilDeployment (c , apiObject .GetName (), ns , pred , time .Minute * 5 ); err != nil {
273+ t .Fatalf ("Deployment not ready in time: %v" , err )
274+ }
275+ // Wait for cluster to be completely ready
276+ if err := waitUntilClusterHealth (client , func (h driver.ClusterHealth ) error {
277+ return clusterHealthEqualsSpec (h , apiObject .Spec )
278+ }); err != nil {
279+ t .Fatalf ("Cluster not running in expected health in time: %v" , err )
280+ }
281+ }
282+ return nil
283+ }, & apiObject .Status )
284+
285+ // Cleanup
286+ removeDeployment (c , depl .GetName (), ns )
287+ }
288+
184289// TestResilienceService
185290// Tests handling of individual service deletions
186291func TestResilienceService (t * testing.T ) {
@@ -190,7 +295,7 @@ func TestResilienceService(t *testing.T) {
190295 ns := getNamespace (t )
191296
192297 // Prepare deployment config
193- depl := newDeployment ("test-service-resilience" + uniuri .NewLen (4 ))
298+ depl := newDeployment ("test-service-resilience- " + uniuri .NewLen (4 ))
194299 depl .Spec .Mode = api .NewMode (api .DeploymentModeCluster )
195300 depl .Spec .SetDefaults (depl .GetName ()) // this must be last
196301
0 commit comments