diff --git a/components/databricks/actions/create-sql-warehouse/create-sql-warehouse.mjs b/components/databricks/actions/create-sql-warehouse/create-sql-warehouse.mjs new file mode 100644 index 0000000000000..3efeb90ef1d60 --- /dev/null +++ b/components/databricks/actions/create-sql-warehouse/create-sql-warehouse.mjs @@ -0,0 +1,171 @@ +import databricks from "../../databricks.app.mjs"; +import constants from "../../common/constants.mjs"; +import utils from "../../common/utils.mjs"; +import { ConfigurationError } from "@pipedream/platform"; + +export default { + key: "databricks-create-sql-warehouse", + name: "Create SQL Warehouse", + description: "Creates a new SQL Warehouse in Databricks. [See the documentation](https://docs.databricks.com/api/workspace/warehouses/create)", + version: "0.0.1", + type: "action", + props: { + databricks, + name: { + type: "string", + label: "Warehouse Name", + description: "A human-readable name for the warehouse", + }, + clusterSize: { + type: "string", + label: "Cluster Size", + description: "Size of the cluster", + options: constants.CLUSTER_SIZES, + }, + autoStopMinutes: { + type: "integer", + label: "Auto Stop (minutes)", + description: + "Minutes of inactivity before auto-stop. 0 disables auto-stop. Must be 0 or ≥ 10.", + optional: true, + default: 10, + }, + minNumClusters: { + type: "integer", + label: "Min Number of Clusters", + description: "Minimum number of clusters to maintain (> 0 and ≤ min(max_num_clusters, 30)).", + optional: true, + default: 1, + }, + maxNumClusters: { + type: "integer", + label: "Max Number of Clusters", + description: "Maximum number of clusters for autoscaler (≥ min_num_clusters and ≤ 30).", + optional: true, + default: 1, + }, + enablePhoton: { + type: "boolean", + label: "Enable Photon", + description: "Whether the warehouse should use Photon optimized clusters.", + optional: true, + }, + enableServerlessCompute: { + type: "boolean", + label: "Enable Serverless Compute", + description: "Whether the warehouse should use serverless compute.", + optional: true, + }, + warehouseType: { + type: "string", + label: "Warehouse Type", + description: + "Warehouse type: PRO or CLASSIC. Set PRO + enableServerlessCompute = true to use serverless.", + options: [ + "TYPE_UNSPECIFIED", + "CLASSIC", + "PRO", + ], + optional: true, + }, + spotInstancePolicy: { + type: "string", + label: "Spot Instance Policy", + description: "Configures whether the warehouse should use spot instances.", + options: [ + "POLICY_UNSPECIFIED", + "COST_OPTIMIZED", + "RELIABILITY_OPTIMIZED", + ], + optional: true, + }, + channel: { + type: "object", + label: "Channel", + description: + "Channel details. Example: `{ \"name\": \"CHANNEL_NAME_CUSTOM\", \"dbsql_version\": \"2023.35\" }`", + optional: true, + }, + tags: { + type: "object", + label: "Tags", + description: + "Custom key-value tags for resources associated with this SQL Warehouse.", + optional: true, + }, + instanceProfileArn: { + type: "string", + label: "Instance Profile ARN (Deprecated)", + description: "Deprecated. Instance profile used to pass IAM role to the cluster.", + optional: true, + }, + }, + + async run({ $ }) { + const payload = { + name: this.name, + cluster_size: this.clusterSize, + }; + + if (this.autoStopMinutes !== undefined) { + if (this.autoStopMinutes !== 0 && this.autoStopMinutes < 10) { + throw new ConfigurationError("autoStopMinutes must be 0 or ≥ 10."); + } + payload.auto_stop_mins = this.autoStopMinutes; + } + + const minNumClusters = this.minNumClusters ?? 1; + if (minNumClusters < 1 || minNumClusters > 30) { + throw new ConfigurationError("minNumClusters must be between 1 and 30."); + } + payload.min_num_clusters = minNumClusters; + + if (this.maxNumClusters !== undefined) { + if ( + this.maxNumClusters < payload.min_num_clusters || + this.maxNumClusters > 30 + ) { + throw new ConfigurationError( + `maxNumClusters must be ≥ minNumClusters (${payload.min_num_clusters}) and ≤ 30.`, + ); + } + payload.max_num_clusters = this.maxNumClusters; + } + + const parsedTags = utils.parseObject(this.tags); + const tagArray = Object.entries(parsedTags).map(([ + key, + value, + ]) => ({ + key, + value, + })); + if (tagArray.length) { + payload.tags = { + custom_tags: tagArray, + }; + } + + if (this.enablePhoton !== undefined) + payload.enable_photon = this.enablePhoton; + if (this.enableServerlessCompute !== undefined) + payload.enable_serverless_compute = this.enableServerlessCompute; + if (this.warehouseType) payload.warehouse_type = this.warehouseType; + if (this.spotInstancePolicy) + payload.spot_instance_policy = this.spotInstancePolicy; + if (this.channel) payload.channel = utils.parseObject(this.channel); + if (this.instanceProfileArn) + payload.instance_profile_arn = this.instanceProfileArn; + + const response = await this.databricks.createSQLWarehouse({ + data: payload, + $, + }); + + $.export( + "$summary", + `Successfully created SQL Warehouse: ${response?.name || this.name}`, + ); + return response; + }, +}; diff --git a/components/databricks/actions/delete-sql-warehouse/delete-sql-warehouse.mjs b/components/databricks/actions/delete-sql-warehouse/delete-sql-warehouse.mjs new file mode 100644 index 0000000000000..2eeea69a7713a --- /dev/null +++ b/components/databricks/actions/delete-sql-warehouse/delete-sql-warehouse.mjs @@ -0,0 +1,30 @@ +import databricks from "../../databricks.app.mjs"; + +export default { + key: "databricks-delete-sql-warehouse", + name: "Delete SQL Warehouse", + description: "Deletes a SQL Warehouse by ID. [See the documentation](https://docs.databricks.com/api/workspace/warehouses/delete)", + version: "0.0.1", + type: "action", + props: { + databricks, + warehouseId: { + description: "The ID of the SQL Warehouse to delete", + propDefinition: [ + databricks, + "warehouseId", + ], + }, + }, + async run({ $ }) { + await this.databricks.deleteSQLWarehouse({ + warehouseId: this.warehouseId, + $, + }); + + $.export("$summary", `Successfully deleted SQL Warehouse with ID ${this.warehouseId}`); + return { + success: true, + }; + }, +}; diff --git a/components/databricks/actions/edit-sql-warehouse/edit-sql-warehouse.mjs b/components/databricks/actions/edit-sql-warehouse/edit-sql-warehouse.mjs new file mode 100644 index 0000000000000..e61b6e987109c --- /dev/null +++ b/components/databricks/actions/edit-sql-warehouse/edit-sql-warehouse.mjs @@ -0,0 +1,183 @@ +import databricks from "../../databricks.app.mjs"; +import constants from "../../common/constants.mjs"; +import utils from "../../common/utils.mjs"; +import { ConfigurationError } from "@pipedream/platform"; + +export default { + key: "databricks-edit-sql-warehouse", + name: "Edit SQL Warehouse", + description: "Edits the configuration of an existing SQL Warehouse. [See the documentation](https://docs.databricks.com/api/workspace/warehouses/edit)", + version: "0.0.1", + type: "action", + props: { + databricks, + warehouseId: { + description: "The ID of the SQL Warehouse to edit", + propDefinition: [ + databricks, + "warehouseId", + ], + }, + name: { + type: "string", + label: "Warehouse Name", + description: "Logical name for the warehouse. Must be unique within an org and under 100 characters.", + optional: true, + }, + clusterSize: { + type: "string", + label: "Cluster Size", + description: "Size of clusters allocated for this warehouse.", + options: constants.CLUSTER_SIZES, + optional: true, + }, + autoStopMins: { + type: "integer", + label: "Auto Stop (minutes)", + description: "Minutes of inactivity before auto-stop. 0 disables autostop. Must be 0 or ≥ 10.", + optional: true, + }, + minNumClusters: { + type: "integer", + label: "Min Number of Clusters", + description: "Minimum number of available clusters (> 0 and ≤ min(max_num_clusters, 30)).", + optional: true, + }, + maxNumClusters: { + type: "integer", + label: "Max Number of Clusters", + description: "Maximum number of clusters for autoscaler (≥ min_num_clusters and ≤ 30).", + optional: true, + }, + enablePhoton: { + type: "boolean", + label: "Enable Photon", + description: "Use Photon optimized clusters.", + optional: true, + }, + enableServerlessCompute: { + type: "boolean", + label: "Enable Serverless Compute", + description: "Use serverless compute for this warehouse.", + optional: true, + }, + warehouseType: { + type: "string", + label: "Warehouse Type", + description: "Set to PRO (recommended) or CLASSIC. Set PRO + enable serverless to use serverless.", + options: [ + "TYPE_UNSPECIFIED", + "CLASSIC", + "PRO", + ], + optional: true, + }, + spotInstancePolicy: { + type: "string", + label: "Spot Instance Policy", + description: "Whether the warehouse should use spot instances.", + options: [ + "POLICY_UNSPECIFIED", + "COST_OPTIMIZED", + "RELIABILITY_OPTIMIZED", + ], + optional: true, + }, + tags: { + type: "object", + label: "Tags", + description: "Key-value tags for all resources associated with this warehouse (fewer than 45 tags).", + optional: true, + }, + channel: { + type: "object", + label: "Channel", + description: "Channel details. Example: `{ \"name\": \"CHANNEL_NAME_CUSTOM\", \"dbsql_version\": \"2023.35\" }`", + optional: true, + }, + instanceProfileArn: { + type: "string", + label: "Instance Profile ARN (Deprecated)", + description: "Deprecated. Instance profile used to pass IAM role to the cluster.", + optional: true, + }, + }, + async run({ $ }) { + const payload = {}; + + if (this.name !== undefined) { + if (typeof this.name !== "string" || this.name.length >= 100) { + throw new ConfigurationError("name must be a string with fewer than 100 characters."); + } + payload.name = this.name; + } + if (this.clusterSize !== undefined) payload.cluster_size = this.clusterSize; + + if (this.autoStopMins !== undefined) { + if (this.autoStopMins !== 0 && this.autoStopMins < 10) { + throw new ConfigurationError("autoStopMins must be 0 or >= 10."); + } + payload.auto_stop_mins = this.autoStopMins; + } + + if (this.minNumClusters !== undefined) { + if (this.minNumClusters < 1 || this.minNumClusters > 30) { + throw new ConfigurationError("minNumClusters must be between 1 and 30."); + } + payload.min_num_clusters = this.minNumClusters; + } + + if (this.maxNumClusters !== undefined) { + if (this.maxNumClusters < 1 || this.maxNumClusters > 30) { + throw new ConfigurationError("maxNumClusters must be between 1 and 30."); + } + if (this.minNumClusters !== undefined && this.maxNumClusters < this.minNumClusters) { + throw new ConfigurationError("maxNumClusters must be >= minNumClusters."); + } + payload.max_num_clusters = this.maxNumClusters; + } + + if (this.enablePhoton !== undefined) payload.enable_photon = this.enablePhoton; + if (this.enableServerlessCompute !== undefined) { + if (this.warehouseType === "CLASSIC" && this.enableServerlessCompute) { + throw new ConfigurationError("Serverless compute requires warehouseType = PRO."); + } + payload.enable_serverless_compute = this.enableServerlessCompute; + } + + const parsedTags = utils.parseObject(this.tags); + const tagArray = Object.entries(parsedTags).map(([ + key, + value, + ]) => ({ + key, + value, + })); + if (tagArray.length) { + payload.tags = { + custom_tags: tagArray, + }; + } + if (this.warehouseType !== undefined) payload.warehouse_type = this.warehouseType; + if (this.spotInstancePolicy !== undefined) { + payload.spot_instance_policy = this.spotInstancePolicy; + } + if (this.channel !== undefined) payload.channel = utils.parseObject(this.channel); + if (this.instanceProfileArn !== undefined) { + payload.instance_profile_arn = this.instanceProfileArn; + } + + if (!Object.keys(payload).length) { + throw new ConfigurationError("No fields to update. Provide at least one property."); + } + + const response = await this.databricks.editSQLWarehouse({ + warehouseId: this.warehouseId, + data: payload, + $, + }); + + $.export("$summary", `Successfully edited SQL Warehouse ID ${this.warehouseId}`); + return response; + }, +}; diff --git a/components/databricks/actions/get-run-output/get-run-output.mjs b/components/databricks/actions/get-run-output/get-run-output.mjs index 1fb6c77c9fcdd..ecfa86fcf0576 100644 --- a/components/databricks/actions/get-run-output/get-run-output.mjs +++ b/components/databricks/actions/get-run-output/get-run-output.mjs @@ -4,7 +4,7 @@ export default { key: "databricks-get-run-output", name: "Get Run Output", description: "Retrieve the output and metadata of a single task run. [See the documentation](https://docs.databricks.com/en/workflows/jobs/jobs-2.0-api.html#runs-get-output)", - version: "0.0.1", + version: "0.0.2", type: "action", props: { databricks, diff --git a/components/databricks/actions/get-sql-warehouse-config/get-sql-warehouse-config.mjs b/components/databricks/actions/get-sql-warehouse-config/get-sql-warehouse-config.mjs new file mode 100644 index 0000000000000..37202334854c5 --- /dev/null +++ b/components/databricks/actions/get-sql-warehouse-config/get-sql-warehouse-config.mjs @@ -0,0 +1,19 @@ +import databricks from "../../databricks.app.mjs"; + +export default { + key: "databricks-get-sql-warehouse-config", + name: "Get SQL Warehouse Config", + description: "Retrieves the global configuration for SQL Warehouses. [See the documentation](https://docs.databricks.com/api/workspace/warehouses/getworkspacewarehouseconfig)", + version: "0.0.1", + type: "action", + props: { + databricks, + }, + async run({ $ }) { + const response = await this.databricks.getSQLWarehouseConfig({ + $, + }); + $.export("$summary", "Successfully retrieved SQL Warehouse configuration"); + return response; + }, +}; diff --git a/components/databricks/actions/get-sql-warehouse-permissions/get-sql-warehouse-permissions.mjs b/components/databricks/actions/get-sql-warehouse-permissions/get-sql-warehouse-permissions.mjs new file mode 100644 index 0000000000000..66ec10e7d75a7 --- /dev/null +++ b/components/databricks/actions/get-sql-warehouse-permissions/get-sql-warehouse-permissions.mjs @@ -0,0 +1,28 @@ +import databricks from "../../databricks.app.mjs"; + +export default { + key: "databricks-get-sql-warehouse-permissions", + name: "Get SQL Warehouse Permissions", + description: "Retrieves the permissions for a specific SQL Warehouse. [See the documentation](https://docs.databricks.com/api/workspace/warehouses/getpermissions)", + version: "0.0.1", + type: "action", + props: { + databricks, + warehouseId: { + description: "The ID of the SQL Warehouse to fetch permissions for", + propDefinition: [ + databricks, + "warehouseId", + ], + }, + }, + async run({ $ }) { + const response = await this.databricks.getSQLWarehousePermissions({ + warehouseId: this.warehouseId, + $, + }); + + $.export("$summary", `Retrieved permissions for SQL Warehouse ID ${this.warehouseId}`); + return response; + }, +}; diff --git a/components/databricks/actions/get-sql-warehouse/get-sql-warehouse.mjs b/components/databricks/actions/get-sql-warehouse/get-sql-warehouse.mjs new file mode 100644 index 0000000000000..3c5849846d41f --- /dev/null +++ b/components/databricks/actions/get-sql-warehouse/get-sql-warehouse.mjs @@ -0,0 +1,28 @@ +import databricks from "../../databricks.app.mjs"; + +export default { + key: "databricks-get-sql-warehouse", + name: "Get SQL Warehouse", + description: "Retrieves details for a specific SQL Warehouse. [See docs](https://docs.databricks.com/api/workspace/warehouses/get)", + version: "0.0.1", + type: "action", + props: { + databricks, + warehouseId: { + description: "The ID of the SQL Warehouse to retrieve", + propDefinition: [ + databricks, + "warehouseId", + ], + }, + }, + async run({ $ }) { + const response = await this.databricks.getSQLWarehouse({ + warehouseId: this.warehouseId, + $, + }); + + $.export("$summary", `Retrieved details for SQL Warehouse ID ${this.warehouseId}`); + return response; + }, +}; diff --git a/components/databricks/actions/list-runs/list-runs.mjs b/components/databricks/actions/list-runs/list-runs.mjs index 4ad98bd866b54..f24e52369b6e9 100644 --- a/components/databricks/actions/list-runs/list-runs.mjs +++ b/components/databricks/actions/list-runs/list-runs.mjs @@ -4,7 +4,7 @@ export default { key: "databricks-list-runs", name: "List Runs", description: "Lists all runs available to the user. [See the documentation](https://docs.databricks.com/en/workflows/jobs/jobs-2.0-api.html#runs-list)", - version: "0.0.1", + version: "0.0.2", type: "action", props: { databricks, diff --git a/components/databricks/actions/list-sql-warehouses/list-sql-warehouses.mjs b/components/databricks/actions/list-sql-warehouses/list-sql-warehouses.mjs new file mode 100644 index 0000000000000..fbcf1865e22ed --- /dev/null +++ b/components/databricks/actions/list-sql-warehouses/list-sql-warehouses.mjs @@ -0,0 +1,28 @@ +import databricks from "../../databricks.app.mjs"; + +export default { + key: "databricks-list-sql-warehouses", + name: "List SQL Warehouses", + description: "Lists all SQL Warehouses available in the Databricks workspace. [See the documentation](https://docs.databricks.com/api/workspace/warehouses/list)", + version: "0.0.1", + type: "action", + props: { + databricks, + }, + async run({ $ }) { + const { warehouses } = await this.databricks.listSQLWarehouses({ + $, + }); + + if (!warehouses?.length) { + $.export("$summary", "No warehouses found."); + return []; + } + + $.export("$summary", `Successfully retrieved ${warehouses.length} warehouse${warehouses.length === 1 + ? "" + : "s"}.`); + + return warehouses; + }, +}; diff --git a/components/databricks/actions/run-job-now/run-job-now.mjs b/components/databricks/actions/run-job-now/run-job-now.mjs index f0c75c2c1a8cb..5de3e46e4ea59 100644 --- a/components/databricks/actions/run-job-now/run-job-now.mjs +++ b/components/databricks/actions/run-job-now/run-job-now.mjs @@ -4,7 +4,7 @@ export default { key: "databricks-run-job-now", name: "Run Job Now", description: "Run a job now and return the id of the triggered run. [See the documentation](https://docs.databricks.com/en/workflows/jobs/jobs-2.0-api.html#runs-list)", - version: "0.0.1", + version: "0.0.2", type: "action", props: { databricks, diff --git a/components/databricks/actions/set-sql-warehouse-config/set-sql-warehouse-config.mjs b/components/databricks/actions/set-sql-warehouse-config/set-sql-warehouse-config.mjs new file mode 100644 index 0000000000000..730cd3b96cb26 --- /dev/null +++ b/components/databricks/actions/set-sql-warehouse-config/set-sql-warehouse-config.mjs @@ -0,0 +1,161 @@ +import databricks from "../../databricks.app.mjs"; +import utils from "../../common/utils.mjs"; +import { ConfigurationError } from "@pipedream/platform"; + +export default { + key: "databricks-set-sql-warehouse-config", + name: "Set SQL Warehouse Config", + description: "Updates the global configuration for SQL Warehouses. [See the documentation](https://docs.databricks.com/api/workspace/warehouses/setworkspacewarehouseconfig)", + version: "0.0.1", + type: "action", + props: { + databricks, + instanceProfileArn: { + type: "string", + label: "Instance Profile ARN", + description: "Instance profile ARN used to pass an IAM role to clusters (AWS).", + optional: true, + }, + googleServiceAccount: { + type: "string", + label: "Google Service Account", + description: "Service account email used for GCP workspaces, if applicable.", + optional: true, + }, + securityPolicy: { + type: "string", + label: "Security Policy", + description: "Workspace-wide security policy for SQL Warehouses (if applicable).", + options: [ + "NONE", + "DATA_ACCESS_CONTROL", + "PASSTHROUGH", + ], + optional: true, + }, + channel: { + type: "object", + label: "Channel", + description: "Channel details. Example: `{ \"name\": \"CHANNEL_NAME_CUSTOM\", \"dbsql_version\": \"2023.35\" }`", + optional: true, + }, + enabledWarehouseTypes: { + type: "string[]", + label: "Enabled Warehouse Types", + description: "Specify which warehouse types are enabled. Example item: `{ \"warehouse_type\": \"PRO\", \"enabled\": true }`", + optional: true, + }, + configParam: { + type: "object", + label: "Config Parameters", + description: "General config key/value pairs. Example item: `{ \"key\": \"some.config\", \"value\": \"true\" }`", + optional: true, + }, + globalParam: { + type: "object", + label: "Global Parameters", + description: "Global config key/value pairs applied to all warehouses.", + optional: true, + }, + sqlConfigurationParameters: { + type: "object", + label: "SQL Configuration Parameters", + description: "SQL-specific configuration key/value pairs.", + optional: true, + }, + dataAccessConfig: { + type: "object", + label: "Data Access Config", + description: "Key/value pairs for data access configuration (e.g., credentials passthrough, external storage access).", + optional: true, + }, + }, + async run({ $ }) { + const current = await this.databricks.getSQLWarehouseConfig({ + $, + }); + const allowed = [ + "enable_serverless_compute", + "instance_profile_arn", + "google_service_account", + "security_policy", + "channel", + "enabled_warehouse_types", + "config_param", + "global_param", + "sql_configuration_parameters", + "data_access_config", + ]; + const payload = Object.fromEntries( + Object.entries(current || {}).filter(([ + k, + ]) => allowed.includes(k)), + ); + + if (this.instanceProfileArn !== undefined) { + payload.instance_profile_arn = this.instanceProfileArn; + } + if (this.googleServiceAccount !== undefined) { + payload.google_service_account = this.googleServiceAccount; + } + if (this.securityPolicy !== undefined) { + payload.security_policy = this.securityPolicy; + } + if (this.channel !== undefined) { + payload.channel = utils.parseObject(this.channel); + } + const enabledWarehouseTypes = utils.parseObject(this.enabledWarehouseTypes); + if (Array.isArray(enabledWarehouseTypes) && enabledWarehouseTypes.length) { + payload.enabled_warehouse_types = enabledWarehouseTypes.map((item, idx) => { + let obj = item; + if (typeof item === "string") { + try { obj = JSON.parse(item); } catch (e) { + throw new ConfigurationError(`enabledWarehouseTypes[${idx}] must be valid JSON: ${e.message}`); + } + } + if (!obj || typeof obj !== "object") { + throw new ConfigurationError(`enabledWarehouseTypes[${idx}] must be an object with { "warehouse_type": string, "enabled": boolean }`); + } + const { + warehouse_type, enabled, + } = obj; + if (typeof warehouse_type !== "string" || typeof enabled !== "boolean") { + throw new ConfigurationError(`enabledWarehouseTypes[${idx}] invalid shape; expected { "warehouse_type": string, "enabled": boolean }`); + } + return { + warehouse_type, + enabled: Boolean(enabled), + }; + }); + } + const configParam = utils.parseObject(this.configParam); + if (Array.isArray(configParam) && configParam.length) { + payload.config_param = { + configuration_pairs: configParam, + }; + } + const globalParam = utils.parseObject(this.globalParam); + if (Array.isArray(globalParam) && globalParam.length) { + payload.global_param = { + configuration_pairs: globalParam, + }; + } + const sqlConfigurationParameters = utils.parseObject(this.sqlConfigurationParameters); + if (Array.isArray(sqlConfigurationParameters) && sqlConfigurationParameters.length) { + payload.sql_configuration_parameters = { + configuration_pairs: sqlConfigurationParameters, + }; + } + const dataAccessConfig = utils.parseObject(this.dataAccessConfig); + if (Array.isArray(dataAccessConfig) && dataAccessConfig.length) { + payload.data_access_config = dataAccessConfig; + } + const response = await this.databricks.setSQLWarehouseConfig({ + data: payload, + $, + }); + + $.export("$summary", "Successfully updated SQL Warehouse configuration"); + return response; + }, +}; diff --git a/components/databricks/actions/set-sql-warehouse-permissions/set-sql-warehouse-permissions.mjs b/components/databricks/actions/set-sql-warehouse-permissions/set-sql-warehouse-permissions.mjs new file mode 100644 index 0000000000000..7fc5ae029df47 --- /dev/null +++ b/components/databricks/actions/set-sql-warehouse-permissions/set-sql-warehouse-permissions.mjs @@ -0,0 +1,45 @@ +import databricks from "../../databricks.app.mjs"; +import utils from "../../common/utils.mjs"; +import { ConfigurationError } from "@pipedream/platform"; + +export default { + key: "databricks-set-sql-warehouse-permissions", + name: "Set SQL Warehouse Permissions", + description: "Updates the permissions for a specific SQL Warehouse. [See docs](https://docs.databricks.com/api/workspace/warehouses/setpermissions)", + version: "0.0.1", + type: "action", + props: { + databricks, + warehouseId: { + description: "The ID of the SQL Warehouse to update permissions for", + propDefinition: [ + databricks, + "warehouseId", + ], + }, + accessControlList: { + type: "string[]", + label: "Access Control List", + description: "List of access control entries. Each entry must include one of `user_name`, `group_name`, or `service_principal_name`, and a `permission_level` (`CAN_VIEW`, `CAN_MONITOR`, `CAN_USE`, `CAN_MANAGE`).", + }, + }, + async run({ $ }) { + let acl = utils.parseObject(this.accessControlList); + if (!Array.isArray(acl)) { + throw new ConfigurationError("Access Control List must be an array"); + } + acl = acl.filter((entry) => entry && Object.keys(entry).length > 0); + + const response = await this.databricks.setSQLWarehousePermissions({ + warehouseId: this.warehouseId, + data: { + access_control_list: acl, + }, + $, + }); + + $.export("$summary", `Successfully updated permissions for SQL Warehouse ID ${this.warehouseId}`); + return response; + }, + +}; diff --git a/components/databricks/actions/start-sql-warehouse/start-sql-warehouse.mjs b/components/databricks/actions/start-sql-warehouse/start-sql-warehouse.mjs new file mode 100644 index 0000000000000..2de2b61cba5ac --- /dev/null +++ b/components/databricks/actions/start-sql-warehouse/start-sql-warehouse.mjs @@ -0,0 +1,28 @@ +import databricks from "../../databricks.app.mjs"; + +export default { + key: "databricks-start-sql-warehouse", + name: "Start SQL Warehouse", + description: "Starts a SQL Warehouse by ID. [See the documentation](https://docs.databricks.com/api/workspace/warehouses/start)", + version: "0.0.1", + type: "action", + props: { + databricks, + warehouseId: { + description: "The ID of the SQL Warehouse to start", + propDefinition: [ + databricks, + "warehouseId", + ], + }, + }, + async run({ $ }) { + const response = await this.databricks.startSQLWarehouse({ + warehouseId: this.warehouseId, + $, + }); + + $.export("$summary", `Successfully started SQL Warehouse with ID ${this.warehouseId}`); + return response; + }, +}; diff --git a/components/databricks/actions/stop-sql-warehouse/stop-sql-warehouse.mjs b/components/databricks/actions/stop-sql-warehouse/stop-sql-warehouse.mjs new file mode 100644 index 0000000000000..1388ec5102b61 --- /dev/null +++ b/components/databricks/actions/stop-sql-warehouse/stop-sql-warehouse.mjs @@ -0,0 +1,28 @@ +import databricks from "../../databricks.app.mjs"; + +export default { + key: "databricks-stop-sql-warehouse", + name: "Stop SQL Warehouse", + description: "Stops a SQL Warehouse by ID. [See the documentation](https://docs.databricks.com/api/workspace/warehouses/stop)", + version: "0.0.1", + type: "action", + props: { + databricks, + warehouseId: { + description: "The ID of the SQL Warehouse to stop", + propDefinition: [ + databricks, + "warehouseId", + ], + }, + }, + async run({ $ }) { + const response = await this.databricks.stopSQLWarehouse({ + warehouseId: this.warehouseId, + $, + }); + + $.export("$summary", `Successfully stopped SQL Warehouse with ID ${this.warehouseId}`); + return response; + }, +}; diff --git a/components/databricks/common/constants.mjs b/components/databricks/common/constants.mjs new file mode 100644 index 0000000000000..4b53df7a27a86 --- /dev/null +++ b/components/databricks/common/constants.mjs @@ -0,0 +1,15 @@ +export const CLUSTER_SIZES = [ + "2X-Small", + "X-Small", + "Small", + "Medium", + "Large", + "X-Large", + "2X-Large", + "3X-Large", + "4X-Large", +]; + +export default { + CLUSTER_SIZES, +}; diff --git a/components/databricks/common/utils.mjs b/components/databricks/common/utils.mjs new file mode 100644 index 0000000000000..40bdddb456371 --- /dev/null +++ b/components/databricks/common/utils.mjs @@ -0,0 +1,31 @@ +const parseObject = (obj) => { + if (!obj) return {}; + + if (typeof obj === "string") { + try { + return JSON.parse(obj); + } catch (e) { + return obj; + } + } + + if (Array.isArray(obj)) { + return obj.map((item) => parseObject(item)); + } + + if (typeof obj === "object") { + return Object.fromEntries(Object.entries(obj).map(([ + key, + value, + ]) => [ + key, + parseObject(value), + ])); + } + + return obj; +}; + +export default { + parseObject, +}; diff --git a/components/databricks/databricks.app.mjs b/components/databricks/databricks.app.mjs index 6daaf8eec3e84..05d6f88d697ab 100644 --- a/components/databricks/databricks.app.mjs +++ b/components/databricks/databricks.app.mjs @@ -44,6 +44,21 @@ export default { })) || []; }, }, + warehouseId: { + type: "string", + label: "Warehouse ID", + description: "The ID of the SQL Warehouse to get runs from", + async options() { + const { warehouses } = await this.listSQLWarehouses(); + return warehouses?.map(({ + id: value, + name: label, + }) => ({ + value, + label, + })) || []; + }, + }, }, methods: { _baseUrl() { @@ -90,5 +105,99 @@ export default { ...args, }); }, + createSQLWarehouse(args = {}) { + return this._makeRequest({ + path: "/sql/warehouses", + method: "POST", + ...args, + }); + }, + deleteSQLWarehouse({ + warehouseId, ...args + }) { + return this._makeRequest({ + path: `/sql/warehouses/${warehouseId}`, + method: "DELETE", + ...args, + }); + }, + getSQLWarehouse({ + warehouseId, ...args + }) { + return this._makeRequest({ + path: `/sql/warehouses/${warehouseId}`, + method: "GET", + ...args, + }); + }, + listSQLWarehouses(args = {}) { + return this._makeRequest({ + path: "/sql/warehouses", + ...args, + }); + }, + editSQLWarehouse({ + warehouseId, ...args + }) { + return this._makeRequest({ + path: `/sql/warehouses/${warehouseId}/edit`, + method: "POST", + ...args, + }); + }, + startSQLWarehouse({ + warehouseId, ...args + }) { + return this._makeRequest({ + path: `/sql/warehouses/${warehouseId}/start`, + method: "POST", + ...args, + }); + }, + + stopSQLWarehouse({ + warehouseId, ...args + }) { + return this._makeRequest({ + path: `/sql/warehouses/${warehouseId}/stop`, + method: "POST", + ...args, + }); + }, + + getSQLWarehouseConfig(args = {}) { + return this._makeRequest({ + path: "/sql/config/warehouses", + method: "GET", + ...args, + }); + }, + + setSQLWarehouseConfig(args = {}) { + return this._makeRequest({ + path: "/sql/config/warehouses", + method: "PUT", + ...args, + }); + }, + getSQLWarehousePermissions({ + warehouseId, ...args + }) { + return this._makeRequest({ + path: `/permissions/warehouses/${warehouseId}`, + method: "GET", + ...args, + }); + }, + + setSQLWarehousePermissions({ + warehouseId, ...args + }) { + return this._makeRequest({ + path: `/permissions/warehouses/${warehouseId}`, + method: "PUT", + ...args, + }); + }, }, }; diff --git a/components/databricks/package.json b/components/databricks/package.json index 50b863968a934..f49e7482191ef 100644 --- a/components/databricks/package.json +++ b/components/databricks/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/databricks", - "version": "0.1.0", + "version": "0.2.0", "description": "Pipedream Databricks Components", "main": "databricks.app.mjs", "keywords": [