Skip to content

Commit ce53bfd

Browse files
jfrancoaclaude
andcommitted
Add collection export commands (create, get, cancel).
Implements CLI support for exporting collections to external storage backends (S3, GCS, Azure, filesystem) in Parquet format. Includes unit tests, integration tests, and skill documentation updates. Closes #158 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 539606a commit ce53bfd

12 files changed

Lines changed: 1076 additions & 6 deletions

File tree

.claude/skills/contributing-to-weaviate-cli/references/architecture.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ class CollectionManager:
8181
self.client.collections.create(name=collection, ...)
8282
```
8383

84+
Manager files: `collection_manager.py`, `tenant_manager.py`, `data_manager.py`, `backup_manager.py`, `export_manager.py`, `role_manager.py`, `user_manager.py`, `node_manager.py`, `shard_manager.py`, `cluster_manager.py`, `alias_manager.py`, `benchmark_manager.py`, `config_manager.py`
85+
8486
Managers handle:
8587
- Input validation and error messages
8688
- Weaviate client API calls

.claude/skills/operating-weaviate-cli/SKILL.md

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,13 +113,13 @@ weaviate-cli [--config-file FILE] [--user USER] <group> <command> [--json] [opti
113113

114114
| Group | Description |
115115
|-------|-------------|
116-
| `create` | Create collections, tenants, data, backups, roles, users, aliases, replications |
117-
| `get` | Inspect collections, tenants, shards, backups, roles, users, nodes, aliases, replications |
116+
| `create` | Create collections, tenants, data, backups, exports, roles, users, aliases, replications |
117+
| `get` | Inspect collections, tenants, shards, backups, exports, roles, users, nodes, aliases, replications |
118118
| `update` | Update collections, tenants, shards, data, users, aliases |
119119
| `delete` | Delete collections, tenants, data, roles, users, aliases, replications |
120120
| `query` | Query data (fetch/vector/keyword/hybrid/uuid), replications, sharding state |
121121
| `restore` | Restore backups |
122-
| `cancel` | Cancel backups and replications |
122+
| `cancel` | Cancel backups, exports, and replications |
123123
| `assign` | Assign roles to users, permissions to roles |
124124
| `revoke` | Revoke roles from users, permissions from roles |
125125
| `benchmark` | Run QPS benchmarks |
@@ -219,6 +219,25 @@ Backends: `s3`, `gcs`, `filesystem`. Options: `--include`, `--exclude`, `--wait`
219219

220220
See [references/backups.md](references/backups.md).
221221

222+
### Collection Export
223+
224+
```bash
225+
weaviate-cli create export-collection --export_id my-export --backend s3 --file_format parquet --wait --json
226+
weaviate-cli create export-collection --export_id my-export --backend s3 --include "Movies,Books" --json
227+
weaviate-cli create export-collection --export_id my-export --backend s3 --exclude "TempData" --json
228+
weaviate-cli create export-collection --export_id my-export --backend s3 --bucket my-bucket --path /exports --json
229+
weaviate-cli get export-collection --export_id my-export --backend s3 --json
230+
weaviate-cli cancel export-collection --export_id my-export --backend s3 --json
231+
```
232+
233+
Backends: `filesystem`, `s3`, `gcs`, `azure`. File formats: `parquet`.
234+
235+
Options: `--include`, `--exclude` (mutually exclusive), `--wait`, `--bucket`, `--path`
236+
237+
**Prerequisite**: The export backend must be configured on the Weaviate cluster (e.g., `ENABLE_BACKUP=true` for S3 via MinIO in local-k8s).
238+
239+
See [references/exports.md](references/exports.md).
240+
222241
### RBAC (Roles, Users, Permissions)
223242

224243
```bash
@@ -362,6 +381,13 @@ hot/active <--> cold/inactive
362381
5. For timestamp-based TTL on existing collections: `--inverted_index timestamp` must be set at creation or already enabled
363382
6. For property-based TTL: the date property must exist, be `date` type, and have filterable or rangeable index
364383

384+
### Collection Export Workflow
385+
1. `create export-collection --backend s3 --export_id my-export --wait` -- create and wait for completion
386+
2. `get export-collection --backend s3 --export_id my-export` -- check status (includes shard-level progress)
387+
3. `cancel export-collection --backend s3 --export_id my-export` -- cancel in-progress export
388+
389+
**Prerequisite**: The export backend must be configured on the cluster. For local-k8s, deploy with `ENABLE_BACKUP=true` to enable S3 via MinIO.
390+
365391
### Alias Workflow
366392
1. `create collection --collection Movies_v1` -- create the target collection
367393
2. `create alias Movies Movies_v1` -- create alias pointing to collection
@@ -416,6 +442,7 @@ When new commands or options are added to `weaviate-cli`:
416442
- [references/search.md](references/search.md) -- Search types, options, and selection guide
417443
- [references/tenants.md](references/tenants.md) -- Tenant state machine and management
418444
- [references/backups.md](references/backups.md) -- Backup/restore options and notes
445+
- [references/exports.md](references/exports.md) -- Collection export options and notes
419446
- [references/rbac.md](references/rbac.md) -- Permission format, actions, and examples
420447
- [references/cluster.md](references/cluster.md) -- Nodes, shards, replication operations
421448
- [references/benchmark.md](references/benchmark.md) -- Benchmark options and output modes
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Collection Export Reference
2+
3+
Export collections from Weaviate to external storage backends in Parquet format.
4+
5+
## Create Export
6+
```bash
7+
weaviate-cli create export-collection --export_id my-export --backend s3 --file_format parquet --wait --json
8+
weaviate-cli create export-collection --export_id my-export --backend s3 --include "Movies,Books" --json
9+
weaviate-cli create export-collection --export_id my-export --backend gcs --exclude "TempData" --json
10+
weaviate-cli create export-collection --export_id my-export --backend s3 --bucket my-bucket --path /exports --wait --json
11+
```
12+
13+
## Check Export Status
14+
```bash
15+
weaviate-cli get export-collection --export_id my-export --backend s3 --json
16+
```
17+
18+
Returns shard-level progress including objects exported per shard, errors, and timing.
19+
20+
## Cancel Export
21+
```bash
22+
weaviate-cli cancel export-collection --export_id my-export --backend s3 --json
23+
```
24+
25+
Only works while the export is in progress. Returns an error if the export has already completed.
26+
27+
## Options
28+
29+
**Create:**
30+
- `--export_id` -- Export identifier (default: "test-export")
31+
- `--backend` -- filesystem, s3, gcs, azure (default: filesystem)
32+
- `--file_format` -- Export format: parquet (default: parquet)
33+
- `--include` -- Comma-separated collections to include
34+
- `--exclude` -- Comma-separated collections to exclude
35+
- `--wait` -- Wait for completion
36+
- `--bucket` -- Bucket name for cloud storage backends
37+
- `--path` -- Path within the storage backend
38+
39+
**Get Status:**
40+
- `--export_id`, `--backend` -- Same as create
41+
- `--bucket`, `--path` -- Optional, for locating the export
42+
43+
**Cancel:**
44+
- `--export_id`, `--backend` -- Same as create
45+
- `--bucket`, `--path` -- Optional, for locating the export
46+
47+
## Prerequisites
48+
49+
1. The export backend must be configured on the Weaviate cluster
50+
2. For local-k8s, deploy with `ENABLE_BACKUP=true` to enable S3 via MinIO
51+
3. `--include` and `--exclude` are mutually exclusive
52+
53+
## Notes
54+
55+
- `--wait` blocks until the export completes (SUCCESS, FAILED, or CANCELED)
56+
- Without `--wait`, the command returns immediately with status STARTED
57+
- Poll progress with `get export-collection` to monitor shard-level status
58+
- Export uses the same storage backends as backups (S3, GCS, Azure, filesystem)
59+
- The `--bucket` defaults to the cluster's configured backup bucket if not specified

requirements-dev.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
weaviate-client>=4.16.7
1+
weaviate-client @ git+https://github.com/weaviate/weaviate-python-client.git@export_collection
22
click==8.1.7
33
twine
44
pytest

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ classifiers =
3737
include_package_data = True
3838
python_requires = >=3.9
3939
install_requires =
40-
weaviate-client>=4.19.0
40+
weaviate-client @ git+https://github.com/weaviate/weaviate-python-client.git@export_collection
4141
click==8.1.7
4242
semver>=3.0.2
4343
numpy>=1.24.0
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
import json
2+
import pytest
3+
import weaviate
4+
from weaviate_cli.managers.collection_manager import CollectionManager
5+
from weaviate_cli.managers.config_manager import ConfigManager
6+
from weaviate_cli.managers.data_manager import DataManager
7+
from weaviate_cli.managers.export_manager import ExportManager
8+
9+
10+
EXPORT_COLLECTION = "ExportTestCollection"
11+
12+
13+
@pytest.fixture
14+
def client() -> weaviate.WeaviateClient:
15+
config = ConfigManager()
16+
return config.get_client()
17+
18+
19+
@pytest.fixture
20+
def collection_manager(client: weaviate.WeaviateClient) -> CollectionManager:
21+
return CollectionManager(client)
22+
23+
24+
@pytest.fixture
25+
def data_manager(client: weaviate.WeaviateClient) -> DataManager:
26+
return DataManager(client)
27+
28+
29+
@pytest.fixture
30+
def export_manager(client: weaviate.WeaviateClient) -> ExportManager:
31+
return ExportManager(client)
32+
33+
34+
@pytest.fixture
35+
def setup_collection(collection_manager, data_manager):
36+
"""Create a collection with data for export tests."""
37+
try:
38+
collection_manager.create_collection(
39+
collection=EXPORT_COLLECTION,
40+
replication_factor=1,
41+
vectorizer="none",
42+
force_auto_schema=True,
43+
)
44+
data_manager.create_data(
45+
collection=EXPORT_COLLECTION,
46+
limit=100,
47+
randomize=True,
48+
consistency_level="one",
49+
)
50+
yield
51+
finally:
52+
if collection_manager.client.collections.exists(EXPORT_COLLECTION):
53+
collection_manager.delete_collection(collection=EXPORT_COLLECTION)
54+
55+
56+
def test_create_export_and_get_status(
57+
export_manager: ExportManager, setup_collection, capsys
58+
):
59+
"""Test creating an export and getting its status."""
60+
try:
61+
# Create export with wait
62+
export_manager.create_export(
63+
export_id="integration-test-export",
64+
backend="s3",
65+
file_format="parquet",
66+
include=EXPORT_COLLECTION,
67+
wait=True,
68+
json_output=False,
69+
)
70+
71+
out = capsys.readouterr().out
72+
assert "integration-test-export" in out
73+
assert "created successfully" in out
74+
75+
# Get status
76+
export_manager.get_export_status(
77+
export_id="integration-test-export",
78+
backend="s3",
79+
json_output=True,
80+
)
81+
82+
out = capsys.readouterr().out
83+
data = json.loads(out)
84+
assert data["export_id"] == "integration-test-export"
85+
assert data["status"] == "SUCCESS"
86+
assert EXPORT_COLLECTION in data["collections"]
87+
assert "shard_status" in data
88+
except Exception:
89+
raise
90+
91+
92+
def test_create_export_json_output(
93+
export_manager: ExportManager, setup_collection, capsys
94+
):
95+
"""Test creating an export with JSON output."""
96+
export_manager.create_export(
97+
export_id="integration-json-export",
98+
backend="s3",
99+
file_format="parquet",
100+
wait=True,
101+
json_output=True,
102+
)
103+
104+
out = capsys.readouterr().out
105+
data = json.loads(out)
106+
assert data["status"] == "success"
107+
assert data["export_id"] == "integration-json-export"
108+
assert data["export_status"] == "SUCCESS"
109+
110+
111+
def test_create_export_with_exclude(
112+
export_manager: ExportManager, setup_collection, capsys
113+
):
114+
"""Test creating an export with exclude filter."""
115+
export_manager.create_export(
116+
export_id="integration-exclude-export",
117+
backend="s3",
118+
file_format="parquet",
119+
exclude=EXPORT_COLLECTION,
120+
wait=True,
121+
json_output=True,
122+
)
123+
124+
out = capsys.readouterr().out
125+
data = json.loads(out)
126+
assert data["status"] == "success"
127+
assert EXPORT_COLLECTION not in data.get("collections", [])
128+
129+
130+
def test_create_export_include_and_exclude_raises(
131+
export_manager: ExportManager, setup_collection
132+
):
133+
"""Test that specifying both include and exclude raises an error."""
134+
with pytest.raises(Exception) as exc_info:
135+
export_manager.create_export(
136+
export_id="should-fail",
137+
backend="s3",
138+
file_format="parquet",
139+
include=EXPORT_COLLECTION,
140+
exclude="OtherCollection",
141+
)
142+
assert "include" in str(exc_info.value).lower()
143+
assert "exclude" in str(exc_info.value).lower()
144+
145+
146+
def test_cancel_export(export_manager: ExportManager, setup_collection, capsys):
147+
"""Test canceling an export."""
148+
# Create export without waiting
149+
export_manager.create_export(
150+
export_id="integration-cancel-export",
151+
backend="s3",
152+
file_format="parquet",
153+
wait=False,
154+
)
155+
capsys.readouterr() # Clear output
156+
157+
# Try to cancel — may succeed or fail depending on timing
158+
try:
159+
export_manager.cancel_export(
160+
export_id="integration-cancel-export",
161+
backend="s3",
162+
json_output=True,
163+
)
164+
out = capsys.readouterr().out
165+
data = json.loads(out)
166+
assert data["status"] == "success"
167+
except Exception:
168+
# Export may have already finished — that's OK
169+
pass

0 commit comments

Comments
 (0)