Skip to content

Commit 7766093

Browse files
authored
Merge pull request #40 from RAprogramm/39
39
2 parents ebb5de9 + 08e87d8 commit 7766093

3 files changed

Lines changed: 66 additions & 2 deletions

File tree

openapi/normalize_spec.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,53 @@ def add_undocumented_account_status_fields(spec):
198198
props.setdefault(name, schema)
199199

200200

201+
def add_undocumented_project_resource_fields(spec):
202+
"""Expose project resources and app→project linkage the API returns.
203+
204+
The live ``GET /projects/{project_id}/resources`` returns far more
205+
collections than the spec documents (verified against production):
206+
``apps``, ``agents``, ``domains``, ``knowledgebases``, ``mailboxes``,
207+
``registries``, ``cdn``, ``monitorings`` and ``routers`` alongside the six
208+
documented ones. Only ``apps`` is added here — its element shape was
209+
verified to match the documented ``app`` schema exactly; the other
210+
collections stay untouched until their shapes can be checked against live
211+
data.
212+
213+
Live ``app`` objects also carry a ``project_id`` the spec omits — the only
214+
way to attribute an app to a project from the apps list.
215+
216+
Both additions are defensive (optional, nullable) so a missing field never
217+
breaks deserialization. Run on every regeneration, so they survive
218+
upstream spec syncs automatically.
219+
"""
220+
app = spec.get("components", {}).get("schemas", {}).get("app")
221+
if isinstance(app, dict):
222+
app.setdefault("properties", {}).setdefault(
223+
"project_id", {"type": "integer", "nullable": True}
224+
)
225+
226+
path = spec.get("paths", {}).get("/api/v1/projects/{project_id}/resources", {})
227+
schema = (
228+
path.get("get", {})
229+
.get("responses", {})
230+
.get("200", {})
231+
.get("content", {})
232+
.get("application/json", {})
233+
.get("schema", {})
234+
)
235+
for part in schema.get("allOf", []):
236+
props = part.get("properties")
237+
if isinstance(props, dict) and "servers" in props:
238+
props.setdefault(
239+
"apps",
240+
{
241+
"type": "array",
242+
"items": {"$ref": "#/components/schemas/app"},
243+
"nullable": True,
244+
},
245+
)
246+
247+
201248
_RENAMED_PROPERTIES = {
202249
"ssh-keys": "ssh_keys",
203250
"knowledgebases": "knowledge_bases",
@@ -409,6 +456,7 @@ def normalize(spec):
409456
localize_tags(spec)
410457
nullable_response_id(spec)
411458
add_undocumented_account_status_fields(spec)
459+
add_undocumented_project_resource_fields(spec)
412460
rename_mismatched_properties(spec)
413461
relax_overstrict_required(spec)
414462
relax_apps_preset_required(spec)

src/models/app.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,14 @@ pub struct App {
120120
pub language: Option<String>,
121121
/// Время запуска приложения.
122122
#[serde(rename = "start_time", skip_serializing_if = "Option::is_none")]
123-
pub start_time: Option<chrono::DateTime<chrono::FixedOffset>>
123+
pub start_time: Option<chrono::DateTime<chrono::FixedOffset>>,
124+
#[serde(
125+
rename = "project_id",
126+
default,
127+
with = "::serde_with::rust::double_option",
128+
skip_serializing_if = "Option::is_none"
129+
)]
130+
pub project_id: Option<Option<i32>>
124131
}
125132

126133
impl App {
@@ -152,7 +159,8 @@ impl App {
152159
disk_status: None,
153160
is_qemu_agent: None,
154161
language: None,
155-
start_time: None
162+
start_time: None,
163+
project_id: None
156164
}
157165
}
158166
}

src/models/get_all_project_resources_200_response.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@ pub struct GetAllProjectResources200Response {
2828
pub dedicated_servers: Vec<models::DedicatedServer>,
2929
#[serde(rename = "meta")]
3030
pub meta: Box<models::Meta>,
31+
#[serde(
32+
rename = "apps",
33+
default,
34+
with = "::serde_with::rust::double_option",
35+
skip_serializing_if = "Option::is_none"
36+
)]
37+
pub apps: Option<Option<Vec<models::App>>>,
3138
/// ID запроса, который можно указывать при обращении в службу технической
3239
/// поддержки, чтобы помочь определить проблему.
3340
#[serde(rename = "response_id", deserialize_with = "Option::deserialize")]
@@ -53,6 +60,7 @@ impl GetAllProjectResources200Response {
5360
databases,
5461
dedicated_servers,
5562
meta: Box::new(meta),
63+
apps: None,
5664
response_id
5765
}
5866
}

0 commit comments

Comments
 (0)