Skip to content

Commit 7b12b2f

Browse files
committed
Adding description to event notification rule config
1 parent 226f9bd commit 7b12b2f

File tree

4 files changed

+277
-5
lines changed

4 files changed

+277
-5
lines changed

.changeset/plenty-garlics-jump.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"wrangler": minor
3+
---
4+
5+
feature: allowing users to specify a description when creating an event notification rule

packages/wrangler/src/__tests__/r2.test.ts

Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,6 +1001,258 @@ describe("r2", () => {
10011001
`);
10021002
});
10031003

1004+
it("follows happy path as expected with prefix", async () => {
1005+
const eventTypes: R2EventType[] = ["object-create", "object-delete"];
1006+
const actions: R2EventableOperation[] = [];
1007+
const bucketName = "my-bucket";
1008+
const queue = "my-queue";
1009+
1010+
const config: PutNotificationRequestBody = {
1011+
rules: [
1012+
{
1013+
actions: eventTypes.reduce(
1014+
(acc, et) => acc.concat(actionsForEventCategories[et]),
1015+
actions
1016+
),
1017+
prefix: "ruleprefix",
1018+
},
1019+
],
1020+
};
1021+
msw.use(
1022+
http.put(
1023+
"*/accounts/:accountId/event_notifications/r2/:bucketName/configuration/queues/:queueUUID",
1024+
async ({ request, params }) => {
1025+
const { accountId } = params;
1026+
expect(accountId).toEqual("some-account-id");
1027+
expect(await request.json()).toEqual({
1028+
...config,
1029+
// We fill in `prefix` & `suffix` with empty strings if not
1030+
// provided
1031+
rules: [{ ...config.rules[0], suffix: "" }],
1032+
});
1033+
expect(request.headers.get("authorization")).toEqual(
1034+
"Bearer some-api-token"
1035+
);
1036+
return HttpResponse.json(createFetchResult({}));
1037+
},
1038+
{ once: true }
1039+
),
1040+
http.get(
1041+
"*/accounts/:accountId/queues?*",
1042+
async ({ request, params }) => {
1043+
const url = new URL(request.url);
1044+
const { accountId } = params;
1045+
const nameParams = url.searchParams.getAll("name");
1046+
1047+
expect(accountId).toEqual("some-account-id");
1048+
expect(nameParams[0]).toEqual(queue);
1049+
expect(request.headers.get("authorization")).toEqual(
1050+
"Bearer some-api-token"
1051+
);
1052+
return HttpResponse.json({
1053+
success: true,
1054+
errors: [],
1055+
messages: [],
1056+
result: [
1057+
{
1058+
queue_id: "queue-id",
1059+
queue_name: queue,
1060+
created_on: "",
1061+
producers: [],
1062+
consumers: [],
1063+
producers_total_count: 1,
1064+
consumers_total_count: 0,
1065+
modified_on: "",
1066+
},
1067+
],
1068+
});
1069+
},
1070+
{ once: true }
1071+
)
1072+
);
1073+
await expect(
1074+
runWrangler(
1075+
`r2 bucket notification create ${bucketName} --queue ${queue} --event-types ${eventTypes.join(
1076+
" "
1077+
)} --prefix "ruleprefix"`
1078+
)
1079+
).resolves.toBe(undefined);
1080+
expect(std.out).toMatchInlineSnapshot(`
1081+
"Creating event notification rule for object creation and deletion (PutObject,CompleteMultipartUpload,CopyObject,DeleteObject,LifecycleDeletion)
1082+
Event notification rule created successfully!"
1083+
`);
1084+
});
1085+
1086+
it("follows happy path as expected with suffix", async () => {
1087+
const eventTypes: R2EventType[] = ["object-create", "object-delete"];
1088+
const actions: R2EventableOperation[] = [];
1089+
const bucketName = "my-bucket";
1090+
const queue = "my-queue";
1091+
1092+
const config: PutNotificationRequestBody = {
1093+
rules: [
1094+
{
1095+
actions: eventTypes.reduce(
1096+
(acc, et) => acc.concat(actionsForEventCategories[et]),
1097+
actions
1098+
),
1099+
suffix: "rulesuffix",
1100+
},
1101+
],
1102+
};
1103+
msw.use(
1104+
http.put(
1105+
"*/accounts/:accountId/event_notifications/r2/:bucketName/configuration/queues/:queueUUID",
1106+
async ({ request, params }) => {
1107+
const { accountId } = params;
1108+
expect(accountId).toEqual("some-account-id");
1109+
expect(await request.json()).toEqual({
1110+
...config,
1111+
// We fill in `prefix` & `suffix` with empty strings if not
1112+
// provided
1113+
rules: [{ ...config.rules[0], prefix: "" }],
1114+
});
1115+
expect(request.headers.get("authorization")).toEqual(
1116+
"Bearer some-api-token"
1117+
);
1118+
return HttpResponse.json(createFetchResult({}));
1119+
},
1120+
{ once: true }
1121+
),
1122+
http.get(
1123+
"*/accounts/:accountId/queues?*",
1124+
async ({ request, params }) => {
1125+
const url = new URL(request.url);
1126+
const { accountId } = params;
1127+
const nameParams = url.searchParams.getAll("name");
1128+
1129+
expect(accountId).toEqual("some-account-id");
1130+
expect(nameParams[0]).toEqual(queue);
1131+
expect(request.headers.get("authorization")).toEqual(
1132+
"Bearer some-api-token"
1133+
);
1134+
return HttpResponse.json({
1135+
success: true,
1136+
errors: [],
1137+
messages: [],
1138+
result: [
1139+
{
1140+
queue_id: "queue-id",
1141+
queue_name: queue,
1142+
created_on: "",
1143+
producers: [],
1144+
consumers: [],
1145+
producers_total_count: 1,
1146+
consumers_total_count: 0,
1147+
modified_on: "",
1148+
},
1149+
],
1150+
});
1151+
},
1152+
{ once: true }
1153+
)
1154+
);
1155+
await expect(
1156+
runWrangler(
1157+
`r2 bucket notification create ${bucketName} --queue ${queue} --event-types ${eventTypes.join(
1158+
" "
1159+
)} --suffix "rulesuffix"`
1160+
)
1161+
).resolves.toBe(undefined);
1162+
expect(std.out).toMatchInlineSnapshot(`
1163+
"Creating event notification rule for object creation and deletion (PutObject,CompleteMultipartUpload,CopyObject,DeleteObject,LifecycleDeletion)
1164+
Event notification rule created successfully!"
1165+
`);
1166+
});
1167+
1168+
it("follows happy path as expected with description", async () => {
1169+
const eventTypes: R2EventType[] = ["object-create", "object-delete"];
1170+
const actions: R2EventableOperation[] = [];
1171+
const bucketName = "my-bucket";
1172+
const queue = "my-queue";
1173+
1174+
const config: PutNotificationRequestBody = {
1175+
rules: [
1176+
{
1177+
actions: eventTypes.reduce(
1178+
(acc, et) => acc.concat(actionsForEventCategories[et]),
1179+
actions
1180+
),
1181+
description: "rule description",
1182+
},
1183+
],
1184+
};
1185+
msw.use(
1186+
http.put(
1187+
"*/accounts/:accountId/event_notifications/r2/:bucketName/configuration/queues/:queueUUID",
1188+
async ({ request, params }) => {
1189+
const { accountId } = params;
1190+
expect(accountId).toEqual("some-account-id");
1191+
expect(await request.json()).toEqual({
1192+
...config,
1193+
// We fill in `prefix` & `suffix` with empty strings if not
1194+
// provided
1195+
rules: [
1196+
{
1197+
...config.rules[0],
1198+
prefix: "",
1199+
suffix: "",
1200+
},
1201+
],
1202+
});
1203+
expect(request.headers.get("authorization")).toEqual(
1204+
"Bearer some-api-token"
1205+
);
1206+
return HttpResponse.json(createFetchResult({}));
1207+
},
1208+
{ once: true }
1209+
),
1210+
http.get(
1211+
"*/accounts/:accountId/queues?*",
1212+
async ({ request, params }) => {
1213+
const url = new URL(request.url);
1214+
const { accountId } = params;
1215+
const nameParams = url.searchParams.getAll("name");
1216+
1217+
expect(accountId).toEqual("some-account-id");
1218+
expect(nameParams[0]).toEqual(queue);
1219+
expect(request.headers.get("authorization")).toEqual(
1220+
"Bearer some-api-token"
1221+
);
1222+
return HttpResponse.json({
1223+
success: true,
1224+
errors: [],
1225+
messages: [],
1226+
result: [
1227+
{
1228+
queue_id: "queue-id",
1229+
queue_name: queue,
1230+
created_on: "",
1231+
producers: [],
1232+
consumers: [],
1233+
producers_total_count: 1,
1234+
consumers_total_count: 0,
1235+
modified_on: "",
1236+
},
1237+
],
1238+
});
1239+
},
1240+
{ once: true }
1241+
)
1242+
);
1243+
await expect(
1244+
runWrangler(
1245+
`r2 bucket notification create ${bucketName} --queue ${queue} --event-types ${eventTypes.join(
1246+
" "
1247+
)} --description "rule description"`
1248+
)
1249+
).resolves.toBe(undefined);
1250+
expect(std.out).toMatchInlineSnapshot(`
1251+
"Creating event notification rule for object creation and deletion (PutObject,CompleteMultipartUpload,CopyObject,DeleteObject,LifecycleDeletion)
1252+
Event notification rule created successfully!"
1253+
`);
1254+
});
1255+
10041256
it("errors if required options are not provided", async () => {
10051257
await expect(
10061258
runWrangler("r2 bucket notification create notification-test-001")
@@ -1029,6 +1281,7 @@ describe("r2", () => {
10291281
--suffix The suffix that an object must match to emit event notifications (note: regular expressions not supported) [string]
10301282
--queue The name of the queue that will receive event notification messages [string] [required]
10311283
-J, --jurisdiction The jurisdiction where the bucket exists [string]"
1284+
--description A description that can be used to identify the event notification rule after creation [string]"
10321285
`);
10331286
});
10341287
});

packages/wrangler/src/r2/helpers.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,7 @@ type NotificationRule = {
379379
prefix?: string;
380380
suffix?: string;
381381
actions: R2EventableOperation[];
382+
description?: string;
382383
};
383384
type GetNotificationRule = {
384385
ruleId: string;
@@ -550,7 +551,8 @@ export async function putEventNotificationConfig(
550551
queueName: string,
551552
eventTypes: R2EventType[],
552553
prefix?: string,
553-
suffix?: string
554+
suffix?: string,
555+
description?: string
554556
): Promise<void> {
555557
const queue = await getQueue(config, queueName);
556558
const headers = eventNotificationHeaders(apiCredentials, jurisdiction);
@@ -560,9 +562,14 @@ export async function putEventNotificationConfig(
560562
actions = actions.concat(actionsForEventCategories[et]);
561563
}
562564

563-
const body: PutNotificationRequestBody = {
564-
rules: [{ prefix, suffix, actions }],
565-
};
565+
const body: PutNotificationRequestBody =
566+
description === undefined
567+
? {
568+
rules: [{ prefix, suffix, actions }],
569+
}
570+
: {
571+
rules: [{ prefix, suffix, actions, description }],
572+
};
566573
const ruleFor = eventTypes.map((et) =>
567574
et === "object-create" ? "creation" : "deletion"
568575
);

packages/wrangler/src/r2/notification.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,11 @@ export function CreateOptions(yargs: CommonYargsArgv) {
9494
alias: "J",
9595
requiresArg: true,
9696
type: "string",
97+
})
98+
.option("description", {
99+
describe:
100+
"A description that can be used to identify the event notification rule after creation",
101+
type: "string",
97102
});
98103
}
99104

@@ -111,6 +116,7 @@ export async function CreateHandler(
111116
prefix = "",
112117
suffix = "",
113118
jurisdiction = "",
119+
description,
114120
} = args;
115121
await putEventNotificationConfig(
116122
config,
@@ -121,7 +127,8 @@ export async function CreateHandler(
121127
queue,
122128
eventTypes as R2EventType[],
123129
prefix,
124-
suffix
130+
suffix,
131+
description
125132
);
126133
logger.log("Event notification rule created successfully!");
127134
}

0 commit comments

Comments
 (0)