github.com/weaviate/weaviate@v1.24.6/adapters/handlers/rest/clusterapi/backups_test.go (about) 1 // _ _ 2 // __ _____ __ ___ ___ __ _| |_ ___ 3 // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \ 4 // \ V V / __/ (_| |\ V /| | (_| | || __/ 5 // \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___| 6 // 7 // Copyright © 2016 - 2024 Weaviate B.V. All rights reserved. 8 // 9 // CONTACT: hello@weaviate.io 10 // 11 12 package clusterapi_test 13 14 import ( 15 "context" 16 "net/http" 17 "net/http/httptest" 18 "net/url" 19 "testing" 20 21 "github.com/stretchr/testify/mock" 22 "github.com/stretchr/testify/require" 23 "github.com/weaviate/weaviate/adapters/clients" 24 "github.com/weaviate/weaviate/adapters/handlers/rest/clusterapi" 25 "github.com/weaviate/weaviate/usecases/backup" 26 ) 27 28 func TestInternalBackupsAPI(t *testing.T) { 29 nodes := []*backupNode{ 30 { 31 name: "node1", 32 backupManager: &fakeBackupManager{}, 33 }, 34 { 35 name: "node2", 36 backupManager: &fakeBackupManager{}, 37 }, 38 } 39 hosts := setupClusterAPI(t, nodes) 40 41 for _, node := range nodes { 42 node.backupManager.On("OnCanCommit", &backup.Request{Method: backup.OpCreate}). 43 Return(&backup.CanCommitResponse{}) 44 node.backupManager.On("OnCommit", &backup.StatusRequest{}).Return(nil) 45 node.backupManager.On("OnAbort", &backup.AbortRequest{}).Return(nil) 46 } 47 48 coord := newFakeCoordinator(newFakeNodeResolver(hosts)) 49 50 t.Run("can commit, commit", func(t *testing.T) { 51 err := coord.Backup(context.Background(), &backup.Request{Method: backup.OpCreate}, false) 52 require.Nil(t, err) 53 }) 54 55 t.Run("abort", func(t *testing.T) { 56 err := coord.Backup(context.Background(), &backup.Request{Method: backup.OpCreate}, true) 57 require.Nil(t, err) 58 }) 59 } 60 61 func setupClusterAPI(t *testing.T, nodes []*backupNode) map[string]string { 62 hosts := make(map[string]string) 63 64 for _, node := range nodes { 65 backupsHandler := clusterapi.NewBackups(node.backupManager, clusterapi.NewNoopAuthHandler()) 66 67 mux := http.NewServeMux() 68 mux.Handle("/backups/can-commit", backupsHandler.CanCommit()) 69 mux.Handle("/backups/commit", backupsHandler.Commit()) 70 mux.Handle("/backups/abort", backupsHandler.Abort()) 71 mux.Handle("/backups/status", backupsHandler.Status()) 72 server := httptest.NewServer(mux) 73 74 parsedURL, err := url.Parse(server.URL) 75 require.Nil(t, err) 76 77 hosts[node.name] = parsedURL.Host 78 } 79 80 return hosts 81 } 82 83 type backupNode struct { 84 name string 85 backupManager *fakeBackupManager 86 } 87 88 func newFakeNodeResolver(hosts map[string]string) *fakeNodeResolver { 89 return &fakeNodeResolver{hosts: hosts} 90 } 91 92 type fakeNodeResolver struct { 93 hosts map[string]string 94 } 95 96 func (r *fakeNodeResolver) NodeHostName(nodeName string) (string, bool) { 97 if host, ok := r.hosts[nodeName]; ok { 98 return host, true 99 } 100 return "", false 101 } 102 103 func (r *fakeNodeResolver) HostNames() []string { 104 hosts := make([]string, len(r.hosts)) 105 count := 0 106 for _, host := range r.hosts { 107 hosts[count] = host 108 count++ 109 } 110 return hosts 111 } 112 113 func newFakeCoordinator(resolver *fakeNodeResolver) *fakeCoordinator { 114 return &fakeCoordinator{ 115 client: clients.NewClusterBackups(&http.Client{}), 116 nodeResolver: resolver, 117 } 118 } 119 120 type fakeCoordinator struct { 121 client *clients.ClusterBackups 122 nodeResolver *fakeNodeResolver 123 } 124 125 func (c *fakeCoordinator) Backup(ctx context.Context, req *backup.Request, abort bool) error { 126 if abort { 127 return c.abort(ctx) 128 } 129 130 for _, host := range c.nodeResolver.HostNames() { 131 _, err := c.client.CanCommit(ctx, host, req) 132 if err != nil { 133 return err 134 } 135 } 136 137 for _, host := range c.nodeResolver.HostNames() { 138 err := c.client.Commit(ctx, host, &backup.StatusRequest{}) 139 if err != nil { 140 return err 141 } 142 } 143 144 return nil 145 } 146 147 func (c *fakeCoordinator) abort(ctx context.Context) error { 148 for _, host := range c.nodeResolver.HostNames() { 149 err := c.client.Abort(ctx, host, &backup.AbortRequest{}) 150 if err != nil { 151 return err 152 } 153 } 154 155 return nil 156 } 157 158 type fakeBackupManager struct { 159 mock.Mock 160 } 161 162 func (m *fakeBackupManager) OnCanCommit(ctx context.Context, req *backup.Request) *backup.CanCommitResponse { 163 args := m.Called(req) 164 return args.Get(0).(*backup.CanCommitResponse) 165 } 166 167 func (m *fakeBackupManager) OnCommit(ctx context.Context, req *backup.StatusRequest) error { 168 args := m.Called(req) 169 return args.Error(0) 170 } 171 172 func (m *fakeBackupManager) OnAbort(ctx context.Context, req *backup.AbortRequest) error { 173 args := m.Called(req) 174 return args.Error(0) 175 } 176 177 func (m *fakeBackupManager) OnStatus(ctx context.Context, req *backup.StatusRequest) *backup.StatusResponse { 178 args := m.Called(req) 179 return args.Get(0).(*backup.StatusResponse) 180 }