Skip to content

Commit

Permalink
Add private host option for private networks support in hyperdrive (#…
Browse files Browse the repository at this point in the history
…4932)

* Add private host option

* add tests and changeset, plus small improvements

* private_host not privateHost

* remove urlencoded username from e2e tests

* More private host changes

---------

Co-authored-by: Emilio Assuncao <emilio@cloudflare.com>
  • Loading branch information
xortive and OilyLime committed Mar 28, 2024
1 parent 3e5a932 commit dc0c1dc
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 25 deletions.
5 changes: 5 additions & 0 deletions .changeset/bright-planets-unite.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"wrangler": minor
---

feature: Add support for private networking in Hyperdrive configs
4 changes: 2 additions & 2 deletions packages/wrangler/e2e/dev.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,7 @@ describe("hyperdrive dev tests", () => {
[[hyperdrive]]
binding = "HYPERDRIVE"
id = "hyperdrive_id"
localConnectionString = "postgresql://user%3Aname:%21pass@127.0.0.1:${port}/some_db"
localConnectionString = "postgresql://user:%21pass@127.0.0.1:${port}/some_db"
`,
"src/index.ts": dedent`
export default {
Expand Down Expand Up @@ -516,7 +516,7 @@ describe("hyperdrive dev tests", () => {
);
const url = new URL(text);
expect(url.pathname).toBe("/some_db");
expect(url.username).toBe("user:name");
expect(url.username).toBe("user");
expect(url.password).toBe("!pass");
expect(url.host).not.toBe("localhost");
});
Expand Down
111 changes: 88 additions & 23 deletions packages/wrangler/src/__tests__/hyperdrive.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ describe("hyperdrive commands", () => {
it("should handle creating a hyperdrive config", async () => {
mockHyperdriveRequest();
await runWrangler(
"hyperdrive create test123 --connection-string='postgresql://test:password@example.com:12345/neondb'"
"hyperdrive create test123 --connection-string='postgresql://test:password@example.com:12345/database'"
);
expect(std.out).toMatchInlineSnapshot(`
"🚧 Creating 'test123'
Expand All @@ -118,8 +118,9 @@ describe("hyperdrive commands", () => {
\\"origin\\": {
\\"host\\": \\"example.com\\",
\\"port\\": 12345,
\\"database\\": \\"neondb\\",
\\"user\\": \\"test\\"
\\"database\\": \\"database\\",
\\"user\\": \\"test\\",
\\"private_host\\": false
},
\\"caching\\": {
\\"disabled\\": false
Expand All @@ -131,7 +132,7 @@ 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@example.com/neondb'"
"hyperdrive create test123 --connection-string='postgresql://test:password@example.com/database'"
);
expect(std.out).toMatchInlineSnapshot(`
"🚧 Creating 'test123'
Expand All @@ -142,8 +143,9 @@ describe("hyperdrive commands", () => {
\\"origin\\": {
\\"host\\": \\"example.com\\",
\\"port\\": 5432,
\\"database\\": \\"neondb\\",
\\"user\\": \\"test\\"
\\"database\\": \\"database\\",
\\"user\\": \\"test\\",
\\"private_host\\": false
},
\\"caching\\": {
\\"disabled\\": false
Expand All @@ -155,7 +157,7 @@ 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"
"hyperdrive create test123 --connection-string='postgresql://test:password@example.com:12345/database' --max-age=30 --swr=15"
);
expect(std.out).toMatchInlineSnapshot(`
"🚧 Creating 'test123'
Expand All @@ -166,8 +168,9 @@ describe("hyperdrive commands", () => {
\\"origin\\": {
\\"host\\": \\"example.com\\",
\\"port\\": 12345,
\\"database\\": \\"neondb\\",
\\"user\\": \\"test\\"
\\"database\\": \\"database\\",
\\"user\\": \\"test\\",
\\"private_host\\": false
},
\\"caching\\": {
\\"disabled\\": false,
Expand All @@ -178,6 +181,31 @@ describe("hyperdrive commands", () => {
`);
});

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

it("should handle creating a hyperdrive config if the user is URL encoded", async () => {
mockHyperdriveRequest();
await runWrangler(
Expand All @@ -193,7 +221,8 @@ describe("hyperdrive commands", () => {
\\"host\\": \\"example.com\\",
\\"port\\": 5432,
\\"database\\": \\"neondb\\",
\\"user\\": \\"user:name\\"
\\"user\\": \\"user:name\\",
\\"private_host\\": false
},
\\"caching\\": {
\\"disabled\\": false
Expand All @@ -217,7 +246,8 @@ describe("hyperdrive commands", () => {
\\"host\\": \\"example.com\\",
\\"port\\": 5432,
\\"database\\": \\"neondb\\",
\\"user\\": \\"test\\"
\\"user\\": \\"test\\",
\\"private_host\\": false
},
\\"caching\\": {
\\"disabled\\": false
Expand All @@ -241,7 +271,8 @@ describe("hyperdrive commands", () => {
\\"host\\": \\"example.com\\",
\\"port\\": 5432,
\\"database\\": \\"/\\"weird/\\" dbname\\",
\\"user\\": \\"test\\"
\\"user\\": \\"test\\",
\\"private_host\\": false
},
\\"caching\\": {
\\"disabled\\": false
Expand All @@ -258,7 +289,7 @@ describe("hyperdrive commands", () => {
┌──────────────────────────────────────┬─────────┬────────┬────────────────┬──────┬──────────┬────────────────────┐
│ id │ name │ user │ host │ port │ database │ caching │
├──────────────────────────────────────┼─────────┼────────┼────────────────┼──────┼──────────┼────────────────────┤
│ xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx │ test123 │ test │ example.com │ 5432 │ neondb │ {\\"disabled\\":false} │
│ xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx │ test123 │ test │ example.com │ 5432 │ database │ {\\"disabled\\":false} │
├──────────────────────────────────────┼─────────┼────────┼────────────────┼──────┼──────────┼────────────────────┤
│ yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy │ new-db │ dbuser │ www.google.com │ 3211 │ mydb │ {\\"disabled\\":false} │
└──────────────────────────────────────┴─────────┴────────┴────────────────┴──────┴──────────┴────────────────────┘"
Expand All @@ -275,8 +306,9 @@ describe("hyperdrive commands", () => {
\\"origin\\": {
\\"host\\": \\"example.com\\",
\\"port\\": 5432,
\\"database\\": \\"neondb\\",
\\"user\\": \\"test\\"
\\"database\\": \\"database\\",
\\"user\\": \\"test\\",
\\"private_host\\": false
},
\\"caching\\": {
\\"disabled\\": false
Expand Down Expand Up @@ -309,7 +341,33 @@ describe("hyperdrive commands", () => {
\\"host\\": \\"example.com\\",
\\"port\\": 1234,
\\"database\\": \\"mydb\\",
\\"user\\": \\"newuser\\"
\\"user\\": \\"newuser\\",
\\"private_host\\": false
},
\\"caching\\": {
\\"disabled\\": false
}
}"
`);
});

it("should handle updating a hyperdrive config's origin with private host", async () => {
mockHyperdriveRequest();
await runWrangler(
`hyperdrive update xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx --origin-host=private.example.com --origin-port=1234 --database=mydb --origin-user=newuser --origin-password='passw0rd!' --private-host=true`
);
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\\": \\"private.example.com\\",
\\"port\\": 1234,
\\"database\\": \\"mydb\\",
\\"user\\": \\"newuser\\",
\\"private_host\\": true
},
\\"caching\\": {
\\"disabled\\": false
Expand Down Expand Up @@ -347,8 +405,9 @@ describe("hyperdrive commands", () => {
\\"origin\\": {
\\"host\\": \\"example.com\\",
\\"port\\": 5432,
\\"database\\": \\"neondb\\",
\\"user\\": \\"test\\"
\\"database\\": \\"database\\",
\\"user\\": \\"test\\",
\\"private_host\\": false
},
\\"caching\\": {
\\"disabled\\": false,
Expand All @@ -373,8 +432,9 @@ describe("hyperdrive commands", () => {
\\"origin\\": {
\\"host\\": \\"example.com\\",
\\"port\\": 5432,
\\"database\\": \\"neondb\\",
\\"user\\": \\"test\\"
\\"database\\": \\"database\\",
\\"user\\": \\"test\\",
\\"private_host\\": false
},
\\"caching\\": {
\\"disabled\\": true
Expand All @@ -397,8 +457,9 @@ describe("hyperdrive commands", () => {
\\"origin\\": {
\\"host\\": \\"example.com\\",
\\"port\\": 5432,
\\"database\\": \\"neondb\\",
\\"user\\": \\"test\\"
\\"database\\": \\"database\\",
\\"user\\": \\"test\\",
\\"private_host\\": false
},
\\"caching\\": {
\\"disabled\\": false
Expand All @@ -414,8 +475,9 @@ const defaultConfig: HyperdriveConfig = {
origin: {
host: "example.com",
port: 5432,
database: "neondb",
database: "database",
user: "test",
private_host: false,
},
caching: {
disabled: false,
Expand Down Expand Up @@ -447,6 +509,7 @@ function mockHyperdriveRequest() {
database: reqBody.origin.database,
scheme: reqBody.origin.protocol,
user: reqBody.origin.user,
private_host: reqBody.origin.private_host,
},
caching: reqBody.caching,
},
Expand All @@ -473,6 +536,7 @@ function mockHyperdriveRequest() {
port: reqBody.origin.port,
database: reqBody.origin.database,
user: reqBody.origin.user,
private_host: reqBody.origin.private_host,
}
: defaultConfig.origin,
caching: reqBody.caching ?? defaultConfig.caching,
Expand Down Expand Up @@ -503,6 +567,7 @@ function mockHyperdriveRequest() {
port: 3211,
database: "mydb",
user: "dbuser",
private_host: false,
},
caching: {
disabled: false,
Expand Down
1 change: 1 addition & 0 deletions packages/wrangler/src/hyperdrive/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export type PublicOrigin = Origin & {
scheme?: string;
database?: string;
user?: string;
private_host?: boolean;
};

export type OriginWithPassword = PublicOrigin & {
Expand Down
7 changes: 7 additions & 0 deletions packages/wrangler/src/hyperdrive/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ export function options(yargs: CommonYargsArgv) {
describe:
"Indicates the number of seconds cache may serve the response after it becomes stale, cannot be set when caching is disabled",
},
"private-host": {
type: "boolean",
describe:
"Whether the provided host is part of your Cloudflare Zero Trust private network",
default: false,
},
})
.epilogue(hyperdriveBetaWarning);
}
Expand Down Expand Up @@ -91,6 +97,7 @@ export async function handler(
database: decodeURIComponent(url.pathname.replace("/", "")),
user: decodeURIComponent(url.username),
password: decodeURIComponent(url.password),
private_host: args.privateHost ?? false,
},
caching: {
disabled: args.cachingDisabled,
Expand Down
7 changes: 7 additions & 0 deletions packages/wrangler/src/hyperdrive/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ export function options(yargs: CommonYargsArgv) {
describe:
"Indicates the number of seconds cache may serve the response after it becomes stale, cannot be set when caching is disabled",
},
"private-host": {
type: "boolean",
describe:
"Whether the provided host is part of your Cloudflare Zero Trust private network",
default: false,
},
})
.epilogue(hyperdriveBetaWarning);
}
Expand Down Expand Up @@ -116,6 +122,7 @@ export async function handler(
database: args.database,
user: args.originUser,
password: args.originPassword,
private_host: args.privateHost,
};
}

Expand Down

0 comments on commit dc0c1dc

Please sign in to comment.