Skip to content

test(signature-v4-multi-region): long-lived resources for cfkvs sigv4a e2e test #7050

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 5, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
import "@aws-sdk/signature-v4a";

import { Sha256 } from "@aws-crypto/sha256-js";
import { CloudFrontClient, CreateKeyValueStoreCommand, DeleteKeyValueStoreCommand } from "@aws-sdk/client-cloudfront";
import { CloudFrontKeyValueStoreClient, DescribeKeyValueStoreCommand } from "@aws-sdk/client-cloudfront-keyvaluestore";
import { GetCallerIdentityCommand, STSClient } from "@aws-sdk/client-sts";
import { CloudFrontClient, CreateKeyValueStoreCommand, DescribeKeyValueStoreCommand } from "@aws-sdk/client-cloudfront";
import {
CloudFrontKeyValueStoreClient,
DescribeKeyValueStoreCommand as KVSDescribeCommand,
} from "@aws-sdk/client-cloudfront-keyvaluestore";
import { defaultProvider } from "@aws-sdk/credential-provider-node";
import { SignatureV4MultiRegion } from "@aws-sdk/signature-v4-multi-region";
import { HttpRequest } from "@smithy/protocol-http";
import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";

const LONG_TIMEOUT = 300000;

// Long-lived resource name
const KEY_VALUE_STORE_NAME = "jsv3-e2e-cfkvs-sigv4a";

const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));

// Helper util to poll until KVS is ready
Expand All @@ -23,13 +28,9 @@ async function waitForKeyValueStoreReady(
const startTime = Date.now();
while (Date.now() - startTime < timeoutMs) {
try {
const response = await client.send(new DescribeKeyValueStoreCommand({ KvsARN: arn }));
const response = await client.send(new KVSDescribeCommand({ KvsARN: arn }));
// if describe doesn't throw ResourceNotFound, it's ready enough for the test
if (response.KvsARN === arn) {
// Optionally wait for 'Deployed' status if needed, but findable is often enough
// if (response.Status === "Deployed") {
// return;
// }
return;
}
} catch (error: any) {
Expand All @@ -49,19 +50,13 @@ async function waitForKeyValueStoreReady(
describe("CloudFront KeyValue Store with SignatureV4a (JS Implementation)", () => {
let cfClient: CloudFrontClient;
let kvsClient: CloudFrontKeyValueStoreClient;
let keyValueStoreName: string;
let keyValueStoreARN: string;
let keyValueStoreETag: string;
let signer: SignatureV4MultiRegion;
let keyValueStoreETag: string;

beforeAll(async () => {
vi.setConfig({ testTimeout: LONG_TIMEOUT, hookTimeout: LONG_TIMEOUT });

const stsClient = new STSClient({ region: "us-west-2" });
const { Account } = await stsClient.send(new GetCallerIdentityCommand({}));
const timestamp = Date.now();
keyValueStoreName = `test-store-${Account}-${timestamp}`;

signer = new SignatureV4MultiRegion({
service: "cloudfront-keyvaluestore",
region: "*",
Expand All @@ -80,30 +75,43 @@ describe("CloudFront KeyValue Store with SignatureV4a (JS Implementation)", () =
disableHostPrefix: true,
});

const createResponse = await cfClient.send(
new CreateKeyValueStoreCommand({
Name: keyValueStoreName,
})
);
keyValueStoreARN = createResponse.KeyValueStore!.ARN!;
keyValueStoreETag = createResponse.ETag!;
// Try to get the existing key value store
try {
const describeResponse = await cfClient.send(
new DescribeKeyValueStoreCommand({
Name: KEY_VALUE_STORE_NAME,
})
);
keyValueStoreARN = describeResponse.KeyValueStore!.ARN!;
keyValueStoreETag = describeResponse.ETag!;
console.log(`Using existing KeyValueStore: ${keyValueStoreARN}`);
} catch (error: any) {
if (error.name === "EntityNotFound") {
console.log(`KeyValueStore ${KEY_VALUE_STORE_NAME} does not exist. Creating it now...`);
// Create the key value store if it doesn't exist
const createResponse = await cfClient.send(
new CreateKeyValueStoreCommand({
Name: KEY_VALUE_STORE_NAME,
})
);
keyValueStoreARN = createResponse.KeyValueStore!.ARN!;
keyValueStoreETag = createResponse.ETag!;
console.log(`Created new KeyValueStore: ${keyValueStoreARN}`);
} else {
throw error;
}
}

// Make sure the key-value store is ready
await waitForKeyValueStoreReady(kvsClient, keyValueStoreARN);
}, LONG_TIMEOUT);

afterAll(async () => {
vi.setConfig({ testTimeout: LONG_TIMEOUT });

try {
await cfClient.send(
new DeleteKeyValueStoreCommand({
Name: keyValueStoreName,
IfMatch: keyValueStoreETag,
})
);
} catch (error) {
console.error("Failed to delete key-value store:", error);
}
// key-value store is a long-lived resource, so we don't delete it
cfClient?.destroy?.();
kvsClient?.destroy?.();
});

it("should use SignatureV4a JS implementation for CFKVS (mocked)", async () => {
Expand All @@ -129,7 +137,7 @@ describe("CloudFront KeyValue Store with SignatureV4a (JS Implementation)", () =
});

it("should describe the key-value store using SignatureV4a", async () => {
const response = await kvsClient.send(new DescribeKeyValueStoreCommand({ KvsARN: keyValueStoreARN }));
const response = await kvsClient.send(new KVSDescribeCommand({ KvsARN: keyValueStoreARN }));
expect(response.KvsARN).toBe(keyValueStoreARN);
expect(["READY", "Deployed"]).toContain(response.Status);
});
Expand Down
Loading