| 1 | package host |
| 2 | |
| 3 | import ( |
| 4 | "context" |
| 5 | "errors" |
| 6 | "os" |
| 7 | "testing" |
| 8 | |
| 9 | "github.com/aws/aws-sdk-go-v2/aws" |
| 10 | "github.com/aws/aws-sdk-go-v2/credentials" |
| 11 | awss3 "github.com/aws/aws-sdk-go-v2/service/s3" |
| 12 | s3types "github.com/aws/aws-sdk-go-v2/service/s3/types" |
| 13 | "github.com/aws/smithy-go" |
| 14 | ) |
| 15 | |
| 16 | // TestT4StorageProbeMinio runs T4's store probe (§7.3, §14.1) against a |
| 17 | // real S3 server: with the delivered variables of a bound store it lists, |
| 18 | // puts, gets and deletes .carlos-move-probe/<move id> and leaves nothing; |
| 19 | // with wrong credentials T4 fails with the store's sentence. It runs only |
| 20 | // where .amadan/ci.d/30-minio-contract stands a MinIO up (CARLOS_MINIO_TEST |
| 21 | // and the MINIO_* variables, as TestDeliveredContractMinio reads them). |
| 22 | func TestT4StorageProbeMinio(t *testing.T) { |
| 23 | if os.Getenv("CARLOS_MINIO_TEST") != "1" { |
| 24 | t.Skip("set CARLOS_MINIO_TEST=1 (with a running MinIO and the MINIO_* env vars) to run the T4 probe test; see .amadan/ci.d/30-minio-contract") |
| 25 | } |
| 26 | need := func(name string) string { |
| 27 | v := os.Getenv(name) |
| 28 | if v == "" { |
| 29 | t.Fatalf("%s is not set", name) |
| 30 | } |
| 31 | return v |
| 32 | } |
| 33 | endpoint, key, secret, bucket := need("MINIO_ENDPOINT"), need("MINIO_SCOPED_KEY"), need("MINIO_SCOPED_SECRET"), need("MINIO_BUCKET") |
| 34 | ctx := context.Background() |
| 35 | env := map[string]string{ |
| 36 | "STORE_BUCKET": bucket, "STORE_ENDPOINT": endpoint, "STORE_REGION": "us-east-1", |
| 37 | "STORE_ACCESS_KEY": key, "STORE_SECRET_KEY": secret, |
| 38 | } |
| 39 | if prefix, err := probeStores(ctx, env, p1ID); err != nil { |
| 40 | t.Fatalf("probe of %s: %v", prefix, err) |
| 41 | } |
| 42 | // The probe object is gone. |
| 43 | c := awss3.New(awss3.Options{ |
| 44 | Region: "us-east-1", Credentials: credentials.NewStaticCredentialsProvider(key, secret, ""), |
| 45 | BaseEndpoint: aws.String(endpoint), UsePathStyle: true, |
| 46 | RequestChecksumCalculation: aws.RequestChecksumCalculationWhenRequired, |
| 47 | ResponseChecksumValidation: aws.ResponseChecksumValidationWhenRequired, |
| 48 | }) |
| 49 | _, err := c.HeadObject(ctx, &awss3.HeadObjectInput{Bucket: aws.String(bucket), Key: aws.String(".carlos-move-probe/" + p1ID)}) |
| 50 | // Only a not-found answer proves it is gone: AccessDenied or any other |
| 51 | // error says nothing about the object. |
| 52 | var apiErr smithy.APIError |
| 53 | var notFound *s3types.NotFound |
| 54 | if err == nil || !(errors.As(err, ¬Found) || (errors.As(err, &apiErr) && (apiErr.ErrorCode() == "NotFound" || apiErr.ErrorCode() == "NoSuchKey"))) { |
| 55 | t.Fatalf("the probe object is not shown gone (head: %v)", err) |
| 56 | } |
| 57 | |
| 58 | // Wrong credentials: T4 fails with the store's sentence. |
| 59 | env["STORE_SECRET_KEY"] = "not-the-secret" |
| 60 | w := &movesWorker{cfg: moveCfg{ProbeStore: probeStores}} |
| 61 | got := w.checkStorage(ctx, heldEnv{env: env}, p1ID) |
| 62 | if got.OK || got.Reason != t4Failed("STORE") { |
| 63 | t.Fatalf("T4 with wrong credentials = %+v", got) |
| 64 | } |
| 65 | } |
| 66 | |