github.com/weaviate/weaviate@v1.24.6/test/modules/backup-azure/backup_backend_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 test 13 14 import ( 15 "context" 16 "encoding/json" 17 "fmt" 18 "os" 19 "path/filepath" 20 "testing" 21 "time" 22 23 "github.com/pkg/errors" 24 "github.com/sirupsen/logrus" 25 logrustest "github.com/sirupsen/logrus/hooks/test" 26 "github.com/stretchr/testify/assert" 27 "github.com/stretchr/testify/require" 28 "github.com/weaviate/weaviate/entities/backup" 29 "github.com/weaviate/weaviate/entities/moduletools" 30 mod "github.com/weaviate/weaviate/modules/backup-azure" 31 "github.com/weaviate/weaviate/test/docker" 32 moduleshelper "github.com/weaviate/weaviate/test/helper/modules" 33 ubak "github.com/weaviate/weaviate/usecases/backup" 34 "github.com/weaviate/weaviate/usecases/config" 35 ) 36 37 func Test_AzureBackend_Backup(t *testing.T) { 38 ctx := context.Background() 39 compose, err := docker.New().WithAzurite().Start(ctx) 40 if err != nil { 41 t.Fatal(errors.Wrapf(err, "cannot start")) 42 } 43 44 t.Setenv(envAzureEndpoint, compose.GetAzurite().URI()) 45 46 t.Run("store backup meta", moduleLevelStoreBackupMeta) 47 t.Run("copy objects", moduleLevelCopyObjects) 48 t.Run("copy files", moduleLevelCopyFiles) 49 50 if err := compose.Terminate(ctx); err != nil { 51 t.Fatal(errors.Wrapf(err, "failed to terminate test containers")) 52 } 53 } 54 55 func moduleLevelStoreBackupMeta(t *testing.T) { 56 testCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second) 57 defer cancel() 58 59 dataDir := t.TempDir() 60 className := "BackupClass" 61 backupID := "backup_id" 62 containerName := "container" 63 endpoint := os.Getenv(envAzureEndpoint) 64 metadataFilename := "backup.json" 65 66 t.Log("setup env") 67 t.Setenv(envAzureEndpoint, endpoint) 68 t.Setenv(envAzureStorageConnectionString, fmt.Sprintf(connectionString, endpoint)) 69 t.Setenv(envAzureContainer, containerName) 70 moduleshelper.CreateAzureContainer(testCtx, t, endpoint, containerName) 71 defer moduleshelper.DeleteAzureContainer(testCtx, t, endpoint, containerName) 72 73 t.Run("store backup meta in Azure", func(t *testing.T) { 74 t.Setenv(envAzureContainer, containerName) 75 azure := mod.New() 76 err := azure.Init(testCtx, newFakeModuleParams(dataDir)) 77 require.Nil(t, err) 78 79 t.Run("access permissions", func(t *testing.T) { 80 err := azure.Initialize(testCtx, backupID) 81 assert.Nil(t, err) 82 }) 83 84 t.Run("backup meta does not exist yet", func(t *testing.T) { 85 meta, err := azure.GetObject(testCtx, backupID, metadataFilename) 86 assert.Nil(t, meta) 87 assert.NotNil(t, err) 88 assert.IsType(t, backup.ErrNotFound{}, err) 89 }) 90 91 t.Run("put backup meta on backend", func(t *testing.T) { 92 desc := &backup.BackupDescriptor{ 93 StartedAt: time.Now(), 94 CompletedAt: time.Time{}, 95 ID: backupID, 96 Classes: []backup.ClassDescriptor{ 97 { 98 Name: className, 99 }, 100 }, 101 Status: string(backup.Started), 102 Version: ubak.Version, 103 } 104 105 b, err := json.Marshal(desc) 106 require.Nil(t, err) 107 108 err = azure.PutObject(testCtx, backupID, metadataFilename, b) 109 require.Nil(t, err) 110 111 dest := azure.HomeDir(backupID) 112 113 expected := fmt.Sprintf("http://%s/devstoreaccount1/%s/%s", os.Getenv(envAzureEndpoint), containerName, backupID) 114 assert.Equal(t, expected, dest) 115 }) 116 117 t.Run("assert backup meta contents", func(t *testing.T) { 118 obj, err := azure.GetObject(testCtx, backupID, metadataFilename) 119 require.Nil(t, err) 120 121 var meta backup.BackupDescriptor 122 err = json.Unmarshal(obj, &meta) 123 require.Nil(t, err) 124 assert.NotEmpty(t, meta.StartedAt) 125 assert.Empty(t, meta.CompletedAt) 126 assert.Equal(t, meta.Status, string(backup.Started)) 127 assert.Empty(t, meta.Error) 128 assert.Len(t, meta.Classes, 1) 129 assert.Equal(t, meta.Classes[0].Name, className) 130 assert.Equal(t, meta.Version, ubak.Version) 131 assert.Nil(t, meta.Classes[0].Error) 132 }) 133 }) 134 } 135 136 func moduleLevelCopyObjects(t *testing.T) { 137 testCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second) 138 defer cancel() 139 140 dataDir := t.TempDir() 141 key := "moduleLevelCopyObjects" 142 backupID := "backup_id" 143 containerName := "container" 144 endpoint := os.Getenv(envAzureEndpoint) 145 146 t.Log("setup env") 147 t.Setenv(envAzureEndpoint, endpoint) 148 t.Setenv(envAzureStorageConnectionString, fmt.Sprintf(connectionString, endpoint)) 149 t.Setenv(envAzureContainer, containerName) 150 moduleshelper.CreateAzureContainer(testCtx, t, endpoint, containerName) 151 defer moduleshelper.DeleteAzureContainer(testCtx, t, endpoint, containerName) 152 153 t.Run("copy objects", func(t *testing.T) { 154 t.Setenv(envAzureContainer, containerName) 155 azure := mod.New() 156 err := azure.Init(testCtx, newFakeModuleParams(dataDir)) 157 require.Nil(t, err) 158 159 t.Run("put object to bucket", func(t *testing.T) { 160 err := azure.PutObject(testCtx, backupID, key, []byte("hello")) 161 assert.Nil(t, err) 162 }) 163 164 t.Run("get object from bucket", func(t *testing.T) { 165 meta, err := azure.GetObject(testCtx, backupID, key) 166 assert.Nil(t, err) 167 assert.Equal(t, []byte("hello"), meta) 168 }) 169 }) 170 } 171 172 func moduleLevelCopyFiles(t *testing.T) { 173 testCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second) 174 defer cancel() 175 176 dataDir := t.TempDir() 177 key := "moduleLevelCopyFiles" 178 backupID := "backup_id" 179 containerName := "container" 180 endpoint := os.Getenv(envAzureEndpoint) 181 182 t.Log("setup env") 183 t.Setenv(envAzureEndpoint, endpoint) 184 t.Setenv(envAzureStorageConnectionString, fmt.Sprintf(connectionString, endpoint)) 185 t.Setenv(envAzureContainer, containerName) 186 moduleshelper.CreateAzureContainer(testCtx, t, endpoint, containerName) 187 defer moduleshelper.DeleteAzureContainer(testCtx, t, endpoint, containerName) 188 189 t.Run("copy files", func(t *testing.T) { 190 fpaths := moduleshelper.CreateTestFiles(t, dataDir) 191 fpath := fpaths[0] 192 expectedContents, err := os.ReadFile(fpath) 193 require.Nil(t, err) 194 require.NotNil(t, expectedContents) 195 196 t.Setenv(envAzureContainer, containerName) 197 azure := mod.New() 198 err = azure.Init(testCtx, newFakeModuleParams(dataDir)) 199 require.Nil(t, err) 200 201 t.Run("verify source data path", func(t *testing.T) { 202 assert.Equal(t, dataDir, azure.SourceDataPath()) 203 }) 204 205 t.Run("copy file to backend", func(t *testing.T) { 206 srcPath, _ := filepath.Rel(dataDir, fpath) 207 err := azure.PutFile(testCtx, backupID, key, srcPath) 208 require.Nil(t, err) 209 210 contents, err := azure.GetObject(testCtx, backupID, key) 211 require.Nil(t, err) 212 assert.Equal(t, expectedContents, contents) 213 }) 214 215 t.Run("fetch file from backend", func(t *testing.T) { 216 destPath := dataDir + "/file_0.copy.db" 217 218 err := azure.WriteToFile(testCtx, backupID, key, destPath) 219 require.Nil(t, err) 220 221 contents, err := os.ReadFile(destPath) 222 require.Nil(t, err) 223 assert.Equal(t, expectedContents, contents) 224 }) 225 }) 226 } 227 228 type fakeModuleParams struct { 229 logger logrus.FieldLogger 230 provider fakeStorageProvider 231 config config.Config 232 } 233 234 func newFakeModuleParams(dataPath string) *fakeModuleParams { 235 logger, _ := logrustest.NewNullLogger() 236 return &fakeModuleParams{ 237 logger: logger, 238 provider: fakeStorageProvider{dataPath: dataPath}, 239 } 240 } 241 242 func (f *fakeModuleParams) GetStorageProvider() moduletools.StorageProvider { 243 return &f.provider 244 } 245 246 func (f *fakeModuleParams) GetAppState() interface{} { 247 return nil 248 } 249 250 func (f *fakeModuleParams) GetLogger() logrus.FieldLogger { 251 return f.logger 252 } 253 254 func (f *fakeModuleParams) GetConfig() config.Config { 255 return f.config 256 } 257 258 type fakeStorageProvider struct { 259 dataPath string 260 } 261 262 func (f *fakeStorageProvider) Storage(name string) (moduletools.Storage, error) { 263 return nil, nil 264 } 265 266 func (f *fakeStorageProvider) DataPath() string { 267 return f.dataPath 268 }