Firebase Cloud Function configuration - firebase

While I find the Cloud Functions in Firebase fairly convenient, I have troubles figuring out how to configure them in any way. the firebase init generated the firebase.json that contains functions.predeploy property, but are there any other options available? I cannot find any schema for this file.
By default my cloud function is deployed as Node.js 6 application. How do I define that I want to use Node.js 8 which is already supported by the platform? How can I change the amount of used memory? How do I define the environment variables? All of these can be specified through cli commands or from UI, but will be overriden during the next deployment. Isn't there something I could add to my firebase.json that would allow me to specify these values as a permanent thing? Or is it that I actually have to work with the full-blown Google Cloud and the Deployment Manager in order to get it to work?

All of your questions are answered in the documentation.
Set the node version.
Set the version by adding an engines field to the package.json file
that was created in your functions/ directory during initialization.
For example, if you prefer to use only version 8, edit package.json to
add this line:
"engines": {"node": "8"}
Specify other runtime config.
To set memory allocation and timeout in functions source code, use the
runWith parameter introduced in Firebase SDK for Cloud Functions
2.0.0. This runtime option accepts a JSON object conforming to the RuntimeOptions interface, which defines values for timeoutSeconds and
memory. For example, this storage function uses 1GB of memory and
times out after 300 seconds:
const runtimeOpts = { timeoutSeconds: 300, memory: '1GB' }
exports.myStorageFunction = functions
.runWith(runtimeOpts)
.storage
.object()
.onFinalize((object) = > {
// do some complicated things that take a lot of memory and time });
Set environment config.

Related

Is there a way to add new field to all of the documents in a firestore collection?

I have a collection that needs to be updated. There's a need to add new field and fill it out based on the existing field.
Let's say I have a collection called documents:
documents/{documentId}: {
existingField: ['foo', 'bar'],
myNewField ['foo', 'bar']
}
documents/{anotherDocumentId}: {
existingField: ['baz'],
myNewField ['baz']
}
// ... and so on
I already tried to fire up local cloud function from emulator that loops for each document and writes to production data based on the logic I need. The problem is that function can only live up to max of 30 seconds. What I need would be some kind of console tool that I can run as admin (using service-account) to quickly manage my needs.
How do you handle such cases?
Firebase does not provide a console or tool to do migrations.
You can write a program to run on your development machine that uses the one of the backend SDKs (like the Firebase Admin SDK) to query, iterate, and update the documents and let it run as long as you want.
There is nothing specific built into the API for this type of data migration. You'll have to update each document in turn, which typically involves also reading all documents (or at least their IDs).
While it is possible to do this on Cloud Functions, I find it easier to do it with a local Node.js script, as that doesn't have the runtime limits Cloud Functions imposes.

Is there a way to use both test keys localhost and live keys remote with firebase functions

I have a project were I set up keys as such.
Live keys
functions:config:set stripe.secret="sk_live_..." stripe.publishable="pk_live_..."
Test keys
functions:config:set stripe.secret="sk_test_..." stripe.publishable="pk_test_..."
The application is in its beta stage but live. So there's a lot more changes still done in code.
So I want to avoid setting the keys each time I want to test out some new feature on localhost.
Is there a way to configure firebase functions, to correspond to different Environments?
When on localhost, it should validate with test keys and with on remote live keys?
There isn't a special per-environment configuration. What you can do instead is use the unique id of the project to determine which settings it should apply. Functions can read the deployed project id out of the process environment with GCP_PROJECT
const project_id = process.env.GCP_PROJECT
The values you should use during development is a matter of opinion - do whatever suits you the best.
I believe you can make a .runtimeconfig.json file in your functions directory, which the emulators will read.
For example, first set your local values with `firebase functions config:set stripe.secret="sk_test_...",
Then, run firebase functions config:get > .runtimeconfig.json
When that file is present, from my experience, your firebase emulators will read from that, and you won't keep overwriting production config variables.
Docs: https://firebase.google.com/docs/functions/local-emulator#set_up_functions_configuration_optional

Can I set the firebase.functions 's config value in cloud functions?

I've a use case, where in I want to maintain some rarely changing constants in firebase and load them into my cloud functions project (project-1) when there is a constants.changed config value is set to true. During the next request execution, I'll update my JS file with modified constants and reload the node cache for that file using
delete require.cache[require.resolve('./constants.js')].
Also, here I want to re-set the flag constants.changed to false so that next request won't really do the same thing!. In this way I can avoid hitting firebase continuously in each request for that rarely changing constants document.
I could set this config manually, but I've another system (cloud functions project [project-2]) which actually makes these changes to the constants. Hence I want the cloud function in project-2 to to set the firebase cloud functions config value constants.changed to true.
Am I running after a mirage? is this even possible to achieve. I've checked int the documentation, but seems the Config interface is not exposing such a functionality!
It is not possible to achieve what I said in the question!
Two basic premise is not considered in the above requirement narration.
Cloud functions config when changed, the cloud functions using that config need to be re-deployed to make the changes take effect.
Seems the cloud functions running on the server are in read only file system.
Both the above two limitations makes it impossible to achieve what I've asked for. But it would be a nice to have feature (hot deployments!)

Can Firebase RemoteConfig be accessed from cloud functions

I'm using Firebase as a simple game-server and have some settings that are relevant for both client and backend and would like to keep them in RemoteConfig for consistency, but not sure if I can access it from my cloud functions in a simple way (I don't consider going through the REST interface a "simple" way)
As far as I can tell there is no mention of it in the docs, so I guess it's not possible, but does anyone know for sure?
firebaser here
There is a public REST API that allows you to read and set Firebase Remote Config conditions. This API requires that you have full administrative access to the Firebase project, so must only be used on a trusted environment (such as your development machine, a server you control or Cloud Functions).
There is no public API to get Firebase Remote Config settings from a client environment at the moment. Sorry I don't have better news.
This is probably only included in newer versions of firebase (8th or 9th and above if I'm not mistaken).
// We first need to import remoteConfig function.
import { remoteConfig } from firebase-admin
// Then in your cloud function we use it to fetch our remote config values.
const remoteConfigTemplate = await remoteConfig().getTemplate().catch(e => {
// Your error handling if fetching fails...
}
// Next it is just matter of extracting the values, which is kinda convoluted,
// let's say you want to extract `game_version` field from remote config:
const gameVersion = remoteConfigTemplate.parameters.game_version.defaultValue.value
So parameters are always followed by the name of the field that you defined in Firebase console's remote config, in this example game_version.
It's a mouthful (or typeful) but that's how you get it.
Also note that if value is stored as JSON string, you will need to parse it before usage, commonly: JSON.parse(gameVersion).
Similar process is outlined in Firebase docs.

Setting NODE_ENV for firebase function

I am moving some of my firebase-queue workers to Firebase Functions. I have used process.env.NODE_ENV to set some of the configuration for the workers depending on the environment in which I am running them. Is there a way to set the NODE_ENV for the functions while deploying them. I understand that the recommended way to provide such config options is via firebase.config.set which I have verified works as expected but just wanted to check if there is a way to set the NODE_ENV also. When I try to print out the NODE_ENV inside of a function, it is always set to production.
Following Google's Best practices and reserved environment variables in their documentation
Environment variables that are provided by the environment might change in future runtime versions. As a best practice, we recommend that you do not depend on or modify any environment variables that you have not set explicitly.
Basically don't use NODE_ENV. Use your own environment variables and set them accordingly.
NOTE: This documentations is from Google Cloud Functions. Firebase functions are like a wrapper around google cloud functions. Check this question
There is currently no way to set custom environment variables such as process.env.NODE_ENV. What you want to do can only be done for Google Cloud functions and you need to use the gcloud command-line tool.
https://cloud.google.com/functions/docs/env-var#accessing_environment_variables_at_runtime
Other options
If you are developing specifically for Firebase and need a similar solution, then there are options.
Conditions based on project ID
You can access the project id if you are having test, staging and production projects and want to have different behavior or logging depending on the environment.
process.env.GCLOUD_PROJECT is set to your GCP project ID so you can build logic based on that.
if (process.env.GCLOUD_PROJECT === 'my-production-project') {
// Only in production
} else {
// Do something for the test environments
}
Cloud Function Environment Variables
As you already mentioned there's the cloud functions environment variables also. You can effectively create build pipelines that are configuring your environment configuration upon build/deploy and later access them in your cloud function.
- firebase functions:config:set runtime.env="production" --token $FIREBASE_DEPLOY_KEY
Accessing the configuration is effectively the same as your process.env but can not be accessed outside of the scope of a cloud function (i.e. you can't use it in a global variable declaration).
if (functions.config().runtime.env === 'production') {
// Only in production
} else {
// Do something for the test environments
}
At the time I'm answering this question the Firebase SDK for Cloud Functions offers built-in environment configuration out of the box.
Set environment configuration for your project
$ firebase functions:config:set [values...]
Example
$ firebase functions:config:set someservice.key="THE API KEY" someservice.id="THE CLIENT ID"
Get environment configuration for your project
$ firebase functions:config:get [path]
Example
const functions = require('firebase-functions')
console.log(functions.config().someservice.id)
NOTE: You must redeploy functions to make the new configuration available.

Resources