Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Ignore quota project in GCF source uploads (#6917)
* Ignore quota project in GCF source uploads

* Changelog

* Remove superfluous change

* format + fix tests

---------

Co-authored-by: Joe Hanley <[email protected]>
  • Loading branch information
inlined and joehan committed Mar 27, 2024
commit 1f8f98ef177dc7f2e0d3efce65fa92203e4d3393
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
- Released Firestore Emulator 1.19.4. This version fixes a minor bug with reserve ids and adds a `reset` endpoint for Datastore Mode.
- Released PubSub Emulator 0.8.2. This version includes support for `no_wrapper` options.
- Fixes issue where GitHub actions service account cannot add preview URLs to Auth authorized domains. (#6895)
- Fixes issue where GOOGLE_CLOUD_QUOTA_PROJECT breaks functions source uploads (#6917)
7 changes: 6 additions & 1 deletion src/apiv2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ interface BaseRequestOptions<T> extends VerbOptions {
responseType?: "json" | "stream" | "xml";
redirect?: "error" | "follow" | "manual";
compress?: boolean;
ignoreQuotaProject?: boolean;
}

interface RequestOptionsWithSignal<T> extends BaseRequestOptions<T> {
Expand Down Expand Up @@ -268,7 +269,11 @@ export class Client {
reqOptions.headers.set("Content-Type", "application/json");
}
}
if (GOOGLE_CLOUD_QUOTA_PROJECT && GOOGLE_CLOUD_QUOTA_PROJECT !== "") {
if (
!reqOptions.ignoreQuotaProject &&
GOOGLE_CLOUD_QUOTA_PROJECT &&
GOOGLE_CLOUD_QUOTA_PROJECT !== ""
) {
reqOptions.headers.set(GOOG_USER_PROJECT_HEADER, GOOGLE_CLOUD_QUOTA_PROJECT);
}
return reqOptions;
Expand Down
27 changes: 22 additions & 5 deletions src/deploy/functions/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as clc from "colorette";
import * as fs from "fs";

import { checkHttpIam } from "./checkIam";
import { logSuccess, logWarning } from "../../utils";
import { logLabeledWarning, logSuccess, logWarning } from "../../utils";
import { Options } from "../../options";
import { configForCodebase } from "../../functions/projectConfig";
import * as args from "./args";
Expand All @@ -30,9 +30,20 @@ async function uploadSourceV1(
file: source.functionsSourceV1!,
stream: fs.createReadStream(source.functionsSourceV1!),
};
await gcs.upload(uploadOpts, uploadUrl, {
"x-goog-content-length-range": "0,104857600",
});
if (process.env.GOOGLE_CLOUD_QUOTA_PROJECT) {
logLabeledWarning(
"functions",
"GOOGLE_CLOUD_QUTOA_PROJECT is not usable when uploading source for Cloud Functions.",
);
}
await gcs.upload(
uploadOpts,
uploadUrl,
{
"x-goog-content-length-range": "0,104857600",
},
true, // ignoreQuotaProject
);
return uploadUrl;
}

Expand All @@ -51,7 +62,13 @@ async function uploadSourceV2(
file: source.functionsSourceV2!,
stream: fs.createReadStream(source.functionsSourceV2!),
};
await gcs.upload(uploadOpts, res.uploadUrl);
if (process.env.GOOGLE_CLOUD_QUOTA_PROJECT) {
logLabeledWarning(
"functions",
"GOOGLE_CLOUD_QUTOA_PROJECT is not usable when uploading source for Cloud Functions.",
);
}
await gcs.upload(uploadOpts, res.uploadUrl, undefined, true /* ignoreQuotaProject */);
return res.storageSource;
}

Expand Down
2 changes: 2 additions & 0 deletions src/gcp/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ export async function upload(
source: any,
uploadUrl: string,
extraHeaders?: Record<string, string>,
ignoreQuotaProject?: boolean,
): Promise<any> {
const url = new URL(uploadUrl);
const localAPIClient = new Client({ urlPrefix: url.origin, auth: false });
Expand All @@ -196,6 +197,7 @@ export async function upload(
},
body: source.stream,
skipLog: { resBody: true },
ignoreQuotaProject,
});
return {
generation: res.response.headers.get("x-goog-generation"),
Expand Down
22 changes: 22 additions & 0 deletions src/test/apiv2.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,28 @@ describe("apiv2", () => {
expect(nock.isDone()).to.be.true;
});

it("should allow explicitly ignoring GOOGLE_CLOUD_QUOTA_PROJECT", async () => {
nock("https://example.com")
.get("/path/to/foo")
.reply(function (this: nock.ReplyFnContext): nock.ReplyFnResult {
expect(this.req.headers["x-goog-user-project"]).is.undefined;
return [200, { success: true }];
});
const prev = process.env["GOOGLE_CLOUD_QUOTA_PROJECT"];
process.env["GOOGLE_CLOUD_QUOTA_PROJECT"] = "unit tests, silly";

const c = new Client({ urlPrefix: "https://example.com" });
const r = await c.request({
method: "GET",
path: "/path/to/foo",
ignoreQuotaProject: true,
});
process.env["GOOGLE_CLOUD_QUOTA_PROJECT"] = prev;

expect(r.body).to.deep.equal({ success: true });
expect(nock.isDone()).to.be.true;
});

it("should handle a 204 response with no data", async () => {
nock("https://example.com").get("/path/to/foo").reply(204);

Expand Down