Skip to main content

clickhouse_cloud_api/
meta.rs

1//! Operation stability metadata.
2//!
3//! `BETA_OPERATIONS` mirrors `x-badges` entries on operations in the ClickHouse
4//! Cloud OpenAPI spec. The list is kept sorted so [`is_beta_operation`] can use
5//! `binary_search` and snapshot diffs stay readable.
6//!
7//! Consumers — including this crate's own CLI — can use [`is_beta_operation`]
8//! to render a "(Beta)" affordance derived from the spec rather than maintained
9//! by hand.
10//!
11//! Regenerate from the snapshot with:
12//!
13//! ```text
14//! python3 scripts/regenerate-beta-lists.py
15//! ```
16//!
17//! The shared OpenAPI analyzer reports drift if this list differs from the
18//! snapshot or live spec.
19
20/// Snake-case operation IDs (matching [`crate::client::Client`] method names)
21/// that the OpenAPI spec marks Beta via `x-badges`.
22pub const BETA_OPERATIONS: &[&str] = &[
23    "backup_bucket_create",
24    "backup_bucket_delete",
25    "backup_bucket_get",
26    "backup_bucket_update",
27    "click_pipe_schema_discovery",
28    "click_stack_create_alert",
29    "click_stack_create_connection",
30    "click_stack_create_dashboard",
31    "click_stack_create_role",
32    "click_stack_create_saved_search",
33    "click_stack_create_source",
34    "click_stack_create_webhook",
35    "click_stack_delete_alert",
36    "click_stack_delete_connection",
37    "click_stack_delete_dashboard",
38    "click_stack_delete_role",
39    "click_stack_delete_saved_search",
40    "click_stack_delete_source",
41    "click_stack_delete_webhook",
42    "click_stack_get_alert",
43    "click_stack_get_connection",
44    "click_stack_get_dashboard",
45    "click_stack_get_role",
46    "click_stack_get_saved_search",
47    "click_stack_get_source",
48    "click_stack_list_alerts",
49    "click_stack_list_connections",
50    "click_stack_list_dashboards",
51    "click_stack_list_roles",
52    "click_stack_list_saved_searches",
53    "click_stack_list_sources",
54    "click_stack_list_webhooks",
55    "click_stack_update_alert",
56    "click_stack_update_connection",
57    "click_stack_update_dashboard",
58    "click_stack_update_role",
59    "click_stack_update_saved_search",
60    "click_stack_update_source",
61    "click_stack_update_webhook",
62    "click_stack_validate_dashboard",
63    "organization_quota_get",
64    "organization_quotas_get_list",
65    "postgres_instance_config_get",
66    "postgres_instance_config_patch",
67    "postgres_instance_config_post",
68    "postgres_instance_create_read_replica",
69    "postgres_instance_metrics_get",
70    "postgres_instance_prometheus_get",
71    "postgres_instance_restore",
72    "postgres_org_prometheus_get",
73    "postgres_service_certs_get",
74    "postgres_service_create",
75    "postgres_service_delete",
76    "postgres_service_get",
77    "postgres_service_get_list",
78    "postgres_service_patch",
79    "postgres_service_patch_state",
80    "postgres_service_set_password",
81    "scaling_schedule_delete",
82    "scaling_schedule_get",
83    "scaling_schedule_upsert",
84    "service_clickhouse_setting_delete",
85    "service_clickhouse_setting_get",
86    "service_clickhouse_settings_list_get",
87    "service_clickhouse_settings_schema_get",
88    "service_clickhouse_settings_update",
89    "slow_query_pattern_get",
90    "slow_query_patterns_get_list",
91];
92
93/// Returns `true` if `name` matches a client method backed by a Beta endpoint.
94///
95/// `name` is the snake-case method name (e.g. `"postgres_service_get_list"`).
96pub fn is_beta_operation(name: &str) -> bool {
97    BETA_OPERATIONS.binary_search(&name).is_ok()
98}
99
100/// Schema fields the OpenAPI spec marks `deprecated: true`, as
101/// `(RustStructName, specFieldName)` pairs. Covers both response-side and
102/// request-side schemas.
103///
104/// These fields are removed from the struct entirely unless the
105/// `deprecated-fields` Cargo feature is enabled — each one carries a
106/// `#[cfg(feature = "deprecated-fields")]` marker in [`crate::models`]. By
107/// default the field does not exist, so:
108///
109/// - On response structs, referencing it is a compile error and it never
110///   appears in serialized output; deserializing a payload that still contains
111///   it just ignores the extra key.
112/// - On request structs, callers cannot set it and `skip_serializing_if` keeps
113///   it off the wire entirely.
114///
115/// The list is kept sorted so [`is_deprecated_field`] can use `binary_search`
116/// and snapshot diffs stay readable.
117///
118/// Regenerate from the snapshot with:
119///
120/// ```text
121/// python3 scripts/regenerate-deprecated-fields.py
122/// ```
123///
124/// The script derives struct names from spec schema names alone, so a schema
125/// modeled as both a request and a response type needs the `{Name}Response`
126/// entry added by hand after regenerating (e.g. `ClickPipeScalingResponse`).
127/// The analyzer expects the pair once per Rust type the schema maps to, so a
128/// dropped response-variant entry fails the drift check rather than passing
129/// silently.
130///
131/// The shared OpenAPI analyzer reports drift if this list differs from the
132/// spec or if a field here lacks the `#[cfg(feature = "deprecated-fields")]`
133/// marker in `models.rs` (or vice versa).
134pub const DEPRECATED_FIELDS: &[(&str, &str)] = &[
135    ("ApiKey", "roles"),
136    ("ApiKeyPatchRequest", "roles"),
137    ("ApiKeyPostRequest", "roles"),
138    ("ClickPipeScaling", "concurrency"),
139    ("ClickPipeScalingPatchRequest", "concurrency"),
140    ("ClickPipeScalingResponse", "concurrency"),
141    ("ClickStackTileInput", "asRatio"),
142    ("ClickStackTileInput", "series"),
143    ("Invitation", "role"),
144    ("InvitationPostRequest", "role"),
145    ("Member", "role"),
146    ("MemberPatchRequest", "role"),
147    ("OrganizationPrivateEndpointsPatch", "add"),
148    ("Service", "maxTotalMemoryGb"),
149    ("Service", "minTotalMemoryGb"),
150    ("Service", "tier"),
151    ("ServicePostRequest", "maxTotalMemoryGb"),
152    ("ServicePostRequest", "minTotalMemoryGb"),
153    ("ServicePostRequest", "privateEndpointIds"),
154    ("ServicePostRequest", "tier"),
155    ("ServiceScalingPatchRequest", "maxTotalMemoryGb"),
156    ("ServiceScalingPatchRequest", "minTotalMemoryGb"),
157    ("ServiceScalingPatchResponse", "maxTotalMemoryGb"),
158    ("ServiceScalingPatchResponse", "minTotalMemoryGb"),
159    ("ServiceScalingPatchResponse", "tier"),
160];
161
162/// Returns `true` if `(struct_name, field_name)` is a deprecated field that
163/// this crate removes from the generated struct by default.
164///
165/// `field_name` is the spec (camelCase) field name, e.g.
166/// `is_deprecated_field("Service", "tier")`.
167pub fn is_deprecated_field(struct_name: &str, field_name: &str) -> bool {
168    DEPRECATED_FIELDS
169        .binary_search(&(struct_name, field_name))
170        .is_ok()
171}
172
173#[cfg(test)]
174mod tests {
175    use super::*;
176
177    #[test]
178    fn list_is_sorted_and_unique() {
179        for pair in BETA_OPERATIONS.windows(2) {
180            assert!(
181                pair[0] < pair[1],
182                "BETA_OPERATIONS must be sorted and unique; {:?} >= {:?}",
183                pair[0],
184                pair[1],
185            );
186        }
187    }
188
189    #[test]
190    fn is_beta_operation_matches_constant() {
191        assert!(is_beta_operation("scaling_schedule_get"));
192        assert!(is_beta_operation("postgres_service_get_list"));
193        assert!(!is_beta_operation("services_list"));
194        assert!(!is_beta_operation("not_a_real_op"));
195    }
196
197    #[test]
198    fn deprecated_fields_are_sorted_and_unique() {
199        for pair in DEPRECATED_FIELDS.windows(2) {
200            assert!(
201                pair[0] < pair[1],
202                "DEPRECATED_FIELDS must be sorted and unique; {:?} >= {:?}",
203                pair[0],
204                pair[1],
205            );
206        }
207    }
208
209    #[test]
210    fn is_deprecated_field_matches_constant() {
211        assert!(is_deprecated_field("Service", "tier"));
212        assert!(is_deprecated_field("ApiKey", "roles"));
213        assert!(is_deprecated_field("ServicePostRequest", "tier"));
214        assert!(is_deprecated_field("InvitationPostRequest", "role"));
215        assert!(!is_deprecated_field("Service", "name"));
216        assert!(!is_deprecated_field("NotAStruct", "tier"));
217    }
218}