Skip to content

Commit

Permalink
Add jurisdiction option to R2 event notification wrangler actions (#6945
Browse files Browse the repository at this point in the history
)
  • Loading branch information
bthwaites authored Oct 22, 2024
1 parent 127615a commit 6b97353
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 19 deletions.
5 changes: 5 additions & 0 deletions .changeset/tasty-jeans-train.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"wrangler": minor
---

Add jurisdiction option to R2 event notification wrangler actions
14 changes: 10 additions & 4 deletions packages/wrangler/src/__tests__/r2.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -912,7 +912,10 @@ describe("r2", () => {
-c, --config Path to .toml configuration file [string]
-e, --env Environment to use for operations and .env files [string]
-h, --help Show help [boolean]
-v, --version Show version number [boolean]"
-v, --version Show version number [boolean]
OPTIONS
-J, --jurisdiction The jurisdiction where the bucket exists [string]"
`);
});
});
Expand Down Expand Up @@ -1024,7 +1027,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]
-J, --jurisdiction The jurisdiction where the bucket exists [string]"
`);
});
});
Expand Down Expand Up @@ -1178,8 +1182,10 @@ describe("r2", () => {
-v, --version Show version number [boolean]
OPTIONS
--queue The name of the queue that corresponds to the event notification rule. If no rule is provided, all event notification rules associated with the bucket and queue will be deleted [string] [required]
--rule The ID of the event notification rule to delete [string]"
--queue The name of the queue that corresponds to the event notification rule. If no rule is provided, all event notification rules associated with the bucket and queue will be deleted [string] [required]
--rule The ID of the event notification rule to delete [string]
-J, --jurisdiction The jurisdiction where the bucket exists [string]"
`);
});
});
Expand Down
5 changes: 3 additions & 2 deletions packages/wrangler/src/__tests__/r2/helpers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ describe("event notifications", () => {
authEmail: "[email protected]",
authKey: "some-big-secret",
};
const result = eventNotificationHeaders(creds);
const result = eventNotificationHeaders(creds, "");
expect(result).toMatchObject({
"X-Auth-Key": creds.authKey,
"X-Auth-Email": creds.authEmail,
Expand All @@ -91,9 +91,10 @@ describe("event notifications", () => {

test("API token eventNotificationHeaders", () => {
const creds: ApiCredentials = { apiToken: "some-api-token" };
const result = eventNotificationHeaders(creds);
const result = eventNotificationHeaders(creds, "eu");
expect(result).toMatchObject({
Authorization: `Bearer ${creds.apiToken}`,
"cf-r2-jurisdiction": "eu",
});
});
});
17 changes: 12 additions & 5 deletions packages/wrangler/src/r2/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,8 @@ export type DeleteNotificationRequestBody = {
};

export function eventNotificationHeaders(
apiCredentials: ApiCredentials
apiCredentials: ApiCredentials,
jurisdiction: string
): HeadersInit {
const headers: HeadersInit = {
"Content-Type": "application/json",
Expand All @@ -435,6 +436,9 @@ export function eventNotificationHeaders(
headers["X-Auth-Key"] = apiCredentials.authKey;
headers["X-Auth-Email"] = apiCredentials.authEmail;
}
if (jurisdiction !== "") {
headers["cf-r2-jurisdiction"] = jurisdiction;
}
return headers;
}

Expand Down Expand Up @@ -486,9 +490,10 @@ export async function tableFromNotificationGetResponse(
export async function listEventNotificationConfig(
apiCredentials: ApiCredentials,
accountId: string,
bucketName: string
bucketName: string,
jurisdiction: string
): Promise<GetNotificationConfigResponse> {
const headers = eventNotificationHeaders(apiCredentials);
const headers = eventNotificationHeaders(apiCredentials, jurisdiction);
logger.log(`Fetching notification rules for bucket ${bucketName}...`);
const res = await fetchResult<GetNotificationConfigResponse>(
`/accounts/${accountId}/event_notifications/r2/${bucketName}/configuration`,
Expand Down Expand Up @@ -541,13 +546,14 @@ export async function putEventNotificationConfig(
apiCredentials: ApiCredentials,
accountId: string,
bucketName: string,
jurisdiction: string,
queueName: string,
eventTypes: R2EventType[],
prefix?: string,
suffix?: string
): Promise<void> {
const queue = await getQueue(config, queueName);
const headers = eventNotificationHeaders(apiCredentials);
const headers = eventNotificationHeaders(apiCredentials, jurisdiction);
let actions: R2EventableOperation[] = [];

for (const et of eventTypes) {
Expand Down Expand Up @@ -576,11 +582,12 @@ export async function deleteEventNotificationConfig(
apiCredentials: ApiCredentials,
accountId: string,
bucketName: string,
jurisdiction: string,
queueName: string,
ruleId: string | undefined
): Promise<null> {
const queue = await getQueue(config, queueName);
const headers = eventNotificationHeaders(apiCredentials);
const headers = eventNotificationHeaders(apiCredentials, jurisdiction);
if (ruleId !== undefined) {
logger.log(`Deleting event notifications rule "${ruleId}"...`);
const body: DeleteNotificationRequestBody =
Expand Down
46 changes: 38 additions & 8 deletions packages/wrangler/src/r2/notification.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,18 @@ import type {
import type { R2EventType } from "./helpers";

export function ListOptions(yargs: CommonYargsArgv) {
return yargs.positional("bucket", {
describe: "The name of the R2 bucket to get event notification rules for",
type: "string",
demandOption: true,
});
return yargs
.positional("bucket", {
describe: "The name of the R2 bucket to get event notification rules for",
type: "string",
demandOption: true,
})
.option("jurisdiction", {
describe: "The jurisdiction where the bucket exists",
alias: "J",
requiresArg: true,
type: "string",
});
}

export async function ListHandler(
Expand All @@ -37,10 +44,12 @@ export async function ListHandler(
const config = readConfig(args.config, args);
const accountId = await requireAuth(config);
const apiCreds = requireApiToken();
const { bucket, jurisdiction = "" } = args;
const resp = await listEventNotificationConfig(
apiCreds,
accountId,
`${args.bucket}`
bucket,
jurisdiction
);
const tableOutput = await tableFromNotificationGetResponse(config, resp);
logger.log(tableOutput.map((x) => formatLabelledValues(x)).join("\n\n"));
Expand Down Expand Up @@ -79,6 +88,12 @@ export function CreateOptions(yargs: CommonYargsArgv) {
demandOption: true,
requiresArg: true,
type: "string",
})
.option("jurisdiction", {
describe: "The jurisdiction where the bucket exists",
alias: "J",
requiresArg: true,
type: "string",
});
}

Expand All @@ -89,12 +104,20 @@ 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 = "",
jurisdiction = "",
} = args;
await putEventNotificationConfig(
config,
apiCreds,
accountId,
bucket,
jurisdiction,
queue,
eventTypes as R2EventType[],
prefix,
Expand Down Expand Up @@ -122,6 +145,12 @@ export function DeleteOptions(yargs: CommonYargsArgv) {
describe: "The ID of the event notification rule to delete",
requiresArg: false,
type: "string",
})
.option("jurisdiction", {
describe: "The jurisdiction where the bucket exists",
alias: "J",
requiresArg: true,
type: "string",
});
}

Expand All @@ -132,12 +161,13 @@ export async function DeleteHandler(
const config = readConfig(args.config, args);
const accountId = await requireAuth(config);
const apiCreds = requireApiToken();
const { bucket, queue, rule } = args;
const { bucket, queue, rule, jurisdiction = "" } = args;
await deleteEventNotificationConfig(
config,
apiCreds,
accountId,
bucket,
jurisdiction,
queue,
rule
);
Expand Down

0 comments on commit 6b97353

Please sign in to comment.