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.
- demo_uc_setup/__init__.py +0 -0
- demo_uc_setup/common.py +49 -0
- demo_uc_setup/config.py +23 -0
- demo_uc_setup/unity_catalog_setup.py +82 -0
- demo_uc_setup/unity_catalog_teardown.py +28 -0
- demo_uc_setup-0.1.0.dist-info/METADATA +105 -0
- demo_uc_setup-0.1.0.dist-info/RECORD +8 -0
- demo_uc_setup-0.1.0.dist-info/WHEEL +4 -0
File without changes
|
demo_uc_setup/common.py
ADDED
@@ -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.")
|
demo_uc_setup/config.py
ADDED
@@ -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,,
|