Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(s3-control): support S3 Outposts control plane (#1553)
* chore(s3-control): update s3 control model * feat(middleware-sdk-s3-control): add outpost-endpoints middleware * feat(client-s3-control): codegen client and remove host prefix customization Remove the host prefix customziation because with new S3 control model, the host prefix is modeled. So no customization is needed. * feat(middleware-sdk-s3-control): remove host prefix customization implementation * feat(middleware-sdk-s3-control): add outpost control plane customization * feat(client-s3-control): integrate outposts control plane customization * test(client-s3-control): add functional test * docs(middleware-sdk-s3-control): add more docs
- Loading branch information
1 parent
92e1fc4
commit 0439946
Showing
58 changed files
with
7,345 additions
and
1,410 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
/// <reference types="mocha" /> | ||
import { expect } from "chai"; | ||
import { S3Control } from "./S3Control"; | ||
import { FinalizeRequestMiddleware } from "@aws-sdk/types"; | ||
|
||
describe("S3Control Client", () => { | ||
// Middleware intercept request and return it before reaching the HTTP client. It records the request and context | ||
// and return them in the Metadata. | ||
const interceptionMiddleware: FinalizeRequestMiddleware<any, any> = (next, context) => (args) => { | ||
return Promise.resolve({ output: { $metadata: { request: args.request } }, response: "" as any }); | ||
}; | ||
const region = "us-east-1"; | ||
const credentials = { accessKeyId: "AKID", secretAccessKey: "SECRET" }; | ||
const s3Control = new S3Control({ region, credentials }); | ||
s3Control.middlewareStack.add(interceptionMiddleware, { step: "finalizeRequest", name: "interceptionMiddleware" }); | ||
const HEADER_OUTPOST_ID = "x-amz-outpost-id"; | ||
const HEADER_ACCOUNT_ID = "x-amz-account-id"; | ||
const dateStr = new Date().toISOString().substr(0, 10).replace(/[\-:]/g, ""); | ||
|
||
describe("CreateBucket", () => { | ||
it("should populate correct endpoint and signing region", async () => { | ||
const { | ||
// @ts-ignore request is set in $metadata by interception middleware. | ||
$metadata: { request }, | ||
} = await s3Control.createBucket({ Bucket: "Bucket" }); | ||
expect(request.hostname).eql(`s3-control.${region}.amazonaws.com`); | ||
expect(request.headers["authorization"]).contains( | ||
`Credential=${credentials.accessKeyId}/${dateStr}/${region}/s3/aws4_request` | ||
); | ||
}); | ||
|
||
it("should populate correct endpoint and signing region if OutpostId is supplied", async () => { | ||
const OutpostId = "123456789012"; | ||
const { | ||
// @ts-ignore request is set in $metadata by interception middleware. | ||
$metadata: { request }, | ||
} = await s3Control.createBucket({ Bucket: "Bucket", OutpostId }); | ||
expect(request.hostname).eql(`s3-outposts.${region}.amazonaws.com`); | ||
expect(request.headers[HEADER_OUTPOST_ID]).eql(OutpostId); | ||
expect(request.headers["authorization"]).contains( | ||
`Credential=${credentials.accessKeyId}/${dateStr}/${region}/s3-outposts/aws4_request` | ||
); | ||
}); | ||
}); | ||
|
||
describe("ListRegionalBuckets", () => { | ||
const AccountId = "123456789012"; | ||
it("should populate correct endpoint and signing region", async () => { | ||
const { | ||
// @ts-ignore request is set in $metadata by interception middleware. | ||
$metadata: { request }, | ||
} = await s3Control.listRegionalBuckets({ AccountId }); | ||
expect(request.hostname).eql(`${AccountId}.s3-control.${region}.amazonaws.com`); | ||
expect(request.headers["authorization"]).contains( | ||
`Credential=${credentials.accessKeyId}/${dateStr}/${region}/s3/aws4_request` | ||
); | ||
}); | ||
|
||
it("should populate correct endpoint and signing region if OutpostId is supplied", async () => { | ||
const OutpostId = "123456789012"; | ||
const { | ||
// @ts-ignore request is set in $metadata by interception middleware. | ||
$metadata: { request }, | ||
} = await s3Control.listRegionalBuckets({ AccountId, OutpostId }); | ||
expect(request.hostname).eql(`s3-outposts.${region}.amazonaws.com`); | ||
expect(request.headers[HEADER_OUTPOST_ID]).eql(OutpostId); | ||
expect(request.headers[HEADER_ACCOUNT_ID]).eql(AccountId); | ||
expect(request.headers["authorization"]).contains( | ||
`Credential=${credentials.accessKeyId}/${dateStr}/${region}/s3-outposts/aws4_request` | ||
); | ||
}); | ||
}); | ||
|
||
// Use GetAccessPointCommand to validate the customizations for Access Point ARN customizations | ||
describe("Outposts Access Point ARN", () => { | ||
const AccountId = "123456789012"; | ||
const OutpostId = "op-01234567890123456"; | ||
const accesspointArn = `arn:aws:s3-outposts:${region}:${AccountId}:outpost:${OutpostId}:accesspoint:myaccesspoint`; | ||
it("should populate correct endpoint if Access Point name is non-ARN", async () => { | ||
const { | ||
// @ts-ignore request is set in $metadata by interception middleware. | ||
$metadata: { request }, | ||
} = await s3Control.getAccessPoint({ Name: "FakeAccessPoint", AccountId }); | ||
expect(request.hostname).eql(`${AccountId}.s3-control.${region}.amazonaws.com`); | ||
expect(request.headers["authorization"]).contains( | ||
`Credential=${credentials.accessKeyId}/${dateStr}/${region}/s3/aws4_request` | ||
); | ||
}); | ||
|
||
it("should populate correct endpoint and signing region if Access Point name is ARN", async () => { | ||
const { | ||
// @ts-ignore request is set in $metadata by interception middleware. | ||
$metadata: { request }, | ||
} = await s3Control.getAccessPoint({ Name: accesspointArn }); | ||
expect(request.hostname).eql(`s3-outposts.${region}.amazonaws.com`); | ||
expect(request.headers[HEADER_OUTPOST_ID]).eql(OutpostId); | ||
expect(request.headers[HEADER_ACCOUNT_ID]).eql(AccountId); | ||
expect(request.headers["authorization"]).contains( | ||
`Credential=${credentials.accessKeyId}/${dateStr}/${region}/s3-outposts/aws4_request` | ||
); | ||
}); | ||
}); | ||
|
||
// Use GetBucketCommand to validate the customizations for Bucket ARN customizations | ||
describe("Outposts Bucket ARN", () => { | ||
const AccountId = "123456789012"; | ||
const OutpostId = "op-01234567890123456"; | ||
const bucketArn = `arn:aws:s3-outposts:${region}:${AccountId}:outpost/${OutpostId}/bucket/bucket-id"`; | ||
it("should populate correct endpoint if Bucket name is non-ARN", async () => { | ||
const { | ||
// @ts-ignore request is set in $metadata by interception middleware. | ||
$metadata: { request }, | ||
} = await s3Control.getBucket({ Bucket: "BucketName", AccountId }); | ||
expect(request.hostname).eql(`${AccountId}.s3-control.${region}.amazonaws.com`); | ||
expect(request.headers["authorization"]).contains( | ||
`Credential=${credentials.accessKeyId}/${dateStr}/${region}/s3/aws4_request` | ||
); | ||
}); | ||
|
||
it("should populate correct endpoint and signing region if Bucket name is ARN", async () => { | ||
const { | ||
// @ts-ignore request is set in $metadata by interception middleware. | ||
$metadata: { request }, | ||
} = await s3Control.getBucket({ Bucket: bucketArn }); | ||
expect(request.hostname).eql(`s3-outposts.${region}.amazonaws.com`); | ||
expect(request.headers[HEADER_OUTPOST_ID]).eql(OutpostId); | ||
expect(request.headers[HEADER_ACCOUNT_ID]).eql(AccountId); | ||
expect(request.headers["authorization"]).contains( | ||
`Credential=${credentials.accessKeyId}/${dateStr}/${region}/s3-outposts/aws4_request` | ||
); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.