Skip to content

Commit e7c4298

Browse files
committed
Adding description to event notification rule config
1 parent a5ac45d commit e7c4298

File tree

4 files changed

+285
-7
lines changed

4 files changed

+285
-7
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": patch
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: 254 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -998,6 +998,258 @@ describe("r2", () => {
998998
`);
999999
});
10001000

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

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;
@@ -544,7 +545,8 @@ export async function putEventNotificationConfig(
544545
queueName: string,
545546
eventTypes: R2EventType[],
546547
prefix?: string,
547-
suffix?: string
548+
suffix?: string,
549+
description?: string
548550
): Promise<void> {
549551
const queue = await getQueue(config, queueName);
550552
const headers = eventNotificationHeaders(apiCredentials);
@@ -554,9 +556,14 @@ export async function putEventNotificationConfig(
554556
actions = actions.concat(actionsForEventCategories[et]);
555557
}
556558

557-
const body: PutNotificationRequestBody = {
558-
rules: [{ prefix, suffix, actions }],
559-
};
559+
const body: PutNotificationRequestBody =
560+
description === undefined
561+
? {
562+
rules: [{ prefix, suffix, actions }],
563+
}
564+
: {
565+
rules: [{ prefix, suffix, actions, description }],
566+
};
560567
const ruleFor = eventTypes.map((et) =>
561568
et === "object-create" ? "creation" : "deletion"
562569
);

packages/wrangler/src/r2/notification.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@ export function CreateOptions(yargs: CommonYargsArgv) {
7979
demandOption: true,
8080
requiresArg: true,
8181
type: "string",
82+
})
83+
.option("description", {
84+
describe:
85+
"The description of why the event notification rule was created",
86+
type: "string",
8287
});
8388
}
8489

@@ -89,7 +94,14 @@ export async function CreateHandler(
8994
const config = readConfig(args.config, args);
9095
const accountId = await requireAuth(config);
9196
const apiCreds = requireApiToken();
92-
const { bucket, queue, eventTypes, prefix = "", suffix = "" } = args;
97+
const {
98+
bucket,
99+
queue,
100+
eventTypes,
101+
prefix = "",
102+
suffix = "",
103+
description,
104+
} = args;
93105
await putEventNotificationConfig(
94106
config,
95107
apiCreds,
@@ -98,7 +110,8 @@ export async function CreateHandler(
98110
queue,
99111
eventTypes as R2EventType[],
100112
prefix,
101-
suffix
113+
suffix,
114+
description
102115
);
103116
logger.log("Event notification rule created successfully!");
104117
}

0 commit comments

Comments
 (0)