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