Line data Source code
1 : //! Structs representing the JSON formats used in the compute_ctl's HTTP API.
2 :
3 : use std::fmt::Display;
4 :
5 : use chrono::{DateTime, Utc};
6 : use jsonwebtoken::jwk::JwkSet;
7 : use serde::{Deserialize, Serialize, Serializer};
8 :
9 : use crate::privilege::Privilege;
10 : use crate::spec::{ComputeSpec, Database, ExtVersion, PgIdent, Role};
11 :
12 0 : #[derive(Serialize, Debug, Deserialize)]
13 : pub struct GenericAPIError {
14 : pub error: String,
15 : }
16 :
17 : /// All configuration parameters necessary for a compute. When
18 : /// [`ComputeConfig::spec`] is provided, it means that the compute is attached
19 : /// to a tenant. [`ComputeConfig::compute_ctl_config`] will always be provided
20 : /// and contains parameters necessary for operating `compute_ctl` independently
21 : /// of whether a tenant is attached to the compute or not.
22 : ///
23 : /// This also happens to be the body of `compute_ctl`'s /configure request.
24 0 : #[derive(Debug, Deserialize, Serialize)]
25 : pub struct ComputeConfig {
26 : /// The compute spec
27 : pub spec: Option<ComputeSpec>,
28 :
29 : /// The compute_ctl configuration
30 : #[allow(dead_code)]
31 : pub compute_ctl_config: ComputeCtlConfig,
32 : }
33 :
34 : impl From<ControlPlaneConfigResponse> for ComputeConfig {
35 0 : fn from(value: ControlPlaneConfigResponse) -> Self {
36 0 : Self {
37 0 : spec: value.spec,
38 0 : compute_ctl_config: value.compute_ctl_config,
39 0 : }
40 0 : }
41 : }
42 :
43 : #[derive(Debug, Clone, Serialize)]
44 : pub struct ExtensionInstallResponse {
45 : pub extension: PgIdent,
46 : pub version: ExtVersion,
47 : }
48 :
49 : /// Response of the /status API
50 0 : #[derive(Serialize, Debug, Deserialize)]
51 : #[serde(rename_all = "snake_case")]
52 : pub struct ComputeStatusResponse {
53 : pub start_time: DateTime<Utc>,
54 : pub tenant: Option<String>,
55 : pub timeline: Option<String>,
56 : pub status: ComputeStatus,
57 : #[serde(serialize_with = "rfc3339_serialize")]
58 : pub last_active: Option<DateTime<Utc>>,
59 : pub error: Option<String>,
60 : }
61 :
62 0 : #[derive(Serialize, Clone, Copy, Debug, Deserialize, PartialEq, Eq)]
63 : #[serde(rename_all = "snake_case")]
64 : pub enum ComputeStatus {
65 : // Spec wasn't provided at start, waiting for it to be
66 : // provided by control-plane.
67 : Empty,
68 : // Compute configuration was requested.
69 : ConfigurationPending,
70 : // Compute node has spec and initial startup and
71 : // configuration is in progress.
72 : Init,
73 : // Compute is configured and running.
74 : Running,
75 : // New spec is being applied.
76 : Configuration,
77 : // Either startup or configuration failed,
78 : // compute will exit soon or is waiting for
79 : // control-plane to terminate it.
80 : Failed,
81 : // Termination requested
82 : TerminationPending,
83 : // Terminated Postgres
84 : Terminated,
85 : }
86 :
87 : impl Display for ComputeStatus {
88 0 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
89 0 : match self {
90 0 : ComputeStatus::Empty => f.write_str("empty"),
91 0 : ComputeStatus::ConfigurationPending => f.write_str("configuration-pending"),
92 0 : ComputeStatus::Init => f.write_str("init"),
93 0 : ComputeStatus::Running => f.write_str("running"),
94 0 : ComputeStatus::Configuration => f.write_str("configuration"),
95 0 : ComputeStatus::Failed => f.write_str("failed"),
96 0 : ComputeStatus::TerminationPending => f.write_str("termination-pending"),
97 0 : ComputeStatus::Terminated => f.write_str("terminated"),
98 : }
99 0 : }
100 : }
101 :
102 0 : pub fn rfc3339_serialize<S>(x: &Option<DateTime<Utc>>, s: S) -> Result<S::Ok, S::Error>
103 0 : where
104 0 : S: Serializer,
105 0 : {
106 0 : if let Some(x) = x {
107 0 : x.to_rfc3339().serialize(s)
108 : } else {
109 0 : s.serialize_none()
110 : }
111 0 : }
112 :
113 : /// Response of the /metrics.json API
114 : #[derive(Clone, Debug, Default, Serialize)]
115 : pub struct ComputeMetrics {
116 : /// Time spent waiting in pool
117 : pub wait_for_spec_ms: u64,
118 :
119 : /// Time spent checking if safekeepers are synced
120 : pub sync_sk_check_ms: u64,
121 :
122 : /// Time spent syncing safekeepers (walproposer.c).
123 : /// In most cases this should be zero.
124 : pub sync_safekeepers_ms: u64,
125 :
126 : /// Time it took to establish a pg connection to the pageserver.
127 : /// This is two roundtrips, so it's a good proxy for compute-pageserver
128 : /// latency. The latency is usually 0.2ms, but it's not safe to assume
129 : /// that.
130 : pub pageserver_connect_micros: u64,
131 :
132 : /// Time to get basebackup from pageserver and write it to disk.
133 : pub basebackup_ms: u64,
134 :
135 : /// Compressed size of basebackup received.
136 : pub basebackup_bytes: u64,
137 :
138 : /// Time spent starting potgres. This includes initialization of shared
139 : /// buffers, preloading extensions, and other pg operations.
140 : pub start_postgres_ms: u64,
141 :
142 : /// Time spent applying pg catalog updates that were made in the console
143 : /// UI. This should be 0 when startup time matters, since cplane tries
144 : /// to do these updates eagerly, and passes the skip_pg_catalog_updates
145 : /// when it's safe to skip this step.
146 : pub config_ms: u64,
147 :
148 : /// Total time, from when we receive the spec to when we're ready to take
149 : /// pg connections.
150 : pub total_startup_ms: u64,
151 : pub load_ext_ms: u64,
152 : pub num_ext_downloaded: u64,
153 : pub largest_ext_size: u64, // these are measured in bytes
154 : pub total_ext_download_size: u64,
155 : }
156 :
157 : #[derive(Clone, Debug, Default, Serialize)]
158 : pub struct CatalogObjects {
159 : pub roles: Vec<Role>,
160 : pub databases: Vec<Database>,
161 : }
162 :
163 0 : #[derive(Clone, Debug, Deserialize, Serialize)]
164 : pub struct ComputeCtlConfig {
165 : /// Set of JSON web keys that the compute can use to authenticate
166 : /// communication from the control plane.
167 : pub jwks: JwkSet,
168 : pub tls: Option<TlsConfig>,
169 : }
170 :
171 : impl Default for ComputeCtlConfig {
172 0 : fn default() -> Self {
173 0 : Self {
174 0 : jwks: JwkSet {
175 0 : keys: Vec::default(),
176 0 : },
177 0 : tls: None,
178 0 : }
179 0 : }
180 : }
181 :
182 0 : #[derive(Clone, Debug, Deserialize, Serialize)]
183 : pub struct TlsConfig {
184 : pub key_path: String,
185 : pub cert_path: String,
186 : }
187 :
188 : /// Response of the `/computes/{compute_id}/spec` control-plane API.
189 0 : #[derive(Deserialize, Debug)]
190 : pub struct ControlPlaneConfigResponse {
191 : pub spec: Option<ComputeSpec>,
192 : pub status: ControlPlaneComputeStatus,
193 : pub compute_ctl_config: ComputeCtlConfig,
194 : }
195 :
196 0 : #[derive(Deserialize, Clone, Copy, Debug, PartialEq, Eq)]
197 : #[serde(rename_all = "snake_case")]
198 : pub enum ControlPlaneComputeStatus {
199 : // Compute is known to control-plane, but it's not
200 : // yet attached to any timeline / endpoint.
201 : Empty,
202 : // Compute is attached to some timeline / endpoint and
203 : // should be able to start with provided spec.
204 : Attached,
205 : }
206 :
207 : #[derive(Clone, Debug, Default, Serialize)]
208 : pub struct InstalledExtension {
209 : pub extname: String,
210 : pub version: String,
211 : pub n_databases: u32, // Number of databases using this extension
212 : pub owned_by_superuser: String,
213 : }
214 :
215 : #[derive(Clone, Debug, Default, Serialize)]
216 : pub struct InstalledExtensions {
217 : pub extensions: Vec<InstalledExtension>,
218 : }
219 :
220 : #[derive(Clone, Debug, Default, Serialize)]
221 : pub struct ExtensionInstallResult {
222 : pub extension: PgIdent,
223 : pub version: ExtVersion,
224 : }
225 : #[derive(Clone, Debug, Default, Serialize)]
226 : pub struct SetRoleGrantsResponse {
227 : pub database: PgIdent,
228 : pub schema: PgIdent,
229 : pub privileges: Vec<Privilege>,
230 : pub role: PgIdent,
231 : }
|