import { DB_SQL_INITIAL_TEXT, EditorLanguage, FormComponentType, InputDataType, Plugin, PluginResponseType, PluginType, FormItem } from '../../types/index.js'; import { PARAMETERIZED_SQL_DESCRIPTION, PUBLIC_INTEGRATIONS_LOGO_URL, DOCS_BASE_URL } from './constants.js'; import { makeDropdownItem } from './shared/db.js'; const DatabricksPluginVersions = { V1: '0.0.1', V2: '0.0.2', V3: '0.0.3', V4: '0.0.4', V5: '0.0.5' }; enum ConnectionType { PERSONAL_ACCESS_TOKEN = '1', MACHINE_TO_MACHINE = '2', OAUTH_TOKEN_FEDERATION = '3' } const CONNECTION_METHODS_AND_DISPLAY_NAMES_V2 = { [ConnectionType.MACHINE_TO_MACHINE]: 'Machine-to-machine', [ConnectionType.OAUTH_TOKEN_FEDERATION]: 'OAuth token federation', [ConnectionType.PERSONAL_ACCESS_TOKEN]: 'Personal access token' }; const BASE_HOST = { label: 'Host', name: 'connection.hostUrl', componentType: FormComponentType.INPUT_TEXT, placeholder: 'warehouse-staging.cloud.databricks.com', rules: [{ required: true, message: 'Host is required' }] }; const BASE_PORT = { label: 'Port', name: 'connection.port', componentType: FormComponentType.INPUT_TEXT, dataType: InputDataType.NUMBER, initialValue: 443, rules: [{ required: true, message: 'Port is required' }] }; const BASE_PATH = { label: 'Path', name: 'connection.path', componentType: FormComponentType.INPUT_TEXT, placeholder: '/sql/1.0/warehouses/warehouse', rules: [{ required: true, message: 'Path is required' }] }; const BASE_ACCESS_TOKEN = { label: 'Access token', name: 'connection.token', componentType: FormComponentType.INPUT_TEXT, dataType: InputDataType.PASSWORD, rules: [{ required: true, message: 'Access token is required' }] }; const BASE_DEFAULT_CATALOG = { label: 'Default catalog', name: 'connection.defaultCatalog', componentType: FormComponentType.INPUT_TEXT, placeholder: 'catalog' }; const BASE_DEFAULT_SCHEMA = { label: 'Default schema', name: 'connection.defaultSchema', componentType: FormComponentType.INPUT_TEXT, placeholder: 'default' }; const BASE_SCOPED_CATALOG_SCHEMAS = { label: 'Scoped catalogs and schemas', name: 'connection.scopedCatalogSchemas', componentType: FormComponentType.INPUT_TEXT, placeholder: 'catalog1.schema1, catalog1.schema2, catalog2', initialValue: '', ldFlag: 'integrations.databricks.scoped', tooltip: { markdownText: 'Comma-separated list of catalog.schema pairs. Use just catalog name (without dot) to include all schemas from that catalog.' } }; const BASE_SUBJECT_TOKEN_SOURCE = { label: 'Subject token source', name: 'authConfig.subjectTokenSource', componentType: FormComponentType.DROPDOWN, initialValue: 'SUBJECT_TOKEN_SOURCE_LOGIN_IDENTITY_PROVIDER', rules: [{ required: true, message: 'Subject token source is required' }], options: [ makeDropdownItem('SUBJECT_TOKEN_SOURCE_LOGIN_IDENTITY_PROVIDER', 'Login Identity Provider'), makeDropdownItem('SUBJECT_TOKEN_SOURCE_STATIC_TOKEN', 'Static Token') ] }; const BASE_TOKEN_URL = { label: 'Token URL', name: 'authConfig.tokenUrl', componentType: FormComponentType.INPUT_TEXT, placeholder: 'https://your-token-endpoint.com/oauth/token', rules: [{ required: true, message: 'Token URL is required' }] }; const BASE_CLIENT_ID = { label: 'Service Principal UUID', name: 'authConfig.clientId', componentType: FormComponentType.INPUT_TEXT, placeholder: 'optional-service-principal-uuid', rules: [{ required: false }] }; const BASE_STATIC_TOKEN = { label: 'Static Token', name: 'authConfig.subjectTokenSourceStaticToken', componentType: FormComponentType.INPUT_TEXT, dataType: InputDataType.PASSWORD, // Hidden input for security rules: [{ required: true, message: 'Static token is required when using static token source' }] }; const BASE_SCOPE = { label: 'Scope', name: 'authConfig.scope', componentType: FormComponentType.INPUT_TEXT, initialValue: 'all-apis', rules: [{ required: true }] }; export const DatabricksPlugin: Plugin = { id: 'databricks', name: 'Databricks SQL Warehouse', moduleName: 'DatabricksPlugin', modulePath: 'plugins/databricks/DatabricksPlugin', iconLocation: `${PUBLIC_INTEGRATIONS_LOGO_URL}/databricks.png`, docsUrl: `${DOCS_BASE_URL}/databricks`, type: PluginType.DB, responseType: PluginResponseType.TABLE, hasRawRequest: true, hasMetadata: true, rawRequestName: 'Executed SQL', datasourceTemplate: { sections: [ { name: 'main', items: [ { label: 'Display name', name: 'name', startVersion: DatabricksPluginVersions.V1, componentType: FormComponentType.INPUT_TEXT, placeholder: 'ProdDB', rules: [{ required: true, message: 'Display name is required' }] }, { label: 'Auth Type Field', name: 'authTypeField', hidden: true, componentType: FormComponentType.INPUT_TEXT, startVersion: DatabricksPluginVersions.V3, initialValue: 'oauthType', rules: [{ required: false }], display: { show: { 'connection.connectionType': [ConnectionType.OAUTH_TOKEN_FEDERATION] } } }, { label: 'OAuth Type', name: 'oauthType', hidden: true, componentType: FormComponentType.INPUT_TEXT, startVersion: DatabricksPluginVersions.V3, initialValue: 'oauth-token-exchange', rules: [{ required: false }], display: { show: { 'connection.connectionType': [ConnectionType.OAUTH_TOKEN_FEDERATION] } } }, { label: 'Subject Token Type', name: 'authConfig.subjectTokenType', hidden: true, componentType: FormComponentType.INPUT_TEXT, startVersion: DatabricksPluginVersions.V3, initialValue: 'urn:ietf:params:oauth:token-type:jwt', rules: [{ required: false }], display: { show: { 'connection.connectionType': [ConnectionType.OAUTH_TOKEN_FEDERATION] } } }, // HOST { ...BASE_HOST, startVersion: DatabricksPluginVersions.V1, endVersion: DatabricksPluginVersions.V1 } as FormItem, { ...BASE_HOST, startVersion: DatabricksPluginVersions.V2, display: { show: { 'connection.connectionType': [ ConnectionType.PERSONAL_ACCESS_TOKEN, ConnectionType.MACHINE_TO_MACHINE, ConnectionType.OAUTH_TOKEN_FEDERATION ] } } } as FormItem, // PORT { ...BASE_PORT, startVersion: DatabricksPluginVersions.V1, endVersion: DatabricksPluginVersions.V1 } as FormItem, { ...BASE_PORT, startVersion: DatabricksPluginVersions.V2, display: { show: { 'connection.connectionType': [ ConnectionType.PERSONAL_ACCESS_TOKEN, ConnectionType.MACHINE_TO_MACHINE, ConnectionType.OAUTH_TOKEN_FEDERATION ] } } } as FormItem, // PATH { ...BASE_PATH, startVersion: DatabricksPluginVersions.V1, endVersion: DatabricksPluginVersions.V1 } as FormItem, { ...BASE_PATH, startVersion: DatabricksPluginVersions.V2, display: { show: { 'connection.connectionType': [ ConnectionType.PERSONAL_ACCESS_TOKEN, ConnectionType.MACHINE_TO_MACHINE, ConnectionType.OAUTH_TOKEN_FEDERATION ] } } } as FormItem, // SCOPED CATALOG SCHEMAS (shown when feature flag is enabled) { ...BASE_SCOPED_CATALOG_SCHEMAS, startVersion: DatabricksPluginVersions.V4, display: { show: { 'connection.connectionType': [ ConnectionType.PERSONAL_ACCESS_TOKEN, ConnectionType.MACHINE_TO_MACHINE, ConnectionType.OAUTH_TOKEN_FEDERATION ] } } } as FormItem, { ...BASE_DEFAULT_CATALOG, startVersion: DatabricksPluginVersions.V1, endVersion: DatabricksPluginVersions.V1 } as FormItem, { ...BASE_DEFAULT_CATALOG, startVersion: DatabricksPluginVersions.V2, display: { show: { 'connection.connectionType': [ ConnectionType.PERSONAL_ACCESS_TOKEN, ConnectionType.MACHINE_TO_MACHINE, ConnectionType.OAUTH_TOKEN_FEDERATION ] } } } as FormItem, { ...BASE_DEFAULT_SCHEMA, startVersion: DatabricksPluginVersions.V1, endVersion: DatabricksPluginVersions.V1 } as FormItem, { ...BASE_DEFAULT_SCHEMA, startVersion: DatabricksPluginVersions.V2, display: { show: { 'connection.connectionType': [ ConnectionType.PERSONAL_ACCESS_TOKEN, ConnectionType.MACHINE_TO_MACHINE, ConnectionType.OAUTH_TOKEN_FEDERATION ] } } } as FormItem, { label: 'Connection method', name: 'connection.connectionType', startVersion: DatabricksPluginVersions.V2, endVersion: DatabricksPluginVersions.V2, componentType: FormComponentType.DROPDOWN, initialValue: ConnectionType.MACHINE_TO_MACHINE, rules: [{ required: true }], options: Object.entries(CONNECTION_METHODS_AND_DISPLAY_NAMES_V2).map(([value, displayName]) => makeDropdownItem(value, displayName) ) }, { label: 'Connection method', name: 'connection.connectionType', startVersion: DatabricksPluginVersions.V3, componentType: FormComponentType.DROPDOWN, initialValue: ConnectionType.MACHINE_TO_MACHINE, rules: [{ required: true }], options: Object.entries(CONNECTION_METHODS_AND_DISPLAY_NAMES_V2).map(([value, displayName]) => makeDropdownItem(value, displayName) ) }, // ACCESS TOKEN { ...BASE_ACCESS_TOKEN, startVersion: DatabricksPluginVersions.V1, endVersion: DatabricksPluginVersions.V1 } as FormItem, { ...BASE_ACCESS_TOKEN, startVersion: DatabricksPluginVersions.V2, display: { show: { 'connection.connectionType': [ConnectionType.PERSONAL_ACCESS_TOKEN] } } } as FormItem, // OAUTH CLIENT ID { label: 'OAuth client ID', name: 'connection.oauthClientId', componentType: FormComponentType.INPUT_TEXT, rules: [{ required: true, message: 'OAuth client ID is required' }], startVersion: DatabricksPluginVersions.V2, display: { show: { 'connection.connectionType': [ConnectionType.MACHINE_TO_MACHINE] } } } as FormItem, // OAUTH CLIENT SECRET { label: 'OAuth client secret', name: 'connection.oauthClientSecret', componentType: FormComponentType.INPUT_TEXT, dataType: InputDataType.PASSWORD, rules: [{ required: true, message: 'OAuth client secret is required' }], startVersion: DatabricksPluginVersions.V2, display: { show: { 'connection.connectionType': [ConnectionType.MACHINE_TO_MACHINE] } } } as FormItem, { ...BASE_SUBJECT_TOKEN_SOURCE, startVersion: DatabricksPluginVersions.V3, display: { show: { 'connection.connectionType': [ConnectionType.OAUTH_TOKEN_FEDERATION] } } } as FormItem, { ...BASE_STATIC_TOKEN, startVersion: DatabricksPluginVersions.V3, display: { show: { 'connection.connectionType': [ConnectionType.OAUTH_TOKEN_FEDERATION], 'authConfig.subjectTokenSource': ['SUBJECT_TOKEN_SOURCE_STATIC_TOKEN'] } } } as FormItem, { ...BASE_TOKEN_URL, startVersion: DatabricksPluginVersions.V3, display: { show: { 'connection.connectionType': [ConnectionType.OAUTH_TOKEN_FEDERATION] } } } as FormItem, { ...BASE_CLIENT_ID, startVersion: DatabricksPluginVersions.V3, display: { show: { 'connection.connectionType': [ConnectionType.OAUTH_TOKEN_FEDERATION] } } } as FormItem, { ...BASE_SCOPE, startVersion: DatabricksPluginVersions.V3, // NOTE: @joeyagreco - `all-apis` is the only scope that databricks allows, so we just hardcode and hide to prevent users from changing and having connection issues hidden: true, initialValue: 'all-apis', display: { show: { 'connection.connectionType': [ConnectionType.OAUTH_TOKEN_FEDERATION] } } } as FormItem ] } ] }, actionTemplate: { sections: [ { name: 'main', items: [ { // Hidden operation field to prevent wrapStringInterpolation from adding backticks label: 'Operation', name: 'operation', hidden: true, startVersion: DatabricksPluginVersions.V1, componentType: FormComponentType.DROPDOWN, initialValue: 'SQL_OPERATION_RUN_SQL', options: [makeDropdownItem('SQL_OPERATION_RUN_SQL', 'Run SQL')] }, { label: 'Parameters (:PARAM_1, :PARAM_2, ...)', name: 'runSql.parameters', startVersion: DatabricksPluginVersions.V5, ldFlag: 'clark.parameterized-apis.v2.enabled', componentType: FormComponentType.DYNAMIC_INPUT_TEXT, placeholder: '[param1, param2, ...]', tooltip: { markdownText: 'JavaScript expression that evaluates to an array of parameter values. Use `:PARAM_1`, `:PARAM_2`, etc. in your SQL query to reference these parameters.' } }, { label: '', // Query name: 'runSql.sqlBody', startVersion: DatabricksPluginVersions.V1, endVersion: DatabricksPluginVersions.V4, componentType: FormComponentType.CODE_EDITOR, language: EditorLanguage.SQL, initialValue: DB_SQL_INITIAL_TEXT }, { label: '', // Query name: 'runSql.sqlBody', startVersion: DatabricksPluginVersions.V5, componentType: FormComponentType.CODE_EDITOR, language: EditorLanguage.SQL, initialValue: DB_SQL_INITIAL_TEXT } ] }, { name: 'advanced:main', items: [ { label: 'Use parameterized SQL', name: 'runSql.useParameterized', startVersion: DatabricksPluginVersions.V1, endVersion: DatabricksPluginVersions.V4, componentType: FormComponentType.SWITCH, initialValue: true, tooltip: { markdownText: PARAMETERIZED_SQL_DESCRIPTION } }, { label: 'Use parameterized SQL', name: 'runSql.useParameterized', startVersion: DatabricksPluginVersions.V5, ldFlag: '!clark.parameterized-apis.v2.enabled', componentType: FormComponentType.SWITCH, initialValue: true, tooltip: { markdownText: PARAMETERIZED_SQL_DESCRIPTION }, display: { show: { 'runSql.parameters': ['undefined'] } } }, { label: 'Use parameterized SQL', name: 'runSql.useParameterized', startVersion: DatabricksPluginVersions.V5, ldFlag: 'clark.parameterized-apis.v2.enabled', componentType: FormComponentType.SWITCH, initialValue: undefined, tooltip: { markdownText: PARAMETERIZED_SQL_DESCRIPTION }, display: { show: { 'runSql.parameters': ['undefined'] } } } ] } ] } };