Skip to content

Commit

Permalink
improve(r2): Update Sippy endpoint request payloads to match new schema
Browse files Browse the repository at this point in the history
  • Loading branch information
sdnts committed Feb 7, 2024
1 parent e61dba5 commit b816018
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 73 deletions.
5 changes: 5 additions & 0 deletions .changeset/five-cooks-share.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"wrangler": patch
---

Update API calls for Sippy's endpoints
58 changes: 34 additions & 24 deletions packages/wrangler/src/__tests__/r2.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ describe("r2", () => {
runWrangler("r2 bucket foo")
).rejects.toThrowErrorMatchingInlineSnapshot(`"Unknown argument: foo"`);
expect(std.err).toMatchInlineSnapshot(`
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mUnknown argument: foo[0m
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mUnknown argument: foo[0m
"
`);
Expand Down Expand Up @@ -117,7 +117,7 @@ describe("r2", () => {
-J, --jurisdiction The jurisdiction where the new bucket will be created [string]"
`);
expect(std.err).toMatchInlineSnapshot(`
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mNot enough non-option arguments: got 0, need at least 1[0m
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mNot enough non-option arguments: got 0, need at least 1[0m
"
`);
Expand Down Expand Up @@ -149,7 +149,7 @@ describe("r2", () => {
-J, --jurisdiction The jurisdiction where the new bucket will be created [string]"
`);
expect(std.err).toMatchInlineSnapshot(`
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mUnknown arguments: def, ghi[0m
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mUnknown arguments: def, ghi[0m
"
`);
Expand Down Expand Up @@ -222,7 +222,7 @@ describe("r2", () => {
-J, --jurisdiction The jurisdiction where the bucket exists [string]"
`);
expect(std.err).toMatchInlineSnapshot(`
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mNot enough non-option arguments: got 0, need at least 1[0m
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mNot enough non-option arguments: got 0, need at least 1[0m
"
`);
Expand Down Expand Up @@ -254,7 +254,7 @@ describe("r2", () => {
-J, --jurisdiction The jurisdiction where the bucket exists [string]"
`);
expect(std.err).toMatchInlineSnapshot(`
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mUnknown arguments: def, ghi[0m
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mUnknown arguments: def, ghi[0m
"
`);
Expand Down Expand Up @@ -293,7 +293,7 @@ describe("r2", () => {
runWrangler("r2 bucket sippy foo")
).rejects.toThrowErrorMatchingInlineSnapshot(`"Unknown argument: foo"`);
expect(std.err).toMatchInlineSnapshot(`
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mUnknown argument: foo[0m
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mUnknown argument: foo[0m
"
`);
Expand Down Expand Up @@ -326,19 +326,24 @@ describe("r2", () => {
"*/accounts/some-account-id/r2/buckets/testBucket/sippy",
async (request, response, context) => {
expect(await request.json()).toEqual({
access_key: "aws-secret",
bucket: "awsBucket",
key_id: "aws-key",
provider: "AWS",
r2_access_key: "some-secret",
r2_key_id: "some-key",
source: {
provider: "aws",
bucket: "awsBucket",
accessKeyId: "aws-key",
secretAccessKey: "aws-secret",
},
destination: {
provider: "r2",
accessKeyId: "some-key",
secretAccessKey: "some-secret",
},
});
return response.once(context.json(createFetchResult({})));
}
)
);
await runWrangler(
"r2 bucket sippy enable testBucket --r2-key-id=some-key --r2-secret-access-key=some-secret --provider=AWS --key-id=aws-key --secret-access-key=aws-secret --bucket=awsBucket"
"r2 bucket sippy enable testBucket --r2-access-key-id=some-key --r2-secret-access-key=some-secret --provider=AWS --key-id=aws-key --secret-access-key=aws-secret --bucket=awsBucket"
);
expect(std.out).toMatchInlineSnapshot(
`"✨ Successfully enabled Sippy on the 'testBucket' bucket."`
Expand All @@ -353,19 +358,24 @@ describe("r2", () => {
"*/accounts/some-account-id/r2/buckets/testBucket/sippy",
async (request, response, context) => {
expect(await request.json()).toEqual({
private_key: "gcs-private-key",
bucket: "gcsBucket",
client_email: "gcs-client-email",
provider: "GCS",
r2_access_key: "some-secret",
r2_key_id: "some-key",
source: {
provider: "gcs",
bucket: "gcsBucket",
clientEmail: "gcs-client-email",
privateKey: "gcs-private-key",
},
destination: {
provider: "r2",
accessKeyId: "some-key",
secretAccessKey: "some-secret",
},
});
return response.once(context.json(createFetchResult({})));
}
)
);
await runWrangler(
"r2 bucket sippy enable testBucket --r2-key-id=some-key --r2-secret-access-key=some-secret --provider=GCS --client-email=gcs-client-email --private-key=gcs-private-key --bucket=gcsBucket"
"r2 bucket sippy enable testBucket --r2-access-key-id=some-key --r2-secret-access-key=some-secret --provider=GCS --client-email=gcs-client-email --private-key=gcs-private-key --bucket=gcsBucket"
);
expect(std.out).toMatchInlineSnapshot(
`"✨ Successfully enabled Sippy on the 'testBucket' bucket."`
Expand Down Expand Up @@ -408,7 +418,7 @@ describe("r2", () => {
--r2-secret-access-key The secret access key for this R2 bucket [string]"
`);
expect(std.err).toMatchInlineSnapshot(`
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mNot enough non-option arguments: got 0, need at least 1[0m
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mNot enough non-option arguments: got 0, need at least 1[0m
"
`);
Expand Down Expand Up @@ -442,7 +452,7 @@ describe("r2", () => {
-J, --jurisdiction The jurisdiction where the bucket exists [string]"
`);
expect(std.err).toMatchInlineSnapshot(`
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mNot enough non-option arguments: got 0, need at least 1[0m
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mNot enough non-option arguments: got 0, need at least 1[0m
"
`);
Expand Down Expand Up @@ -493,7 +503,7 @@ describe("r2", () => {
-J, --jurisdiction The jurisdiction where the bucket exists [string]"
`);
expect(std.err).toMatchInlineSnapshot(`
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mNot enough non-option arguments: got 0, need at least 1[0m
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mNot enough non-option arguments: got 0, need at least 1[0m
"
`);
Expand Down Expand Up @@ -658,7 +668,7 @@ describe("r2", () => {
);

expect(std.err).toMatchInlineSnapshot(`
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mArguments pipe and file are mutually exclusive[0m
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mArguments pipe and file are mutually exclusive[0m
"
`);
Expand Down
39 changes: 21 additions & 18 deletions packages/wrangler/src/r2/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,26 +260,27 @@ export async function deleteR2Sippy(
);
}

export type R2Credentials = {
bucket: string;
r2_key_id: string;
r2_access_key: string;
};

export type SippyPutConfig = R2Credentials &
(
export type SippyPutConfig = {
source:
| {
provider: "AWS";
zone: string | undefined;
key_id: string;
access_key: string;
provider: "aws";
region: string;
bucket: string;
accessKeyId: string;
secretAccessKey: string;
}
| {
provider: "GCS";
client_email: string;
private_key: string;
}
);
provider: "gcs";
bucket: string;
clientEmail: string;
privateKey: string;
};
destination: {
provider: "r2";
accessKeyId: string;
secretAccessKey: string;
};
};

/**
* Enable sippy on the bucket with the given name
Expand All @@ -290,7 +291,9 @@ export async function putR2Sippy(
config: SippyPutConfig,
jurisdiction?: string
): Promise<void> {
const headers: HeadersInit = {};
const headers: HeadersInit = {
"Content-Type": "application/json",
};
if (jurisdiction !== undefined) {
headers["cf-r2-jurisdiction"] = jurisdiction;
}
Expand Down
74 changes: 43 additions & 31 deletions packages/wrangler/src/r2/sippy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import type {
import type { SippyPutConfig } from "./helpers";

const NO_SUCH_OBJECT_KEY = 10007;
const SIPPY_PROVIDER_CHOICES = ["AWS", "GCS"];
const SIPPY_PROVIDER_CHOICES = ["aws", "gcs"];

export function EnableOptions(yargs: CommonYargsArgv) {
return yargs
Expand All @@ -38,7 +38,7 @@ export function EnableOptions(yargs: CommonYargsArgv) {
description: "(AWS provider only) The region of the upstream bucket",
string: true,
})
.option("key-id", {
.option("access-key-id", {
description:
"(AWS provider only) The secret access key id for the upstream bucket",
string: true,
Expand All @@ -63,7 +63,7 @@ export function EnableOptions(yargs: CommonYargsArgv) {
"(GCS provider only) The private key for your Google Cloud service account key",
string: true,
})
.option("r2-key-id", {
.option("r2-access-key-id", {
description: "The secret access key id for this R2 bucket",
string: true,
})
Expand Down Expand Up @@ -97,14 +97,14 @@ export async function EnableHandler(
throw new UserError(`Must specify ${args.provider} bucket name.`);
}

if (args.provider == "AWS") {
if (args.provider === "AWS") {
args.region ??= await prompt(
"Enter the AWS region where your S3 bucket is located (example: us-west-2):"
);
args.keyId ??= await prompt(
args.accessKeyId ??= await prompt(
"Enter your AWS Access Key ID (requires read and list access):"
);
if (!args.keyId) {
if (!args.accessKeyId) {
throw new UserError("Must specify an AWS Access Key ID.");
}
args.secretAccessKey ??= await prompt(
Expand All @@ -113,7 +113,7 @@ export async function EnableHandler(
if (!args.secretAccessKey) {
throw new UserError("Must specify an AWS Secret Access Key.");
}
} else if (args.provider == "GCS") {
} else if (args.provider === "GCS") {
if (
!(args.clientEmail && args.privateKey) &&
!args.serviceAccountKeyFile
Expand All @@ -129,10 +129,10 @@ export async function EnableHandler(
}
}

args.r2KeyId ??= await prompt(
args.r2AccessKeyId ??= await prompt(
"Enter your R2 Access Key ID (requires read and write access):"
);
if (!args.r2KeyId) {
if (!args.r2AccessKeyId) {
throw new UserError("Must specify an R2 Access Key ID.");
}
args.r2SecretAccessKey ??= await prompt("Enter your R2 Secret Access Key:");
Expand All @@ -141,46 +141,58 @@ export async function EnableHandler(
}
}

let sippyConfig = {
bucket: args.bucket ?? "",
r2_key_id: args.r2KeyId ?? "",
r2_access_key: args.r2SecretAccessKey ?? "",
} as SippyPutConfig;
let sippyConfig: SippyPutConfig;

if (args.provider == "AWS") {
if (!(args.keyId && args.secretAccessKey)) {
if (args.provider === "AWS") {
if (!(args.accessKeyId && args.secretAccessKey)) {
throw new UserError(
`Error: must provide --key-id and --secret-access-key.`
"Error: must provide --access-key-id and --secret-access-key."
);
}

sippyConfig = {
...sippyConfig,
provider: "AWS",
zone: args.region,
key_id: args.keyId,
access_key: args.secretAccessKey,
source: {
provider: "aws",
region: args.region,
bucket: args.bucket,
accessKeyId: args.accessKeyId,
secretAccessKey: args.secretAccessKey,
},
destination: {
provider: "r2",
accessKeyId: args.r2AccessKeyId,
secretAccessKey: args.r2SecretAccessKey,
},
};
} else if (args.provider == "GCS") {
} else if (args.provider === "GCS") {
if (args.serviceAccountKeyFile) {
const serviceAccount = JSON.parse(
readFileSync(args.serviceAccountKeyFile)
);
if ("client_email" in serviceAccount && "private_key" in serviceAccount) {
args.clientEmail = serviceAccount["client_email"];
args.privateKey = serviceAccount["private_key"];
args.clientEmail = serviceAccount.client_email;
args.privateKey = serviceAccount.private_key;
}
}
if (!(args.clientEmail && args.privateKey)) {
throw new UserError(
`Error: must provide --service-account-key-file or --client-email and --private-key.`
"Error: must provide --service-account-key-file or --client-email and --private-key."
);
}
args.privateKey = args.privateKey.replace(/\\n/g, "\n");

sippyConfig = {
...sippyConfig,
provider: "GCS",
client_email: args.clientEmail,
private_key: args.privateKey,
source: {
provider: "gcs",
bucket: args.bucket,
clientEmail: args.clientEmail,
privateKey: args.privateKey,
},
destination: {
provider: "r2",
accessKeyId: args.r2AccessKeyId,
secretAccessKey: args.r2SecretAccessKey,
},
};
}

Expand Down Expand Up @@ -218,7 +230,7 @@ export async function GetHandler(
);
logger.log(`Sippy upstream bucket: ${sippyBucket}.`);
} catch (e) {
if (e instanceof APIError && "code" in e && e.code == NO_SUCH_OBJECT_KEY) {
if (e instanceof APIError && "code" in e && e.code === NO_SUCH_OBJECT_KEY) {
logger.log(`No Sippy configuration found for the '${args.name}' bucket.`);
} else {
throw e;
Expand Down

0 comments on commit b816018

Please sign in to comment.