demo_uc_setup 0.1.0__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
File without changes
@@ -0,0 +1,49 @@
1
+ import logging
2
+ from typing import TypeVar, Generic
3
+ from databricks.sdk import WorkspaceClient
4
+
5
+ from demo_uc_setup.config import Config
6
+
7
+ # Example of a type variable bound to our Config class
8
+ T = TypeVar("T", bound=Config)
9
+
10
+ class Task(Generic[T]):
11
+ """
12
+ A reusable Task base class that works both locally and in Databricks notebooks.
13
+ When running locally, requires databricks_host and databricks_token.
14
+ When running in a notebook, these parameters are optional.
15
+ """
16
+
17
+ def __init__(self, config_class: type[T]):
18
+ # Instantiate the typed configuration
19
+ self.config: T = config_class()
20
+ # Setup a basic logger
21
+ self.logger = logging.getLogger(self.__class__.__name__)
22
+ logging.basicConfig(level=logging.INFO)
23
+
24
+ # Create a Databricks workspace client with or without credentials
25
+ if self.config.databricks_host and self.config.databricks_token:
26
+ # Local execution with credentials
27
+ self.workspace_client = WorkspaceClient(
28
+ host=self.config.databricks_host,
29
+ token=self.config.databricks_token
30
+ )
31
+ else:
32
+ # Notebook execution - no credentials needed
33
+ self.workspace_client = WorkspaceClient()
34
+
35
+ @classmethod
36
+ def entrypoint(cls, *args, **kwargs):
37
+ """
38
+ Creates an instance of the task and runs it. If you
39
+ want a consistent run pattern, place it here.
40
+ """
41
+ instance = cls(*args, **kwargs)
42
+ instance.run()
43
+
44
+ def run(self):
45
+ """
46
+ The main entrypoint for the task's execution.
47
+ Override this in subclasses to implement custom logic.
48
+ """
49
+ self.logger.info("Base Task run method. Override in subclasses.")
@@ -0,0 +1,23 @@
1
+ from pydantic_settings import BaseSettings
2
+ from typing import Optional
3
+
4
+ class Config(BaseSettings):
5
+ """
6
+ Configuration class using Pydantic BaseSettings.
7
+ By default, each field can be overridden by environment
8
+ variables matching the field name (in uppercase).
9
+ For example, DATABRICKS_HOST, DATABRICKS_TOKEN, etc.
10
+ """
11
+
12
+ # Databricks connection settings - optional for notebook execution
13
+ databricks_host: Optional[str] = None
14
+ databricks_token: Optional[str] = None
15
+
16
+ # Default names for Unity Catalog demo objects
17
+ demo_catalog_name: str = "demo_catalog"
18
+ demo_schemas: list[str] = ["demo_schema_1", "demo_schema_2"] # List of schemas
19
+ demo_volume_name: str = "demo_volume" # This could also be a list if needed
20
+
21
+ class Config:
22
+ env_file = ".env" # or any custom file, if desired
23
+ env_file_encoding = "utf-8"
@@ -0,0 +1,82 @@
1
+ from typing import Type
2
+ from databricks.sdk.service import catalog
3
+ from demo_uc_setup.common import Task, T
4
+ from demo_uc_setup.config import Config
5
+
6
+ class UnityCatalogSetupTask(Task[Config]):
7
+ """
8
+ A task to ensure catalogs, schemas, and volumes exist
9
+ in the Databricks workspace. Uses typed config for
10
+ resource names, credentials, etc.
11
+ """
12
+
13
+ def __init__(self, config_class: Type[T] = Config):
14
+ super().__init__(config_class)
15
+
16
+ def run(self):
17
+ self.logger.info("Starting Unity Catalog setup...")
18
+
19
+ # 1) Ensure the catalog exists
20
+ catalog_name = self.config.demo_catalog_name
21
+ self.logger.info(f"Ensuring catalog '{catalog_name}'")
22
+ try:
23
+ self.workspace_client.catalogs.get(name=catalog_name)
24
+ self.logger.info(f"Catalog '{catalog_name}' already exists.")
25
+ except Exception:
26
+ self.logger.info(f"Catalog '{catalog_name}' not found; creating it.")
27
+ self.workspace_client.catalogs.create(
28
+ name=catalog_name,
29
+ comment="Demo Catalog for Databricks demos"
30
+ )
31
+
32
+ # 2) Ensure all schemas exist and create volumes within each schema
33
+ for schema_name in self.config.demo_schemas:
34
+ # Create schema
35
+ self.logger.info(f"Ensuring schema '{catalog_name}.{schema_name}'")
36
+ try:
37
+ self.workspace_client.schemas.get(
38
+ name=schema_name,
39
+ catalog_name=catalog_name
40
+ )
41
+ self.logger.info(f"Schema '{catalog_name}.{schema_name}' already exists.")
42
+ except Exception:
43
+ try:
44
+ self.logger.info(f"Schema '{catalog_name}.{schema_name}' not found; creating it.")
45
+ self.workspace_client.schemas.create(
46
+ name=schema_name,
47
+ catalog_name=catalog_name,
48
+ comment=f"Demo Schema {schema_name} for Databricks demos"
49
+ )
50
+ except Exception as e:
51
+ if "already exists" in str(e):
52
+ self.logger.info(f"Schema '{catalog_name}.{schema_name}' already exists (caught during creation).")
53
+ else:
54
+ raise e
55
+
56
+ # Create volume within this schema
57
+ volume_name = self.config.demo_volume_name
58
+ self.logger.info(f"Ensuring volume '{catalog_name}.{schema_name}.{volume_name}'")
59
+ try:
60
+ self.workspace_client.volumes.get(
61
+ name=volume_name,
62
+ catalog_name=catalog_name,
63
+ schema_name=schema_name
64
+ )
65
+ self.logger.info(f"Volume '{catalog_name}.{schema_name}.{volume_name}' already exists.")
66
+ except Exception:
67
+ try:
68
+ self.logger.info(f"Volume '{catalog_name}.{schema_name}.{volume_name}' not found; creating it.")
69
+ self.workspace_client.volumes.create(
70
+ name=volume_name,
71
+ catalog_name=catalog_name,
72
+ schema_name=schema_name,
73
+ volume_type=catalog.VolumeType.MANAGED,
74
+ comment=f"Demo Volume for schema {schema_name}"
75
+ )
76
+ except Exception as e:
77
+ if "already exists" in str(e):
78
+ self.logger.info(f"Volume '{catalog_name}.{schema_name}.{volume_name}' already exists (caught during creation).")
79
+ else:
80
+ raise e
81
+
82
+ self.logger.info("Unity Catalog setup complete!")
@@ -0,0 +1,28 @@
1
+ from typing import Type
2
+ from databricks.sdk import WorkspaceClient
3
+ from demo_uc_setup.common import Task, T
4
+ from demo_uc_setup.config import Config
5
+
6
+ class UnityCatalogTeardownTask(Task[Config]):
7
+ """
8
+ A task to delete (teardown) the Unity Catalog resources in
9
+ the configured Databricks workspace. Uses typed config for
10
+ resource names, credentials, etc.
11
+ """
12
+
13
+ def __init__(self, config_class: Type[T] = Config):
14
+ super().__init__(config_class)
15
+
16
+ def run(self):
17
+ self.logger.info("Starting teardown of Unity Catalog resources...")
18
+
19
+ catalog_name = self.config.demo_catalog_name
20
+ self.logger.info(f"Deleting catalog '{catalog_name}' and its dependencies (force=True).")
21
+
22
+ try:
23
+ self.workspace_client.catalogs.delete(name=catalog_name, force=True)
24
+ self.logger.info(f"Catalog '{catalog_name}' (and its contents) successfully deleted.")
25
+ except Exception as e:
26
+ self.logger.error(f"Failed to delete catalog '{catalog_name}'. Reason: {e}")
27
+
28
+ self.logger.info("Unity Catalog teardown complete!")
@@ -0,0 +1,105 @@
1
+ Metadata-Version: 2.4
2
+ Name: demo_uc_setup
3
+ Version: 0.1.0
4
+ Summary: A reusable task-based framework for managing Unity Catalog in Databricks
5
+ Requires-Python: >=3.11
6
+ Requires-Dist: databricks-connect>=16.1.1
7
+ Requires-Dist: databricks-sdk>=0.44.1
8
+ Requires-Dist: pydantic-settings>=2.8.0
9
+ Requires-Dist: pydantic>=2.10.6
10
+ Description-Content-Type: text/markdown
11
+
12
+ # Databricks Unity Catalog Setup Demo
13
+
14
+ A Python package that demonstrates automated setup and teardown of Databricks Unity Catalog resources using the Databricks SDK. This package provides a reusable framework for managing Unity Catalog resources programmatically, both from local environments and within Databricks notebooks.
15
+
16
+ ## Features
17
+
18
+ - Automated creation of Unity Catalog resources:
19
+ - Catalogs
20
+ - Schemas
21
+ - Volumes
22
+ - Configurable resource naming via environment variables
23
+ - Support for both local execution and Databricks notebook execution
24
+ - Type-safe configuration management using Pydantic
25
+ - Clean teardown functionality
26
+
27
+ ## Prerequisites
28
+
29
+ - Python 3.8+
30
+ - A Databricks workspace with Unity Catalog enabled
31
+ - Appropriate permissions to create/manage Unity Catalog resources
32
+
33
+ ## Installation
34
+
35
+ ```bash
36
+ pip install demo-uc-setup
37
+ ```
38
+
39
+ ## Configuration
40
+
41
+ The package uses environment variables for configuration. You can set these either in your environment or in a `.env` file:
42
+
43
+ ```env
44
+ # Required for local execution (optional in Databricks notebooks)
45
+ DATABRICKS_HOST=your-workspace-url
46
+ DATABRICKS_TOKEN=your-pat-token
47
+
48
+ # Optional - override default resource names
49
+ DEMO_CATALOG_NAME=custom_catalog_name
50
+ DEMO_SCHEMAS=["schema1", "schema2"]
51
+ DEMO_VOLUME_NAME=custom_volume_name
52
+ ```
53
+
54
+ ## Usage
55
+
56
+ ### Local Execution
57
+
58
+ ```python
59
+ from demo_uc_setup.unity_catalog_setup import UnityCatalogSetupTask
60
+ from demo_uc_setup.unity_catalog_teardown import UnityCatalogTeardownTask
61
+
62
+ # Setup Unity Catalog resources
63
+ UnityCatalogSetupTask.entrypoint()
64
+
65
+ # Teardown Unity Catalog resources
66
+ UnityCatalogTeardownTask.entrypoint()
67
+ ```
68
+
69
+ ### Databricks Notebook Execution
70
+
71
+ ```python
72
+ %pip install demo-uc-setup
73
+
74
+ from demo_uc_setup.unity_catalog_setup import UnityCatalogSetupTask
75
+ UnityCatalogSetupTask.entrypoint()
76
+ ```
77
+
78
+ ## Default Resource Names
79
+
80
+ If not overridden via environment variables, the package will create:
81
+ - A catalog named `demo_catalog`
82
+ - Two schemas: `demo_schema_1` and `demo_schema_2`
83
+ - A volume named `demo_volume` in each schema
84
+
85
+ ## Extending the Framework
86
+
87
+ The package provides a reusable `Task` base class that can be extended for custom Unity Catalog operations:
88
+
89
+ ```python
90
+ from demo_uc_setup.common import Task
91
+ from demo_uc_setup.config import Config
92
+
93
+ class CustomTask(Task[Config]):
94
+ def run(self):
95
+ self.logger.info("Starting custom task...")
96
+ # Your custom logic here
97
+ ```
98
+
99
+ ## Contributing
100
+
101
+ Contributions are welcome! Please feel free to submit a Pull Request.
102
+
103
+ ## License
104
+
105
+ This project is licensed under the MIT License - see the LICENSE file for details.
@@ -0,0 +1,8 @@
1
+ demo_uc_setup/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ demo_uc_setup/common.py,sha256=r5v-nUh7EoGsR4ecQi-pA9NJVRyJlRgOtc_9JxQWjxs,1754
3
+ demo_uc_setup/config.py,sha256=Jwl5anXQ6Ceq-hRyjZ9gUtBaC3iqqJXZCkLjNYjny1o,873
4
+ demo_uc_setup/unity_catalog_setup.py,sha256=3jfIlS9_nxJpXcoGbXJ2Pj4EefqAlpo-GTV8MShoa1w,3680
5
+ demo_uc_setup/unity_catalog_teardown.py,sha256=jHcT4iWeyUIlFDhvUGSfTW2RAYL7d-0sW4VU_uLuRd4,1095
6
+ demo_uc_setup-0.1.0.dist-info/METADATA,sha256=aVkYiBtNuljFYng3CL2JPMLbzkBupHhFYMRiEBDLRjc,2934
7
+ demo_uc_setup-0.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
8
+ demo_uc_setup-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.27.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any