Skip to content
7 changes: 7 additions & 0 deletions src/dataconnect/ensureApis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,10 @@ export async function ensureApis(projectId: string): Promise<void> {
await ensure(projectId, api.cloudSQLAdminOrigin(), prefix);
await ensure(projectId, api.computeOrigin(), prefix);
}

export async function ensureSparkApis(projectId: string): Promise<void> {
const prefix = "dataconnect";
// These are the APIs that can be enabled without a billing account.
await ensure(projectId, api.dataconnectOrigin(), prefix);
await ensure(projectId, api.cloudSQLAdminOrigin(), prefix);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh, TIL that this API doesn't require billing

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I was a little surprised by that haha

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

}
20 changes: 16 additions & 4 deletions src/init/features/dataconnect/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Setup } from "../..";
import { provisionCloudSql } from "../../../dataconnect/provisionCloudSql";
import { checkForFreeTrialInstance } from "../../../dataconnect/freeTrial";
import * as cloudsql from "../../../gcp/cloudsql/cloudsqladmin";
import { ensureApis } from "../../../dataconnect/ensureApis";
import { ensureApis, ensureSparkApis } from "../../../dataconnect/ensureApis";
import * as experiments from "../../../experiments";
import {
listLocations,
Expand All @@ -21,6 +21,7 @@ import { parseCloudSQLInstanceName, parseServiceName } from "../../../dataconnec
import { logger } from "../../../logger";
import { readTemplateSync } from "../../../templates";
import { logSuccess } from "../../../utils";
import { checkBillingEnabled } from "../../../gcp/cloudbilling";

const DATACONNECT_YAML_TEMPLATE = readTemplateSync("init/dataconnect/dataconnect.yaml");
const DATACONNECT_YAML_COMPAT_EXPERIMENT_TEMPLATE = readTemplateSync(
Expand Down Expand Up @@ -86,7 +87,8 @@ async function askQuestions(setup: Setup, config: Config): Promise<RequiredInfo>
schemaGql: [],
shouldProvisionCSQL: false,
};
info = await promptForService(setup, info);
const isBillingEnabled = setup.projectId ? await checkBillingEnabled(setup.projectId) : false;
info = await promptForService(setup, info, isBillingEnabled);

if (info.cloudSqlInstanceId === "") {
info = await promptForCloudSQLInstance(setup, info);
Expand All @@ -112,6 +114,7 @@ async function askQuestions(setup: Setup, config: Config): Promise<RequiredInfo>
info.shouldProvisionCSQL = !!(
setup.projectId &&
(info.isNewInstance || info.isNewDatabase) &&
isBillingEnabled &&
(await confirm({
message:
"Would you like to provision your CloudSQL instance and database now? This will take a few minutes.",
Expand Down Expand Up @@ -217,9 +220,18 @@ function subConnectorYamlValues(replacementValues: { connectorId: string }): str
return replaced;
}

async function promptForService(setup: Setup, info: RequiredInfo): Promise<RequiredInfo> {
async function promptForService(
setup: Setup,
info: RequiredInfo,
isBillingEnabled: boolean,
): Promise<RequiredInfo> {
if (setup.projectId) {
await ensureApis(setup.projectId);
if (isBillingEnabled) {
// Enabling compute.googleapis.com requires a Blaze plan.
await ensureApis(setup.projectId);
} else {
await ensureSparkApis(setup.projectId);
}
// TODO (b/344021748): Support initing with services that have existing sources/files
const existingServices = await listAllServices(setup.projectId);
const existingServicesAndSchemas = await Promise.all(
Expand Down