composable-data-stack 0.8.0__tar.gz → 0.9.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/PKG-INFO +183 -110
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/README.md +179 -107
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/cli/image_verification.py +12 -3
- composable_data_stack-0.9.1/cli/k8s_renderer.py +1476 -0
- composable_data_stack-0.9.1/cli/k8s_runner.py +288 -0
- composable_data_stack-0.9.1/cli/k8s_security.py +125 -0
- composable_data_stack-0.9.1/cli/loader.py +341 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/cli/main.py +388 -11
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/cli/planner.py +21 -2
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/cli/preflight.py +7 -1
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/cli/renderer.py +74 -9
- composable_data_stack-0.9.1/cli/resolver.py +71 -0
- composable_data_stack-0.9.1/cli/resources/module.schema.json +705 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/cli/state.py +51 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/cli/up_runner.py +50 -7
- composable_data_stack-0.9.1/cli/utils.py +35 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/cli/validator.py +29 -4
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/composable_data_stack.egg-info/PKG-INFO +183 -110
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/composable_data_stack.egg-info/SOURCES.txt +20 -1
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/composable_data_stack.egg-info/requires.txt +4 -2
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/pyproject.toml +6 -4
- composable_data_stack-0.9.1/tests/test_ai_profile_review.py +113 -0
- composable_data_stack-0.9.1/tests/test_bump_changelog.py +113 -0
- composable_data_stack-0.9.1/tests/test_compose_to_module.py +310 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/tests/test_dagster_entrypoint_backend_guard.py +48 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/tests/test_dagster_hardening.py +3 -1
- composable_data_stack-0.9.1/tests/test_dbt_hardening.py +132 -0
- composable_data_stack-0.9.1/tests/test_dlt_postgres_wiring.py +145 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/tests/test_getter.py +30 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/tests/test_image_security_scan_workflow.py +7 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/tests/test_image_verification.py +120 -0
- composable_data_stack-0.9.1/tests/test_k3d_e2e_profile.py +52 -0
- composable_data_stack-0.9.1/tests/test_k3d_exposure.py +134 -0
- composable_data_stack-0.9.1/tests/test_k8s_renderer.py +602 -0
- composable_data_stack-0.9.1/tests/test_k8s_runner.py +239 -0
- composable_data_stack-0.9.1/tests/test_k8s_security.py +127 -0
- composable_data_stack-0.9.1/tests/test_loader.py +210 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/tests/test_main.py +775 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/tests/test_planner.py +268 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/tests/test_preflight.py +39 -1
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/tests/test_publish_images_workflow.py +82 -11
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/tests/test_render_example_profile.py +4 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/tests/test_renderer.py +219 -0
- composable_data_stack-0.9.1/tests/test_resolver.py +87 -0
- composable_data_stack-0.9.1/tests/test_secrets.py +160 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/tests/test_security.py +163 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/tests/test_state.py +48 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/tests/test_superset_hardening.py +56 -14
- composable_data_stack-0.9.1/tests/test_tender_analytics.py +186 -0
- composable_data_stack-0.9.1/tests/test_tender_dashboard.py +175 -0
- composable_data_stack-0.9.1/tests/test_test_runner_timeout.py +69 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/tests/test_up_runner.py +27 -0
- composable_data_stack-0.9.1/tests/test_utils.py +101 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/tests/test_validator.py +62 -0
- composable_data_stack-0.9.1/tests/test_vendored_llm_client.py +89 -0
- composable_data_stack-0.8.0/cli/loader.py +0 -179
- composable_data_stack-0.8.0/cli/resolver.py +0 -28
- composable_data_stack-0.8.0/cli/resources/module.schema.json +0 -204
- composable_data_stack-0.8.0/cli/utils.py +0 -22
- composable_data_stack-0.8.0/tests/test_resolver.py +0 -53
- composable_data_stack-0.8.0/tests/test_secrets.py +0 -48
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/LICENSE +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/cli/__init__.py +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/cli/constants.py +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/cli/diagnostics.py +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/cli/getter.py +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/cli/graph.py +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/cli/image_updates.py +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/cli/overlay.py +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/cli/resources/__init__.py +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/cli/resources/contract.schema.json +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/cli/resources/profile.schema.json +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/cli/resources/rule-schema.json +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/cli/resources/rule-set.json +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/cli/secrets.py +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/cli/security.py +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/cli/security_common.py +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/composable_data_stack.egg-info/dependency_links.txt +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/composable_data_stack.egg-info/entry_points.txt +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/composable_data_stack.egg-info/top_level.txt +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/setup.cfg +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/tests/test_cds_workflow.py +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/tests/test_completion.py +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/tests/test_compose_runtime_smoke.py +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/tests/test_dagster_config_generation.py +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/tests/test_dagster_definitions_uri.py +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/tests/test_duckdb_hardening.py +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/tests/test_environment_classification.py +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/tests/test_environment_cli.py +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/tests/test_graph.py +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/tests/test_image_updates.py +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/tests/test_markdown_mermaid_blocks.py +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/tests/test_module_isolation.py +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/tests/test_modules_no_committed_secrets.py +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/tests/test_mvp_proof_workflow.py +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/tests/test_overlay.py +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/tests/test_python_version_alignment.py +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/tests/test_release_version_check.py +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/tests/test_resolve_profile_path.py +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/tests/test_smoke_example_profile.py +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/tests/test_standalone_module_profile.py +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/tests/test_trivyignore.py +0 -0
- {composable_data_stack-0.8.0 → composable_data_stack-0.9.1}/tests/test_upstream_image_hardening.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: composable-data-stack
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.9.1
|
|
4
4
|
Summary: CLI for validating and composing composable data stack profiles
|
|
5
5
|
Author: Ronald Hensbergen
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -22,64 +22,169 @@ Description-Content-Type: text/markdown
|
|
|
22
22
|
License-File: LICENSE
|
|
23
23
|
Requires-Dist: PyYAML>=6.0
|
|
24
24
|
Requires-Dist: jsonschema>=4.22.0
|
|
25
|
-
Requires-Dist: jinja2>=3.0
|
|
26
25
|
Requires-Dist: packaging>=23.0
|
|
27
26
|
Requires-Dist: rich>=15.0
|
|
28
27
|
Provides-Extra: completion
|
|
29
28
|
Requires-Dist: argcomplete<4,>=3.0.0; extra == "completion"
|
|
29
|
+
Provides-Extra: test
|
|
30
|
+
Requires-Dist: jinja2>=3.0; extra == "test"
|
|
30
31
|
Provides-Extra: dev
|
|
31
32
|
Requires-Dist: coverage>=7.6; extra == "dev"
|
|
32
33
|
Requires-Dist: bandit>=1.7; extra == "dev"
|
|
33
34
|
Requires-Dist: pip-audit>=2.7; extra == "dev"
|
|
34
|
-
Requires-Dist: ruff==0.16.
|
|
35
|
+
Requires-Dist: ruff==0.16.8; extra == "dev"
|
|
35
36
|
Dynamic: license-file
|
|
36
37
|
|
|
37
38
|
# 🚀 Composable Data Stack (CDS)
|
|
38
39
|
|
|
39
|
-
> **
|
|
40
|
-
>
|
|
40
|
+
> **The modern data stack has a composition problem. CDS is an open framework
|
|
41
|
+
> for building data platforms that can evolve without being rebuilt.**
|
|
41
42
|
|
|
42
|
-

|
|
43
|
+

|
|
43
44
|
|
|
44
|
-
|
|
45
|
+
Project:
|
|
46
|
+
|
|
47
|
+
[](https://github.com/RonaldHensbergen/composable-data-stack/actions/workflows/ci.yml)
|
|
48
|
+
[](https://pypi.org/project/composable-data-stack/)
|
|
49
|
+
[](LICENSE)
|
|
50
|
+
|
|
51
|
+
SonarCloud — Quality Gate & Ratings:
|
|
45
52
|
|
|
46
|
-
|
|
53
|
+
[](https://sonarcloud.io/summary/new_code?id=RonaldHensbergen_composable-data-stack)
|
|
54
|
+
[](https://sonarcloud.io/summary/new_code?id=RonaldHensbergen_composable-data-stack)
|
|
55
|
+
[](https://sonarcloud.io/summary/new_code?id=RonaldHensbergen_composable-data-stack)
|
|
56
|
+
[](https://sonarcloud.io/summary/new_code?id=RonaldHensbergen_composable-data-stack)
|
|
47
57
|
|
|
48
|
-
|
|
58
|
+
SonarCloud — Issues:
|
|
49
59
|
|
|
50
|
-
|
|
60
|
+
[](https://sonarcloud.io/summary/new_code?id=RonaldHensbergen_composable-data-stack)
|
|
61
|
+
[](https://sonarcloud.io/summary/new_code?id=RonaldHensbergen_composable-data-stack)
|
|
62
|
+
[](https://sonarcloud.io/summary/new_code?id=RonaldHensbergen_composable-data-stack)
|
|
51
63
|
|
|
52
|
-
|
|
53
|
-
- **Contribute**: open a discussion, file an issue, or send a PR to help shape CDS
|
|
54
|
-
- **Proof it**: if you run it in a real workflow, share your feedback — good or bad
|
|
64
|
+
SonarCloud — Metrics:
|
|
55
65
|
|
|
56
|
-
|
|
66
|
+
[](https://sonarcloud.io/summary/new_code?id=RonaldHensbergen_composable-data-stack)
|
|
67
|
+
[](https://sonarcloud.io/summary/new_code?id=RonaldHensbergen_composable-data-stack)
|
|
68
|
+
[](https://sonarcloud.io/summary/new_code?id=RonaldHensbergen_composable-data-stack)
|
|
57
69
|
|
|
58
70
|
---
|
|
59
71
|
|
|
60
|
-
|
|
72
|
+
You start with a straightforward goal: orchestrate some pipelines, store the
|
|
73
|
+
data, and make it useful.
|
|
61
74
|
|
|
62
|
-
|
|
75
|
+
Then the tool decisions begin.
|
|
63
76
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
77
|
+
Airflow, Dagster, or Prefect? Iceberg, Delta, or Hudi? Superset or Metabase?
|
|
78
|
+
Every choice opens another comparison, another integration, and another
|
|
79
|
+
architecture diagram. Every diagram looks different. Every tool has its own
|
|
80
|
+
configuration model, assumptions, and lifecycle. Before long, the platform is
|
|
81
|
+
less a designed system than a collection of decisions held together by custom
|
|
82
|
+
code and institutional memory.
|
|
67
83
|
|
|
68
|
-
|
|
84
|
+
The hardest question is no longer **"Which tool is best?"** It is **"How do
|
|
85
|
+
these tools fit together, and can we change our minds later?"**
|
|
69
86
|
|
|
70
|
-
|
|
87
|
+
## Why Data Platforms Have a Composition Problem
|
|
71
88
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
89
|
+
The modern data ecosystem is excellent at producing capable tools and terrible
|
|
90
|
+
at making them work as interchangeable parts.
|
|
91
|
+
|
|
92
|
+
Teams are expected to assemble orchestration, storage, transformation,
|
|
93
|
+
cataloging, observability, security, and BI into one dependable platform. But
|
|
94
|
+
the boundaries between those tools are usually implicit. Connection details
|
|
95
|
+
leak into environment variables. Service names become dependencies. Deployment
|
|
96
|
+
logic assumes a specific vendor. Compatibility lives in a staff engineer's
|
|
97
|
+
head—or is discovered during an incident.
|
|
98
|
+
|
|
99
|
+
That fragmentation creates a familiar cycle:
|
|
100
|
+
|
|
101
|
+
- evaluate an overwhelming number of tools
|
|
102
|
+
- debate architecture instead of delivering data products
|
|
103
|
+
- hand-build integrations that only one team understands
|
|
104
|
+
- duplicate stacks across development, CI, and production
|
|
105
|
+
- postpone upgrades because nobody knows what they will break
|
|
106
|
+
- accept lock-in because replacing one component feels like replacing the
|
|
107
|
+
platform
|
|
108
|
+
|
|
109
|
+
This is not primarily a tooling problem. **It is a composition problem.** We
|
|
110
|
+
have many good components, but no shared way to declare what they provide,
|
|
111
|
+
what they need, and whether a particular assembly is valid.
|
|
112
|
+
|
|
113
|
+
## The Cost of Choosing Wrong
|
|
114
|
+
|
|
115
|
+
A technology choice that looks local rarely stays local.
|
|
116
|
+
|
|
117
|
+
Choose an orchestrator and its concepts spread into deployment, secrets,
|
|
118
|
+
logging, and team workflows. Choose a table format and it constrains engines,
|
|
119
|
+
catalogs, and migration paths. Choose a BI layer and dashboards become coupled
|
|
120
|
+
to authentication, database behavior, and operational assumptions.
|
|
121
|
+
|
|
122
|
+
The bill arrives later:
|
|
123
|
+
|
|
124
|
+
- migrations become multi-quarter programs
|
|
125
|
+
- upgrades become risky, manual compatibility exercises
|
|
126
|
+
- platform teams maintain glue code instead of platform capabilities
|
|
127
|
+
- product teams wait while engineers renegotiate architecture
|
|
128
|
+
- vendors gain leverage because the cost of leaving keeps rising
|
|
129
|
+
|
|
130
|
+
There is no universally correct stack, and pretending otherwise is expensive.
|
|
131
|
+
The right choice today may be the wrong choice at a different scale, under a
|
|
132
|
+
new regulatory constraint, or after the team learns more. A healthy platform
|
|
133
|
+
must make change routine—not heroic.
|
|
134
|
+
|
|
135
|
+
## What If Data Platforms Were Composable?
|
|
136
|
+
|
|
137
|
+
What if a data platform described capabilities and interfaces before naming
|
|
138
|
+
products?
|
|
139
|
+
|
|
140
|
+
What if an orchestrator could request a database contract without hardcoding a
|
|
141
|
+
specific database? What if a profile could declare a supported combination,
|
|
142
|
+
validate it before deployment, and produce the runtime configuration? What if
|
|
143
|
+
replacing a component meant satisfying the same contract instead of rebuilding
|
|
144
|
+
every integration around it?
|
|
145
|
+
|
|
146
|
+
That is the goal of **Composable Data Stack (CDS)**.
|
|
147
|
+
|
|
148
|
+
CDS is an open-source framework for defining, validating, securing, and
|
|
149
|
+
assembling data platforms from reusable components. Think of it as
|
|
150
|
+
**Infrastructure as Code for the shape of a data platform**: the components,
|
|
151
|
+
the interfaces between them, and the rules that make the whole stack coherent.
|
|
152
|
+
|
|
153
|
+
CDS introduces three building blocks:
|
|
76
154
|
|
|
77
|
-
|
|
155
|
+
- 🔧 **Modules** package reusable capabilities such as orchestration, storage,
|
|
156
|
+
BI, and secret management.
|
|
157
|
+
- 🔗 **Contracts** define explicit, testable interfaces between those
|
|
158
|
+
capabilities.
|
|
159
|
+
- 🧩 **Profiles** compose modules into supported, reproducible stacks.
|
|
78
160
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
-
|
|
161
|
+
Instead of burying platform architecture in scripts and tribal knowledge, CDS
|
|
162
|
+
makes it declarative. It answers:
|
|
163
|
+
|
|
164
|
+
- **How do these tools fit together?** Through explicit contracts and declared
|
|
165
|
+
bindings.
|
|
166
|
+
- **What happens if I replace a component later?** CDS validates the new
|
|
167
|
+
composition against the same requirements before runtime.
|
|
168
|
+
- **How do I avoid vendor and technology lock-in?** Consumers depend on
|
|
169
|
+
capabilities, not hardcoded product identities.
|
|
170
|
+
|
|
171
|
+
The result is composability without chaos, flexibility with guarantees, and a
|
|
172
|
+
platform that can evolve without starting over.
|
|
173
|
+
|
|
174
|
+
## ⚡ Why CDS
|
|
175
|
+
|
|
176
|
+
Most teams are forced into one of two bad options:
|
|
177
|
+
|
|
178
|
+
|Approach|What You Gain|What It Costs|
|
|
179
|
+
|---|---|---|
|
|
180
|
+
|Monolithic stack|A consistent starting point|Rigid boundaries and an expensive exit|
|
|
181
|
+
|Custom integrations|Freedom to choose every component|Fragile glue, inconsistent stacks, and hidden coupling|
|
|
182
|
+
|CDS|Explicit composition and replaceable components|A contract and profile model the community maintains together|
|
|
183
|
+
|
|
184
|
+
CDS does not claim that every tool is interchangeable or that integration
|
|
185
|
+
complexity disappears. It makes compatibility explicit, validates known
|
|
186
|
+
constraints early, and gives the ecosystem a shared place to improve how tools
|
|
187
|
+
compose.
|
|
83
188
|
|
|
84
189
|
---
|
|
85
190
|
|
|
@@ -87,10 +192,12 @@ CDS gives you the best of both:
|
|
|
87
192
|
|
|
88
193
|
Use CDS if you:
|
|
89
194
|
|
|
195
|
+
- expect your architecture to evolve as requirements change
|
|
90
196
|
- want to swap tools (Airflow ↔ Dagster, Superset ↔ Metabase)
|
|
91
197
|
- need reproducible environments across dev, CI, and prod
|
|
92
198
|
- are building a platform for multiple teams
|
|
93
199
|
- want contract-driven integration instead of implicit coupling
|
|
200
|
+
- want to contribute to an open interoperability model for data tooling
|
|
94
201
|
|
|
95
202
|
CDS may be overkill if:
|
|
96
203
|
|
|
@@ -99,7 +206,7 @@ CDS may be overkill if:
|
|
|
99
206
|
|
|
100
207
|
---
|
|
101
208
|
|
|
102
|
-
## 🏗️
|
|
209
|
+
## 🏗️ See Composition in Practice
|
|
103
210
|
|
|
104
211
|
The `local-dagster-postgres-superset` profile defines:
|
|
105
212
|
|
|
@@ -107,7 +214,7 @@ The `local-dagster-postgres-superset` profile defines:
|
|
|
107
214
|
- Postgres -> storage
|
|
108
215
|
- Superset -> BI
|
|
109
216
|
|
|
110
|
-
|
|
217
|
+
CDS then:
|
|
111
218
|
|
|
112
219
|
1. Validates module definitions
|
|
113
220
|
2. Resolves contract bindings
|
|
@@ -116,7 +223,8 @@ The `local-dagster-postgres-superset` profile defines:
|
|
|
116
223
|
|
|
117
224
|
`cds plan` resolves the full dependency graph before runtime configuration is generated, ensuring all module interactions are valid and predictable.
|
|
118
225
|
|
|
119
|
-
|
|
226
|
+
The composition model creates a path to replace components while preserving
|
|
227
|
+
the contracts the rest of the platform depends on:
|
|
120
228
|
|
|
121
229
|
```text
|
|
122
230
|
Dagster -> Airflow
|
|
@@ -134,23 +242,7 @@ CDS wires modules through **contracts**, not direct dependencies. This section h
|
|
|
134
242
|
|
|
135
243
|
Below, `local-dagster-postgres-superset` wires Dagster to Postgres to Superset through contracts:
|
|
136
244
|
|
|
137
|
-
|
|
138
|
-
flowchart TD
|
|
139
|
-
Dagster[Dagster]
|
|
140
|
-
Postgres[(Postgres)]
|
|
141
|
-
Superset[Superset]
|
|
142
|
-
|
|
143
|
-
Dagster -->|transformation-runner| Postgres
|
|
144
|
-
Postgres -->|warehouse-query| Superset
|
|
145
|
-
|
|
146
|
-
classDef tool stroke:#818cf8,fill:#eef2ff
|
|
147
|
-
classDef database stroke:#2dd4bf,fill:#f0fdfa
|
|
148
|
-
classDef viz stroke:#a78bfa,fill:#f5f3ff
|
|
149
|
-
|
|
150
|
-
class Dagster tool
|
|
151
|
-
class Postgres database
|
|
152
|
-
class Superset viz
|
|
153
|
-
```
|
|
245
|
+

|
|
154
246
|
|
|
155
247
|
### Internal Flow
|
|
156
248
|
|
|
@@ -172,51 +264,7 @@ consumption in Superset), see
|
|
|
172
264
|
[docs/profile-testing/test-plan.md](docs/profile-testing/test-plan.md) and
|
|
173
265
|
[docs/profile-testing/failure-path-and-ci.md](docs/profile-testing/failure-path-and-ci.md).
|
|
174
266
|
|
|
175
|
-
|
|
176
|
-
flowchart TD
|
|
177
|
-
subgraph compile["Compile-time (cds)"]
|
|
178
|
-
direction TB
|
|
179
|
-
Profile[/profile.yaml/]
|
|
180
|
-
Validate[Validate]
|
|
181
|
-
Security["Security checks<br/>(cds test only)"]
|
|
182
|
-
Plan[Plan]
|
|
183
|
-
Render[Render]
|
|
184
|
-
Compose[/docker-compose.yaml/]
|
|
185
|
-
Stop1((stops here))
|
|
186
|
-
|
|
187
|
-
Profile --> Validate
|
|
188
|
-
Validate -->|structural + contract checks| Security
|
|
189
|
-
Security -->|rule-based checks| Plan
|
|
190
|
-
Plan -->|resolve + substitute| Render
|
|
191
|
-
Render --> Compose
|
|
192
|
-
|
|
193
|
-
Validate -.->|E020, E041, E042, E081| Stop1
|
|
194
|
-
end
|
|
195
|
-
|
|
196
|
-
subgraph runtime["Runtime (docker compose, cds up only)"]
|
|
197
|
-
direction TB
|
|
198
|
-
Build["docker compose build<br/>(skip with --no-build)"]
|
|
199
|
-
Up["docker compose up"]
|
|
200
|
-
Env[(".env file")]
|
|
201
|
-
Containers["running containers,<br/>real secret values injected"]
|
|
202
|
-
|
|
203
|
-
Build --> Up
|
|
204
|
-
Env -.->|resolves CDS_VAR| Up
|
|
205
|
-
Up --> Containers
|
|
206
|
-
end
|
|
207
|
-
|
|
208
|
-
Compose --> Build
|
|
209
|
-
|
|
210
|
-
classDef stage stroke:#818cf8,fill:#eef2ff
|
|
211
|
-
classDef artifact stroke:#2dd4bf,fill:#f0fdfa
|
|
212
|
-
classDef stop stroke:#f87171,fill:#fef2f2,stroke-dasharray: 3 3
|
|
213
|
-
classDef runtimeNode stroke:#a78bfa,fill:#f5f3ff
|
|
214
|
-
|
|
215
|
-
class Validate,Security,Plan,Render stage
|
|
216
|
-
class Profile,Compose artifact
|
|
217
|
-
class Stop1 stop
|
|
218
|
-
class Build,Up,Env,Containers runtimeNode
|
|
219
|
-
```
|
|
267
|
+

|
|
220
268
|
|
|
221
269
|
This mirrors the [`cds` command table](#️-cli) below: `validate`, `plan`, and `render` are each callable on their own; `security` only runs as part of `cds test`, not `cds up`. Module and contract definitions follow the [Contract-First](#contract-first) design principle, so most of what "Validate" and "Plan" check comes directly from `module.yaml` and `profile.yaml`.
|
|
222
270
|
|
|
@@ -246,15 +294,18 @@ cds security local-dagster-postgres-superset
|
|
|
246
294
|
|
|
247
295
|
## 📦 What You Get
|
|
248
296
|
|
|
249
|
-
When
|
|
297
|
+
When a profile compiles, CDS produces:
|
|
250
298
|
|
|
251
299
|
- validated module graph
|
|
252
300
|
- resolved contract bindings
|
|
253
301
|
- dependency-aware execution plan
|
|
254
302
|
- generated Docker Compose configuration
|
|
303
|
+
- generated Helm chart for Kubernetes
|
|
255
304
|
- reproducible stack definition
|
|
256
305
|
|
|
257
|
-
This
|
|
306
|
+
This turns a declarative platform design into a reproducible, runnable local
|
|
307
|
+
data stack—and turns architectural assumptions into things the project can
|
|
308
|
+
inspect, validate, and improve.
|
|
258
309
|
|
|
259
310
|
---
|
|
260
311
|
|
|
@@ -284,6 +335,10 @@ The `cds up` command and generated local profiles additionally require:
|
|
|
284
335
|
- Write access to the checkout for `.env`, `docker-compose.yml`, and workdir
|
|
285
336
|
data
|
|
286
337
|
|
|
338
|
+
For Kubernetes, install Helm and kubectl and provide an explicit kube context.
|
|
339
|
+
The local k3s workflow uses k3d and is documented in
|
|
340
|
+
[docs/kubernetes.md](docs/kubernetes.md).
|
|
341
|
+
|
|
287
342
|
Docker Desktop on Windows must use the WSL 2 backend. See the
|
|
288
343
|
[support policy](docs/support-policy.md) for supported operating systems and
|
|
289
344
|
runtime versions. For platform-specific setup from an empty machine, follow
|
|
@@ -448,6 +503,12 @@ cds render local-dagster-postgres-superset
|
|
|
448
503
|
|
|
449
504
|
By default, this writes `docker-compose.yml` to the project root.
|
|
450
505
|
|
|
506
|
+
Render the same plan as a Helm chart with:
|
|
507
|
+
|
|
508
|
+
```bash
|
|
509
|
+
cds render local-dagster-postgres-superset --target helm
|
|
510
|
+
```
|
|
511
|
+
|
|
451
512
|
Use a custom location when needed:
|
|
452
513
|
|
|
453
514
|
```bash
|
|
@@ -714,12 +775,13 @@ runs, with a dedicated diagnostic code:
|
|
|
714
775
|
|cds get \<profile\> [--remote \<owner/repo\>] [--ref \<ref\>] [--local \<dir\>] [--into \<dir\>]|Fetch a profile plus its dependent module/runtime assets from GitHub into a local CDS layout|
|
|
715
776
|
|cds list profiles\|modules\|images [--remote \<owner/repo\>] [--ref \<ref\>] [--local \<dir\>]|List available profiles, module sources, or module images and check for newer versions; add `--remote`/`--local` to inspect another repository before fetching from it|
|
|
716
777
|
|cds init [profile]|Generate a project `.env` template from profile secret definitions|
|
|
717
|
-
|cds validate [profile]|Validate modules and contracts|
|
|
778
|
+
|cds validate [profile]|Validate modules and contracts; use `--target helm` for Kubernetes checks|
|
|
718
779
|
|cds preflight [profile]|Check runtime tools, required environment values, and host ports without starting services|
|
|
719
780
|
|cds plan [profile]|Resolve dependencies and generate an execution plan|
|
|
720
|
-
|cds render [profile]|Generate Docker Compose
|
|
721
|
-
|cds up [profile]|Validate, plan, render,
|
|
722
|
-
|cds
|
|
781
|
+
|cds render [profile]|Generate Docker Compose or a Helm chart from a resolved plan|
|
|
782
|
+
|cds up [profile]|Validate, plan, render, and start the Compose or Helm target; use `--target helm` for Kubernetes|
|
|
783
|
+
|cds down [profile]|Stop Compose or uninstall a Helm release; Helm PVCs are retained by default|
|
|
784
|
+
|cds state [profile]|Show Compose services or Kubernetes workloads grouped by health|
|
|
723
785
|
|cds test [profile]|One-shot smoke validation: validate, security, plan, and render|
|
|
724
786
|
|cds security [profile]|Run rule-based security validation on a profile|
|
|
725
787
|
|cds diff [profile] --from \<env\> --to \<env\>|Show effective configuration differences between two environment overlays, secrets never included|
|
|
@@ -937,11 +999,11 @@ MVP ready:
|
|
|
937
999
|
- security checks
|
|
938
1000
|
- profile composition
|
|
939
1001
|
- Docker Compose rendering
|
|
1002
|
+
- Kubernetes Helm rendering and local k3s lifecycle
|
|
1003
|
+
- runtime startup, health state, and shutdown
|
|
940
1004
|
|
|
941
1005
|
Next:
|
|
942
1006
|
|
|
943
|
-
- runtime orchestration
|
|
944
|
-
- Kubernetes support
|
|
945
1007
|
- advanced secret providers
|
|
946
1008
|
- stack bootstrap and health checks
|
|
947
1009
|
|
|
@@ -952,7 +1014,20 @@ See [docs/support-policy.md](docs/support-policy.md) for OS support policy and p
|
|
|
952
1014
|
|
|
953
1015
|
## 🤝 Contributing
|
|
954
1016
|
|
|
955
|
-
|
|
1017
|
+
CDS will only become a useful interoperability layer if the people building and
|
|
1018
|
+
operating data platforms shape it together.
|
|
1019
|
+
|
|
1020
|
+
- **Run a profile** and report what works, what breaks, and what is missing.
|
|
1021
|
+
- **Document compatibility** between providers and consumers with evidence.
|
|
1022
|
+
- **Add or improve modules** without coupling them to a specific stack.
|
|
1023
|
+
- **Strengthen the model** through contracts, validation, security rules, and
|
|
1024
|
+
representative profiles.
|
|
1025
|
+
- **Star and follow** the
|
|
1026
|
+
[repository](https://github.com/RonaldHensbergen/composable-data-stack) if
|
|
1027
|
+
you want to track the project.
|
|
1028
|
+
|
|
1029
|
+
Real-world feedback is especially valuable. CDS should reflect how platforms
|
|
1030
|
+
actually fail and evolve, not how architecture diagrams pretend they do.
|
|
956
1031
|
|
|
957
1032
|
Please read these first:
|
|
958
1033
|
|
|
@@ -964,18 +1039,16 @@ Please read these first:
|
|
|
964
1039
|
- [CHANGELOG.md](CHANGELOG.md)
|
|
965
1040
|
- [RELEASE.md](RELEASE.md)
|
|
966
1041
|
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
- adding new modules
|
|
970
|
-
- improving profile examples
|
|
971
|
-
- extending contract definitions
|
|
972
|
-
- adding validation or security rules
|
|
1042
|
+
Development helper tools are located in the gitignored `tools/` directory. See
|
|
1043
|
+
`tools/pr-cli/README.md` for PR creation scripts.
|
|
973
1044
|
|
|
974
1045
|
---
|
|
975
1046
|
|
|
976
1047
|
## 📖 Documentation
|
|
977
1048
|
|
|
978
1049
|
- [Quickstart](README.md#-quickstart) — get running in 5 minutes
|
|
1050
|
+
- [How CDS Works](docs/how-it-works.md) — C4 + sequence diagrams of the validate → plan → render engine
|
|
1051
|
+
- [Kubernetes Target](docs/kubernetes.md): Helm rendering and isolated local k3s workflow
|
|
979
1052
|
- [From Docker Compose to CDS Profile](docs/from-docker-to-cds-profile.md) — complete transformation guide
|
|
980
1053
|
- [Architecture](docs/architecture.md) — design and core concepts
|
|
981
1054
|
- [Modules](docs/modules.md) — how to structure reusable components
|