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 `beta_operations_match_spec` test in `tests/spec_coverage_test.rs` fails
18//! if this list drifts from the 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_stack_create_alert",
28    "click_stack_create_dashboard",
29    "click_stack_delete_alert",
30    "click_stack_delete_dashboard",
31    "click_stack_get_alert",
32    "click_stack_get_dashboard",
33    "click_stack_list_alerts",
34    "click_stack_list_dashboards",
35    "click_stack_list_sources",
36    "click_stack_list_webhooks",
37    "click_stack_update_alert",
38    "click_stack_update_dashboard",
39    "postgres_instance_config_get",
40    "postgres_instance_config_patch",
41    "postgres_instance_config_post",
42    "postgres_instance_create_read_replica",
43    "postgres_instance_prometheus_get",
44    "postgres_instance_restore",
45    "postgres_org_prometheus_get",
46    "postgres_service_certs_get",
47    "postgres_service_create",
48    "postgres_service_delete",
49    "postgres_service_get",
50    "postgres_service_get_list",
51    "postgres_service_patch",
52    "postgres_service_patch_state",
53    "postgres_service_set_password",
54    "scaling_schedule_delete",
55    "scaling_schedule_get",
56    "scaling_schedule_upsert",
57    "service_clickhouse_setting_get",
58    "service_clickhouse_settings_list_get",
59    "service_clickhouse_settings_schema_get",
60    "service_clickhouse_settings_update",
61];
62
63/// Returns `true` if `name` matches a client method backed by a Beta endpoint.
64///
65/// `name` is the snake-case method name (e.g. `"postgres_service_get_list"`).
66pub fn is_beta_operation(name: &str) -> bool {
67    BETA_OPERATIONS.binary_search(&name).is_ok()
68}
69
70/// Schema fields the OpenAPI spec marks `deprecated: true`, as
71/// `(RustStructName, specFieldName)` pairs. Covers both response-side and
72/// request-side schemas.
73///
74/// These fields are removed from the struct entirely unless the
75/// `deprecated-fields` Cargo feature is enabled — each one carries a
76/// `#[cfg(feature = "deprecated-fields")]` marker in [`crate::models`]. By
77/// default the field does not exist, so:
78///
79/// - On response structs, referencing it is a compile error and it never
80///   appears in serialized output; deserializing a payload that still contains
81///   it just ignores the extra key.
82/// - On request structs, callers cannot set it and `skip_serializing_if` keeps
83///   it off the wire entirely.
84///
85/// The list is kept sorted so [`is_deprecated_field`] can use `binary_search`
86/// and snapshot diffs stay readable.
87///
88/// Regenerate from the snapshot with:
89///
90/// ```text
91/// python3 scripts/regenerate-deprecated-fields.py
92/// ```
93///
94/// The `deprecated_fields_match_spec` test in `tests/spec_coverage_test.rs`
95/// fails if this list drifts from the spec, and `deprecated_fields_hidden`
96/// fails if a field here lacks the `#[cfg(feature = "deprecated-fields")]`
97/// marker in `models.rs` (or vice versa).
98pub const DEPRECATED_FIELDS: &[(&str, &str)] = &[
99    ("ApiKey", "roles"),
100    ("ApiKeyPatchRequest", "roles"),
101    ("ApiKeyPostRequest", "roles"),
102    ("ClickPipeScaling", "concurrency"),
103    ("ClickPipeScalingPatchRequest", "concurrency"),
104    ("ClickStackTileInput", "asRatio"),
105    ("ClickStackTileInput", "series"),
106    ("Invitation", "role"),
107    ("InvitationPostRequest", "role"),
108    ("Member", "role"),
109    ("MemberPatchRequest", "role"),
110    ("OrganizationPrivateEndpointsPatch", "add"),
111    ("Service", "maxTotalMemoryGb"),
112    ("Service", "minTotalMemoryGb"),
113    ("Service", "tier"),
114    ("ServicePostRequest", "maxTotalMemoryGb"),
115    ("ServicePostRequest", "minTotalMemoryGb"),
116    ("ServicePostRequest", "privateEndpointIds"),
117    ("ServicePostRequest", "tier"),
118    ("ServiceScalingPatchRequest", "maxTotalMemoryGb"),
119    ("ServiceScalingPatchRequest", "minTotalMemoryGb"),
120    ("ServiceScalingPatchResponse", "maxTotalMemoryGb"),
121    ("ServiceScalingPatchResponse", "minTotalMemoryGb"),
122    ("ServiceScalingPatchResponse", "tier"),
123];
124
125/// Returns `true` if `(struct_name, field_name)` is a deprecated field that
126/// this crate removes from the generated struct by default.
127///
128/// `field_name` is the spec (camelCase) field name, e.g.
129/// `is_deprecated_field("Service", "tier")`.
130pub fn is_deprecated_field(struct_name: &str, field_name: &str) -> bool {
131    DEPRECATED_FIELDS
132        .binary_search(&(struct_name, field_name))
133        .is_ok()
134}
135
136#[cfg(test)]
137mod tests {
138    use super::*;
139
140    #[test]
141    fn list_is_sorted_and_unique() {
142        for pair in BETA_OPERATIONS.windows(2) {
143            assert!(
144                pair[0] < pair[1],
145                "BETA_OPERATIONS must be sorted and unique; {:?} >= {:?}",
146                pair[0],
147                pair[1],
148            );
149        }
150    }
151
152    #[test]
153    fn is_beta_operation_matches_constant() {
154        assert!(is_beta_operation("scaling_schedule_get"));
155        assert!(is_beta_operation("postgres_service_get_list"));
156        assert!(!is_beta_operation("services_list"));
157        assert!(!is_beta_operation("not_a_real_op"));
158    }
159
160    #[test]
161    fn deprecated_fields_are_sorted_and_unique() {
162        for pair in DEPRECATED_FIELDS.windows(2) {
163            assert!(
164                pair[0] < pair[1],
165                "DEPRECATED_FIELDS must be sorted and unique; {:?} >= {:?}",
166                pair[0],
167                pair[1],
168            );
169        }
170    }
171
172    #[test]
173    fn is_deprecated_field_matches_constant() {
174        assert!(is_deprecated_field("Service", "tier"));
175        assert!(is_deprecated_field("ApiKey", "roles"));
176        assert!(is_deprecated_field("ServicePostRequest", "tier"));
177        assert!(is_deprecated_field("InvitationPostRequest", "role"));
178        assert!(!is_deprecated_field("Service", "name"));
179        assert!(!is_deprecated_field("NotAStruct", "tier"));
180    }
181}