diff --git a/packages/databricks-vscode-types/index.ts b/packages/databricks-vscode-types/index.ts index c0f1792fb..ab129cdf3 100644 --- a/packages/databricks-vscode-types/index.ts +++ b/packages/databricks-vscode-types/index.ts @@ -12,6 +12,7 @@ export interface PublicApi { connectionManager: { onDidChangeState: Event; + login(interactive?: boolean, force?: boolean): Promise; waitForConnect(): Promise; get state(): ConnectionState; diff --git a/packages/databricks-vscode/src/configuration/ConnectionManager.ts b/packages/databricks-vscode/src/configuration/ConnectionManager.ts index 1be1f50f2..2a31b5757 100644 --- a/packages/databricks-vscode/src/configuration/ConnectionManager.ts +++ b/packages/databricks-vscode/src/configuration/ConnectionManager.ts @@ -23,6 +23,7 @@ import {Mutex} from "../locking"; import {MetadataService} from "./auth/MetadataService"; import {Events, Telemetry} from "../telemetry"; import {AutoLoginSource, ManualLoginSource} from "../telemetry/constants"; +import {Barrier} from "../locking/Barrier"; // eslint-disable-next-line @typescript-eslint/naming-convention const {NamedLogger} = logging; @@ -59,6 +60,8 @@ export class ConnectionManager implements Disposable { public readonly onDidChangeSyncDestination = this.onDidChangeSyncDestinationEmitter.event; + private readonly initialization = new Barrier(); + constructor( private cli: CliWrapper, private readonly configModel: ConfigModel, @@ -169,6 +172,7 @@ export class ConnectionManager implements Disposable { this.loginWithSavedAuth.bind(this, "targetChange") ) ); + this.initialization.resolve(); } } @@ -205,6 +209,14 @@ export class ConnectionManager implements Disposable { return this.apiClient?.config.authType; } + // Only used through public API + public async login(interactive?: boolean, force?: boolean) { + await this.initialization.promise; + if (this.state !== "CONNECTED" || force) { + await this.configureLogin("api"); + } + } + private async loginWithSavedAuth(source: AutoLoginSource) { const recordEvent = this.telemetry.start(Events.AUTO_LOGIN); try { diff --git a/packages/databricks-vscode/src/locking/Barrier.ts b/packages/databricks-vscode/src/locking/Barrier.ts new file mode 100644 index 000000000..4c741a4b2 --- /dev/null +++ b/packages/databricks-vscode/src/locking/Barrier.ts @@ -0,0 +1,9 @@ +export class Barrier { + public promise: Promise; + public resolve: () => void = () => {}; + constructor() { + this.promise = new Promise((resolve) => { + this.resolve = resolve; + }); + } +} diff --git a/packages/databricks-vscode/src/telemetry/constants.ts b/packages/databricks-vscode/src/telemetry/constants.ts index 5b578ed0a..f786fc0ed 100644 --- a/packages/databricks-vscode/src/telemetry/constants.ts +++ b/packages/databricks-vscode/src/telemetry/constants.ts @@ -23,7 +23,11 @@ export enum Events { /* eslint-enable @typescript-eslint/naming-convention */ export type AutoLoginSource = "init" | "hostChange" | "targetChange"; -export type ManualLoginSource = "authTypeSwitch" | "authTypeLogin" | "command"; +export type ManualLoginSource = + | "authTypeSwitch" + | "authTypeLogin" + | "command" + | "api"; export type BundleRunResourceType = "pipelines" | "jobs"; /** Documentation about all of the properties and metrics of the event. */