github.com/percona/percona-xtradb-cluster-operator@v1.14.0/pkg/pxc/backup/storage/options_test.go (about) 1 package storage 2 3 import ( 4 "context" 5 "reflect" 6 "testing" 7 8 corev1 "k8s.io/api/core/v1" 9 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 10 "k8s.io/apimachinery/pkg/runtime" 11 "sigs.k8s.io/controller-runtime/pkg/client/fake" 12 13 api "github.com/percona/percona-xtradb-cluster-operator/pkg/apis/pxc/v1" 14 ) 15 16 func TestGetS3Options(t *testing.T) { 17 ctx := context.Background() 18 19 const ns = "my-ns" 20 21 const storageName = "my-storage" 22 const secretName = "my-secret" 23 const accessKeyID = "some-access-key" 24 const secretAccessKey = "some-secret-key" 25 26 boolPtr := func(b bool) *bool { return &b } 27 28 tests := []struct { 29 name string 30 destination string 31 bucket string 32 accessKeyID string 33 secretAccessKey string 34 endpoint string 35 region string 36 verifyTLS *bool 37 storage *api.BackupStorageSpec 38 39 expected *S3Options 40 expectedErr string 41 }{ 42 { 43 name: "no secret", 44 bucket: "somebucket", 45 endpoint: "some-endpoint", 46 region: "some-region", 47 expected: &S3Options{ 48 Endpoint: "some-endpoint", 49 BucketName: "somebucket", 50 Region: "some-region", 51 VerifyTLS: true, 52 }, 53 }, 54 { 55 name: "with secret", 56 bucket: "somebucket", 57 accessKeyID: accessKeyID, 58 secretAccessKey: secretAccessKey, 59 expected: &S3Options{ 60 BucketName: "somebucket", 61 AccessKeyID: accessKeyID, 62 SecretAccessKey: secretAccessKey, 63 VerifyTLS: true, 64 Region: "us-east-1", 65 }, 66 }, 67 { 68 name: "bucket without prefix", 69 bucket: "my-bucket", 70 expected: &S3Options{ 71 BucketName: "my-bucket", 72 VerifyTLS: true, 73 Region: "us-east-1", 74 }, 75 }, 76 { 77 name: "bucket with prefix", 78 bucket: "my-bucket/prefix", 79 expected: &S3Options{ 80 BucketName: "my-bucket", 81 Prefix: "prefix/", 82 VerifyTLS: true, 83 Region: "us-east-1", 84 }, 85 }, 86 { 87 name: "destination with bucket", 88 destination: "s3://invalid-bucket/prefix/backup-name", 89 bucket: "my-bucket", 90 expected: &S3Options{ 91 BucketName: "my-bucket", 92 VerifyTLS: true, 93 Region: "us-east-1", 94 }, 95 }, 96 { 97 name: "destination without prefix", 98 destination: "s3://destination-bucket/backup-name", 99 expected: &S3Options{ 100 BucketName: "destination-bucket", 101 VerifyTLS: true, 102 Region: "us-east-1", 103 }, 104 }, 105 { 106 name: "destination with prefix", 107 destination: "s3://destination-bucket/prefix/backup-name", 108 expected: &S3Options{ 109 BucketName: "destination-bucket", 110 Prefix: "prefix/", 111 VerifyTLS: true, 112 Region: "us-east-1", 113 }, 114 }, 115 { 116 name: "no destination", 117 expectedErr: "bucket name is not set", 118 }, 119 { 120 name: "verifyTLS in backup", 121 bucket: "somebucket", 122 verifyTLS: boolPtr(false), 123 expected: &S3Options{ 124 BucketName: "somebucket", 125 VerifyTLS: false, 126 Region: "us-east-1", 127 }, 128 }, 129 { 130 name: "verifyTLS in backup and cluster", 131 bucket: "somebucket", 132 verifyTLS: boolPtr(true), 133 storage: &api.BackupStorageSpec{ 134 VerifyTLS: boolPtr(false), 135 }, 136 expected: &S3Options{ 137 BucketName: "somebucket", 138 VerifyTLS: false, 139 Region: "us-east-1", 140 }, 141 }, 142 } 143 144 for _, tt := range tests { 145 t.Run(tt.name, func(t *testing.T) { 146 backup := testBackup(ns, storageName, tt.destination, tt.verifyTLS, &api.BackupStorageS3Spec{ 147 Bucket: tt.bucket, 148 CredentialsSecret: secretName, 149 Region: tt.region, 150 EndpointURL: tt.endpoint, 151 }, nil) 152 153 var cluster *api.PerconaXtraDBCluster 154 if tt.storage != nil { 155 cluster = &api.PerconaXtraDBCluster{ 156 Spec: api.PerconaXtraDBClusterSpec{ 157 Backup: &api.PXCScheduledBackup{ 158 Storages: map[string]*api.BackupStorageSpec{ 159 storageName: tt.storage, 160 }, 161 }, 162 }, 163 } 164 } 165 166 objs := []runtime.Object{} 167 if tt.accessKeyID != "" || tt.secretAccessKey != "" { 168 objs = append(objs, &corev1.Secret{ 169 ObjectMeta: metav1.ObjectMeta{ 170 Name: secretName, 171 Namespace: ns, 172 }, 173 Data: map[string][]byte{ 174 "AWS_ACCESS_KEY_ID": []byte(tt.accessKeyID), 175 "AWS_SECRET_ACCESS_KEY": []byte(tt.secretAccessKey), 176 }, 177 }) 178 } 179 cl := fake.NewClientBuilder().WithRuntimeObjects(objs...).Build() 180 181 opts, err := getS3Options(ctx, cl, cluster, backup) 182 if err != nil && tt.expectedErr != err.Error() { 183 t.Fatal(err) 184 } 185 if !reflect.DeepEqual(opts, tt.expected) { 186 t.Fatalf("expected: %+v, got: %+v", tt.expected, opts) 187 } 188 }) 189 } 190 } 191 192 func TestGetAzureOptions(t *testing.T) { 193 ctx := context.Background() 194 195 const ns = "my-ns" 196 197 const storageName = "my-storage" 198 const secretName = "my-secret" 199 const accountName = "some-access-key" 200 const accountKey = "some-secret-key" 201 202 tests := []struct { 203 name string 204 destination string 205 container string 206 accountName string 207 accountKey string 208 endpoint string 209 210 expected *AzureOptions 211 expectedErr string 212 }{ 213 { 214 name: "no secret", 215 container: "some-container", 216 endpoint: "some-endpoint", 217 expectedErr: `failed to get secret: secrets "my-secret" not found`, 218 }, 219 { 220 name: "container without prefix", 221 container: "my-container", 222 accountName: accountName, 223 accountKey: accountKey, 224 endpoint: "some-endpoint", 225 expected: &AzureOptions{ 226 StorageAccount: accountName, 227 AccessKey: accountKey, 228 Container: "my-container", 229 Endpoint: "some-endpoint", 230 }, 231 }, 232 { 233 name: "container with prefix", 234 container: "my-container/prefix", 235 accountName: accountName, 236 accountKey: accountKey, 237 expected: &AzureOptions{ 238 StorageAccount: accountName, 239 AccessKey: accountKey, 240 Container: "my-container", 241 Prefix: "prefix/", 242 }, 243 }, 244 { 245 name: "destination with container", 246 destination: "azure://invalid-container/prefix/backup-name", 247 container: "my-container", 248 accountName: accountName, 249 accountKey: accountKey, 250 expected: &AzureOptions{ 251 StorageAccount: accountName, 252 AccessKey: accountKey, 253 Container: "my-container", 254 }, 255 }, 256 { 257 name: "destination without prefix", 258 destination: "azure://destination-container/backup-name", 259 accountName: accountName, 260 accountKey: accountKey, 261 expected: &AzureOptions{ 262 StorageAccount: accountName, 263 AccessKey: accountKey, 264 Container: "destination-container", 265 }, 266 }, 267 { 268 name: "destination with prefix", 269 destination: "azure://destination-container/prefix/backup-name", 270 accountName: accountName, 271 accountKey: accountKey, 272 expected: &AzureOptions{ 273 StorageAccount: accountName, 274 AccessKey: accountKey, 275 Container: "destination-container", 276 Prefix: "prefix/", 277 }, 278 }, 279 { 280 name: "no destination", 281 accountName: accountName, 282 accountKey: accountKey, 283 expectedErr: "container name is not set", 284 }, 285 } 286 287 for _, tt := range tests { 288 t.Run(tt.name, func(t *testing.T) { 289 backup := testBackup(ns, storageName, tt.destination, nil, nil, &api.BackupStorageAzureSpec{ 290 ContainerPath: tt.container, 291 CredentialsSecret: secretName, 292 Endpoint: tt.endpoint, 293 }) 294 295 objs := []runtime.Object{} 296 if tt.accountName != "" || tt.accountKey != "" { 297 objs = append(objs, testSecret(ns, secretName, map[string][]byte{ 298 "AZURE_STORAGE_ACCOUNT_NAME": []byte(tt.accountName), 299 "AZURE_STORAGE_ACCOUNT_KEY": []byte(tt.accountKey), 300 })) 301 } 302 cl := fake.NewClientBuilder().WithRuntimeObjects(objs...).Build() 303 304 opts, err := getAzureOptions(ctx, cl, backup) 305 if err != nil && tt.expectedErr != err.Error() { 306 t.Fatal(err) 307 } 308 if !reflect.DeepEqual(opts, tt.expected) { 309 t.Fatalf("expected: %+v, got: %+v", tt.expected, opts) 310 } 311 }) 312 } 313 } 314 315 func testSecret(ns string, name string, data map[string][]byte) *corev1.Secret { 316 return &corev1.Secret{ 317 ObjectMeta: metav1.ObjectMeta{ 318 Name: name, 319 Namespace: ns, 320 }, 321 Data: data, 322 } 323 } 324 325 func testBackup(ns string, storageName string, destination string, verifyTLS *bool, s3 *api.BackupStorageS3Spec, azure *api.BackupStorageAzureSpec) *api.PerconaXtraDBClusterBackup { 326 return &api.PerconaXtraDBClusterBackup{ 327 ObjectMeta: metav1.ObjectMeta{ 328 Name: "my-backup", 329 Namespace: ns, 330 }, 331 Spec: api.PXCBackupSpec{ 332 StorageName: storageName, 333 }, 334 Status: api.PXCBackupStatus{ 335 Destination: api.PXCBackupDestination(destination), 336 S3: s3, 337 Azure: azure, 338 VerifyTLS: verifyTLS, 339 }, 340 } 341 }