clickhouse-cloud-api
Typed Rust client for the ClickHouse Cloud API.
Development
Structure
| Path | Purpose |
|---|---|
src/client.rs |
Client struct with an async method per API endpoint |
src/models.rs |
Request/response types matching the OpenAPI spec |
src/error.rs |
Error types (Http, Json, Api) |
clickhouse_cloud_openapi.json |
Checked-in copy of the spec (used by tests) |
tests/spec_coverage_test.rs |
Validates client methods, model types, and field optionality match the spec |
Field optionality
The OpenAPI spec uses two conventions for marking fields required vs optional:
- Schemas with a
requiredarray (newer/beta endpoints) use standard OpenAPI semantics. - Schemas without
required(GA/legacy endpoints) treat fields whose description starts with"Optional"as optional. Everything else is implicitly required.
Additional rules:
- PATCH request schemas (name contains
Patchand ends withRequest) are always all-optional. - Nullable fields (
type: ["string", "null"]oroneOfwith null) are alwaysOption<T>, even if required.
In models.rs, required non-nullable fields use bare types (T) and optional/nullable fields use Option<T>. All fields keep #[serde(default)] so deserialization is tolerant of partial data.
Scripts
# Show a JSON manifest of required/optional fields per schema
# Update models.rs field types to match the spec
# Check for drift between the live spec and the library (dry run)
When the spec adds proper required arrays everywhere
The spec team plans to add standard required metadata to all schemas in a future version. When that happens:
# 1. Download the updated spec
# 2. Update models.rs
# 3. Fix any test assertions for fields that changed
The resolution logic automatically prefers required arrays over the description heuristic, so no structural changes are needed.
Testing
Live-API lifecycle suites are #[ignore]d by default (they provision real resources):
ClickPipes E2E binaries live under tests/clickpipes/ and are declared as named [[test]] entries in Cargo.toml. Each per-source binary provisions its own ClickHouse Cloud service and exercises one source; clickpipe_e2e_test runs every stage in parallel against a single shared service:
All require CLICKHOUSE_CLOUD_API_KEY, CLICKHOUSE_CLOUD_API_SECRET, CLICKHOUSE_CLOUD_TEST_ORG_ID, CLICKHOUSE_CLOUD_TEST_PROVIDER, and CLICKHOUSE_CLOUD_TEST_REGION in the environment, and are wired into the scheduled Cloud Integration GitHub Actions workflow. The ClickPipes E2E suites additionally need AWS credentials and an eu-west-1 region quota; clickpipe_smoke_test reads a pre-provisioned service ID from CLICKHOUSE_CLOUD_TEST_CLICKPIPE_SERVICE_ID.
The spec_coverage_test suite checks three things against the checked-in spec:
- Every OpenAPI operation has a matching
pub async fninclient.rs - Every OpenAPI schema has a matching
pub struct/pub enuminmodels.rs - Every field's
Option<T>vsTmatches the spec's required/optional semantics
There are also #[ignore]d variants that run the same checks against the live spec.
Optionality exemptions
Occasionally the spec marks a field as required but the API actually treats it as optional (e.g. sending an empty string triggers a 400 BAD_REQUEST). In these cases we override the field to Option<T> in models.rs and add the field to the OPTIONALITY_EXEMPTIONS list in spec_coverage_test.rs.
The test prints a NOTE: line for every exemption that fires, and fails if an exemption becomes stale (i.e. the spec was corrected upstream and the override is no longer needed). To add a new exemption, add a ("RustStructName", "specFieldName") entry to the constant with a comment explaining why.