Skip to content

Commit 1b3e319

Browse files
committed
refactor fastly client into class based api
1 parent 96b3493 commit 1b3e319

File tree

14 files changed

+1208
-712
lines changed

14 files changed

+1208
-712
lines changed

ab-testing/dictionary-deploy-lambda/src/deploy-dictionary.ts

Lines changed: 8 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
1-
import {
2-
calculateUpdates,
3-
getDictionaryItems,
4-
updateDictionaryItems,
5-
verifyDictionaryName,
6-
} from "../../lib/fastly-api.ts";
1+
import type { FastlyDictionary } from "../../lib/fastly/dictionary.ts";
2+
import { calculateUpdates } from "../../lib/fastly/utils.ts";
73
import type { KeyValue } from "./fetch-artifact.ts";
84

95
/**
@@ -14,49 +10,27 @@ import type { KeyValue } from "./fetch-artifact.ts";
1410
* @param keyValues An array of key-value pairs to deploy to the dictionary.
1511
*/
1612
export const deployDictionary = async (
17-
{
18-
dictionaryName,
19-
dictionaryId,
20-
serviceId,
21-
activeVersion,
22-
}: {
23-
dictionaryName: string;
24-
dictionaryId: string;
25-
serviceId: string;
26-
activeVersion: number;
27-
},
13+
dictionary: FastlyDictionary,
2814
keyValues: KeyValue[],
2915
) => {
30-
await verifyDictionaryName({
31-
serviceId,
32-
activeVersion,
33-
dictionaryName,
34-
dictionaryId,
35-
});
36-
37-
const currentKeyValues = await getDictionaryItems({
38-
dictionaryId,
39-
});
16+
const currentKeyValues = await dictionary.getItems();
4017

4118
const updates = calculateUpdates(keyValues, currentKeyValues);
4219

4320
if (updates.length === 0) {
44-
console.log(`No key-values need updating in '${dictionaryName}'`);
21+
console.log(`No key-values need updating in '${dictionary.name}'`);
4522
} else {
4623
Map.groupBy(updates, (item) => item.op).forEach((items, op) => {
4724
console.log(
48-
`Performing ${items.length} ${op} operations in '${dictionaryName}'`,
25+
`Performing ${items.length} ${op} operations in '${dictionary.name}'`,
4926
);
5027
});
5128

5229
console.log(
53-
`Performing ${updates.length} total operations in '${dictionaryName}'`,
30+
`Performing ${updates.length} total operations in '${dictionary.name}'`,
5431
);
5532

56-
const response = await updateDictionaryItems({
57-
dictionaryId,
58-
items: updates,
59-
});
33+
const response = await dictionary.updateItems(updates);
6034

6135
if (response.status !== "ok") {
6236
throw new Error(`Failed to update mvt groups dictionary`);

ab-testing/dictionary-deploy-lambda/src/deploy.ts

Lines changed: 5 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { FastlyDictionary } from "../../lib/fastly/dictionary.ts";
12
import { deployDictionary } from "./deploy-dictionary.ts";
23
import { fetchDictionaryArtifact } from "./fetch-artifact.ts";
34

@@ -6,42 +7,25 @@ const STAGE = process.env.STAGE ?? "CODE";
67

78
const CONFIG_PREFIX = `/${STAGE}/config/ab-testing`;
89

9-
type ServiceInfo = {
10-
activeVersion: { number: number };
11-
serviceId: string;
12-
};
13-
1410
type ArtifactInfo = {
1511
artifact: string;
16-
dictionaryName: string;
17-
dictionaryId: string;
12+
dictionary: FastlyDictionary;
1813
};
1914

2015
/**
2116
* Fetches dictionary artifacts from S3 and deploys them to Fastly dictionaries in parallel.
2217
* @param serviceInfo The Fastly service information including active version and service ID.
2318
* @param deployments An array of artifact deployment information.
2419
*/
25-
export const fetchAndDeployArtifacts = async (
26-
{ activeVersion, serviceId }: ServiceInfo,
27-
deployments: ArtifactInfo[],
28-
) => {
20+
export const fetchAndDeployArtifacts = async (deployments: ArtifactInfo[]) => {
2921
try {
3022
await Promise.all(
31-
deployments.map(({ artifact, dictionaryName, dictionaryId }) =>
23+
deployments.map(({ artifact, dictionary }) =>
3224
fetchDictionaryArtifact(
3325
ARTIFACT_BUCKET_NAME,
3426
`${CONFIG_PREFIX}/${artifact}`,
3527
).then((abTestGroups) =>
36-
deployDictionary(
37-
{
38-
serviceId,
39-
activeVersion: activeVersion.number,
40-
dictionaryName,
41-
dictionaryId,
42-
},
43-
abTestGroups,
44-
),
28+
deployDictionary(dictionary, abTestGroups),
4529
),
4630
),
4731
);

ab-testing/dictionary-deploy-lambda/src/index.ts

Lines changed: 38 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { GetParameterCommand, SSMClient } from "@aws-sdk/client-ssm";
12
import type { Handler } from "aws-cdk-lib/aws-lambda";
23
import type { CloudFormationCustomResourceEvent, Context } from "aws-lambda";
34
import { send } from "cfn-response";
@@ -9,48 +10,57 @@ import {
910
serviceId,
1011
serviceName,
1112
} from "../../lib/config.ts";
12-
import { getService } from "../../lib/fastly-api.ts";
13+
import { FastlyClient } from "../../lib/fastly/client.ts";
1314
import { fetchAndDeployArtifacts } from "./deploy.ts";
1415

16+
const ssmClient = new SSMClient({ region: "eu-west-1" });
17+
18+
const getSecureString = async (name: string) => {
19+
const response = await ssmClient.send(
20+
new GetParameterCommand({
21+
Name: name,
22+
WithDecryption: true,
23+
}),
24+
);
25+
return response.Parameter?.Value;
26+
};
27+
1528
export const handler: Handler = async (
1629
event: CloudFormationCustomResourceEvent,
1730
context: Context,
1831
): Promise<void> => {
19-
const service = await getService(serviceId);
20-
if (service.name !== serviceName) {
21-
throw new Error(
22-
`Service ID ${serviceId} does not match the expected service name ${serviceName}`,
23-
);
24-
}
25-
26-
const activeVersion = service.versions.find(
27-
(v: { active: boolean }) => v.active,
32+
const apiToken = await getSecureString(
33+
`/ab-testing-deploy/${process.env.STAGE}/fastly-api-token`,
2834
);
2935

30-
if (!activeVersion) {
31-
throw new Error(`No active version found for service ${service.name}`);
36+
if (!apiToken) {
37+
throw new Error("Fastly API token not found in SSM Parameter Store");
3238
}
3339

40+
const fastly = new FastlyClient(apiToken);
41+
const service = await fastly.getService(serviceId, serviceName);
42+
43+
const abTestsDictionary = await service.getDictionary(
44+
abTestsDictionaryId,
45+
abTestsDictionaryName,
46+
);
47+
const mvtDictionary = await service.getDictionary(
48+
mvtDictionaryId,
49+
mvtDictionaryName,
50+
);
51+
3452
if (event.RequestType === "Create" || event.RequestType === "Update") {
3553
try {
36-
await fetchAndDeployArtifacts(
54+
await fetchAndDeployArtifacts([
55+
{
56+
artifact: "ab-test-groups.json",
57+
dictionary: abTestsDictionary,
58+
},
3759
{
38-
activeVersion,
39-
serviceId,
60+
artifact: "mvt-groups.json",
61+
dictionary: mvtDictionary,
4062
},
41-
[
42-
{
43-
artifact: "ab-test-groups.json",
44-
dictionaryName: abTestsDictionaryName,
45-
dictionaryId: abTestsDictionaryId,
46-
},
47-
{
48-
artifact: "mvt-groups.json",
49-
dictionaryName: mvtDictionaryName,
50-
dictionaryId: mvtDictionaryId,
51-
},
52-
],
53-
);
63+
]);
5464

5565
send(event, context, "SUCCESS");
5666
} catch (error) {

0 commit comments

Comments
 (0)