Skip to content

Commit

Permalink
Fix memory options for some functions (#3924)
Browse files Browse the repository at this point in the history
* Fix memory options for some functions

* Add additional units for futureproofing
  • Loading branch information
inlined committed Nov 30, 2021
1 parent 5951900 commit d1d58ec
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 8 deletions.
5 changes: 3 additions & 2 deletions CHANGELOG.md
@@ -1,3 +1,4 @@
- Corrects a bug where containers in Artifact Registry would not be deleted if a function has an upper case character in its name
- Corrects a bug where containers in Artifact Registry would not be deleted if a function has an upper case character in its name (#3918)
- Fixes issue where providing the `--project` flag during `init` would not be recognized with a default project already set. (#3870)
- New HTTPS functions only allow secure traffic.
- Fixes issue with setting memory limits for some functions (#3924)
- New HTTPS functions only allow secure traffic. (#3923)
55 changes: 52 additions & 3 deletions src/gcp/cloudfunctionsv2.ts
Expand Up @@ -88,7 +88,7 @@ export interface ServiceConfig {
uri?: string;

timeoutSeconds?: number;
availableMemoryMb?: number;
availableMemory?: string;
environmentVariables?: Record<string, string>;
maxInstanceCount?: number;
minInstanceCount?: number;
Expand Down Expand Up @@ -163,6 +163,43 @@ interface GenerateUploadUrlResponse {
storageSource: StorageSource;
}

// AvailableMemory suffixes and their byte count.
type MemoryUnit = "" | "k" | "M" | "G" | "T" | "Ki" | "Mi" | "Gi" | "Ti";
const BYTES_PER_UNIT: Record<MemoryUnit, number> = {
"": 1,
k: 1e3,
M: 1e6,
G: 1e9,
T: 1e12,
Ki: 1 << 10,
Mi: 1 << 20,
Gi: 1 << 30,
Ti: 1 << 40,
};

/**
* Returns the float-precision number of Mega(not Mebi)bytes in a
* Kubernetes-style quantity
* Must serve the same results as
* https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/apimachinery/pkg/api/resource/quantity.go
*/
export function megabytes(memory: string): number {
const re = /^([0-9]+(\.[0-9]*)?)(Ki|Mi|Gi|Ti|k|M|G|T|([eE]([0-9]+)))?$/;
const matches = re.exec(memory);
if (!matches) {
throw new Error(`Invalid memory quantity "${memory}""`);
}
const quantity = Number.parseFloat(matches[1]);
let bytes: number;
if (matches[5]) {
bytes = quantity * Math.pow(10, Number.parseFloat(matches[5]));
} else {
const suffix = matches[3] || "";
bytes = quantity * BYTES_PER_UNIT[suffix as MemoryUnit];
}
return bytes / 1e6;
}

/**
* Logs an error from a failed function deployment.
* @param funcName Name of the function that was unsuccessfully deployed.
Expand Down Expand Up @@ -356,13 +393,19 @@ export function functionFromEndpoint(endpoint: backend.Endpoint, source: Storage
proto.copyIfPresent(
gcfFunction.serviceConfig,
endpoint,
"availableMemoryMb",
"environmentVariables",
"vpcConnector",
"vpcConnectorEgressSettings",
"serviceAccountEmail",
"ingressSettings"
);
proto.renameIfPresent(
gcfFunction.serviceConfig,
endpoint,
"availableMemory",
"availableMemoryMb",
(mb: string) => `${mb}M`
);
proto.renameIfPresent(
gcfFunction.serviceConfig,
endpoint,
Expand Down Expand Up @@ -459,12 +502,18 @@ export function endpointFromFunction(gcfFunction: CloudFunction): backend.Endpoi
endpoint,
gcfFunction.serviceConfig,
"serviceAccountEmail",
"availableMemoryMb",
"vpcConnector",
"vpcConnectorEgressSettings",
"ingressSettings",
"environmentVariables"
);
proto.renameIfPresent(
endpoint,
gcfFunction.serviceConfig,
"availableMemoryMb",
"availableMemory",
megabytes
);
proto.renameIfPresent(
endpoint,
gcfFunction.serviceConfig,
Expand Down
23 changes: 20 additions & 3 deletions src/test/gcp/cloudfunctionsv2.spec.ts
Expand Up @@ -50,6 +50,22 @@ describe("cloudfunctionsv2", () => {
updateTime: new Date(),
};

describe("megabytes", () => {
it("Should handle decimal SI units", () => {
expect(cloudfunctionsv2.megabytes("1000k")).to.equal(1);
expect(cloudfunctionsv2.megabytes("1.5M")).to.equal(1.5);
expect(cloudfunctionsv2.megabytes("1G")).to.equal(1000);
});
it("Should handle binary SI units", () => {
expect(cloudfunctionsv2.megabytes("1Mi")).to.equal((1 << 20) / 1e6);
expect(cloudfunctionsv2.megabytes("1Gi")).to.equal((1 << 30) / 1e6);
});
it("Should handle no unit", () => {
expect(cloudfunctionsv2.megabytes("100000")).to.equal(0.1);
expect(cloudfunctionsv2.megabytes("1e9")).to.equal(1000);
expect(cloudfunctionsv2.megabytes("1.5E6")).to.equal(1.5);
});
});
describe("functionFromEndpoint", () => {
const UPLOAD_URL = "https://storage.googleapis.com/projects/-/buckets/sample/source.zip";
it("should guard against version mixing", () => {
Expand Down Expand Up @@ -130,7 +146,6 @@ describe("cloudfunctionsv2", () => {
...ENDPOINT,
httpsTrigger: {},
platform: "gcfv2",
availableMemoryMb: 128,
vpcConnector: "connector",
vpcConnectorEgressSettings: "ALL_TRAFFIC",
ingressSettings: "ALLOW_ALL",
Expand Down Expand Up @@ -159,7 +174,6 @@ describe("cloudfunctionsv2", () => {
vpcConnector: "connector",
vpcConnectorEgressSettings: "ALL_TRAFFIC",
ingressSettings: "ALLOW_ALL",
availableMemoryMb: 128,
serviceAccountEmail: "inlined@google.com",
},
};
Expand All @@ -183,6 +197,7 @@ describe("cloudfunctionsv2", () => {
maxInstances: 42,
minInstances: 1,
timeout: "15s",
availableMemoryMb: 128,
};

const complexGcfFunction: Omit<
Expand All @@ -199,6 +214,7 @@ describe("cloudfunctionsv2", () => {
maxInstanceCount: 42,
minInstanceCount: 1,
timeoutSeconds: 15,
availableMemory: "128M",
},
};

Expand Down Expand Up @@ -290,7 +306,6 @@ describe("cloudfunctionsv2", () => {

it("should copy optional fields", () => {
const extraFields: backend.ServiceConfiguration = {
availableMemoryMb: 128,
vpcConnector: "connector",
vpcConnectorEgressSettings: "ALL_TRAFFIC",
ingressSettings: "ALLOW_ALL",
Expand All @@ -305,6 +320,7 @@ describe("cloudfunctionsv2", () => {
serviceConfig: {
...HAVE_CLOUD_FUNCTION_V2.serviceConfig,
...extraFields,
availableMemory: "128M",
},
labels: {
foo: "bar",
Expand All @@ -316,6 +332,7 @@ describe("cloudfunctionsv2", () => {
httpsTrigger: {},
uri: RUN_URI,
...extraFields,
availableMemoryMb: 128,
labels: {
foo: "bar",
},
Expand Down

0 comments on commit d1d58ec

Please sign in to comment.