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.
Deprecated fields
The OpenAPI spec marks some response fields as deprecated (e.g. Service.tier, ApiKey.roles, Member.role). In almost all cases, these are not needed. The Cloud API library disables them by default, gated by a Cargo feature flag deprecated-fields. Enable this feature if you need to consume deprecated fields.
Scripts
# Show a JSON manifest of required/optional fields per schema
# Regenerate the DEPRECATED_FIELDS constant from the snapshot
# Check for drift between the live spec and the library (dry run)
Field optionality is maintained by hand — edit models.rs directly when the drift check flags a mismatch.
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 DEPRECATED_FIELDSmatches the spec'sdeprecated: truefields (request- and response-side), and each one carries the#[cfg(feature = "deprecated-fields")]marker inmodels.rs
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.