Firebase-tools: firebase emulators:start can't use production firestore but functions:shell can. (GOOGLE_APPLICATION_CREDENTIALS)

Created on 18 Jun 2019  Â·  5Comments  Â·  Source: firebase/firebase-tools


Hi,

Locally emulated firebase cloud functions that access the production firestore work ok when using firebase functions:shell but not firebase emulators:start --only hosting, functions.

This may have something to do with GOOGLE_APPLICATION_CREDENTIALS being set to "" in functionsEmulatorRuntime.ts (for what looks like a good reason), but if it is not set neither functions:shell or emulators:start seem to be able to access the firestore. (I may be misunderstanding the docs.)

(This issue only concerns the production firestore, I can access a locally emulated firestore if I create the Firestore instance directly and don't use the default admin.firestore())

I think emulators:start and functions:shell should have consistent behaviour and allow an approved way to access a production firestore even if that is not through GOOGLE_APPLICATION_CREDENTIALS.

[REQUIRED] Environment info

firebase-tools:
7.0.0
Platform:
macOS Movaje 10.14.5

[REQUIRED] Test case

Tiny github project with a single https invoked cloud function that optionally attempts to set a production (not emulated) firestore document here: tmcf/fbfn-emulator-tests

  • live deploy, WORKS
  • firebase functions:shell WORKS if GOOGLE_APPLICATION_CREDENTIALS set
  • firebase emulators:start --only hosting,functions FAILS always

[REQUIRED] Steps to reproduce

With hosting and functions emulators started:

curl 'http://localhost:5000/firestore_test?id=THX1138&val=hello&write_fstore=true'

[REQUIRED] Expected behavior

200 Ok response, as is gotten with live deploy and with functions:shell

export GOOGLE_APPLICATION_CREDENTIALS=/path/to/credentials
firebase functions:shell
firebase> firestore_test.get('?id=THX1138&val=HELLO&write_fstore=true')
RESPONSE RECEIVED FROM FUNCTION: 200, "{\"id\":\"THX1138\",\"val\":\"HELLO\",\"write_fstore\":\"true\",\"VERSION\":\"1.0.0\"}"

[REQUIRED] Actual behavior

firebase emulators:start --only hosting,functions returns error on function invoke:

âš   Unknown network resource requested!
   - URL: "http://metadata.google.internal./computeMetadata/v1/instance"
>  Error with request:{"id":"THX1138","val":"hello","write_fstore":"true","VERSION":"1.0.0"}
>  Error: Could not load the default credentials. Browse to https://cloud.google.com/docs/authentication/getting-started for more information.
>      at GoogleAuth.getApplicationDefaultAsync (/Users/tmcf/tdev/fbfn-emulator-tests/functions/node_modules/google-auth-library/build/src/auth/googleauth.js:161:19)
>      at process._tickCallback (internal/process/next_tick.js:68:7)```

Log for the above error attached:
firebase-debug.log

Most helpful comment

This behavior will change in 7.2.0 so that if you don't start a certain emulator then your requests still go to production. For example if you do emulators:start --only functions,database then your Realtime Database requests will hit the emulator and your Firestore requests will hit production,

All 5 comments

Hey @tmcf,

Thanks for the thorough bug report!

As you may have suspected from the code comments, this is definitely intentional, however still poorly documented and without an easy work-around.

When using emulators:start we want to keep people inside the local emulation environment unless they specifically ask to be broken out. Right now, you can ask to contact production by manually restoring the GOOGLE_APPLICATION_CREDENTIAL files when running in the emulator.

If you add something like this high up in your functions code (before imports / requires) then firebase-admin will pick up on this credential when running locally.

if (process.env.FUNCTIONS_EMULATOR) {
    process.env.GOOGLE_APPLICATION_CREDENTIAL = "../path/to/local/service_account.json"
}

Eventually this will be a cli flag or some configuration setting, but we need to get approval before we push forward on that!

Anyway since this isn't a technical bug (just a documentation one) I'm going to close this issue, but if I misunderstood or you're still struggling, please re-open!

Have a great friday!

Small note: the fix above should say GOOGLE_APPLICATION_CREDENTIALS with an 'S'.
(Just in case someone is copy-pasting)
@abeisgoat Thanks for the fix.

This behavior will change in 7.2.0 so that if you don't start a certain emulator then your requests still go to production. For example if you do emulators:start --only functions,database then your Realtime Database requests will hit the emulator and your Firestore requests will hit production,

what @samtstern is what realistically is my expected behavior. If you only run the functions emulator, It should connect to production. If you also enable firestore emulation with functions, then it uses the local firestore.

Since you need to explicitly specify that you ONLY want a SPECIFIC emulator to run, naturally that means you want to connect to production for everything else. This is the expected behavior and it should be changed.

@SwissCheese5 it sounds like you like the current behavior but if there's something you think should be changed please open a new issue describing your request!

Was this page helpful?
0 / 5 - 0 ratings