diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml index 6c41b308..788f7a9f 100644 --- a/.github/.OwlBot.lock.yaml +++ b/.github/.OwlBot.lock.yaml @@ -13,4 +13,4 @@ # limitations under the License. docker: image: gcr.io/cloud-devrel-public-resources/owlbot-nodejs:latest - digest: sha256:f59941869d508c6825deeffce180579545fd528f359f549a80a18ec0458d7094 + digest: sha256:fe04ae044dadf5ad88d979dbcc85e0e99372fb5d6316790341e6aca5e4e3fbc8 diff --git a/.kokoro/continuous/node12/system-test.cfg b/.kokoro/continuous/node12/system-test.cfg index 5427efc2..ef48fe2b 100644 --- a/.kokoro/continuous/node12/system-test.cfg +++ b/.kokoro/continuous/node12/system-test.cfg @@ -5,3 +5,8 @@ env_vars: { key: "TRAMPOLINE_BUILD_FILE" value: "github/cloud-debug-nodejs/.kokoro/system-test.sh" } + +env_vars: { + key: "SECRET_MANAGER_KEYS" + value: "long-door-651-kokoro-system-test-service-account" +} \ No newline at end of file diff --git a/.kokoro/presubmit/node12/system-test.cfg b/.kokoro/presubmit/node12/system-test.cfg index 5427efc2..ef48fe2b 100644 --- a/.kokoro/presubmit/node12/system-test.cfg +++ b/.kokoro/presubmit/node12/system-test.cfg @@ -5,3 +5,8 @@ env_vars: { key: "TRAMPOLINE_BUILD_FILE" value: "github/cloud-debug-nodejs/.kokoro/system-test.sh" } + +env_vars: { + key: "SECRET_MANAGER_KEYS" + value: "long-door-651-kokoro-system-test-service-account" +} \ No newline at end of file diff --git a/.kokoro/system-test.sh b/.kokoro/system-test.sh index 87fa0653..0201e9df 100755 --- a/.kokoro/system-test.sh +++ b/.kokoro/system-test.sh @@ -19,7 +19,7 @@ set -eo pipefail export NPM_CONFIG_PREFIX=${HOME}/.npm-global # Setup service account credentials. -export GOOGLE_APPLICATION_CREDENTIALS=${KOKORO_GFILE_DIR}/service-account.json +export GOOGLE_APPLICATION_CREDENTIALS=${KOKORO_GFILE_DIR}/secret_manager/long-door-651-kokoro-system-test-service-account export GCLOUD_PROJECT=long-door-651 cd $(dirname $0)/.. diff --git a/.readme-partials.yaml b/.readme-partials.yaml index c5ce7c62..cb4219f3 100644 --- a/.readme-partials.yaml +++ b/.readme-partials.yaml @@ -49,14 +49,11 @@ body: |- with the longest matching path suffix. If a unique match is found, that file will be used to set the snapshot. - ## Firebase Realtime Database backend + ## Snapshot Debugger - Firebase Realtime Database Backend - The Cloud Debugger API is deprecated and will be turned down in May 2023. - - You can use Firebase Realtime Database for data persistence as an - alternative. - - ### Enabling the agent + This functionality is available for release 6.0.0 onward of this agent and + provides support for the Snapshot Debugger, which is being provided as a + replacement for the deprecated Cloud Debugger service. To enable the agent, add the following at the top of your app's main script or entry point: @@ -70,17 +67,13 @@ body: |- ``` The following params are optional: - * firebaseDbUrl - https://**PROJECT_ID**-cdbg.firebaseio.com will be used if not - provided. where **PROJECT_ID** is your project ID. + * firebaseDbUrl - https://**PROJECT_ID**-cdbg.firebaseio.com will be used if + not provided. where **PROJECT_ID** is your project ID. * firebaseKeyPath - Default google application credentials are used if not provided. - ### Using the Debugger - - Using the Debugger with the Firebase Realtime Database backend requires using - the Snapshot Debugger CLI. - - See the [full Snapshot Debugger CLI documentation][snapshot-debugger-readme]. + See https://github.com/GoogleCloudPlatform/snapshot-debugger and + https://cloud.google.com/debugger/docs/deprecations for more details. ## Limitations and Requirements diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b020e3e..501eca38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Node.js Agent for Google Cloud Debug ChangeLog +## [7.2.2](https://github.com/googleapis/cloud-debug-nodejs/compare/v7.2.1...v7.2.2) (2023-01-16) + + +### Bug Fixes + +* Add timeout to firebase db connection attempt ([#1132](https://github.com/googleapis/cloud-debug-nodejs/issues/1132)) ([8cd89c8](https://github.com/googleapis/cloud-debug-nodejs/commit/8cd89c8adb33f4e3024ef6dcd79861279826aafe)) + ## [7.2.1](https://github.com/googleapis/cloud-debug-nodejs/compare/v7.2.0...v7.2.1) (2022-12-15) diff --git a/README.md b/README.md index 367b721d..e7809add 100644 --- a/README.md +++ b/README.md @@ -99,14 +99,11 @@ because the debug agent resolves a snapshot filename by searching for a file with the longest matching path suffix. If a unique match is found, that file will be used to set the snapshot. -## Firebase Realtime Database backend +## Snapshot Debugger - Firebase Realtime Database Backend -The Cloud Debugger API is deprecated and will be turned down in May 2023. - -You can use Firebase Realtime Database for data persistence as an -alternative. - -### Enabling the agent +This functionality is available for release 6.0.0 onward of this agent and +provides support for the Snapshot Debugger, which is being provided as a +replacement for the deprecated Cloud Debugger service. To enable the agent, add the following at the top of your app's main script or entry point: @@ -120,17 +117,13 @@ require('@google-cloud/debug-agent').start({ ``` The following params are optional: -* firebaseDbUrl - https://**PROJECT_ID**-cdbg.firebaseio.com will be used if not - provided. where **PROJECT_ID** is your project ID. +* firebaseDbUrl - https://**PROJECT_ID**-cdbg.firebaseio.com will be used if + not provided. where **PROJECT_ID** is your project ID. * firebaseKeyPath - Default google application credentials are used if not provided. -### Using the Debugger - -Using the Debugger with the Firebase Realtime Database backend requires using -the Snapshot Debugger CLI. - -See the [full Snapshot Debugger CLI documentation][snapshot-debugger-readme]. +See https://github.com/GoogleCloudPlatform/snapshot-debugger and +https://cloud.google.com/debugger/docs/deprecations for more details. ## Limitations and Requirements diff --git a/package.json b/package.json index 62a602fc..ac59727c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@google-cloud/debug-agent", - "version": "7.2.1", + "version": "7.2.2", "author": "Google Inc.", "description": "Stackdriver Debug Agent for Node.js", "main": "./build/src/index", @@ -45,6 +45,7 @@ }, "dependencies": { "@google-cloud/common": "^4.0.0", + "@fastify/busboy": "1.1.0", "acorn": "^8.0.0", "coffeescript": "^2.0.0", "console-log-level": "^1.4.0", @@ -57,6 +58,11 @@ "source-map": "^0.8.0-beta.0", "split": "^1.0.0" }, + "overrides": { + "firebase-admin": { + "@fastify/busboy": "1.1.0" + } + }, "devDependencies": { "@compodoc/compodoc": "1.1.19", "@types/acorn": "^4.0.2", diff --git a/samples/package.json b/samples/package.json index d1f8dce1..a279069e 100644 --- a/samples/package.json +++ b/samples/package.json @@ -17,7 +17,7 @@ "test": "mocha" }, "dependencies": { - "@google-cloud/debug-agent": "^7.2.1", + "@google-cloud/debug-agent": "^7.2.2", "express": "4.18.2" }, "devDependencies": { diff --git a/src/agent/firebase-controller.ts b/src/agent/firebase-controller.ts index 968a56dd..455b43d9 100644 --- a/src/agent/firebase-controller.ts +++ b/src/agent/firebase-controller.ts @@ -31,6 +31,19 @@ const debuglog = util.debuglog('cdbg.firebase'); const FIREBASE_APP_NAME = 'cdbg'; +/** + * Waits ms milliseconds for the promise to resolve, or rejects with a timeout. + * @param ms + * @param promise + * @returns Promise wrapped in a timeout. + */ +const withTimeout = (ms: number, promise: Promise) => { + const timeout = new Promise((_, reject) => + setTimeout(() => reject(`Timed out after ${ms} ms.`), ms) + ); + return Promise.race([promise, timeout]); +}; + export class FirebaseController implements Controller { db: firebase.database.Database; debuggeeId?: string; @@ -75,54 +88,62 @@ export class FirebaseController implements Controller { } // Build the database URL. - let databaseUrl: string; + const databaseUrls = []; if (options.databaseUrl) { - databaseUrl = options.databaseUrl; + databaseUrls.push(options.databaseUrl); } else { - // TODO: Add fallback to -default - databaseUrl = `https://${projectId}-cdbg.firebaseio.com`; + databaseUrls.push(`https://${projectId}-cdbg.firebaseio.com`); + databaseUrls.push(`https://${projectId}-default-rtdb.firebaseio.com`); } - let app: firebase.app.App; - if (credential) { - app = firebase.initializeApp( - { - credential: credential, - databaseURL: databaseUrl, - }, - FIREBASE_APP_NAME - ); - } else { - // Use the default credentials. - app = firebase.initializeApp( - { - databaseURL: databaseUrl, - }, - FIREBASE_APP_NAME - ); - } + for (const databaseUrl of databaseUrls) { + let app: firebase.app.App; + if (credential) { + app = firebase.initializeApp( + { + credential: credential, + databaseURL: databaseUrl, + }, + FIREBASE_APP_NAME + ); + } else { + // Use the default credentials. + app = firebase.initializeApp( + { + databaseURL: databaseUrl, + }, + FIREBASE_APP_NAME + ); + } - const db = firebase.database(app); + const db = firebase.database(app); - // Test the connection by reading the schema version. - try { - const version_snapshot = await db.ref('cdbg/schema_version').get(); - if (version_snapshot) { - const version = version_snapshot.val(); - debuglog( - `Firebase app initialized. Connected to ${databaseUrl}` + - ` with schema version ${version}` + // Test the connection by reading the schema version. + try { + const version_snapshot = await withTimeout( + 10000, + db.ref('cdbg/schema_version').get() ); - } else { + if (version_snapshot) { + const version = version_snapshot.val(); + debuglog( + `Firebase app initialized. Connected to ${databaseUrl}` + + ` with schema version ${version}` + ); + + return db; + } else { + throw new Error('failed to fetch schema version from database'); + } + } catch (e) { + debuglog(`failed to connect to database ${databaseUrl}: ` + e); app.delete(); - throw new Error('failed to fetch schema version from database'); } - } catch (e) { - app.delete(); - throw e; } - return db; + throw new Error( + `Failed to initialize FirebaseApp, attempted URLs: ${databaseUrls}` + ); } /**