Skip to content
Merged

39 #40

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions openapi/normalize_spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,53 @@ def add_undocumented_account_status_fields(spec):
props.setdefault(name, schema)


def add_undocumented_project_resource_fields(spec):
"""Expose project resources and app→project linkage the API returns.

The live ``GET /projects/{project_id}/resources`` returns far more
collections than the spec documents (verified against production):
``apps``, ``agents``, ``domains``, ``knowledgebases``, ``mailboxes``,
``registries``, ``cdn``, ``monitorings`` and ``routers`` alongside the six
documented ones. Only ``apps`` is added here — its element shape was
verified to match the documented ``app`` schema exactly; the other
collections stay untouched until their shapes can be checked against live
data.

Live ``app`` objects also carry a ``project_id`` the spec omits — the only
way to attribute an app to a project from the apps list.

Both additions are defensive (optional, nullable) so a missing field never
breaks deserialization. Run on every regeneration, so they survive
upstream spec syncs automatically.
"""
app = spec.get("components", {}).get("schemas", {}).get("app")
if isinstance(app, dict):
app.setdefault("properties", {}).setdefault(
"project_id", {"type": "integer", "nullable": True}
)

path = spec.get("paths", {}).get("/api/v1/projects/{project_id}/resources", {})
schema = (
path.get("get", {})
.get("responses", {})
.get("200", {})
.get("content", {})
.get("application/json", {})
.get("schema", {})
)
for part in schema.get("allOf", []):
props = part.get("properties")
if isinstance(props, dict) and "servers" in props:
props.setdefault(
"apps",
{
"type": "array",
"items": {"$ref": "#/components/schemas/app"},
"nullable": True,
},
)


_RENAMED_PROPERTIES = {
"ssh-keys": "ssh_keys",
"knowledgebases": "knowledge_bases",
Expand Down Expand Up @@ -409,6 +456,7 @@ def normalize(spec):
localize_tags(spec)
nullable_response_id(spec)
add_undocumented_account_status_fields(spec)
add_undocumented_project_resource_fields(spec)
rename_mismatched_properties(spec)
relax_overstrict_required(spec)
relax_apps_preset_required(spec)
Expand Down
12 changes: 10 additions & 2 deletions src/models/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,14 @@ pub struct App {
pub language: Option<String>,
/// Время запуска приложения.
#[serde(rename = "start_time", skip_serializing_if = "Option::is_none")]
pub start_time: Option<chrono::DateTime<chrono::FixedOffset>>
pub start_time: Option<chrono::DateTime<chrono::FixedOffset>>,
#[serde(
rename = "project_id",
default,
with = "::serde_with::rust::double_option",
skip_serializing_if = "Option::is_none"
)]
pub project_id: Option<Option<i32>>
}

impl App {
Expand Down Expand Up @@ -152,7 +159,8 @@ impl App {
disk_status: None,
is_qemu_agent: None,
language: None,
start_time: None
start_time: None,
project_id: None
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions src/models/get_all_project_resources_200_response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ pub struct GetAllProjectResources200Response {
pub dedicated_servers: Vec<models::DedicatedServer>,
#[serde(rename = "meta")]
pub meta: Box<models::Meta>,
#[serde(
rename = "apps",
default,
with = "::serde_with::rust::double_option",
skip_serializing_if = "Option::is_none"
)]
pub apps: Option<Option<Vec<models::App>>>,
/// ID запроса, который можно указывать при обращении в службу технической
/// поддержки, чтобы помочь определить проблему.
#[serde(rename = "response_id", deserialize_with = "Option::deserialize")]
Expand All @@ -53,6 +60,7 @@ impl GetAllProjectResources200Response {
databases,
dedicated_servers,
meta: Box::new(meta),
apps: None,
response_id
}
}
Expand Down
Loading