From 6d5d1761c3b2ac155f30e87be6e844e77a91bc24 Mon Sep 17 00:00:00 2001 From: Joanna Wang <annajowang@gmail.com> Date: Tue, 11 Feb 2025 01:25:33 +0000 Subject: [PATCH 1/2] Implement getBackend to auto-pick backends with duplicate names. --- src/apphosting/backend.ts | 50 ++++++++++++++++++++++++++++++++++++++- src/apphosting/rollout.ts | 5 ++-- 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/src/apphosting/backend.ts b/src/apphosting/backend.ts index 8a5aa579901..285b141eac4 100644 --- a/src/apphosting/backend.ts +++ b/src/apphosting/backend.ts @@ -17,7 +17,7 @@ import { Backend, BackendOutputOnlyFields, API_VERSION } from "../gcp/apphosting import { addServiceAccountToRoles } from "../gcp/resourceManager"; import * as iam from "../gcp/iam"; import { FirebaseError, getErrStatus, getError } from "../error"; -import { promptOnce } from "../prompt"; +import { promptOnce, confirm } from "../prompt"; import { DEFAULT_LOCATION } from "./constants"; import { ensure } from "../ensureApiEnabled"; import * as deploymentTool from "../deploymentTool"; @@ -474,3 +474,51 @@ export async function getBackendForAmbiguousLocation( }); return backendsByLocation.get(location)!; } + +/** + * Fetches a backend from the server. If there are multiple backends with the name, it will fetch the first + * in the list and warn the user that there are other backends with the same name that need to be deleted. If + * the force option is specified nad multiple backends have the same name, it throws an error. + */ +export async function getBackend( + projectId: string, + backendId: string, + force?: boolean, +): Promise<apphosting.Backend> { + // TODO: call apphosting.getBackend() once all duplicate named backends have been deleted. + let { unreachable, backends } = await apphosting.listBackends(projectId, "-"); + backends = backends.filter( + (backend) => apphosting.parseBackendName(backend.name).id === backendId, + ); + if (backends.length > 0) { + if (backends.length > 1) { + logWarning( + `You have multiple backends with the same ${backendId} ID. This is no longer supported. ` + + "Please delete and recreate any backends that share an ID with another backend." + ) + if (force) { + throw new FirebaseError( + `Force cannot be used when multiple backends share the same ID`, + ); + }; + const options = {force: force, nonInteractive: false }; + const confirmed = await confirm({ + ...options, + message: `Using backend ${backends[0].name} continue?`, + }); + if (!confirmed) { + throw new FirebaseError("Command aborted."); + } + } + return backends[0]; + } + if (unreachable && unreachable.length !== 0) { + logWarning( + `Backends with the following primary regions are unreachable: ${unreachable}.\n` + + "If your backend is in one of these regions, please try again later." + ); + }; + throw new FirebaseError( + `No backend named ${backendId} found.`, + ); +} diff --git a/src/apphosting/rollout.ts b/src/apphosting/rollout.ts index 32b2bcb8d4e..0a6dbc78b25 100644 --- a/src/apphosting/rollout.ts +++ b/src/apphosting/rollout.ts @@ -13,7 +13,7 @@ import * as poller from "../operation-poller"; import { logBullet, sleep } from "../utils"; import { apphostingOrigin, consoleOrigin } from "../api"; import { DeepOmit } from "../metaprogramming"; -import { getBackendForAmbiguousLocation, getBackendForLocation } from "./backend"; +import { getBackendForAmbiguousLocation, getBackendForLocation, getBackend } from "./backend"; const apphostingPollerOptions: Omit<poller.OperationPollerOptions, "operationResourceName"> = { apiOrigin: apphostingOrigin(), @@ -38,10 +38,9 @@ export async function createRollout( ): Promise<void> { let backend: apphosting.Backend; if (location === "-" || location === "") { - backend = await getBackendForAmbiguousLocation( + backend = await getBackend( projectId, backendId, - "Please select the location of the backend you'd like to roll out:", force, ); location = apphosting.parseBackendName(backend.name).location; From 06eb2c74a50a41e86fd6e032f85f8b0122c411bb Mon Sep 17 00:00:00 2001 From: Joanna Wang <annajowang@gmail.com> Date: Tue, 11 Feb 2025 01:49:27 +0000 Subject: [PATCH 2/2] Remove rollout.ts change --- src/apphosting/rollout.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/apphosting/rollout.ts b/src/apphosting/rollout.ts index 0a6dbc78b25..32b2bcb8d4e 100644 --- a/src/apphosting/rollout.ts +++ b/src/apphosting/rollout.ts @@ -13,7 +13,7 @@ import * as poller from "../operation-poller"; import { logBullet, sleep } from "../utils"; import { apphostingOrigin, consoleOrigin } from "../api"; import { DeepOmit } from "../metaprogramming"; -import { getBackendForAmbiguousLocation, getBackendForLocation, getBackend } from "./backend"; +import { getBackendForAmbiguousLocation, getBackendForLocation } from "./backend"; const apphostingPollerOptions: Omit<poller.OperationPollerOptions, "operationResourceName"> = { apiOrigin: apphostingOrigin(), @@ -38,9 +38,10 @@ export async function createRollout( ): Promise<void> { let backend: apphosting.Backend; if (location === "-" || location === "") { - backend = await getBackend( + backend = await getBackendForAmbiguousLocation( projectId, backendId, + "Please select the location of the backend you'd like to roll out:", force, ); location = apphosting.parseBackendName(backend.name).location;