Skip to content

Commit

Permalink
migrate management API calls to apiv2 (#4569)
Browse files Browse the repository at this point in the history
* migrate management API calls to apiv2

* omit only

* fix method

* delete in the right spot
  • Loading branch information
bkendall committed May 19, 2022
1 parent cb8afa8 commit d86c387
Show file tree
Hide file tree
Showing 6 changed files with 400 additions and 658 deletions.
125 changes: 59 additions & 66 deletions src/management/apps.ts
@@ -1,12 +1,13 @@
import * as fs from "fs";

import * as api from "../api";
import { Client } from "../apiv2";
import { firebaseApiOrigin } from "../api";
import { FirebaseError } from "../error";
import { logger } from "../logger";
import { pollOperation } from "../operation-poller";

const TIMEOUT_MILLIS = 30000;
const APP_LIST_PAGE_SIZE = 100;
export const APP_LIST_PAGE_SIZE = 100;
const CREATE_APP_API_REQUEST_TIMEOUT_MILLIS = 15000;

const WEB_CONFIG_FILE_NAME = "google-config.js";
Expand Down Expand Up @@ -84,6 +85,8 @@ export function getAppPlatform(platform: string): AppPlatform {
}
}

const apiClient = new Client({ urlPrefix: firebaseApiOrigin, apiVersion: "v1beta1" });

/**
* Send an API request to create a new Firebase iOS app and poll the LRO to get the new app
* information.
Expand All @@ -96,16 +99,19 @@ export async function createIosApp(
options: { displayName?: string; appStoreId?: string; bundleId: string }
): Promise<IosAppMetadata> {
try {
const response = await api.request("POST", `/v1beta1/projects/${projectId}/iosApps`, {
auth: true,
origin: api.firebaseApiOrigin,
const response = await apiClient.request<
{ displayName?: string; appStoreId?: string; bundleId: string },
{ name: string }
>({
method: "POST",
path: `/projects/${projectId}/iosApps`,
timeout: CREATE_APP_API_REQUEST_TIMEOUT_MILLIS,
data: options,
body: options,
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const appData = await pollOperation<any>({
pollerName: "Create iOS app Poller",
apiOrigin: api.firebaseApiOrigin,
apiOrigin: firebaseApiOrigin,
apiVersion: "v1beta1",
operationResourceName: response.body.name /* LRO resource name */,
});
Expand All @@ -131,16 +137,19 @@ export async function createAndroidApp(
options: { displayName?: string; packageName: string }
): Promise<AndroidAppMetadata> {
try {
const response = await api.request("POST", `/v1beta1/projects/${projectId}/androidApps`, {
auth: true,
origin: api.firebaseApiOrigin,
const response = await apiClient.request<
{ displayName?: string; packageName: string },
{ name: string }
>({
method: "POST",
path: `/projects/${projectId}/androidApps`,
timeout: CREATE_APP_API_REQUEST_TIMEOUT_MILLIS,
data: options,
body: options,
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const appData = await pollOperation<any>({
pollerName: "Create Android app Poller",
apiOrigin: api.firebaseApiOrigin,
apiOrigin: firebaseApiOrigin,
apiVersion: "v1beta1",
operationResourceName: response.body.name /* LRO resource name */,
});
Expand Down Expand Up @@ -169,16 +178,16 @@ export async function createWebApp(
options: { displayName?: string }
): Promise<WebAppMetadata> {
try {
const response = await api.request("POST", `/v1beta1/projects/${projectId}/webApps`, {
auth: true,
origin: api.firebaseApiOrigin,
const response = await apiClient.request<{ displayName?: string }, { name: string }>({
method: "POST",
path: `/projects/${projectId}/webApps`,
timeout: CREATE_APP_API_REQUEST_TIMEOUT_MILLIS,
data: options,
body: options,
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const appData = await pollOperation<any>({
pollerName: "Create Web app Poller",
apiOrigin: api.firebaseApiOrigin,
apiOrigin: firebaseApiOrigin,
apiVersion: "v1beta1",
operationResourceName: response.body.name /* LRO resource name */,
});
Expand Down Expand Up @@ -211,7 +220,7 @@ function getListAppsResourceString(projectId: string, platform: AppPlatform): st
throw new FirebaseError("Unexpected platform. Only support iOS, Android and Web apps");
}

return `/v1beta1/projects/${projectId}${resourceSuffix}`;
return `/projects/${projectId}${resourceSuffix}`;
}

/**
Expand All @@ -229,19 +238,18 @@ export async function listFirebaseApps(
): Promise<AppMetadata[]> {
const apps: AppMetadata[] = [];
try {
let nextPageToken = "";
let nextPageToken: string | undefined;
do {
const pageTokenQueryString = nextPageToken ? `&pageToken=${nextPageToken}` : "";
const response = await api.request(
"GET",
getListAppsResourceString(projectId, platform) +
`?pageSize=${pageSize}${pageTokenQueryString}`,
{
auth: true,
origin: api.firebaseApiOrigin,
timeout: TIMEOUT_MILLIS,
}
);
const queryParams: { pageSize: number; pageToken?: string } = { pageSize };
if (nextPageToken) {
queryParams.pageToken = nextPageToken;
}
const response = await apiClient.request<void, { apps: any[]; nextPageToken?: string }>({
method: "GET",
path: getListAppsResourceString(projectId, platform),
queryParams,
timeout: TIMEOUT_MILLIS,
});
if (response.body.apps) {
const appsOnPage = response.body.apps.map(
// app.platform does not exist if we use the endpoint for a specific platform
Expand Down Expand Up @@ -283,7 +291,7 @@ function getAppConfigResourceString(appId: string, platform: AppPlatform): strin
throw new FirebaseError("Unexpected app platform");
}

return `/v1beta1/projects/-/${platformResource}/${appId}/config`;
return `/projects/-/${platformResource}/${appId}/config`;
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand Down Expand Up @@ -323,13 +331,13 @@ export function getAppConfigFile(config: any, platform: AppPlatform): AppConfigu
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export async function getAppConfig(appId: string, platform: AppPlatform): Promise<any> {
let response;
try {
response = await api.request("GET", getAppConfigResourceString(appId, platform), {
auth: true,
origin: api.firebaseApiOrigin,
const response = await apiClient.request<void, any>({
method: "GET",
path: getAppConfigResourceString(appId, platform),
timeout: TIMEOUT_MILLIS,
});
return response.body;
} catch (err: any) {
logger.debug(err.message);
throw new FirebaseError(
Expand All @@ -340,7 +348,6 @@ export async function getAppConfig(appId: string, platform: AppPlatform): Promis
}
);
}
return response.body;
}

/**
Expand All @@ -355,14 +362,11 @@ export async function listAppAndroidSha(
): Promise<AppAndroidShaData[]> {
const shaCertificates: AppAndroidShaData[] = [];
try {
const response = await api.request(
"GET",
`/v1beta1/projects/${projectId}/androidApps/${appId}/sha`,
{
auth: true,
origin: api.firebaseApiOrigin,
}
);
const response = await apiClient.request<void, any>({
method: "GET",
path: `/projects/${projectId}/androidApps/${appId}/sha`,
timeout: CREATE_APP_API_REQUEST_TIMEOUT_MILLIS,
});
if (response.body.certificates) {
shaCertificates.push(...response.body.certificates);
}
Expand Down Expand Up @@ -394,19 +398,13 @@ export async function createAppAndroidSha(
options: { shaHash: string; certType: string }
): Promise<AppAndroidShaData> {
try {
const response = await api.request(
"POST",
`/v1beta1/projects/${projectId}/androidApps/${appId}/sha`,
{
auth: true,
origin: api.firebaseApiOrigin,
timeout: CREATE_APP_API_REQUEST_TIMEOUT_MILLIS,
data: options,
}
);

const response = await apiClient.request<{ shaHash: string; certType: string }, any>({
method: "POST",
path: `/projects/${projectId}/androidApps/${appId}/sha`,
body: options,
timeout: CREATE_APP_API_REQUEST_TIMEOUT_MILLIS,
});
const shaCertificate = response.body;

return shaCertificate;
} catch (err: any) {
logger.debug(err.message);
Expand All @@ -432,16 +430,11 @@ export async function deleteAppAndroidSha(
shaId: string
): Promise<void> {
try {
await api.request(
"DELETE",
`/v1beta1/projects/${projectId}/androidApps/${appId}/sha/${shaId}`,
{
auth: true,
origin: api.firebaseApiOrigin,
timeout: CREATE_APP_API_REQUEST_TIMEOUT_MILLIS,
data: null,
}
);
await apiClient.request<void, void>({
method: "DELETE",
path: `/projects/${projectId}/androidApps/${appId}/sha/${shaId}`,
timeout: CREATE_APP_API_REQUEST_TIMEOUT_MILLIS,
});
} catch (err: any) {
logger.debug(err.message);
throw new FirebaseError(
Expand Down
97 changes: 42 additions & 55 deletions src/management/database.ts
Expand Up @@ -3,14 +3,16 @@
* Internal documentation: https://source.corp.google.com/piper///depot/google3/google/firebase/database/v1beta/rtdb_service.proto
*/

import * as api from "../api";
import { Client } from "../apiv2";
import { Constants } from "../emulator/constants";
import { FirebaseError } from "../error";
import { logger } from "../logger";
import { rtdbManagementOrigin } from "../api";
import * as utils from "../utils";
import { FirebaseError } from "../error";
import { Constants } from "../emulator/constants";
const MGMT_API_VERSION = "v1beta";

export const MGMT_API_VERSION = "v1beta";
export const APP_LIST_PAGE_SIZE = 100;
const TIMEOUT_MILLIS = 10000;
const APP_LIST_PAGE_SIZE = 100;
const INSTANCE_RESOURCE_NAME_REGEX = /projects\/([^/]+?)\/locations\/([^/]+?)\/instances\/([^/]*)/;

export enum DatabaseInstanceType {
Expand Down Expand Up @@ -42,6 +44,8 @@ export interface DatabaseInstance {
state: DatabaseInstanceState;
}

const apiClient = new Client({ urlPrefix: rtdbManagementOrigin, apiVersion: MGMT_API_VERSION });

/**
* Populate instanceDetails in commandOptions.
* @param options command options that will be modified to add instanceDetails.
Expand All @@ -62,16 +66,11 @@ export async function getDatabaseInstanceDetails(
instanceName: string
): Promise<DatabaseInstance> {
try {
const response = await api.request(
"GET",
`/${MGMT_API_VERSION}/projects/${projectId}/locations/-/instances/${instanceName}`,
{
auth: true,
origin: api.rtdbManagementOrigin,
timeout: TIMEOUT_MILLIS,
}
);

const response = await apiClient.request({
method: "GET",
path: `/projects/${projectId}/locations/-/instances/${instanceName}`,
timeout: TIMEOUT_MILLIS,
});
return convertDatabaseInstance(response.body);
} catch (err: any) {
logger.debug(err.message);
Expand All @@ -88,10 +87,10 @@ export async function getDatabaseInstanceDetails(
state: DatabaseInstanceState.ACTIVE,
});
}
return utils.reject(
throw new FirebaseError(
`Failed to get instance details for instance: ${instanceName}. See firebase-debug.log for more details.`,
{
code: 2,
exit: 2,
original: err,
}
);
Expand All @@ -112,18 +111,13 @@ export async function createInstance(
databaseType: DatabaseInstanceType
): Promise<DatabaseInstance> {
try {
const response = await api.request(
"POST",
`/${MGMT_API_VERSION}/projects/${projectId}/locations/${location}/instances?databaseId=${instanceName}`,
{
auth: true,
origin: api.rtdbManagementOrigin,
timeout: TIMEOUT_MILLIS,
data: {
type: databaseType,
},
}
);
const response = await apiClient.request({
method: "POST",
path: `/projects/${projectId}/locations/${location}/instances`,
queryParams: { databaseId: instanceName },
body: { type: databaseType },
timeout: TIMEOUT_MILLIS,
});

return convertDatabaseInstance(response.body);
} catch (err: any) {
Expand Down Expand Up @@ -156,21 +150,14 @@ export async function checkInstanceNameAvailable(
location = DatabaseLocation.US_CENTRAL1;
}
try {
await api.request(
"POST",
`/${MGMT_API_VERSION}/projects/${projectId}/locations/${location}/instances?databaseId=${instanceName}&validateOnly=true`,
{
auth: true,
origin: api.rtdbManagementOrigin,
timeout: TIMEOUT_MILLIS,
data: {
type: databaseType,
},
}
);
return {
available: true,
};
await apiClient.request({
method: "POST",
path: `/projects/${projectId}/locations/${location}/instances`,
queryParams: { databaseId: instanceName, validateOnly: "true" },
body: { type: databaseType },
timeout: TIMEOUT_MILLIS,
});
return { available: true };
} catch (err: any) {
logger.debug(
`Invalid Realtime Database instance name: ${instanceName}.${
Expand Down Expand Up @@ -237,18 +224,18 @@ export async function listDatabaseInstances(
): Promise<DatabaseInstance[]> {
const instances: DatabaseInstance[] = [];
try {
let nextPageToken = "";
let nextPageToken: string | undefined = "";
do {
const pageTokenQueryString = nextPageToken ? `&pageToken=${nextPageToken}` : "";
const response = await api.request(
"GET",
`/${MGMT_API_VERSION}/projects/${projectId}/locations/${location}/instances?pageSize=${pageSize}${pageTokenQueryString}`,
{
auth: true,
origin: api.rtdbManagementOrigin,
timeout: TIMEOUT_MILLIS,
}
);
const queryParams: { pageSize: number; pageToken?: string } = { pageSize };
if (nextPageToken) {
queryParams.pageToken = nextPageToken;
}
const response = await apiClient.request<void, { instances: any[]; nextPageToken?: string }>({
method: "GET",
path: `/projects/${projectId}/locations/${location}/instances`,
queryParams,
timeout: TIMEOUT_MILLIS,
});
if (response.body.instances) {
instances.push(...response.body.instances.map(convertDatabaseInstance));
}
Expand Down

0 comments on commit d86c387

Please sign in to comment.