Skip to content

Commit

Permalink
wrangler: Improve hyperdrive create and update to include all current…
Browse files Browse the repository at this point in the history
… caching settings (#5064)

Overruling the GitGuardian false positive that we cannot work out how to turn off.
  • Loading branch information
OilyLime committed Mar 14, 2024
1 parent 03484c2 commit bd935cf
Show file tree
Hide file tree
Showing 6 changed files with 299 additions and 90 deletions.
5 changes: 5 additions & 0 deletions .changeset/strong-drinks-burn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"wrangler": minor
---

feature: Improve create and update logic for hyperdrive to include caching settings
4 changes: 4 additions & 0 deletions .gitguardian.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
version: 2
secret:
ignored-paths:
- "packages/wrangler/src/__tests__/hyperdrive.test.ts"
243 changes: 185 additions & 58 deletions packages/wrangler/src/__tests__/hyperdrive.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { useMockIsTTY } from "./helpers/mock-istty";
import { createFetchResult, msw } from "./helpers/msw";
import { runInTempDir } from "./helpers/run-in-tmp";
import { runWrangler } from "./helpers/run-wrangler";
import type { HyperdriveConfig } from "../hyperdrive/client";

describe("hyperdrive help", () => {
const std = mockConsoleMethods();
Expand Down Expand Up @@ -106,16 +107,16 @@ describe("hyperdrive commands", () => {
it("should handle creating a hyperdrive config", async () => {
mockHyperdriveRequest();
await runWrangler(
"hyperdrive create test123 --connection-string='postgresql://test:password@foo.us-east-2.aws.neon.tech:12345/neondb'"
"hyperdrive create test123 --connection-string='postgresql://test:password@example.com:12345/neondb'"
);
expect(std.out).toMatchInlineSnapshot(`
"🚧 Creating 'test123'
✅ Created new Hyperdrive config
{
\\"id\\": \\"7a040c1eee714e91a30ea6707a2d125c\\",
\\"id\\": \\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\\",
\\"name\\": \\"test123\\",
\\"origin\\": {
\\"host\\": \\"foo.us-east-2.aws.neon.tech\\",
\\"host\\": \\"example.com\\",
\\"port\\": 12345,
\\"database\\": \\"neondb\\",
\\"user\\": \\"test\\"
Expand All @@ -130,16 +131,16 @@ describe("hyperdrive commands", () => {
it("should handle creating a hyperdrive config for postgres without a port specified", async () => {
mockHyperdriveRequest();
await runWrangler(
"hyperdrive create test123 --connection-string='postgresql://test:password@foo.us-east-2.aws.neon.tech/neondb'"
"hyperdrive create test123 --connection-string='postgresql://test:password@example.com/neondb'"
);
expect(std.out).toMatchInlineSnapshot(`
"🚧 Creating 'test123'
✅ Created new Hyperdrive config
{
\\"id\\": \\"7a040c1eee714e91a30ea6707a2d125c\\",
\\"id\\": \\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\\",
\\"name\\": \\"test123\\",
\\"origin\\": {
\\"host\\": \\"foo.us-east-2.aws.neon.tech\\",
\\"host\\": \\"example.com\\",
\\"port\\": 5432,
\\"database\\": \\"neondb\\",
\\"user\\": \\"test\\"
Expand All @@ -151,30 +152,56 @@ describe("hyperdrive commands", () => {
`);
});

it("should handle creating a hyperdrive config with caching options", async () => {
mockHyperdriveRequest();
await runWrangler(
"hyperdrive create test123 --connection-string='postgresql://test:password@example.com:12345/neondb' --max-age=30 --swr=15"
);
expect(std.out).toMatchInlineSnapshot(`
"🚧 Creating 'test123'
✅ Created new Hyperdrive config
{
\\"id\\": \\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\\",
\\"name\\": \\"test123\\",
\\"origin\\": {
\\"host\\": \\"example.com\\",
\\"port\\": 12345,
\\"database\\": \\"neondb\\",
\\"user\\": \\"test\\"
},
\\"caching\\": {
\\"disabled\\": false,
\\"maxAge\\": 30,
\\"staleWhileRevalidate\\": 15
}
}"
`);
});

it("should handle listing configs", async () => {
mockHyperdriveRequest();
await runWrangler("hyperdrive list");
expect(std.out).toMatchInlineSnapshot(`
"📋 Listing Hyperdrive configs
┌───────────────────────────────────────────┬────────┬─────────────────────────────┬──────┬──────────┬────────────────────┐
│ id │ name │ user │ host │ port │ database │ caching │
├───────────────────────────────────────────┼────────┼─────────────────────────────┼──────┼──────────┼────────────────────┤
fb94f15a95ce4afa803bb21794b2802cnew-db │ dbuser │ database.server.com │ 3211mydb │ {\\"disabled\\":false} │
├───────────────────────────────────────────┼────────┼─────────────────────────────┼──────┼──────────┼────────────────────┤
7a040c1eee714e91a30ea6707a2d125ctest123 │ test │ foo.us-east-2.aws.neon.tech5432neondb │ {\\"disabled\\":false} │
└───────────────────────────────────────────┴────────┴─────────────────────────────┴──────┴──────────┴────────────────────┘"
┌──────────────────────────────────────┬────────┬────────────────────────┬──────┬──────────┬────────────────────┐
│ id │ name │ user │ host │ port │ database │ caching │
├──────────────────────────────────────┼────────┼────────────────────────┼──────┼──────────┼────────────────────┤
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxtest123 │ test │ example.com │ 5432neondb │ {\\"disabled\\":false} │
├──────────────────────────────────────┼────────┼────────────────────────┼──────┼──────────┼────────────────────┤
yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyynew-db │ dbuser │ www.google.com3211mydb │ {\\"disabled\\":false} │
└──────────────────────────────────────┴────────┴────────────────────────┴──────┴──────────┴────────────────────┘"
`);
});

it("should handle displaying a config", async () => {
mockHyperdriveRequest();
await runWrangler("hyperdrive get 7a040c1eee714e91a30ea6707a2d125c");
await runWrangler("hyperdrive get xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx");
expect(std.out).toMatchInlineSnapshot(`
"{
\\"id\\": \\"7a040c1eee714e91a30ea6707a2d125c\\",
\\"id\\": \\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\\",
\\"name\\": \\"test123\\",
\\"origin\\": {
\\"host\\": \\"foo.us-east-2.aws.neon.tech\\",
\\"host\\": \\"example.com\\",
\\"port\\": 5432,
\\"database\\": \\"neondb\\",
\\"user\\": \\"test\\"
Expand All @@ -188,62 +215,174 @@ describe("hyperdrive commands", () => {

it("should handle deleting a config", async () => {
mockHyperdriveRequest();
await runWrangler("hyperdrive delete 7a040c1eee714e91a30ea6707a2d125c");
await runWrangler("hyperdrive delete xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx");
expect(std.out).toMatchInlineSnapshot(`
"🗑️ Deleting Hyperdrive database config 7a040c1eee714e91a30ea6707a2d125c
"🗑️ Deleting Hyperdrive database config xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
✅ Deleted"
`);
});

it("should handle updating a hyperdrive config's origin", async () => {
mockHyperdriveRequest();
await runWrangler(
"hyperdrive update xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx --origin-host=example.com --origin-port=1234 --database=mydb --origin-user=newuser --origin-password='passw0rd!'"
);
expect(std.out).toMatchInlineSnapshot(`
"🚧 Updating 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
✅ Updated xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Hyperdrive config
{
\\"id\\": \\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\\",
\\"name\\": \\"test123\\",
\\"origin\\": {
\\"host\\": \\"example.com\\",
\\"port\\": 1234,
\\"database\\": \\"mydb\\",
\\"user\\": \\"newuser\\"
},
\\"caching\\": {
\\"disabled\\": false
}
}"
`);
});

it("should throw an exception when updating a hyperdrive config's origin but not all fields are set", async () => {
mockHyperdriveRequest();
await expect(() =>
runWrangler(
"hyperdrive update xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx --origin-port=1234 --database=mydb --origin-user=newuser"
)
).rejects.toThrow();
expect(std.err).toMatchInlineSnapshot(`
"X [ERROR] When updating the origin, all of the following must be set: origin-host, origin-port, database, origin-user, origin-password
"
`);
expect(std.out).toMatchInlineSnapshot(`
"
If you think this is a bug then please create an issue at https://github.com/cloudflare/workers-sdk/issues/new/choose"
`);
});

it("should handle updating a hyperdrive config's caching settings", async () => {
mockHyperdriveRequest();
await runWrangler(
"hyperdrive update xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx --max-age=30 --swr=15"
);
expect(std.out).toMatchInlineSnapshot(`
"🚧 Updating 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
✅ Updated xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Hyperdrive config
{
\\"id\\": \\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\\",
\\"name\\": \\"test123\\",
\\"origin\\": {
\\"host\\": \\"example.com\\",
\\"port\\": 5432,
\\"database\\": \\"neondb\\",
\\"user\\": \\"test\\"
},
\\"caching\\": {
\\"disabled\\": false,
\\"maxAge\\": 30,
\\"staleWhileRevalidate\\": 15
}
}"
`);
});

it("should handle updating a hyperdrive config's name", async () => {
mockHyperdriveRequest();
await runWrangler(
"hyperdrive update xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx --name='new-name'"
);
expect(std.out).toMatchInlineSnapshot(`
"🚧 Updating 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
✅ Updated xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Hyperdrive config
{
\\"id\\": \\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\\",
\\"name\\": \\"new-name\\",
\\"origin\\": {
\\"host\\": \\"example.com\\",
\\"port\\": 5432,
\\"database\\": \\"neondb\\",
\\"user\\": \\"test\\"
},
\\"caching\\": {
\\"disabled\\": false
}
}"
`);
});
});

const defaultConfig: HyperdriveConfig = {
id: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
name: "test123",
origin: {
host: "example.com",
port: 5432,
database: "neondb",
user: "test",
},
caching: {
disabled: false,
},
};

/** Create a mock handler for Hyperdrive API */
function mockHyperdriveRequest() {
msw.use(
rest.get(
"*/accounts/:accountId/hyperdrive/configs/7a040c1eee714e91a30ea6707a2d125c",
"*/accounts/:accountId/hyperdrive/configs/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
(req, res, ctx) => {
return res.once(ctx.json(createFetchResult(defaultConfig, true)));
}
),
rest.post(
"*/accounts/:accountId/hyperdrive/configs",
async (req, res, ctx) => {
const reqBody = await req.json();
return res.once(
ctx.json(
createFetchResult(
{
id: "7a040c1eee714e91a30ea6707a2d125c",
name: "test123",
id: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
name: reqBody.name,
origin: {
host: "foo.us-east-2.aws.neon.tech",
port: 5432,
database: "neondb",
user: "test",
},
caching: {
disabled: false,
host: reqBody.origin.host,
port: reqBody.origin.port,
database: reqBody.origin.database,
scheme: reqBody.origin.protocol,
user: reqBody.origin.user,
},
caching: reqBody.caching,
},

true
)
)
);
}
),
rest.post(
"*/accounts/:accountId/hyperdrive/configs",
rest.patch(
"*/accounts/:accountId/hyperdrive/configs/:configId",
async (req, res, ctx) => {
const reqBody = await req.json();
return res.once(
ctx.json(
createFetchResult(
{
id: "7a040c1eee714e91a30ea6707a2d125c",
name: "test123",
origin: {
host: "foo.us-east-2.aws.neon.tech",
port: reqBody.origin.port,
database: "neondb",
user: "test",
},
caching: {
disabled: false,
},
id: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
name: reqBody.name ?? defaultConfig.name,
origin:
reqBody.origin !== undefined
? {
host: reqBody.origin.host,
port: reqBody.origin.port,
database: reqBody.origin.database,
user: reqBody.origin.user,
}
: defaultConfig.origin,
caching: reqBody.caching ?? defaultConfig.caching,
},
true
)
Expand All @@ -252,7 +391,7 @@ function mockHyperdriveRequest() {
}
),
rest.delete(
"*/accounts/:accountId/hyperdrive/configs/7a040c1eee714e91a30ea6707a2d125c",
"*/accounts/:accountId/hyperdrive/configs/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
(req, res, ctx) => {
return res.once(ctx.json(createFetchResult(null, true)));
}
Expand All @@ -262,11 +401,12 @@ function mockHyperdriveRequest() {
ctx.json(
createFetchResult(
[
defaultConfig,
{
id: "fb94f15a95ce4afa803bb21794b2802c",
id: "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy",
name: "new-db",
origin: {
host: "database.server.com",
host: "www.google.com",
port: 3211,
database: "mydb",
user: "dbuser",
Expand All @@ -275,19 +415,6 @@ function mockHyperdriveRequest() {
disabled: false,
},
},
{
id: "7a040c1eee714e91a30ea6707a2d125c",
name: "test123",
origin: {
host: "foo.us-east-2.aws.neon.tech",
port: 5432,
database: "neondb",
user: "test",
},
caching: {
disabled: false,
},
},
],
true
)
Expand Down

0 comments on commit bd935cf

Please sign in to comment.