Cloud function triggered by firestore, path gets changed on deployment - firebase

I am trying to deploy a Cloud function written in Python and deployed with Cloud console which is triggered whenever a document is added to a subcollection.
I have specified the path as
users/{userID}/contactDump/{dumpID}
which should mean that whenever a new document is added to the contactDump subcollection for any user, the function should trigger.
According to Google's documentation, this is a valid path structure. Their own documentation has the following
users/{username}/addresses/{addressId}: valid trigger. Monitors all
address documents.
But whenever I deploy the function (which happens fine) the path gets changed to just {dumpID}
N.B the same happens if I try to deploy a function triggered on users/{userID} , after deployment the path gets changed to just {userID}

This issue only happens in the Cloud Console, and it's easy to reproduce by creating a new function with a Firestore Trigger with the following set up:
Once the function is deployed, the trigger section shows the path is not the one added during the function trigger creation, but the one shown is {addressId}.
After getting this result, it made me think that is the same issue you are facing, because although using different Event types, the Document path seems to be changed and only shows the last part of the path we entered in the first place, in this case {addressId}.
For this, as you said that the the function was working fine, I wanted to get the Cloud Function data performing a GET request using the API Explorer from the Cloud Functions documentation where in the request parameters I added the Cloud Function created details.
After executing the API call the response will contain the eventTrigger with the full trigger path.
In the example before, the result is:
{
"eventTrigger": {
"eventType": "providers/cloud.firestore/eventTypes/document.create",
"resource": "projects/<PROJECT_ID>/databases/(default)/documents/users/{username}/addresses/{addressId}",
"service": "firestore.googleapis.com",
"failurePolicy": {}
}
}
The “eventTrigger” from the response contains the original path, users/{username}/addresses/{addressId}, not the one displayed in the console.
This makes me think that the reason why we see only the shortened path in the Cloud Console doesn’t mean that it has been changed, apparently it is only showing the part after the last “/” slash of the path, even though the path present in the Cloud Function is longer.
Since this looks like an issue with how the console displays the path, I've raised this public issue.
If you need to recover the original path, you can use the API, or the gcloud tool:
gcloud functions describe FUNCTION_ID --format 'value(eventTrigger.resource)'

Related

Does Firebase Cloud Functions's HTTP onRequest handler only work with us-central1?

I have a Cloud Function called customIndexHtml like so:
exports.customIndexHtml = functions.region('asia-east2').https.onRequest((req, res) => {
//return a customized HTML
}
Right now it would only work if I remove the region setting and leave it to the default us-central1 server. The function would work, but the latency is high because my app is based in Asia. I've tried the Asian servers closer to me (Singapore, Hongkong), but every time I specify them and try to run, Firebase Cloud Functions would redirect my app to https://uc.appengine.google.com/. My question is, is there anyway to make https.onRequest work with regions other than us-central1?
Note that this is only happening if I am using the https.onRequest() handler, if I use any other handler and specify a region closer to me, it works just fine.
You can deploy a Firebase Function to a specific location, as per your snippet.
https://firebase.google.com/docs/functions/manage-functions?hl=en#modify-region
But you also need to give instructions to your client:
https://firebase.google.com/docs/functions/locations?hl=en#http_and_client-callable_functions
There is also one important notice:
If you are using HTTP functions to serve dynamic content for Firebase Hosting, you must use us-central1.

DialogFlow "Webhook call failed. Error: UNKNOWN."

I have a DialogFlow setup using a firebase function for fulfillments.
I attempted to add two regions to .region() in my index.js file. This led to me deleting my existing firebase function (which had been running on "us-central-1") and adding two new ones for the newly added regions.
After doing so, my dialogflow setup completely fails to do fulfillments. Instead, i get "Webhook call failed. Error: UNKNOWN" with no other details. I tried removing .region() in my index.js, thereby creating a new firebase function similar to the original, but without luck.
I have also tried to add my fulfillment code directly in the inline editor, but this does not work either.
I am at a loss for what to do here. Has anyone experienced similar issues or perhaps know a fix? Please note that the setup worked completely fine prior to adding .region() and deleting the existing firebase function.
NOTE: I am getting a weird error when deploying through the inline editor: "Permission 'cloudfunctions.functions.SetIamPolicy' denied on resource '(my resource)' (or resource may not exist)."
Regarding the following error:
Permission 'cloudfunctions.functions.SetIamPolicy' denied on resource '(my resource)' (or resource may not exist).
I also encountered this when I deleted the function and tried to redeploy it.
I discovered that this occurs when the user (i.e. you) deploying the function does not have sufficient permissions to set IAM policies. In my case, the project was owned by another user whilst I had limited access. After being given owner access, although you likely only need permissions to manage IAM, the function deploys without any errors.
Although you moved the location of the function, you don't mention that you changed the URL for the webhook in Dialogflow to reflect this new location. The URL for Firebase Cloud Functions include the region where the function runs, so if you change the region, you also need to change the fulfillment URL.

Permission errors unit-testing Google Cloud Functions calling firestore db

I'm following the guide at https://firebase.google.com/docs/functions/unit-testing, but I always get " FirebaseError: Missing or insufficient permissions" when I run my test. I have the correct service-account.json file and I'm setting up firebase-functions-test with it (that part goes without error).
I've tried it with the emulator running (setting the FIRESTORE_EMULATOR_HOST var), and without it (which I assume uses live data) but I always get this error, as soon as my code under test does a db request such as:
data = await db().collection('/machines').get()
So my function under test is getting called, but it just can't do anything.
I also tried calling firebase.initializeApp() the same way I do in my front-end app, but that doesn't help, although without it I get the error telling me to call Firebase App.initializeApp().
firebase use is set to my current project.
I also tried running my test as firebase emulators:exec jest, no difference.
Any ideas?

trigger function on firebase deploy functions

Does anyone know if there is an easy way to trigger a function everytime i re-deploy some funciont to firebase?
I have an specific firabase functions which i define inside GCP (this way when i do "firebase deploy" it doesnt re-deploy, unnisntal or touch in any form my current function)
but sometimes i might update this function manually on GCP and i would like to trigger a inner function of its code everytime it happens... is it possible?
ex:
exports.decrementAction = (req, res) => {/*do stuff*/res.status(200).send("ok")};
function auxiliary(){
//to be called on re-deploy
}
Unfortunately, there isn't an easy way for you to trigger a function within a code that is being redeployed. Since this code is only being deployed at the moment, this wouldn't be possible to be done automatically.
The alternative would be to have this function separately from the "root" function in the moment of deploying and use triggers to run this other Cloud Function, when the first is redeployed. This way, it would be possible to run it based in the deployment of the other.
You can get more information on the triggers available for Cloud Functions here: Calling Cloud Functions. With them, you should be able to configure the timing for the execution.
Besides that, it might be worth it to raise a Feature Request for Google's to verify the possibility of adding this in future releases.
Let me know if the information clarified!
I think there exists a manner.
With Pub/Sub you can catch logs from Stackdriver (docs). Those services allow you to store only the logs related to the deployment of a Cloud Function.
The store could be, for instance, Cloud Firestore. As you should know, there is available a trigger for Cloud Firestore events.
Finally, every time an event log related to a function's deployment is generated, it will be stored and triggers a function attached to that event. In the function, you can parse or filter the logs.

Disable Cloud Functions for Firebase through Firebase dashboard (or cli)

Is there a way to disable a Cloud Function for Firebase through the Firebase dashboard?
I deployed a Cloud Function with a bug which caused an infinite loop of the function being triggered, updating the data, then the function triggering again. I discovered the error quickly, but I had to fix the code and redeploy the entire project to get the function to stop triggering.
Even though I deployed the new function, the deployment took some time and the function was triggered hundreds of times (which actually caused others to be triggered hundreds of times).
I'd like to be able to disable a function immediately when this happens, but I don't see any options in the dashboard or through the Firebase CLI.
If you view Cloud Functions in the Cloud Console, you can delete them individually from there: https://console.cloud.google.com/functions
Dont want to delete the function as I want to keep the usage history, logs, health ect?
This work around,long winded, but does the trick:
Disable function:
comment out the code in then function in your index.js
deploy just the firebase function:
firebase deploy --only functions:functionName
Enable function:
uncomment code
redeploy just the function with above line
Unfortunately Firebase has only a delete option and no disable option :(
A thing that I'm doing which isn't particularly neat but does the job. is just add a node in the database. for me I have a weekly script I run where I don't want my cloud functions to run when that's running. so at the top of my function I read that node and if the script is running, I just return early. not ideal but saves me having to comment out and redeploy every time
For me the fastest way is to edit function code directly in Google Cloud Console editor. In case of the HTTP function adding something like this at the beginning of a handler
res.status(500).send('The function is disabled');
return;
I use a solution similar to Red Baron. I have a Firestore Collection of booleans (one for each function) and I check that boolean at the beginning of my function to determine if it's allowed to run. The function will indeed be called, but it won't do anything if that boolean is set to false. It's not a perfect solution because it doesn't completely disable the function. But at least it will retain the log history.

Resources