Skip to content

Commit ff88a50

Browse files
author
Ricardo Antunes
committed
[wrangler] Add network_id support and vpc network commands
1 parent 04a5f4a commit ff88a50

File tree

23 files changed

+1017
-3
lines changed

23 files changed

+1017
-3
lines changed

.changeset/vpc-networks-binding.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
---
2+
"wrangler": minor
3+
"miniflare": minor
4+
"@cloudflare/workers-utils": minor
5+
---
6+
7+
Add `vpc_networks` binding type and `wrangler vpc network` CLI commands
8+
9+
Workers can now bind to an entire Cloudflare Tunnel or an explicitly created VPC network using the new `vpc_networks` configuration field. At runtime, `env.MY_VPC.fetch("http://any-internal-host/")` routes requests through the tunnel without requiring per-target registration.
10+
11+
Example `wrangler.json` configuration:
12+
13+
```jsonc
14+
{
15+
"vpc_networks": [
16+
// Simple case: bind directly to a tunnel
17+
{ "binding": "MY_VPC", "tunnel_id": "your-tunnel-uuid" },
18+
// Custom DNS: bind to an explicitly created network
19+
{ "binding": "MY_DNS_VPC", "network_id": "your-network-uuid" },
20+
],
21+
}
22+
```
23+
24+
New CLI commands for managing VPC networks:
25+
26+
- `wrangler vpc network create <name>` — create a network with `--tunnel-id` and optional `--resolver-ips`
27+
- `wrangler vpc network list` — list all VPC networks
28+
- `wrangler vpc network get <network-id>` — get network details
29+
- `wrangler vpc network update <network-id>` — update a network
30+
- `wrangler vpc network delete <network-id>` — delete a network
31+
32+
Each binding generates a `Fetcher` type for TypeScript type generation. Like `vpc_services`, VPC network bindings are always remote in `wrangler dev`.

packages/wrangler/src/__tests__/api/startDevWorker/utils.test.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,16 @@ describe("convertConfigBindingsToStartWorkerBindings", () => {
8181
service_id: "0199295b-b3ac-7760-8246-bca40877b3e9",
8282
},
8383
],
84+
vpc_networks: [
85+
{
86+
binding: "MY_VPC_NETWORK",
87+
tunnel_id: "0399295b-b3ac-7760-8246-bca40877b3e1",
88+
},
89+
{
90+
binding: "MY_VPC_NETWORK_BY_ID",
91+
network_id: "0499295b-b3ac-7760-8246-bca40877b3e2",
92+
},
93+
],
8494
});
8595
expect(result).toEqual({
8696
AI: {
@@ -136,6 +146,14 @@ describe("convertConfigBindingsToStartWorkerBindings", () => {
136146
service_id: "0199295b-b3ac-7760-8246-bca40877b3e9",
137147
type: "vpc_service",
138148
},
149+
MY_VPC_NETWORK: {
150+
tunnel_id: "0399295b-b3ac-7760-8246-bca40877b3e1",
151+
type: "vpc_network",
152+
},
153+
MY_VPC_NETWORK_BY_ID: {
154+
network_id: "0499295b-b3ac-7760-8246-bca40877b3e2",
155+
type: "vpc_network",
156+
},
139157
});
140158
});
141159

@@ -179,6 +197,7 @@ describe("convertConfigBindingsToStartWorkerBindings", () => {
179197
mtls_certificates: [],
180198
workflows: [],
181199
vpc_services: [],
200+
vpc_networks: [],
182201
});
183202

184203
assert(result);

packages/wrangler/src/__tests__/deploy/durable-objects.test.ts

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1157,6 +1157,135 @@ describe("deploy", () => {
11571157
`);
11581158
});
11591159
});
1160+
describe("vpc_networks", () => {
1161+
it("should upload VPC network bindings", async () => {
1162+
writeWranglerConfig({
1163+
vpc_networks: [
1164+
{
1165+
binding: "VPC_NETWORK",
1166+
tunnel_id: "0199295b-b3ac-7760-8246-bca40877b3e9",
1167+
},
1168+
],
1169+
});
1170+
await fs.promises.writeFile("index.js", `export default {};`);
1171+
mockSubDomainRequest();
1172+
mockUploadWorkerRequest({
1173+
expectedBindings: [
1174+
{
1175+
type: "vpc_network",
1176+
name: "VPC_NETWORK",
1177+
tunnel_id: "0199295b-b3ac-7760-8246-bca40877b3e9",
1178+
},
1179+
],
1180+
});
1181+
1182+
await runWrangler("deploy index.js");
1183+
expect(std.out).toMatchInlineSnapshot(`
1184+
"
1185+
⛅️ wrangler x.x.x
1186+
──────────────────
1187+
Total Upload: xx KiB / gzip: xx KiB
1188+
Worker Startup Time: 100 ms
1189+
Your Worker has access to the following bindings:
1190+
Binding Resource
1191+
env.VPC_NETWORK (0199295b-b3ac-7760-8246-bca40877b3e9) VPC Network
1192+
1193+
Uploaded test-name (TIMINGS)
1194+
Deployed test-name triggers (TIMINGS)
1195+
https://test-name.test-sub-domain.workers.dev
1196+
Current Version ID: Galaxy-Class"
1197+
`);
1198+
});
1199+
1200+
it("should upload multiple VPC network bindings", async () => {
1201+
writeWranglerConfig({
1202+
vpc_networks: [
1203+
{
1204+
binding: "VPC_NET_A",
1205+
tunnel_id: "0199295b-b3ac-7760-8246-bca40877b3e9",
1206+
},
1207+
{
1208+
binding: "VPC_NET_B",
1209+
tunnel_id: "0299295b-b3ac-7760-8246-bca40877b3e0",
1210+
},
1211+
],
1212+
});
1213+
await fs.promises.writeFile("index.js", `export default {};`);
1214+
mockSubDomainRequest();
1215+
mockUploadWorkerRequest({
1216+
expectedBindings: [
1217+
{
1218+
type: "vpc_network",
1219+
name: "VPC_NET_A",
1220+
tunnel_id: "0199295b-b3ac-7760-8246-bca40877b3e9",
1221+
},
1222+
{
1223+
type: "vpc_network",
1224+
name: "VPC_NET_B",
1225+
tunnel_id: "0299295b-b3ac-7760-8246-bca40877b3e0",
1226+
},
1227+
],
1228+
});
1229+
1230+
await runWrangler("deploy index.js");
1231+
expect(std.out).toMatchInlineSnapshot(`
1232+
"
1233+
⛅️ wrangler x.x.x
1234+
──────────────────
1235+
Total Upload: xx KiB / gzip: xx KiB
1236+
Worker Startup Time: 100 ms
1237+
Your Worker has access to the following bindings:
1238+
Binding Resource
1239+
env.VPC_NET_A (0199295b-b3ac-7760-8246-bca40877b3e9) VPC Network
1240+
env.VPC_NET_B (0299295b-b3ac-7760-8246-bca40877b3e0) VPC Network
1241+
1242+
Uploaded test-name (TIMINGS)
1243+
Deployed test-name triggers (TIMINGS)
1244+
https://test-name.test-sub-domain.workers.dev
1245+
Current Version ID: Galaxy-Class"
1246+
`);
1247+
});
1248+
});
1249+
describe("vpc_networks with network_id", () => {
1250+
it("should upload VPC network bindings with network_id", async () => {
1251+
writeWranglerConfig({
1252+
vpc_networks: [
1253+
{
1254+
binding: "VPC_NETWORK",
1255+
network_id: "0199295b-b3ac-7760-8246-bca40877b3e9",
1256+
},
1257+
],
1258+
});
1259+
await fs.promises.writeFile("index.js", `export default {};`);
1260+
mockSubDomainRequest();
1261+
mockUploadWorkerRequest({
1262+
expectedBindings: [
1263+
{
1264+
type: "vpc_network",
1265+
name: "VPC_NETWORK",
1266+
network_id: "0199295b-b3ac-7760-8246-bca40877b3e9",
1267+
},
1268+
],
1269+
});
1270+
1271+
await runWrangler("deploy index.js");
1272+
expect(std.out).toMatchInlineSnapshot(`
1273+
"
1274+
⛅️ wrangler x.x.x
1275+
──────────────────
1276+
Total Upload: xx KiB / gzip: xx KiB
1277+
Worker Startup Time: 100 ms
1278+
Your Worker has access to the following bindings:
1279+
Binding Resource
1280+
env.VPC_NETWORK (0199295b-b3ac-7760-8246-bca40877b3e9) VPC Network
1281+
1282+
Uploaded test-name (TIMINGS)
1283+
Deployed test-name triggers (TIMINGS)
1284+
https://test-name.test-sub-domain.workers.dev
1285+
Current Version ID: Galaxy-Class"
1286+
`);
1287+
});
1288+
});
11601289
describe("mtls_certificates", () => {
11611290
it("should upload mtls_certificate bindings", async () => {
11621291
writeWranglerConfig({

packages/wrangler/src/__tests__/deploy/get-remote-config-diff.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,12 @@ describe("getRemoteConfigsDiff", () => {
384384
service_id: "my-vpc",
385385
},
386386
],
387+
vpc_networks: [
388+
{
389+
binding: "MY_VPC_NET",
390+
tunnel_id: "my-tunnel",
391+
},
392+
],
387393
},
388394
{
389395
name: "my-worker-id",
@@ -488,6 +494,13 @@ describe("getRemoteConfigsDiff", () => {
488494
remote: true,
489495
},
490496
],
497+
vpc_networks: [
498+
{
499+
binding: "MY_VPC_NET",
500+
tunnel_id: "my-tunnel",
501+
remote: true,
502+
},
503+
],
491504
} as unknown as Config
492505
);
493506
expect(diff).toBeNull();

packages/wrangler/src/__tests__/type-generation.test.ts

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,12 @@ const bindingsConfigMock: Omit<
517517
service_id: "0199295b-b3ac-7760-8246-bca40877b3e9",
518518
},
519519
],
520+
vpc_networks: [
521+
{
522+
binding: "VPC_NETWORK_BINDING",
523+
tunnel_id: "0199295b-b3ac-7760-8246-bca40877b3e9",
524+
},
525+
],
520526
};
521527

522528
describe("generate types", () => {
@@ -755,6 +761,7 @@ describe("generate types", () => {
755761
RATE_LIMITER: RateLimit;
756762
WORKER_LOADER_BINDING: WorkerLoader;
757763
VPC_SERVICE_BINDING: Fetcher;
764+
VPC_NETWORK_BINDING: Fetcher;
758765
LOGFWDR_SCHEMA: any;
759766
BROWSER_BINDING: Fetcher;
760767
AI_BINDING: Ai;
@@ -867,6 +874,7 @@ describe("generate types", () => {
867874
RATE_LIMITER: RateLimit;
868875
WORKER_LOADER_BINDING: WorkerLoader;
869876
VPC_SERVICE_BINDING: Fetcher;
877+
VPC_NETWORK_BINDING: Fetcher;
870878
LOGFWDR_SCHEMA: any;
871879
BROWSER_BINDING: Fetcher;
872880
AI_BINDING: Ai;
@@ -1042,6 +1050,7 @@ describe("generate types", () => {
10421050
RATE_LIMITER: RateLimit;
10431051
WORKER_LOADER_BINDING: WorkerLoader;
10441052
VPC_SERVICE_BINDING: Fetcher;
1053+
VPC_NETWORK_BINDING: Fetcher;
10451054
LOGFWDR_SCHEMA: any;
10461055
BROWSER_BINDING: Fetcher;
10471056
AI_BINDING: Ai;
@@ -3295,6 +3304,105 @@ describe("generate types", () => {
32953304
"
32963305
`);
32973306
});
3307+
3308+
it("should generate types for VPC networks bindings", async ({ expect }) => {
3309+
fs.writeFileSync(
3310+
"./index.ts",
3311+
`export default { async fetch(request, env) { return await env.VPC_NET.fetch(request); } };`
3312+
);
3313+
fs.writeFileSync(
3314+
"./wrangler.json",
3315+
JSON.stringify({
3316+
compatibility_date: "2022-01-12",
3317+
name: "test-vpc-networks",
3318+
main: "./index.ts",
3319+
vpc_networks: [
3320+
{
3321+
binding: "VPC_NET",
3322+
tunnel_id: "0199295b-b3ac-7760-8246-bca40877b3e9",
3323+
},
3324+
{
3325+
binding: "VPC_NET_2",
3326+
tunnel_id: "0299295b-b3ac-7760-8246-bca40877b3e0",
3327+
},
3328+
],
3329+
}),
3330+
"utf-8"
3331+
);
3332+
3333+
await runWrangler("types --include-runtime=false");
3334+
expect(std.out).toMatchInlineSnapshot(`
3335+
"
3336+
⛅️ wrangler x.x.x
3337+
──────────────────
3338+
Generating project types...
3339+
3340+
declare namespace Cloudflare {
3341+
interface GlobalProps {
3342+
mainModule: typeof import("./index");
3343+
}
3344+
interface Env {
3345+
VPC_NET: Fetcher;
3346+
VPC_NET_2: Fetcher;
3347+
}
3348+
}
3349+
interface Env extends Cloudflare.Env {}
3350+
3351+
────────────────────────────────────────────────────────────
3352+
✨ Types written to worker-configuration.d.ts
3353+
3354+
📣 Remember to rerun 'wrangler types' after you change your wrangler.json file.
3355+
"
3356+
`);
3357+
});
3358+
3359+
it("should generate types for VPC networks bindings with network_id", async ({
3360+
expect,
3361+
}) => {
3362+
fs.writeFileSync(
3363+
"./index.ts",
3364+
`export default { async fetch(request, env) { return await env.VPC_NET.fetch(request); } };`
3365+
);
3366+
fs.writeFileSync(
3367+
"./wrangler.json",
3368+
JSON.stringify({
3369+
compatibility_date: "2022-01-12",
3370+
name: "test-vpc-networks-by-id",
3371+
main: "./index.ts",
3372+
vpc_networks: [
3373+
{
3374+
binding: "VPC_NET",
3375+
network_id: "0199295b-b3ac-7760-8246-bca40877b3e9",
3376+
},
3377+
],
3378+
}),
3379+
"utf-8"
3380+
);
3381+
3382+
await runWrangler("types --include-runtime=false");
3383+
expect(std.out).toMatchInlineSnapshot(`
3384+
"
3385+
⛅️ wrangler x.x.x
3386+
──────────────────
3387+
Generating project types...
3388+
3389+
declare namespace Cloudflare {
3390+
interface GlobalProps {
3391+
mainModule: typeof import("./index");
3392+
}
3393+
interface Env {
3394+
VPC_NET: Fetcher;
3395+
}
3396+
}
3397+
interface Env extends Cloudflare.Env {}
3398+
3399+
────────────────────────────────────────────────────────────
3400+
✨ Types written to worker-configuration.d.ts
3401+
3402+
📣 Remember to rerun 'wrangler types' after you change your wrangler.json file.
3403+
"
3404+
`);
3405+
});
32983406
});
32993407

33003408
describe("pipeline schema type generation", () => {

0 commit comments

Comments
 (0)