|
1 | 1 | # Teckel |
2 | 2 |
|
3 | | -[](https://github.com/rafafrdz/teckel/actions/workflows/release.yml) |
| 3 | +[](https://github.com/eff3ct0/teckel/actions/workflows/release.yml) |
4 | 4 | [](https://codecov.io/gh/eff3ct0/teckel) |
5 | 5 | [](https://opensource.org/licenses/MIT) |
6 | 6 |
|
7 | | -Teckel is a framework designed to simplify the creation of Apache Spark ETL (Extract, Transform, |
8 | | -Load) processes using YAML configuration files. This tool aims to standardize and streamline ETL workflow creation by |
9 | | -enabling the definition of data transformations in a declarative, user-friendly format without writing extensive code. |
| 7 | +Teckel is a **Scala / Apache Spark reference implementation** of the |
| 8 | +[Teckel Specification](https://github.com/eff3ct0/teckel-spec) — a declarative YAML language for |
| 9 | +defining data transformation pipelines. You describe *what* you want done; Teckel parses the YAML, |
| 10 | +builds the DAG, validates references, and executes it on Spark. |
10 | 11 |
|
11 | 12 |  |
12 | 13 |
|
13 | | -This concept is further developed on my |
14 | | -blog: [Big Data with Zero Code](https://blog.rafaelfernandez.dev/posts/big-data-with-zero-code/) |
| 14 | +Background reading: [Big Data with Zero Code](https://blog.rafaelfernandez.dev/posts/big-data-with-zero-code/). |
15 | 15 |
|
16 | | -## Features |
17 | | - |
18 | | -- **Declarative ETL Configuration:** Define your ETL processes with simple YAML files. |
19 | | -- **Support for Multiple Data Sources:** Easily integrate inputs in CSV, JSON, and Parquet formats. |
20 | | -- **Flexible Transformations:** Perform joins, aggregations, and selections with clear syntax. |
21 | | -- **Spark Compatibility:** Leverage the power of Apache Spark for large-scale data processing. |
| 16 | +## Sibling projects |
22 | 17 |
|
23 | | -## ETL Yaml Example |
| 18 | +| Project | Role | |
| 19 | +|---------|------| |
| 20 | +| [eff3ct0/teckel-spec](https://github.com/eff3ct0/teckel-spec) | Language-agnostic specification (current: **v3.0**). Defines syntax, semantics, expression grammar, validation rules, conformance levels, error catalog. | |
| 21 | +| **eff3ct0/teckel** *(this repo)* | Scala 2.13 + Apache Spark 3.5.x reference implementation. | |
| 22 | +| [eff3ct0/teckel-rs](https://github.com/eff3ct0/teckel-rs) | Rust implementation (parser + model layer for v3.0). | |
24 | 23 |
|
25 | | -Here's an example of a fully defined ETL configuration using a YAML file: |
| 24 | +## Features |
26 | 25 |
|
27 | | -### SQL ETL |
| 26 | +- **Declarative YAML pipelines** — sources, transformations, sinks defined as data, not code. |
| 27 | +- **45+ built-in transformations** — relational (`select`, `where`, `group`, `order`, `join`, |
| 28 | + `union`/`intersect`/`except`, `distinct`, `limit`), column ops (`addColumns`, `dropColumns`, |
| 29 | + `renameColumns`, `castColumns`), analytical (`window`, `pivot`, `unpivot`, `flatten`, `sample`, |
| 30 | + `rollup`, `cube`, `groupingSets`), warehousing (`scd2`, `merge`, `enrich`, `schemaEnforce`), |
| 31 | + control flow (`conditional`, `split`, `sql`), v3.0 additions (`offset`, `tail`, `fillNa`, |
| 32 | + `dropNa`, `replace`, `parse`, `asOfJoin`, `lateralJoin`, `transpose`, `describe`, `crosstab`, |
| 33 | + `hint`), and pluggable `custom` components. |
| 34 | +- **Variable substitution** — `${VAR}` and `${VAR:default}` resolved from env vars. |
| 35 | +- **Secrets** — `{{secrets.<alias>}}` placeholders backed by env vars or pluggable providers. |
| 36 | +- **Hooks** — `preExecution` / `postExecution` shell commands around the pipeline run. |
| 37 | +- **Pipeline config** — backend selection, cache policy, notifications, custom component declarations. |
| 38 | +- **Streaming I/O** — `streamingInput` / `streamingOutput` for Structured Streaming pipelines. |
| 39 | +- **Dry-run & validation** — preview the execution plan and catch broken references before Spark starts. |
| 40 | +- **Doc generation** — render any pipeline as Markdown. |
| 41 | +- **DAG visualization** — Mermaid, DOT, or ASCII output. |
| 42 | +- **Embedded REST server** — expose pipelines as HTTP endpoints with no extra dependencies. |
| 43 | + |
| 44 | +> Naming note: this implementation uses `group` / `order` as the YAML keys (instead of the |
| 45 | +> spec-canonical `groupBy` / `orderBy`). All other top-level keys and operation names match the spec. |
| 46 | +
|
| 47 | +## Quick example |
| 48 | + |
| 49 | +```yaml |
| 50 | +version: "3.0" |
28 | 51 |
|
29 | | -- Simple Example: [here](./docs/etl/simple.yaml) |
30 | | -- Complex Example: [here](./docs/etl/complex.yaml) |
31 | | -- Other Example: [here](./docs/etl/example.yaml) |
| 52 | +input: |
| 53 | + - name: employees |
| 54 | + format: csv |
| 55 | + path: 'data/employees.csv' |
| 56 | + options: |
| 57 | + header: true |
| 58 | + inferSchema: true |
| 59 | + |
| 60 | +transformation: |
| 61 | + - name: active |
| 62 | + where: |
| 63 | + from: employees |
| 64 | + filter: "status = 'active'" |
| 65 | + |
| 66 | + - name: by_dept |
| 67 | + group: |
| 68 | + from: active |
| 69 | + by: [department] |
| 70 | + agg: |
| 71 | + - "count(*) as headcount" |
| 72 | + - "avg(salary) as avg_salary" |
32 | 73 |
|
33 | | -### SQL Transformations |
| 74 | +output: |
| 75 | + - name: by_dept |
| 76 | + format: parquet |
| 77 | + mode: overwrite |
| 78 | + path: 'data/output/by_dept' |
| 79 | +``` |
34 | 80 |
|
35 | | -- `Select` Example: [here](./docs/etl/select.yaml) |
36 | | -- `Where` Example: [here](./docs/etl/where.yaml) |
37 | | -- `Group By` Example: [here](./docs/etl/group-by.yaml) |
38 | | -- `Order By` Example: [here](./docs/etl/order-by.yaml) |
39 | | -- `Join` Example: [here](./docs/etl/join.yaml) |
| 81 | +More examples under [`docs/etl/`](./docs/etl/) — `simple.yaml`, `complex.yaml`, `join.yaml`, |
| 82 | +`window.yaml`, `merge.yaml`, `quality.yaml`, `secrets.yaml`, `streaming.yaml`, and many more. |
40 | 83 |
|
41 | 84 | ## Getting Started |
42 | 85 |
|
43 | 86 | ### Prerequisites |
44 | 87 |
|
45 | | -- **Apache Spark**: Ensure you have Apache Spark installed and properly configured. |
46 | | -- **YAML files**: Create configuration files specifying your data sources and transformations. |
| 88 | +- **JDK 8 or 11** (Spark 3.5.x is not fully supported on Java 17 in all configurations). |
| 89 | +- **Apache Spark 3.5.x** at runtime (declared `provided` in the library artifacts). |
| 90 | +- **YAML pipeline files**. |
47 | 91 |
|
48 | | -#### Deployment on Docker or Kubernetes |
| 92 | +#### Spark on Docker / Kubernetes |
49 | 93 |
|
50 | | -In case of you don't have Apache Spark installed previously, you can deploy an Apache Spark cluster using the following |
51 | | -docker image [ |
52 | | -`eff3ct/spark:latest`](https://hub.docker.com/r/eff3ct/spark) available in |
53 | | -the [eff3ct0/spark-docker](https://github.com/eff3ct0/spark-docker) GitHub repository. |
| 94 | +If you don't already run Spark, the |
| 95 | +[`eff3ct/spark`](https://hub.docker.com/r/eff3ct/spark) image |
| 96 | +([eff3ct0/spark-docker](https://github.com/eff3ct0/spark-docker)) is a ready-to-use cluster. |
54 | 97 |
|
55 | 98 | ### Installation |
56 | 99 |
|
57 | | -Clone the Teckel repository and integrate it with your existing Spark setup: |
| 100 | +Clone and build: |
58 | 101 |
|
59 | 102 | ```bash |
60 | | -git clone https://github.com/rafafrdz/teckel.git |
| 103 | +git clone https://github.com/eff3ct0/teckel.git |
61 | 104 | cd teckel |
| 105 | +sbt cli/assembly |
62 | 106 | ``` |
63 | 107 |
|
64 | | -#### Building the Teckel ETL Uber JAR |
| 108 | +The CLI uber JAR is `cli/target/scala-2.13/teckel-etl_2.13.jar` (Spark bundled in). |
65 | 109 |
|
66 | | -Build the Teckel ETL CLI into an Uber JAR using the following command: |
| 110 | +### CLI |
67 | 111 |
|
68 | | -```bash |
69 | | -sbt cli/assembly |
| 112 | +``` |
| 113 | +-f, --file <path> run the pipeline at <path> |
| 114 | +-c, --console read YAML from stdin |
| 115 | + --dry-run print the execution plan, no Spark |
| 116 | + --doc emit Markdown documentation for the pipeline |
| 117 | + --graph emit the DAG (Mermaid by default) |
| 118 | + --server [--port N] start the embedded REST server |
70 | 119 | ``` |
71 | 120 |
|
72 | | -The resulting JAR, `teckel-etl_2.13.jar`, will be located in the `cli/target/scala-2.13/` directory. |
| 121 | +#### Run from a file |
73 | 122 |
|
74 | | -### Usage in Apache Spark Ecosystem with the CLI |
| 123 | +<details><summary>Demo - Teckel and Apache Spark by Yaml File</summary> |
75 | 124 |
|
76 | | -Once the `teckel-etl_2.13.jar`is ready, use it to execute ETL processes on Apache Spark with the following arguments: |
| 125 | +[](https://www.youtube.com/watch?v=eJwJIbNAtto "Teckel and Apache Spark by Yaml File") |
77 | 126 |
|
78 | | -- `-f` or `--file`: The path to the ETL file. |
79 | | -- `-c` or `--console`: Run the ETL in the console. |
| 127 | +</details> |
80 | 128 |
|
81 | | -#### Example: Running ETL in Apache Spark using STDIN |
| 129 | +```bash |
| 130 | +/opt/spark/bin/spark-submit --class com.eff3ct.teckel.app.Main teckel-etl_2.13.jar -f /path/to/pipeline.yaml |
| 131 | +``` |
| 132 | + |
| 133 | +#### Run from stdin |
82 | 134 |
|
83 | 135 | <details><summary>Demo - Teckel and Apache Spark by STDIN</summary> |
84 | 136 |
|
85 | | -[](https://www.youtube.com/watch?v=V9PzMdZ6u2U "Teckel and Apache Spark by STDIN") |
| 137 | +[](https://www.youtube.com/watch?v=V9PzMdZ6u2U "Teckel and Apache Spark by STDIN") |
86 | 138 |
|
87 | 139 | </details> |
88 | 140 |
|
89 | | -To run the ETL in the **console**, you can use the following command: |
90 | | - |
91 | 141 | ```bash |
92 | | -cat << EOF | /opt/spark/bin/spark-submit --class com.eff3ct.teckel.app.Main teckel-etl_2.13.jar -c |
| 142 | +cat << 'EOF' | /opt/spark/bin/spark-submit --class com.eff3ct.teckel.app.Main teckel-etl_2.13.jar -c |
| 143 | +version: "3.0" |
93 | 144 | input: |
94 | | - - name: table1 |
| 145 | + - name: t |
95 | 146 | format: csv |
96 | 147 | path: '/path/to/data/file.csv' |
97 | 148 | options: |
98 | 149 | header: true |
99 | 150 | sep: '|' |
100 | | -
|
101 | | -
|
102 | 151 | output: |
103 | | - - name: table1 |
| 152 | + - name: t |
104 | 153 | format: parquet |
105 | 154 | mode: overwrite |
106 | 155 | path: '/path/to/output/' |
107 | 156 | EOF |
108 | 157 | ``` |
109 | 158 |
|
110 | | -#### Example: Running ETL in Apache Spark using a file |
111 | | - |
112 | | -<details><summary>Demo - Teckel and Apache Spark by Yaml File</summary> |
113 | | - |
114 | | -[](https://www.youtube.com/watch?v=eJwJIbNAtto "Teckel and Apache Spark by Yaml File") |
115 | | - |
116 | | -</details> |
117 | | - |
118 | | -To run the ETL from a **file**, you can use the following command: |
119 | | - |
120 | | -```bash |
121 | | -/opt/spark/bin/spark-submit --class com.eff3ct.teckel.app.Main teckel-etl_2.13.jar -f /path/to/etl/file.yaml |
122 | | -``` |
123 | | - |
124 | 159 | > [!IMPORTANT] |
125 | 160 | > |
126 | 161 | > **Teckel CLI as dependency / Teckel ETL as framework.** |
127 | 162 | > |
128 | | -> The Teckel CLI is a standalone application that can be used as a dependency in your project. Notice that the uber jar |
129 | | -> name is `teckel-etl` and not `teckel-cli` or `teckel-cli-assembly`. This is because |
130 | | -> we want to distinguish between the Teckel CLI dependency and the ETL framework. |
| 163 | +> The Teckel CLI is also usable as a library dependency. The uber JAR is named `teckel-etl` |
| 164 | +> (not `teckel-cli`) precisely to distinguish the CLI from the framework when both end up on the |
| 165 | +> same classpath. |
131 | 166 | > |
132 | | -> Check the [Integration with Apache Spark](./docs/integration-apache-spark.md) documentation for more information. |
| 167 | +> See [Integration with Apache Spark](./docs/integration-apache-spark.md) for embedding details. |
133 | 168 |
|
134 | 169 | ## Integration with Apache Spark |
135 | 170 |
|
136 | | -Teckel can be integrated with Apache Spark easily just adding either the Teckel CLI or Teckel Api as a |
137 | | -dependency in your project or using it as a framework in your Apache Spark project. |
| 171 | +Teckel integrates with any existing Spark application — either as a CLI invoked via |
| 172 | +`spark-submit`, or as a library (`teckel-api`) embedded in your Scala code. Three entry points |
| 173 | +are exposed: `etl[F, O]` (polymorphic), `etlIO[O]` (fixes `F = IO`), and `unsafeETL[O]` |
| 174 | +(synchronous). See [Integration with Apache Spark](./docs/integration-apache-spark.md). |
138 | 175 |
|
139 | | -Check the [Integration with Apache Spark](./docs/integration-apache-spark.md) documentation for more information. |
| 176 | +## Documentation |
| 177 | + |
| 178 | +The Docusaurus site under [`teckel-docs/`](./teckel-docs/) contains the full guide: |
| 179 | +Getting Started, Transformations, API, CLI, Plugins, and Examples. The canonical language |
| 180 | +reference lives in |
| 181 | +[teckel-spec v3.0](https://github.com/eff3ct0/teckel-spec/blob/master/spec/v3.0/teckel-spec.md). |
140 | 182 |
|
141 | 183 | ## Development and Contribution |
142 | 184 |
|
143 | | -Contributions to Teckel are welcome. If you'd like to contribute, please fork the repository and create a pull request |
144 | | -with your changes. |
| 185 | +Contributions welcome — fork the repository and open a pull request. For changes affecting the |
| 186 | +YAML surface, please cross-check against the |
| 187 | +[Teckel Specification](https://github.com/eff3ct0/teckel-spec) before submitting. |
145 | 188 |
|
146 | 189 | ## License |
147 | 190 |
|
148 | | -Teckel is available under the MIT License. See the [LICENSE](./LICENSE) file for more details. |
149 | | - |
150 | | -If you have any questions regarding the license, feel free to contact Rafael Fernandez. |
| 191 | +Teckel is available under the MIT License. See the [LICENSE](./LICENSE) file for details. |
151 | 192 |
|
152 | | -For any issues or questions, feel free to open an issue on the GitHub repository. |
| 193 | +For any issues or questions, open an issue on GitHub or contact Rafael Fernandez. |
0 commit comments