beampipe-palette 0.5.2__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.
- beampipe_palette-0.5.2/Containerfile +5 -0
- beampipe_palette-0.5.2/HISTORY.md +57 -0
- beampipe_palette-0.5.2/LICENSE +11 -0
- beampipe_palette-0.5.2/MANIFEST.in +11 -0
- beampipe_palette-0.5.2/PKG-INFO +315 -0
- beampipe_palette-0.5.2/README.md +277 -0
- beampipe_palette-0.5.2/assets/brand/beampipe-terminal-logo.png +0 -0
- beampipe_palette-0.5.2/assets/brand/beampipe-terminal-logo.svg +80 -0
- beampipe_palette-0.5.2/assets/readme/imagegen-prompts.md +24 -0
- beampipe_palette-0.5.2/assets/readme/palette-components-terminal.png +0 -0
- beampipe_palette-0.5.2/assets/readme/palette-placement-terminal.png +0 -0
- beampipe_palette-0.5.2/beampipe_palette/VERSION +1 -0
- beampipe_palette-0.5.2/beampipe_palette/__init__.py +53 -0
- beampipe_palette-0.5.2/beampipe_palette/__main__.py +19 -0
- beampipe_palette-0.5.2/beampipe_palette/apps.py +161 -0
- beampipe_palette-0.5.2/beampipe_palette/component.py +14 -0
- beampipe_palette-0.5.2/beampipe_palette/ingest.py +108 -0
- beampipe_palette-0.5.2/beampipe_palette/inventory.py +207 -0
- beampipe_palette-0.5.2/beampipe_palette/publish.py +1024 -0
- beampipe_palette-0.5.2/beampipe_palette.egg-info/PKG-INFO +315 -0
- beampipe_palette-0.5.2/beampipe_palette.egg-info/SOURCES.txt +38 -0
- beampipe_palette-0.5.2/beampipe_palette.egg-info/dependency_links.txt +1 -0
- beampipe_palette-0.5.2/beampipe_palette.egg-info/entry_points.txt +2 -0
- beampipe_palette-0.5.2/beampipe_palette.egg-info/requires.txt +22 -0
- beampipe_palette-0.5.2/beampipe_palette.egg-info/top_level.txt +1 -0
- beampipe_palette-0.5.2/daliuge/palettes/beampipe.palette +402 -0
- beampipe_palette-0.5.2/pyproject.toml +15 -0
- beampipe_palette-0.5.2/requirements-test.txt +14 -0
- beampipe_palette-0.5.2/requirements.txt +4 -0
- beampipe_palette-0.5.2/scripts/generate_palette.py +313 -0
- beampipe_palette-0.5.2/setup.cfg +4 -0
- beampipe_palette-0.5.2/setup.py +57 -0
- beampipe_palette-0.5.2/tests/test_apps.py +231 -0
- beampipe_palette-0.5.2/tests/test_cli.py +13 -0
- beampipe_palette-0.5.2/tests/test_daliuge_pyfunc.py +124 -0
- beampipe_palette-0.5.2/tests/test_distribution.py +72 -0
- beampipe_palette-0.5.2/tests/test_ingest.py +66 -0
- beampipe_palette-0.5.2/tests/test_inventory.py +257 -0
- beampipe_palette-0.5.2/tests/test_publish.py +658 -0
- beampipe_palette-0.5.2/tests/test_publish_palette.py +141 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.5.2 (2026-09-02)
|
|
4
|
+
|
|
5
|
+
- Align native applications and EAGLE metadata with the DALiuGE 6.7 Python
|
|
6
|
+
component guide by making inline component descriptions the palette source.
|
|
7
|
+
- Preserve exact manifest bytes across both DALiuGE 6.6 and 6.7 named pickle
|
|
8
|
+
ports using DALiuGE's serialized-data envelope.
|
|
9
|
+
- Add lazy public exports for both native applications and explicit 6.6/6.7
|
|
10
|
+
runtime qualification lanes.
|
|
11
|
+
|
|
12
|
+
## 0.5.1 (2026-08-27)
|
|
13
|
+
|
|
14
|
+
- Make GitHub release publication explicit and attach both distribution
|
|
15
|
+
artifacts to the release.
|
|
16
|
+
- Install the wheel build prerequisite in CI and correct the real DALiuGE
|
|
17
|
+
FileDROP flush-order regression.
|
|
18
|
+
|
|
19
|
+
## 0.5.0 (2026-08-27)
|
|
20
|
+
|
|
21
|
+
- Publish the first public release under the corrected `beampipe-palette`
|
|
22
|
+
distribution and repository name.
|
|
23
|
+
- Rename the Python import namespace to `beampipe_palette`; this is an
|
|
24
|
+
intentional clean break with no misspelled compatibility module.
|
|
25
|
+
- Update generated EAGLE metadata, installed palette paths, CLI packaging,
|
|
26
|
+
documentation, tests, and repository URLs to the corrected spelling.
|
|
27
|
+
- Include the native manifest-ingest and durable output-publisher components,
|
|
28
|
+
callback-free session handoff, filesystem/S3 publication, and the full
|
|
29
|
+
project-neutral offline qualification suite.
|
|
30
|
+
|
|
31
|
+
## 0.4.0 (development milestone)
|
|
32
|
+
|
|
33
|
+
- Return the verified output-inventory receipt through an atomic,
|
|
34
|
+
execution-scoped session handoff file for remote schedulers.
|
|
35
|
+
- Remove direct Core callbacks and publisher credentials entirely; the control
|
|
36
|
+
plane exclusively owns receipt transport and authentication.
|
|
37
|
+
- Bind every returned receipt to its canonical top-level `execution_id` and
|
|
38
|
+
execution attempt.
|
|
39
|
+
|
|
40
|
+
## 0.3.0 (development milestone)
|
|
41
|
+
|
|
42
|
+
- Replace the manifest-ingest PyFunc with the native, source-style
|
|
43
|
+
`BeampipeIngestApp` BarrierAppDROP.
|
|
44
|
+
- Reduce ingestion to one Core-configured `manifest_path` setting and one
|
|
45
|
+
pickle-encoded manifest FileDROP output.
|
|
46
|
+
- Generate both native palette components deterministically without the
|
|
47
|
+
`dlg_paletteGen` development dependency.
|
|
48
|
+
|
|
49
|
+
## 0.2.0 (development milestone)
|
|
50
|
+
|
|
51
|
+
- Replace the experimental publisher PyFunc with a native, two-port
|
|
52
|
+
`BeampipePublishApp` BarrierAppDROP.
|
|
53
|
+
- Remove graph-level runtime/security overrides and the duplicate upstream
|
|
54
|
+
inventory input; retain only project-owned output patterns.
|
|
55
|
+
- Add immutable filesystem and optional S3-compatible publication backends.
|
|
56
|
+
- Add execution-attempt-scoped receipts and runtime credential handling.
|
|
57
|
+
- Add EAGLE palette, offline tests, packaging, and operator documentation.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Copyright 2021, The University of Western Australia, ICRAR International Centre for Radio Astronomy Research
|
|
2
|
+
|
|
3
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
|
4
|
+
|
|
5
|
+
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
|
6
|
+
|
|
7
|
+
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
|
8
|
+
|
|
9
|
+
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
|
10
|
+
|
|
11
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: beampipe-palette
|
|
3
|
+
Version: 0.5.2
|
|
4
|
+
Summary: Project-neutral DALiuGE components for Beampipe
|
|
5
|
+
Home-page: https://github.com/jbwod/beampipe-palette/
|
|
6
|
+
Author: Beampipe contributors
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Requires-Dist: wcmatch==11.0
|
|
11
|
+
Provides-Extra: daliuge
|
|
12
|
+
Requires-Dist: daliuge-engine<7,>=6.6; extra == "daliuge"
|
|
13
|
+
Provides-Extra: s3
|
|
14
|
+
Requires-Dist: boto3<2,>=1.38; extra == "s3"
|
|
15
|
+
Provides-Extra: test
|
|
16
|
+
Requires-Dist: pytest; extra == "test"
|
|
17
|
+
Requires-Dist: coverage; extra == "test"
|
|
18
|
+
Requires-Dist: flake8; extra == "test"
|
|
19
|
+
Requires-Dist: black; extra == "test"
|
|
20
|
+
Requires-Dist: isort; extra == "test"
|
|
21
|
+
Requires-Dist: pytest-cov; extra == "test"
|
|
22
|
+
Requires-Dist: codecov; extra == "test"
|
|
23
|
+
Requires-Dist: mypy; extra == "test"
|
|
24
|
+
Requires-Dist: gitchangelog; extra == "test"
|
|
25
|
+
Requires-Dist: mkdocs; extra == "test"
|
|
26
|
+
Requires-Dist: build; extra == "test"
|
|
27
|
+
Requires-Dist: wheel; extra == "test"
|
|
28
|
+
Requires-Dist: dlg_paletteGen==0.6.7; extra == "test"
|
|
29
|
+
Dynamic: author
|
|
30
|
+
Dynamic: description
|
|
31
|
+
Dynamic: description-content-type
|
|
32
|
+
Dynamic: home-page
|
|
33
|
+
Dynamic: license-file
|
|
34
|
+
Dynamic: provides-extra
|
|
35
|
+
Dynamic: requires-dist
|
|
36
|
+
Dynamic: requires-python
|
|
37
|
+
Dynamic: summary
|
|
38
|
+
|
|
39
|
+
<p align="center">
|
|
40
|
+
<img src="assets/brand/beampipe-terminal-logo.svg" alt="Beampipe" width="920">
|
|
41
|
+
</p>
|
|
42
|
+
|
|
43
|
+
<p align="center">
|
|
44
|
+
<a href="https://github.com/jbwod/beampipe-palette/actions/workflows/main.yml"><img src="https://github.com/jbwod/beampipe-palette/actions/workflows/main.yml/badge.svg" alt="CI"></a>
|
|
45
|
+
<a href="https://github.com/jbwod/beampipe-palette/releases/tag/v0.5.2"><img src="https://img.shields.io/badge/release-v0.5.2-d6c178?style=flat-square&labelColor=050505" alt="Release v0.5.2"></a>
|
|
46
|
+
<img src="https://img.shields.io/badge/Python-3.10%2B-7fd7e6?style=flat-square&labelColor=050505" alt="Python 3.10 or newer">
|
|
47
|
+
<img src="https://img.shields.io/badge/DALiuGE-6.6%20%7C%206.7-a7cfa3?style=flat-square&labelColor=050505" alt="DALiuGE 6.6 and 6.7 compatible">
|
|
48
|
+
</p>
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
> `beampipe-palette` provides the two project-neutral native [DALiuGE](https://daliuge.icrar.org/) applications that connect a portable graph to [Beampipe Core](https://github.com/jbwod/beampipe-core-v2): one injects Core's immutable execution manifest at the graph boundary, and one verifies durable outputs at the terminal boundary.
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
## `What it does`
|
|
55
|
+
|
|
56
|
+
> - **`Manifest ingress`**: `beampipe-ingest` receives inline JSON injected by Core, canonicalizes it, and emits it once through a path-backed FileDROP.
|
|
57
|
+
|
|
58
|
+
> - **`Durable publication`**: `beampipe-publish` independently discovers every required output, publishes each object create-only, reads it back, and verifies its SHA-256.
|
|
59
|
+
|
|
60
|
+
> - **`Trusted completion evidence`**: the publisher emits `beampipe-output-inventory/v1` to DALiuGE and writes the byte-identical receipt to an attempt-scoped session handoff.
|
|
61
|
+
|
|
62
|
+
> - **`Callback-free remote runs`**: Core retrieves the receipt over its existing SSH/SFTP control connection after Slurm completion. Graphs contain no Core URL, bearer token, storage credential, or project-specific topology.
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
## `Native DALiuGE components`
|
|
66
|
+
|
|
67
|
+
<picture>
|
|
68
|
+
<img src="assets/readme/palette-components-terminal.png" alt="Terminal-style beampipe-ingest and beampipe-publish DALiuGE application nodes with their manifest, completion, and inventory ports" />
|
|
69
|
+
</picture>
|
|
70
|
+
|
|
71
|
+
`beampipe-ingest` and `beampipe-publish` are native `BarrierAppDROP`
|
|
72
|
+
applications—not PyFunc snippets. Their graph-facing contracts stay deliberately
|
|
73
|
+
small; Core and the selected deployment profile supply execution details outside
|
|
74
|
+
the logical graph.
|
|
75
|
+
|
|
76
|
+
### Manifest entering `beampipe-ingest`
|
|
77
|
+
|
|
78
|
+
```json
|
|
79
|
+
{
|
|
80
|
+
"inputs": {},
|
|
81
|
+
"sources": [{
|
|
82
|
+
"source_identifier": "source-1",
|
|
83
|
+
"groups": [{
|
|
84
|
+
"group_key": "group-1",
|
|
85
|
+
"records": [{
|
|
86
|
+
"record_id": "record-1",
|
|
87
|
+
"access_url": "https://data.example/record-1"
|
|
88
|
+
}]
|
|
89
|
+
}]
|
|
90
|
+
}],
|
|
91
|
+
"_beampipe": {
|
|
92
|
+
"selection": [{
|
|
93
|
+
"source_identifier": "source-1",
|
|
94
|
+
"group_key": "group-1",
|
|
95
|
+
"record_ids": ["record-1"]
|
|
96
|
+
}]
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Inventory emitted by `beampipe-publish`
|
|
102
|
+
|
|
103
|
+
```json
|
|
104
|
+
{
|
|
105
|
+
"schema": "beampipe-output-inventory/v1",
|
|
106
|
+
"execution_id":
|
|
107
|
+
"607fd31f-db2a-4978-a64f-ef8ce412483a",
|
|
108
|
+
"execution_attempt": 0,
|
|
109
|
+
"patterns": ["**/result.bin"],
|
|
110
|
+
"pattern_counts": {"**/result.bin": 1},
|
|
111
|
+
"products": [{
|
|
112
|
+
"path": "products/result.bin",
|
|
113
|
+
"bytes": 1048576,
|
|
114
|
+
"sha256":
|
|
115
|
+
"a40f3e3d82fd741d64da75530ccb205588b8fbb5a5fbd7d52f18a77ef85d5e60"
|
|
116
|
+
}],
|
|
117
|
+
"inventory_sha256":
|
|
118
|
+
"5efa576ea4393a413c121862a75efcb5086cffa4b651ec77178dfa1c8caa07ce",
|
|
119
|
+
"durable_destination_uri":
|
|
120
|
+
"file:///srv/products/executions/607fd31f-db2a-4978-a64f-ef8ce412483a/attempt-0",
|
|
121
|
+
"publication": {
|
|
122
|
+
"acknowledged": true,
|
|
123
|
+
"publisher": "beampipe-publish",
|
|
124
|
+
"receipt_id":
|
|
125
|
+
"beampipe-publish/v1:5efa576ea4393a413c121862a75efcb5086cffa4b651ec77178dfa1c8caa07ce",
|
|
126
|
+
"published_at": "2026-08-27T10:32:16Z"
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
The examples show the stable project-neutral fields. Real manifests may add
|
|
132
|
+
project-owned record metadata, while real inventories contain one entry for
|
|
133
|
+
every selected product and the exact hashes observed after durable read-back.
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
## `Where the nodes go`
|
|
137
|
+
|
|
138
|
+
<picture>
|
|
139
|
+
<img src="assets/readme/palette-placement-terminal.png" alt="Terminal-style DALiuGE graph flow showing Core manifest into beampipe-ingest, the project graph and completion barrier, then beampipe-publish and the inventory receipt retrieved by Core" />
|
|
140
|
+
</picture>
|
|
141
|
+
|
|
142
|
+
> - Put **`beampipe-ingest` at the graph boundary**. Core patches its
|
|
143
|
+
> `manifest_path` setting with the immutable execution manifest. Connect its
|
|
144
|
+
> single `manifest_bytes` FileDROP to the first project application that needs
|
|
145
|
+
> those bytes.
|
|
146
|
+
|
|
147
|
+
> - Put **`beampipe-publish after the project-owned completion barrier`**. The
|
|
148
|
+
> barrier must become complete only after every required output is closed and
|
|
149
|
+
> stable. Connect the publisher's `inventory` output to one terminal
|
|
150
|
+
> FileDROP.
|
|
151
|
+
|
|
152
|
+
> - Do not draw a callback edge to Core. On remote Slurm deployments the
|
|
153
|
+
> publisher writes the canonical handoff inside the session; Core pulls and
|
|
154
|
+
> verifies it after the scheduler reports completion.
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
## `First-time setup`
|
|
158
|
+
|
|
159
|
+
Python 3.10 or newer is required. Install the validated public release into the
|
|
160
|
+
same Python environment used by every DALiuGE execution node:
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
python3 -m venv .venv
|
|
164
|
+
source .venv/bin/activate
|
|
165
|
+
python -m pip install \
|
|
166
|
+
https://github.com/jbwod/beampipe-palette/releases/download/v0.5.2/beampipe_palette-0.5.2-py3-none-any.whl
|
|
167
|
+
beampipe-publish --version
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
The released wheel is normally installed into an existing DALiuGE runtime. A
|
|
171
|
+
source checkout can create a self-contained DALiuGE 6.x environment with
|
|
172
|
+
`python -m pip install -e '.[daliuge]'`.
|
|
173
|
+
|
|
174
|
+
Install the bounded S3 transport only on runtimes that select an S3
|
|
175
|
+
destination:
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
python -m pip install \
|
|
179
|
+
'beampipe-palette[s3] @ https://github.com/jbwod/beampipe-palette/archive/refs/tags/v0.5.2.tar.gz'
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Download or load the checked-in EAGLE palette:
|
|
183
|
+
|
|
184
|
+
```text
|
|
185
|
+
https://raw.githubusercontent.com/jbwod/beampipe-palette/v0.5.2/daliuge/palettes/beampipe.palette
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
## `EAGLE graph contract`
|
|
190
|
+
|
|
191
|
+
Load [`daliuge/palettes/beampipe.palette`](daliuge/palettes/beampipe.palette)
|
|
192
|
+
in [EAGLE](https://eagle.icrar.org/). The wheel also installs it at
|
|
193
|
+
`share/beampipe-palette/daliuge/palettes/beampipe.palette` under the active
|
|
194
|
+
Python prefix.
|
|
195
|
+
|
|
196
|
+
| Component | Field | EAGLE usage | Contract |
|
|
197
|
+
|---|---|---|---|
|
|
198
|
+
| `beampipe-ingest` | `manifest_path` | NoPort | inline JSON from Core or an absolute manifest path |
|
|
199
|
+
| `beampipe-ingest` | `manifest_bytes` | OutputPort | one path-backed FileDROP, pickle encoding |
|
|
200
|
+
| `beampipe-publish` | `completion` | InputPort | one project-owned completion FileDROP |
|
|
201
|
+
| `beampipe-publish` | `inventory` | OutputPort | one path-backed canonical inventory FileDROP |
|
|
202
|
+
| `beampipe-publish` | `expected_patterns_json` | NoPort | project-owned JSON string array of required output globs |
|
|
203
|
+
|
|
204
|
+
The Python classes are:
|
|
205
|
+
|
|
206
|
+
```text
|
|
207
|
+
beampipe_palette.apps.BeampipeIngestApp
|
|
208
|
+
beampipe_palette.apps.BeampipePublishApp
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
The ingest output intentionally uses DALiuGE's `pickle` encoding. It wraps the
|
|
212
|
+
canonical bytes with DALiuGE's own serialized-data envelope before the single
|
|
213
|
+
pickle port write. This is the common named-port contract that returns exact
|
|
214
|
+
`bytes` on both DALiuGE 6.6 and 6.7. The publisher uses path-backed FileDROPs
|
|
215
|
+
directly and performs no second DROP write.
|
|
216
|
+
|
|
217
|
+
Projects must set `expected_patterns_json` explicitly. Matching is bounded and
|
|
218
|
+
Core-compatible: `*` and `?` stay within one path component, while `**` is
|
|
219
|
+
allowed only as a complete component. Character classes, brace expansion,
|
|
220
|
+
embedded double-stars, traversal, backslashes, controls, and duplicates are
|
|
221
|
+
rejected. The output tree is scanned once regardless of pattern count.
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
## `Runtime contract`
|
|
225
|
+
|
|
226
|
+
Runtime details are environment variables, never graph fields:
|
|
227
|
+
|
|
228
|
+
| Environment variable | Meaning |
|
|
229
|
+
|---|---|
|
|
230
|
+
| `BEAMPIPE_OUTPUT_ROOT` | source directory containing completed outputs |
|
|
231
|
+
| `BEAMPIPE_OUTPUT_DESTINATION_URI` | base `file://` or `s3://` destination |
|
|
232
|
+
| `BEAMPIPE_EXECUTION_ID` | canonical execution UUID |
|
|
233
|
+
| `BEAMPIPE_EXECUTION_ATTEMPT` | zero-based locked Core `retry_count` |
|
|
234
|
+
| `BEAMPIPE_OUTPUT_INVENTORY_HANDOFF_PATH` | required attempt-scoped receipt path prepared by the session transport |
|
|
235
|
+
|
|
236
|
+
The durable destination is always namespaced as:
|
|
237
|
+
|
|
238
|
+
```text
|
|
239
|
+
<base>/executions/<execution_uuid>/attempt-<retry_count>
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
The handoff path must be absolute, non-root, outside `BEAMPIPE_OUTPUT_ROOT`,
|
|
243
|
+
free of symbolic-link components, and have an existing private parent. No Core
|
|
244
|
+
URL, Core credential, storage secret, project identifier, or output pattern is
|
|
245
|
+
embedded in the component.
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
## `Publication guarantees`
|
|
249
|
+
|
|
250
|
+
> - **`Create-only writes`**: files, inventories, and handoffs are never
|
|
251
|
+
> overwritten. An existing byte-identical object is reused; conflicting
|
|
252
|
+
> evidence fails the run.
|
|
253
|
+
|
|
254
|
+
> - **`Read-back verification`**: every durable file or S3 object is retrieved
|
|
255
|
+
> in full and hashed before it is acknowledged.
|
|
256
|
+
|
|
257
|
+
> - **`Exact retries`**: a retry of the same execution attempt reuses the same
|
|
258
|
+
> canonical inventory bytes and publication timestamp. A later attempt has a
|
|
259
|
+
> separate immutable namespace.
|
|
260
|
+
|
|
261
|
+
> - **`Fail-closed evidence`**: missing patterns, empty outputs, symlinks,
|
|
262
|
+
> unsafe paths, oversized receipts, changed files, partial uploads, and
|
|
263
|
+
> mismatched prior evidence all fail publication.
|
|
264
|
+
|
|
265
|
+
Filesystem destinations use absolute, non-overlapping `file://` roots. S3
|
|
266
|
+
destinations require `beampipe-palette[s3]`, boto3 1.38 or newer, conditional
|
|
267
|
+
single-object/multipart creation, and full object read-back. NGAS is not
|
|
268
|
+
claimed until an adapter can provide authoritative file ID/version assignment
|
|
269
|
+
and retrieval verification.
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
## `Development`
|
|
273
|
+
|
|
274
|
+
The [DALiuGE 6.7 Python component guide](https://daliuge.readthedocs.io/en/v6.7.0/development/app_development/python_components.html)
|
|
275
|
+
uses `dlg_paletteGen` with inline Doxygen metadata. Install the two system
|
|
276
|
+
tools once on Debian/Ubuntu:
|
|
277
|
+
|
|
278
|
+
```bash
|
|
279
|
+
sudo apt-get install doxygen xsltproc
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
```bash
|
|
283
|
+
make virtualenv
|
|
284
|
+
make lint
|
|
285
|
+
make test
|
|
286
|
+
make palette-check
|
|
287
|
+
make docs
|
|
288
|
+
make build
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
Palette generation reads the `EAGLE_START` component descriptions in
|
|
292
|
+
`beampipe_palette/apps.py` through pinned `dlg_paletteGen` 0.6.7, then
|
|
293
|
+
canonicalizes IDs and timestamps so the checked EAGLE palette is deterministic.
|
|
294
|
+
|
|
295
|
+
The offline suite covers both native applications, canonical JSON, path and
|
|
296
|
+
port policy, one-pass discovery, filesystem/S3 create-only publication,
|
|
297
|
+
read-back hashes, exact retries, attempt isolation, session handoff, palette
|
|
298
|
+
signature drift, and project-neutral defaults. CI additionally runs the native
|
|
299
|
+
DALiuGE boundary regression against the released 6.6 engine and the pinned 6.7
|
|
300
|
+
source contract used by the linked 6.7 developer documentation.
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
## `Documentation`
|
|
304
|
+
|
|
305
|
+
| Task | Page |
|
|
306
|
+
|---|---|
|
|
307
|
+
| Download the current wheel and source archive | [v0.5.2 release](https://github.com/jbwod/beampipe-palette/releases/tag/v0.5.2) |
|
|
308
|
+
| Review the publication sequence | [Publisher guide](docs/index.md) |
|
|
309
|
+
| Import the components into EAGLE | [Checked-in palette](daliuge/palettes/beampipe.palette) |
|
|
310
|
+
| Contribute and run the local gates | [Contributing guide](CONTRIBUTING.md) |
|
|
311
|
+
| Review template provenance | [Template notes](ABOUT_THIS_TEMPLATE.md) |
|
|
312
|
+
|
|
313
|
+
This repository was created from ICRAR's
|
|
314
|
+
[`daliuge-component-template`](https://github.com/ICRAR/daliuge-component-template)
|
|
315
|
+
and retains its [license](LICENSE).
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="assets/brand/beampipe-terminal-logo.svg" alt="Beampipe" width="920">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<p align="center">
|
|
6
|
+
<a href="https://github.com/jbwod/beampipe-palette/actions/workflows/main.yml"><img src="https://github.com/jbwod/beampipe-palette/actions/workflows/main.yml/badge.svg" alt="CI"></a>
|
|
7
|
+
<a href="https://github.com/jbwod/beampipe-palette/releases/tag/v0.5.2"><img src="https://img.shields.io/badge/release-v0.5.2-d6c178?style=flat-square&labelColor=050505" alt="Release v0.5.2"></a>
|
|
8
|
+
<img src="https://img.shields.io/badge/Python-3.10%2B-7fd7e6?style=flat-square&labelColor=050505" alt="Python 3.10 or newer">
|
|
9
|
+
<img src="https://img.shields.io/badge/DALiuGE-6.6%20%7C%206.7-a7cfa3?style=flat-square&labelColor=050505" alt="DALiuGE 6.6 and 6.7 compatible">
|
|
10
|
+
</p>
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
> `beampipe-palette` provides the two project-neutral native [DALiuGE](https://daliuge.icrar.org/) applications that connect a portable graph to [Beampipe Core](https://github.com/jbwod/beampipe-core-v2): one injects Core's immutable execution manifest at the graph boundary, and one verifies durable outputs at the terminal boundary.
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
## `What it does`
|
|
17
|
+
|
|
18
|
+
> - **`Manifest ingress`**: `beampipe-ingest` receives inline JSON injected by Core, canonicalizes it, and emits it once through a path-backed FileDROP.
|
|
19
|
+
|
|
20
|
+
> - **`Durable publication`**: `beampipe-publish` independently discovers every required output, publishes each object create-only, reads it back, and verifies its SHA-256.
|
|
21
|
+
|
|
22
|
+
> - **`Trusted completion evidence`**: the publisher emits `beampipe-output-inventory/v1` to DALiuGE and writes the byte-identical receipt to an attempt-scoped session handoff.
|
|
23
|
+
|
|
24
|
+
> - **`Callback-free remote runs`**: Core retrieves the receipt over its existing SSH/SFTP control connection after Slurm completion. Graphs contain no Core URL, bearer token, storage credential, or project-specific topology.
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
## `Native DALiuGE components`
|
|
28
|
+
|
|
29
|
+
<picture>
|
|
30
|
+
<img src="assets/readme/palette-components-terminal.png" alt="Terminal-style beampipe-ingest and beampipe-publish DALiuGE application nodes with their manifest, completion, and inventory ports" />
|
|
31
|
+
</picture>
|
|
32
|
+
|
|
33
|
+
`beampipe-ingest` and `beampipe-publish` are native `BarrierAppDROP`
|
|
34
|
+
applications—not PyFunc snippets. Their graph-facing contracts stay deliberately
|
|
35
|
+
small; Core and the selected deployment profile supply execution details outside
|
|
36
|
+
the logical graph.
|
|
37
|
+
|
|
38
|
+
### Manifest entering `beampipe-ingest`
|
|
39
|
+
|
|
40
|
+
```json
|
|
41
|
+
{
|
|
42
|
+
"inputs": {},
|
|
43
|
+
"sources": [{
|
|
44
|
+
"source_identifier": "source-1",
|
|
45
|
+
"groups": [{
|
|
46
|
+
"group_key": "group-1",
|
|
47
|
+
"records": [{
|
|
48
|
+
"record_id": "record-1",
|
|
49
|
+
"access_url": "https://data.example/record-1"
|
|
50
|
+
}]
|
|
51
|
+
}]
|
|
52
|
+
}],
|
|
53
|
+
"_beampipe": {
|
|
54
|
+
"selection": [{
|
|
55
|
+
"source_identifier": "source-1",
|
|
56
|
+
"group_key": "group-1",
|
|
57
|
+
"record_ids": ["record-1"]
|
|
58
|
+
}]
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Inventory emitted by `beampipe-publish`
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"schema": "beampipe-output-inventory/v1",
|
|
68
|
+
"execution_id":
|
|
69
|
+
"607fd31f-db2a-4978-a64f-ef8ce412483a",
|
|
70
|
+
"execution_attempt": 0,
|
|
71
|
+
"patterns": ["**/result.bin"],
|
|
72
|
+
"pattern_counts": {"**/result.bin": 1},
|
|
73
|
+
"products": [{
|
|
74
|
+
"path": "products/result.bin",
|
|
75
|
+
"bytes": 1048576,
|
|
76
|
+
"sha256":
|
|
77
|
+
"a40f3e3d82fd741d64da75530ccb205588b8fbb5a5fbd7d52f18a77ef85d5e60"
|
|
78
|
+
}],
|
|
79
|
+
"inventory_sha256":
|
|
80
|
+
"5efa576ea4393a413c121862a75efcb5086cffa4b651ec77178dfa1c8caa07ce",
|
|
81
|
+
"durable_destination_uri":
|
|
82
|
+
"file:///srv/products/executions/607fd31f-db2a-4978-a64f-ef8ce412483a/attempt-0",
|
|
83
|
+
"publication": {
|
|
84
|
+
"acknowledged": true,
|
|
85
|
+
"publisher": "beampipe-publish",
|
|
86
|
+
"receipt_id":
|
|
87
|
+
"beampipe-publish/v1:5efa576ea4393a413c121862a75efcb5086cffa4b651ec77178dfa1c8caa07ce",
|
|
88
|
+
"published_at": "2026-08-27T10:32:16Z"
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
The examples show the stable project-neutral fields. Real manifests may add
|
|
94
|
+
project-owned record metadata, while real inventories contain one entry for
|
|
95
|
+
every selected product and the exact hashes observed after durable read-back.
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
## `Where the nodes go`
|
|
99
|
+
|
|
100
|
+
<picture>
|
|
101
|
+
<img src="assets/readme/palette-placement-terminal.png" alt="Terminal-style DALiuGE graph flow showing Core manifest into beampipe-ingest, the project graph and completion barrier, then beampipe-publish and the inventory receipt retrieved by Core" />
|
|
102
|
+
</picture>
|
|
103
|
+
|
|
104
|
+
> - Put **`beampipe-ingest` at the graph boundary**. Core patches its
|
|
105
|
+
> `manifest_path` setting with the immutable execution manifest. Connect its
|
|
106
|
+
> single `manifest_bytes` FileDROP to the first project application that needs
|
|
107
|
+
> those bytes.
|
|
108
|
+
|
|
109
|
+
> - Put **`beampipe-publish after the project-owned completion barrier`**. The
|
|
110
|
+
> barrier must become complete only after every required output is closed and
|
|
111
|
+
> stable. Connect the publisher's `inventory` output to one terminal
|
|
112
|
+
> FileDROP.
|
|
113
|
+
|
|
114
|
+
> - Do not draw a callback edge to Core. On remote Slurm deployments the
|
|
115
|
+
> publisher writes the canonical handoff inside the session; Core pulls and
|
|
116
|
+
> verifies it after the scheduler reports completion.
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
## `First-time setup`
|
|
120
|
+
|
|
121
|
+
Python 3.10 or newer is required. Install the validated public release into the
|
|
122
|
+
same Python environment used by every DALiuGE execution node:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
python3 -m venv .venv
|
|
126
|
+
source .venv/bin/activate
|
|
127
|
+
python -m pip install \
|
|
128
|
+
https://github.com/jbwod/beampipe-palette/releases/download/v0.5.2/beampipe_palette-0.5.2-py3-none-any.whl
|
|
129
|
+
beampipe-publish --version
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
The released wheel is normally installed into an existing DALiuGE runtime. A
|
|
133
|
+
source checkout can create a self-contained DALiuGE 6.x environment with
|
|
134
|
+
`python -m pip install -e '.[daliuge]'`.
|
|
135
|
+
|
|
136
|
+
Install the bounded S3 transport only on runtimes that select an S3
|
|
137
|
+
destination:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
python -m pip install \
|
|
141
|
+
'beampipe-palette[s3] @ https://github.com/jbwod/beampipe-palette/archive/refs/tags/v0.5.2.tar.gz'
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Download or load the checked-in EAGLE palette:
|
|
145
|
+
|
|
146
|
+
```text
|
|
147
|
+
https://raw.githubusercontent.com/jbwod/beampipe-palette/v0.5.2/daliuge/palettes/beampipe.palette
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
## `EAGLE graph contract`
|
|
152
|
+
|
|
153
|
+
Load [`daliuge/palettes/beampipe.palette`](daliuge/palettes/beampipe.palette)
|
|
154
|
+
in [EAGLE](https://eagle.icrar.org/). The wheel also installs it at
|
|
155
|
+
`share/beampipe-palette/daliuge/palettes/beampipe.palette` under the active
|
|
156
|
+
Python prefix.
|
|
157
|
+
|
|
158
|
+
| Component | Field | EAGLE usage | Contract |
|
|
159
|
+
|---|---|---|---|
|
|
160
|
+
| `beampipe-ingest` | `manifest_path` | NoPort | inline JSON from Core or an absolute manifest path |
|
|
161
|
+
| `beampipe-ingest` | `manifest_bytes` | OutputPort | one path-backed FileDROP, pickle encoding |
|
|
162
|
+
| `beampipe-publish` | `completion` | InputPort | one project-owned completion FileDROP |
|
|
163
|
+
| `beampipe-publish` | `inventory` | OutputPort | one path-backed canonical inventory FileDROP |
|
|
164
|
+
| `beampipe-publish` | `expected_patterns_json` | NoPort | project-owned JSON string array of required output globs |
|
|
165
|
+
|
|
166
|
+
The Python classes are:
|
|
167
|
+
|
|
168
|
+
```text
|
|
169
|
+
beampipe_palette.apps.BeampipeIngestApp
|
|
170
|
+
beampipe_palette.apps.BeampipePublishApp
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
The ingest output intentionally uses DALiuGE's `pickle` encoding. It wraps the
|
|
174
|
+
canonical bytes with DALiuGE's own serialized-data envelope before the single
|
|
175
|
+
pickle port write. This is the common named-port contract that returns exact
|
|
176
|
+
`bytes` on both DALiuGE 6.6 and 6.7. The publisher uses path-backed FileDROPs
|
|
177
|
+
directly and performs no second DROP write.
|
|
178
|
+
|
|
179
|
+
Projects must set `expected_patterns_json` explicitly. Matching is bounded and
|
|
180
|
+
Core-compatible: `*` and `?` stay within one path component, while `**` is
|
|
181
|
+
allowed only as a complete component. Character classes, brace expansion,
|
|
182
|
+
embedded double-stars, traversal, backslashes, controls, and duplicates are
|
|
183
|
+
rejected. The output tree is scanned once regardless of pattern count.
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
## `Runtime contract`
|
|
187
|
+
|
|
188
|
+
Runtime details are environment variables, never graph fields:
|
|
189
|
+
|
|
190
|
+
| Environment variable | Meaning |
|
|
191
|
+
|---|---|
|
|
192
|
+
| `BEAMPIPE_OUTPUT_ROOT` | source directory containing completed outputs |
|
|
193
|
+
| `BEAMPIPE_OUTPUT_DESTINATION_URI` | base `file://` or `s3://` destination |
|
|
194
|
+
| `BEAMPIPE_EXECUTION_ID` | canonical execution UUID |
|
|
195
|
+
| `BEAMPIPE_EXECUTION_ATTEMPT` | zero-based locked Core `retry_count` |
|
|
196
|
+
| `BEAMPIPE_OUTPUT_INVENTORY_HANDOFF_PATH` | required attempt-scoped receipt path prepared by the session transport |
|
|
197
|
+
|
|
198
|
+
The durable destination is always namespaced as:
|
|
199
|
+
|
|
200
|
+
```text
|
|
201
|
+
<base>/executions/<execution_uuid>/attempt-<retry_count>
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
The handoff path must be absolute, non-root, outside `BEAMPIPE_OUTPUT_ROOT`,
|
|
205
|
+
free of symbolic-link components, and have an existing private parent. No Core
|
|
206
|
+
URL, Core credential, storage secret, project identifier, or output pattern is
|
|
207
|
+
embedded in the component.
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
## `Publication guarantees`
|
|
211
|
+
|
|
212
|
+
> - **`Create-only writes`**: files, inventories, and handoffs are never
|
|
213
|
+
> overwritten. An existing byte-identical object is reused; conflicting
|
|
214
|
+
> evidence fails the run.
|
|
215
|
+
|
|
216
|
+
> - **`Read-back verification`**: every durable file or S3 object is retrieved
|
|
217
|
+
> in full and hashed before it is acknowledged.
|
|
218
|
+
|
|
219
|
+
> - **`Exact retries`**: a retry of the same execution attempt reuses the same
|
|
220
|
+
> canonical inventory bytes and publication timestamp. A later attempt has a
|
|
221
|
+
> separate immutable namespace.
|
|
222
|
+
|
|
223
|
+
> - **`Fail-closed evidence`**: missing patterns, empty outputs, symlinks,
|
|
224
|
+
> unsafe paths, oversized receipts, changed files, partial uploads, and
|
|
225
|
+
> mismatched prior evidence all fail publication.
|
|
226
|
+
|
|
227
|
+
Filesystem destinations use absolute, non-overlapping `file://` roots. S3
|
|
228
|
+
destinations require `beampipe-palette[s3]`, boto3 1.38 or newer, conditional
|
|
229
|
+
single-object/multipart creation, and full object read-back. NGAS is not
|
|
230
|
+
claimed until an adapter can provide authoritative file ID/version assignment
|
|
231
|
+
and retrieval verification.
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
## `Development`
|
|
235
|
+
|
|
236
|
+
The [DALiuGE 6.7 Python component guide](https://daliuge.readthedocs.io/en/v6.7.0/development/app_development/python_components.html)
|
|
237
|
+
uses `dlg_paletteGen` with inline Doxygen metadata. Install the two system
|
|
238
|
+
tools once on Debian/Ubuntu:
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
sudo apt-get install doxygen xsltproc
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
make virtualenv
|
|
246
|
+
make lint
|
|
247
|
+
make test
|
|
248
|
+
make palette-check
|
|
249
|
+
make docs
|
|
250
|
+
make build
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Palette generation reads the `EAGLE_START` component descriptions in
|
|
254
|
+
`beampipe_palette/apps.py` through pinned `dlg_paletteGen` 0.6.7, then
|
|
255
|
+
canonicalizes IDs and timestamps so the checked EAGLE palette is deterministic.
|
|
256
|
+
|
|
257
|
+
The offline suite covers both native applications, canonical JSON, path and
|
|
258
|
+
port policy, one-pass discovery, filesystem/S3 create-only publication,
|
|
259
|
+
read-back hashes, exact retries, attempt isolation, session handoff, palette
|
|
260
|
+
signature drift, and project-neutral defaults. CI additionally runs the native
|
|
261
|
+
DALiuGE boundary regression against the released 6.6 engine and the pinned 6.7
|
|
262
|
+
source contract used by the linked 6.7 developer documentation.
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
## `Documentation`
|
|
266
|
+
|
|
267
|
+
| Task | Page |
|
|
268
|
+
|---|---|
|
|
269
|
+
| Download the current wheel and source archive | [v0.5.2 release](https://github.com/jbwod/beampipe-palette/releases/tag/v0.5.2) |
|
|
270
|
+
| Review the publication sequence | [Publisher guide](docs/index.md) |
|
|
271
|
+
| Import the components into EAGLE | [Checked-in palette](daliuge/palettes/beampipe.palette) |
|
|
272
|
+
| Contribute and run the local gates | [Contributing guide](CONTRIBUTING.md) |
|
|
273
|
+
| Review template provenance | [Template notes](ABOUT_THIS_TEMPLATE.md) |
|
|
274
|
+
|
|
275
|
+
This repository was created from ICRAR's
|
|
276
|
+
[`daliuge-component-template`](https://github.com/ICRAR/daliuge-component-template)
|
|
277
|
+
and retains its [license](LICENSE).
|
|
Binary file
|