Reputation: 41
I am facing an issue while deploying my Firebase Cloud Functions. The project has three functions: http
, onSchedule
and onObjectFinalized
. The http
and onSchedule
functions deploy successfully, but I encounter an error when deploying the onObjectFinalized
function.
The complete error message I receive is:
$ npm run deploy:prod
> [email protected] deploy:prod
> npm run changeToProd && firebase deploy
> [email protected] changeToProd
> firebase use prod
Now using alias prod (zipshot-prod)
=== Deploying to 'zipshot-prod'...
i deploying functions, hosting
i functions: preparing codebase default for deployment
i functions: ensuring required API cloudfunctions.googleapis.com is enabled...
i functions: ensuring required API cloudbuild.googleapis.com is enabled...
i artifactregistry: ensuring required API artifactregistry.googleapis.com is enabled...
+ functions: required API cloudfunctions.googleapis.com is enabled
+ artifactregistry: required API artifactregistry.googleapis.com is enabled
+ functions: required API cloudbuild.googleapis.com is enabled
i functions: Loading and analyzing source code for codebase default to determine what to deploy
Serving at port 8581
{"severity":"WARNING","message":"params.PROJECT_ID.value() invoked during function deployment, instead of during runtime."}
{"severity":"WARNING","message":"This is usually a mistake. In configs, use Params directly without calling .value()."}
{"severity":"WARNING","message":"example: { memory: memoryParam } not { memory: memoryParam.value() }"}
i functions: preparing functions directory for uploading...
i functions: packaged F:\project\chrome_ext\zipshot\cloud-functions\functions (109.47 KB) for uploading
i functions: ensuring required API cloudscheduler.googleapis.com is enabled...
+ functions: required API cloudscheduler.googleapis.com is enabled
i functions: ensuring required API run.googleapis.com is enabled...
i functions: ensuring required API eventarc.googleapis.com is enabled...
i functions: ensuring required API pubsub.googleapis.com is enabled...
i functions: ensuring required API storage.googleapis.com is enabled...
+ functions: required API run.googleapis.com is enabled
+ functions: required API storage.googleapis.com is enabled
+ functions: required API pubsub.googleapis.com is enabled
+ functions: required API eventarc.googleapis.com is enabled
i functions: generating the service identity for pubsub.googleapis.com...
i functions: generating the service identity for eventarc.googleapis.com...
i functions: Failed to verify the project has the correct IAM bindings for a successful deployment.
i functions: You can either re-run `firebase deploy` as a project owner or manually run the
following set of `gcloud` commands:
i functions: `gcloud projects add-iam-policy-binding zipshot-prod --member=serviceAccount:service-1090842465135@gs-project-accounts.iam.gserviceaccount.com --role=roles/pubsub.publisher`
i functions: `gcloud projects add-iam-policy-binding zipshot-prod --member=serviceAccount:[email protected] --role=roles/iam.serviceAccountTokenCreator`
i functions: `gcloud projects add-iam-policy-binding zipshot-prod --member=serviceAccount:[email protected] --role=roles/run.invoker`
i functions: `gcloud projects add-iam-policy-binding zipshot-prod --member=serviceAccount:[email protected] --role=roles/eventarc.eventReceiver`
Error: We failed to modify the IAM policy for the project. The functions deployment requires
specific roles to be granted to service agents, otherwise the deployment will fail.
Here's a snippet of my index.js
file:
const {onRequest} = require("firebase-functions/v2/https");
const {onObjectFinalized} = require("firebase-functions/v2/storage");
const {getStorage} = require("firebase-admin/storage");
const {onSchedule} = require("firebase-functions/v2/scheduler");
const {initializeApp} = require("firebase-admin/app");
const logger = require("firebase-functions/logger");
// const Storage = require("@google-cloud/storage")
// const {tmpdir} = require("os")
const path = require("path")
const sharp = require("sharp")
// const fs = require("fs-extra")
// const gsc = Storage()
initializeApp();
const app = require("./app.js");
const {projectID} = require("firebase-functions/params")
exports.apiv2 = onRequest({minInstances: 2}, app)
// currently running after every 10 mins
exports.callUploadAfterEveryXmin = onSchedule("*/10 * * * *", async() => {
...
})
/**
* When an image is uploaded in the Storage bucket,
* generate a preview image automatically using sharp.
* This code creates a 600x300 preview image for the
* image saved in a temporary directory, then uploads
* it back to Cloud Storage.
*/
exports.generatePreviewImg = onObjectFinalized(async (event) => {
const fileBucket = event.data.bucket; // Storage bucket containing the file.
const filePath = event.data.name; // File path in the bucket.
const contentType = event.data.contentType; // File content type.
// Exit if this is triggered on a file that is not an image.
if (!contentType.startsWith("image/")) {
return logger.log("This is not an image.");
}
// Exit if the image is already a preview image.
const fileName = path.basename(filePath);
if (fileName.startsWith("preview_")) {
return logger.log("Already a Preview Image.");
}
// Download file into memory from bucket.
const bucket = getStorage().bucket(fileBucket);
const downloadResponse = await bucket.file(filePath).download();
const imageBuffer = downloadResponse[0];
logger.log("Image downloaded!");
// Generate a preview image using sharp.
const previewBuffer = await sharp(imageBuffer).resize({
width: 600,
height: 300,
withoutEnlargement: true,
}).toBuffer();
logger.log("preview image created");
// Prefix 'preview_' to file name.
const thumbFileName = `preview_${fileName}`;
const thumbFilePath = path.join(path.dirname(filePath), thumbFileName);
// Upload the preview image.
const metadata = {contentType: contentType};
await bucket.file(thumbFilePath).save(previewBuffer, {
metadata: metadata,
});
return logger.log("Preview image uploaded!");
});
I have the roles of Cloud Functions Admin
and Editor
The deployment script is as follows:
package.json:
"scripts": {
"deploy:prod": "npm run changeToProd && firebase deploy",
"changeToProd": "firebase use prod"
}
.firebaserc:
{
"projects": {
"default": "dummy-dev",
"dev": "dummy-dev",
"prod": "dummy-prod"
}
}
I have tried checking the documentation and forums, but I couldn't find a solution. Any help or guidance on resolving this issue would be greatly appreciated.
Thank you!
Upvotes: 2
Views: 2027
Reputation: 3157
We fixed it by using an owner account. We gave another account the owner role. The service accounts were automagically created with the correct roles and permissions this way on deploying the cloud functions.
Upvotes: 0
Reputation: 11
I had the exact same problem and I succeed to work arround it by manually creating the function from GCP.
One probable origin of this error may be that I had an "App Engine" service account from 1st generation of Cloud Function with [email protected]
ID member while 'Compute Engine' uses this default account [email protected]
as described in the cloud function docs. But I don't have and couldn't create this 2nd gen default service account...
Thus, I gave theses IAM role to the default 1st generation service account [email protected]
I already have:
While creating manually the cloud function, i entered this service account as trigger : [email protected]
Also, in order to get the logs in GCP Cloud Function, I don't no why but I had to create a Google Storage Service Agent service-PROJECT_NUMBER@gs-project-accounts.iam.gserviceaccount.com
with this role:
The command to do this is the same command indicated in the terminal after the deployement failure described in the post above :
gcloud projects add-iam-policy-binding PROJECT_NAME --member=serviceAccount:service-PROJECT_NUMBER@gs-project-accounts.iam.gserviceaccount.com --role=roles/pubsub.editor
After that, deployement and function work like a charm. I hope it will help !
Upvotes: 0