Skip to content

Commit 022dbd6

Browse files
authored
Make VPC egress settings parameterizeable (#6843)
* Make VPC egress settings parameterizeable * Changelog
1 parent 9d10de3 commit 022dbd6

File tree

5 files changed

+52
-11
lines changed

5 files changed

+52
-11
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
- Fix demo projects + web frameworks with emulators (#6737)
33
- Fix Next.js static routes with server actions (#6664)
44
- Fixed an issue where `GOOGLE_CLOUD_QUOTA_PROJECT` was not correctly respected. (#6801)
5+
- Make VPC egress settings in functions parameterizeable (#6843)

src/deploy/functions/backend.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,13 @@ export function isValidMemoryOption(mem: unknown): mem is MemoryOptions {
177177
return allMemoryOptions.includes(mem as MemoryOptions);
178178
}
179179

180+
/**
181+
* Is a given string a valid VpcEgressSettings?
182+
*/
183+
export function isValidEgressSetting(egress: unknown): egress is VpcEgressSettings {
184+
return egress === "PRIVATE_RANGES_ONLY" || egress === "ALL_TRAFFIC";
185+
}
186+
180187
/** Returns a human-readable name with MB or GB suffix for a MemoryOption (MB). */
181188
export function memoryOptionDisplayName(option: MemoryOptions): string {
182189
return {

src/deploy/functions/build.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ export function isBlockingTriggered(triggered: Triggered): triggered is Blocking
193193

194194
export interface VpcSettings {
195195
connector: string | Expression<string>;
196-
egressSettings?: "PRIVATE_RANGES_ONLY" | "ALL_TRAFFIC" | null;
196+
egressSettings?: "PRIVATE_RANGES_ONLY" | "ALL_TRAFFIC" | Expression<string> | null;
197197
}
198198

199199
export interface SecretEnvVar {
@@ -204,12 +204,6 @@ export interface SecretEnvVar {
204204

205205
export type MemoryOption = 128 | 256 | 512 | 1024 | 2048 | 4096 | 8192 | 16384 | 32768;
206206
const allMemoryOptions: MemoryOption[] = [128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768];
207-
/**
208-
* Is a given number a valid MemoryOption?
209-
*/
210-
export function isValidMemoryOption(mem: unknown): mem is MemoryOption {
211-
return allMemoryOptions.includes(mem as MemoryOption);
212-
}
213207

214208
export type FunctionsPlatform = backend.FunctionsPlatform;
215209
export const AllFunctionsPlatforms: FunctionsPlatform[] = ["gcfv1", "gcfv2"];
@@ -514,7 +508,16 @@ export function toBackend(
514508
}
515509

516510
bkEndpoint.vpc = { connector: bdEndpoint.vpc.connector };
517-
proto.copyIfPresent(bkEndpoint.vpc, bdEndpoint.vpc, "egressSettings");
511+
if (bdEndpoint.vpc.egressSettings) {
512+
const egressSettings = r.resolveString(bdEndpoint.vpc.egressSettings);
513+
if (!backend.isValidEgressSetting(egressSettings)) {
514+
throw new FirebaseError(
515+
`Value "${egressSettings}" is an invalid ` +
516+
"egress setting. Valid values are PRIVATE_RANGES_ONLY and ALL_TRAFFIC",
517+
);
518+
}
519+
bkEndpoint.vpc.egressSettings = egressSettings;
520+
}
518521
} else if (bdEndpoint.vpc === null) {
519522
bkEndpoint.vpc = null;
520523
}

src/deploy/functions/runtimes/discovery/v1alpha1.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as build from "../../build";
2+
import * as backend from "../../backend";
23
import * as params from "../../params";
34
import * as runtimes from "..";
45

@@ -126,7 +127,7 @@ function assertBuildEndpoint(ep: WireEndpoint, id: string): void {
126127
platform: (platform) => build.AllFunctionsPlatforms.includes(platform),
127128
entryPoint: "string",
128129
omit: "Field<boolean>?",
129-
availableMemoryMb: (mem) => mem === null || isCEL(mem) || build.isValidMemoryOption(mem),
130+
availableMemoryMb: (mem) => mem === null || isCEL(mem) || backend.isValidMemoryOption(mem),
130131
maxInstances: "Field<number>?",
131132
minInstances: "Field<number>?",
132133
concurrency: "Field<number>?",

src/test/deploy/functions/build.spec.ts

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { expect } from "chai";
22
import * as build from "../../../deploy/functions/build";
33
import { ParamValue } from "../../../deploy/functions/params";
4+
import { FirebaseError } from "../../../error";
45

56
describe("toBackend", () => {
67
it("populates backend info from Build", () => {
@@ -124,8 +125,8 @@ describe("toBackend", () => {
124125
minInstances: "{{ params.mininstances }}",
125126
serviceAccount: "{{ params.serviceaccount }}",
126127
vpc: {
127-
connector: "projects/project/locations/region/connectors/connector",
128-
egressSettings: "PRIVATE_RANGES_ONLY",
128+
connector: "{{ params.connector }}",
129+
egressSettings: "{{ params.egressSettings }}",
129130
},
130131
ingressSettings: "ALLOW_ALL",
131132
labels: {
@@ -140,6 +141,8 @@ describe("toBackend", () => {
140141
maxinstances: new ParamValue("42", false, { number: true }),
141142
mininstances: new ParamValue("1", false, { number: true }),
142143
serviceaccount: new ParamValue("service-account-1@", false, { string: true }),
144+
connector: new ParamValue("connector", false, { string: true }),
145+
egressSettings: new ParamValue("ALL_TRAFFIC", false, { string: true }),
143146
});
144147
expect(Object.keys(backend.endpoints).length).to.equal(1);
145148
const endpointDef = Object.values(backend.endpoints)[0];
@@ -154,6 +157,32 @@ describe("toBackend", () => {
154157
expect(
155158
"httpsTrigger" in endpointDef.func ? endpointDef.func.httpsTrigger.invoker : [],
156159
).to.have.members(["service-account-2@", "service-account-3@"]);
160+
expect(endpointDef.func.vpc?.connector).to.equal(
161+
"projects/project/locations/us-central1/connectors/connector",
162+
);
163+
expect(endpointDef.func.vpc?.egressSettings).to.equal("ALL_TRAFFIC");
157164
}
158165
});
166+
167+
it("enforces enum correctness for VPC egress settings", () => {
168+
const desiredBuild: build.Build = build.of({
169+
func: {
170+
platform: "gcfv2",
171+
region: ["us-central1"],
172+
project: "project",
173+
runtime: "nodejs16",
174+
entryPoint: "func",
175+
vpc: {
176+
connector: "connector",
177+
egressSettings: "{{ params.egressSettings }}",
178+
},
179+
httpsTrigger: {},
180+
},
181+
});
182+
expect(() => {
183+
build.toBackend(desiredBuild, {
184+
egressSettings: new ParamValue("INVALID", false, { string: true }),
185+
});
186+
}).to.throw(FirebaseError, /Value "INVALID" is an invalid egress setting./);
187+
});
159188
});

0 commit comments

Comments
 (0)