Skip to content

Commit

Permalink
Adding description to event notification rule config
Browse files Browse the repository at this point in the history
  • Loading branch information
jkoe-cf committed Oct 16, 2024
1 parent a5ac45d commit 54c9ce6
Show file tree
Hide file tree
Showing 4 changed files with 284 additions and 7 deletions.
5 changes: 5 additions & 0 deletions .changeset/plenty-garlics-jump.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"wrangler": patch
---

feature: allowing users to specify a description when creating an event notification rule
255 changes: 254 additions & 1 deletion packages/wrangler/src/__tests__/r2.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -998,6 +998,258 @@ describe("r2", () => {
`);
});

it("follows happy path as expected with prefix", async () => {
const eventTypes: R2EventType[] = ["object-create", "object-delete"];
const actions: R2EventableOperation[] = [];
const bucketName = "my-bucket";
const queue = "my-queue";

const config: PutNotificationRequestBody = {
rules: [
{
actions: eventTypes.reduce(
(acc, et) => acc.concat(actionsForEventCategories[et]),
actions
),
prefix: "ruleprefix",
},
],
};
msw.use(
http.put(
"*/accounts/:accountId/event_notifications/r2/:bucketName/configuration/queues/:queueUUID",
async ({ request, params }) => {
const { accountId } = params;
expect(accountId).toEqual("some-account-id");
expect(await request.json()).toEqual({
...config,
// We fill in `prefix` & `suffix` with empty strings if not
// provided
rules: [{ ...config.rules[0], suffix: "" }],
});
expect(request.headers.get("authorization")).toEqual(
"Bearer some-api-token"
);
return HttpResponse.json(createFetchResult({}));
},
{ once: true }
),
http.get(
"*/accounts/:accountId/queues?*",
async ({ request, params }) => {
const url = new URL(request.url);
const { accountId } = params;
const nameParams = url.searchParams.getAll("name");

expect(accountId).toEqual("some-account-id");
expect(nameParams[0]).toEqual(queue);
expect(request.headers.get("authorization")).toEqual(
"Bearer some-api-token"
);
return HttpResponse.json({
success: true,
errors: [],
messages: [],
result: [
{
queue_id: "queue-id",
queue_name: queue,
created_on: "",
producers: [],
consumers: [],
producers_total_count: 1,
consumers_total_count: 0,
modified_on: "",
},
],
});
},
{ once: true }
)
);
await expect(
runWrangler(
`r2 bucket notification create ${bucketName} --queue ${queue} --event-types ${eventTypes.join(
" "
)} --prefix "ruleprefix"`
)
).resolves.toBe(undefined);
expect(std.out).toMatchInlineSnapshot(`
"Creating event notification rule for object creation and deletion (PutObject,CompleteMultipartUpload,CopyObject,DeleteObject,LifecycleDeletion)
Event notification rule created successfully!"
`);
});

it("follows happy path as expected with suffix", async () => {
const eventTypes: R2EventType[] = ["object-create", "object-delete"];
const actions: R2EventableOperation[] = [];
const bucketName = "my-bucket";
const queue = "my-queue";

const config: PutNotificationRequestBody = {
rules: [
{
actions: eventTypes.reduce(
(acc, et) => acc.concat(actionsForEventCategories[et]),
actions
),
suffix: "rulesuffix",
},
],
};
msw.use(
http.put(
"*/accounts/:accountId/event_notifications/r2/:bucketName/configuration/queues/:queueUUID",
async ({ request, params }) => {
const { accountId } = params;
expect(accountId).toEqual("some-account-id");
expect(await request.json()).toEqual({
...config,
// We fill in `prefix` & `suffix` with empty strings if not
// provided
rules: [{ ...config.rules[0], prefix: "" }],
});
expect(request.headers.get("authorization")).toEqual(
"Bearer some-api-token"
);
return HttpResponse.json(createFetchResult({}));
},
{ once: true }
),
http.get(
"*/accounts/:accountId/queues?*",
async ({ request, params }) => {
const url = new URL(request.url);
const { accountId } = params;
const nameParams = url.searchParams.getAll("name");

expect(accountId).toEqual("some-account-id");
expect(nameParams[0]).toEqual(queue);
expect(request.headers.get("authorization")).toEqual(
"Bearer some-api-token"
);
return HttpResponse.json({
success: true,
errors: [],
messages: [],
result: [
{
queue_id: "queue-id",
queue_name: queue,
created_on: "",
producers: [],
consumers: [],
producers_total_count: 1,
consumers_total_count: 0,
modified_on: "",
},
],
});
},
{ once: true }
)
);
await expect(
runWrangler(
`r2 bucket notification create ${bucketName} --queue ${queue} --event-types ${eventTypes.join(
" "
)} --suffix "rulesuffix"`
)
).resolves.toBe(undefined);
expect(std.out).toMatchInlineSnapshot(`
"Creating event notification rule for object creation and deletion (PutObject,CompleteMultipartUpload,CopyObject,DeleteObject,LifecycleDeletion)
Event notification rule created successfully!"
`);
});

it("follows happy path as expected with description", async () => {
const eventTypes: R2EventType[] = ["object-create", "object-delete"];
const actions: R2EventableOperation[] = [];
const bucketName = "my-bucket";
const queue = "my-queue";

const config: PutNotificationRequestBody = {
rules: [
{
actions: eventTypes.reduce(
(acc, et) => acc.concat(actionsForEventCategories[et]),
actions
),
description: "rule description",
},
],
};
msw.use(
http.put(
"*/accounts/:accountId/event_notifications/r2/:bucketName/configuration/queues/:queueUUID",
async ({ request, params }) => {
const { accountId } = params;
expect(accountId).toEqual("some-account-id");
expect(await request.json()).toEqual({
...config,
// We fill in `prefix` & `suffix` with empty strings if not
// provided
rules: [
{
...config.rules[0],
prefix: "",
suffix: "",
},
],
});
expect(request.headers.get("authorization")).toEqual(
"Bearer some-api-token"
);
return HttpResponse.json(createFetchResult({}));
},
{ once: true }
),
http.get(
"*/accounts/:accountId/queues?*",
async ({ request, params }) => {
const url = new URL(request.url);
const { accountId } = params;
const nameParams = url.searchParams.getAll("name");

expect(accountId).toEqual("some-account-id");
expect(nameParams[0]).toEqual(queue);
expect(request.headers.get("authorization")).toEqual(
"Bearer some-api-token"
);
return HttpResponse.json({
success: true,
errors: [],
messages: [],
result: [
{
queue_id: "queue-id",
queue_name: queue,
created_on: "",
producers: [],
consumers: [],
producers_total_count: 1,
consumers_total_count: 0,
modified_on: "",
},
],
});
},
{ once: true }
)
);
await expect(
runWrangler(
`r2 bucket notification create ${bucketName} --queue ${queue} --event-types ${eventTypes.join(
" "
)} --description "rule description"`
)
).resolves.toBe(undefined);
expect(std.out).toMatchInlineSnapshot(`
"Creating event notification rule for object creation and deletion (PutObject,CompleteMultipartUpload,CopyObject,DeleteObject,LifecycleDeletion)
Event notification rule created successfully!"
`);
});

it("errors if required options are not provided", async () => {
await expect(
runWrangler("r2 bucket notification create notification-test-001")
Expand All @@ -1024,7 +1276,8 @@ describe("r2", () => {
--event-types, --event-type The type of event(s) that will emit event notifications [array] [required] [choices: \\"object-create\\", \\"object-delete\\"]
--prefix The prefix that an object must match to emit event notifications (note: regular expressions not supported) [string]
--suffix The suffix that an object must match to emit event notifications (note: regular expressions not supported) [string]
--queue The name of the queue that will receive event notification messages [string] [required]"
--queue The name of the queue that will receive event notification messages [string] [required]
--description Description of the rule [string]"
`);
});
});
Expand Down
15 changes: 11 additions & 4 deletions packages/wrangler/src/r2/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,7 @@ type NotificationRule = {
prefix?: string;
suffix?: string;
actions: R2EventableOperation[];
description?: string;
};
type GetNotificationRule = {
ruleId: string;
Expand Down Expand Up @@ -544,7 +545,8 @@ export async function putEventNotificationConfig(
queueName: string,
eventTypes: R2EventType[],
prefix?: string,
suffix?: string
suffix?: string,
description?: string
): Promise<void> {
const queue = await getQueue(config, queueName);
const headers = eventNotificationHeaders(apiCredentials);
Expand All @@ -554,9 +556,14 @@ export async function putEventNotificationConfig(
actions = actions.concat(actionsForEventCategories[et]);
}

const body: PutNotificationRequestBody = {
rules: [{ prefix, suffix, actions }],
};
const body: PutNotificationRequestBody =
description === undefined
? {
rules: [{ prefix, suffix, actions }],
}
: {
rules: [{ prefix, suffix, actions, description }],
};
const ruleFor = eventTypes.map((et) =>
et === "object-create" ? "creation" : "deletion"
);
Expand Down
16 changes: 14 additions & 2 deletions packages/wrangler/src/r2/notification.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ export function CreateOptions(yargs: CommonYargsArgv) {
demandOption: true,
requiresArg: true,
type: "string",
})
.option("description", {
describe: "Description of the rule",
type: "string",
});
}

Expand All @@ -89,7 +93,14 @@ export async function CreateHandler(
const config = readConfig(args.config, args);
const accountId = await requireAuth(config);
const apiCreds = requireApiToken();
const { bucket, queue, eventTypes, prefix = "", suffix = "" } = args;
const {
bucket,
queue,
eventTypes,
prefix = "",
suffix = "",
description,
} = args;
await putEventNotificationConfig(
config,
apiCreds,
Expand All @@ -98,7 +109,8 @@ export async function CreateHandler(
queue,
eventTypes as R2EventType[],
prefix,
suffix
suffix,
description
);
logger.log("Event notification rule created successfully!");
}
Expand Down

0 comments on commit 54c9ce6

Please sign in to comment.