Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add jurisdiction option to R2 event notification wrangler actions #6945

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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: "test@example.com",
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
Loading