From b1e512a1c613a7a45552296600ec87b41a40a44d Mon Sep 17 00:00:00 2001 From: Quentin Pradet Date: Fri, 29 Nov 2024 17:12:07 +0400 Subject: [PATCH] Add initial version of schema endpoint generation --- compiler-rs/Cargo.lock | 44 + .../openapi_to_clients_schema/Cargo.toml | 7 + .../fixtures/kibana.serverless.yaml | 319 +++++ .../src/endpoints.rs | 171 ++- .../openapi_to_clients_schema/src/lib.rs | 28 +- .../openapi_to_clients_schema/src/main.rs | 32 +- ..._to_clients_schema__kibana_conversion.snap | 1197 +++++++++++++++++ .../openapi_to_clients_schema/src/types.rs | 4 +- 8 files changed, 1782 insertions(+), 20 deletions(-) create mode 100644 compiler-rs/openapi_to_clients_schema/fixtures/kibana.serverless.yaml create mode 100644 compiler-rs/openapi_to_clients_schema/src/snapshots/openapi_to_clients_schema__kibana_conversion.snap diff --git a/compiler-rs/Cargo.lock b/compiler-rs/Cargo.lock index 25c46faaff..b6b4fe36f8 100644 --- a/compiler-rs/Cargo.lock +++ b/compiler-rs/Cargo.lock @@ -242,6 +242,18 @@ dependencies = [ "wasm-bindgen-test", ] +[[package]] +name = "console" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "console_error_panic_hook" version = "0.1.7" @@ -332,6 +344,12 @@ dependencies = [ "time", ] +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + [[package]] name = "env_filter" version = "0.1.2" @@ -515,6 +533,19 @@ dependencies = [ "serde", ] +[[package]] +name = "insta" +version = "1.41.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e9ffc4d4892617c50a928c52b2961cb5174b6fc6ebf252b2fac9d21955c48b8" +dependencies = [ + "console", + "lazy_static", + "linked-hash-map", + "serde", + "similar", +] + [[package]] name = "is_terminal_polyfill" version = "1.70.1" @@ -560,6 +591,12 @@ version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1303532258de1fbe263b4daaaba0e17e3d502b8de57b7845928b92398fb4afd1" +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + [[package]] name = "litemap" version = "0.7.3" @@ -664,6 +701,7 @@ dependencies = [ "clients_schema", "convert_case", "indexmap", + "insta", "openapiv3", "serde_ignored", "serde_json", @@ -983,6 +1021,12 @@ dependencies = [ "libc", ] +[[package]] +name = "similar" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1de1d4f81173b03af4c0cbed3c898f6bff5b870e4a7f5d6f4057d62a7a4b686e" + [[package]] name = "smallvec" version = "1.13.2" diff --git a/compiler-rs/openapi_to_clients_schema/Cargo.toml b/compiler-rs/openapi_to_clients_schema/Cargo.toml index 4ecbaa258f..e2dd896c38 100644 --- a/compiler-rs/openapi_to_clients_schema/Cargo.toml +++ b/compiler-rs/openapi_to_clients_schema/Cargo.toml @@ -20,6 +20,13 @@ convert_case = { workspace = true } tracing = { workspace = true } tracing-subscriber = { workspace = true } +[dev-dependencies] +insta = { version = "1.41.1", features = ["json", "serde"] } + +[profile.dev.package] +insta.opt-level = 3 +similar.opt-level = 3 + # Some json schema implementations #boon = "0.3.1" #jsonschema-transpiler = "1.10.0" diff --git a/compiler-rs/openapi_to_clients_schema/fixtures/kibana.serverless.yaml b/compiler-rs/openapi_to_clients_schema/fixtures/kibana.serverless.yaml new file mode 100644 index 0000000000..8a64750c73 --- /dev/null +++ b/compiler-rs/openapi_to_clients_schema/fixtures/kibana.serverless.yaml @@ -0,0 +1,319 @@ +openapi: 3.0.3 +info: + contact: + name: Kibana Team + description: | + The Kibana REST APIs for Elastic serverless enable you to manage resources + such as connectors, data views, and saved objects. The API calls are + stateless. Each request that you make happens in isolation from other calls + and must include all of the necessary information for Kibana to fulfill the + request. API requests return JSON output, which is a format that is + machine-readable and works well for automation. + + To interact with Kibana APIs, use the following operations: + + - GET: Fetches the information. + - POST: Adds new information. + - PUT: Updates the existing information. + - DELETE: Removes the information. + + You can prepend any Kibana API endpoint with `kbn:` and run the request in + **Dev Tools → Console**. For example: + + ``` + GET kbn:/api/data_views + ``` + + ## Documentation source and versions + + This documentation is derived from the `main` branch of the [kibana](https://github.com/elastic/kibana) repository. + It is provided under license [Attribution-NonCommercial-NoDerivatives 4.0 International](https://creativecommons.org/licenses/by-nc-nd/4.0/). + title: Kibana Serverless APIs + version: 1.0.2 + x-doc-license: + name: Attribution-NonCommercial-NoDerivatives 4.0 International + url: https://creativecommons.org/licenses/by-nc-nd/4.0/ + x-feedbackLink: + label: Feedback + url: https://github.com/elastic/docs-content/issues/new?assignees=&labels=feedback%2Ccommunity&projects=&template=api-feedback.yaml&title=%5BFeedback%5D%3A+ +servers: + - url: https://{kibana_url} + variables: + kibana_url: + default: localhost:5601 +paths: + /api/status: + get: + operationId: SystemStatus + parameters: + - description: The version of the API to use + in: header + name: elastic-api-version + schema: + default: '2023-10-31' + enum: + - '2023-10-31' + type: string + - description: Set to "true" to get the response in v7 format. + in: query + name: v7format + required: false + schema: + type: boolean + - description: Set to "true" to get the response in v8 format. + in: query + name: v8format + required: false + schema: + type: boolean + responses: + '200': + content: + application/json; Elastic-Api-Version=2023-10-31: + schema: + $ref: '#/components/schemas/Kibana_HTTP_APIs_core_status_response' + description: Overall status is OK and Kibana should be functioning normally. + summary: Get Kibana's current status + tags: + - system +components: + schemas: + Kibana_HTTP_APIs_core_status_redactedResponse: + additionalProperties: false + description: A minimal representation of Kibana's operational status. + properties: + status: + additionalProperties: false + properties: + overall: + additionalProperties: false + properties: + level: + description: + Service status levels as human and machine readable + values. + enum: [available, degraded, unavailable, critical] + type: string + required: [level] + type: object + required: [overall] + type: object + required: [status] + type: object + Kibana_HTTP_APIs_core_status_response: + additionalProperties: false + description: Kibana's operational status as well as a detailed breakdown of plugin statuses indication of various loads (like event loop utilization and network traffic) at time of request. + type: object + properties: + metrics: + additionalProperties: false + description: Metric groups collected by Kibana. + type: object + properties: + collection_interval_in_millis: + description: The interval at which metrics should be collected. + type: number + elasticsearch_client: + additionalProperties: false + description: Current network metrics of Kibana's Elasticsearch client. + type: object + properties: + totalActiveSockets: + description: Count of network sockets currently in use. + type: number + totalIdleSockets: + description: Count of network sockets currently idle. + type: number + totalQueuedRequests: + description: Count of requests not yet assigned to sockets. + type: number + required: + - totalActiveSockets + - totalIdleSockets + - totalQueuedRequests + last_updated: + description: The time metrics were collected. + type: string + required: + - elasticsearch_client + - last_updated + - collection_interval_in_millis + name: + description: Kibana instance name. + type: string + status: + additionalProperties: false + type: object + properties: + core: + additionalProperties: false + description: Statuses of core Kibana services. + type: object + properties: + elasticsearch: + additionalProperties: false + type: object + properties: + detail: + description: Human readable detail of the service status. + type: string + documentationUrl: + description: A URL to further documentation regarding this service. + type: string + level: + description: Service status levels as human and machine readable values. + enum: + - available + - degraded + - unavailable + - critical + type: string + meta: + additionalProperties: true + description: An unstructured set of extra metadata about this service. + type: object + summary: + description: A human readable summary of the service status. + type: string + required: + - level + - summary + - meta + savedObjects: + additionalProperties: false + type: object + properties: + detail: + description: Human readable detail of the service status. + type: string + documentationUrl: + description: A URL to further documentation regarding this service. + type: string + level: + description: Service status levels as human and machine readable values. + enum: + - available + - degraded + - unavailable + - critical + type: string + meta: + additionalProperties: true + description: An unstructured set of extra metadata about this service. + type: object + summary: + description: A human readable summary of the service status. + type: string + required: + - level + - summary + - meta + required: + - elasticsearch + - savedObjects + overall: + additionalProperties: false + type: object + properties: + detail: + description: Human readable detail of the service status. + type: string + documentationUrl: + description: A URL to further documentation regarding this service. + type: string + level: + description: Service status levels as human and machine readable values. + enum: + - available + - degraded + - unavailable + - critical + type: string + meta: + additionalProperties: true + description: An unstructured set of extra metadata about this service. + type: object + summary: + description: A human readable summary of the service status. + type: string + required: + - level + - summary + - meta + plugins: + additionalProperties: + additionalProperties: false + type: object + properties: + detail: + description: Human readable detail of the service status. + type: string + documentationUrl: + description: A URL to further documentation regarding this service. + type: string + level: + description: Service status levels as human and machine readable values. + enum: + - available + - degraded + - unavailable + - critical + type: string + meta: + additionalProperties: true + description: An unstructured set of extra metadata about this service. + type: object + summary: + description: A human readable summary of the service status. + type: string + required: + - level + - summary + - meta + description: A dynamic mapping of plugin ID to plugin status. + type: object + required: + - overall + - core + - plugins + uuid: + description: Unique, generated Kibana instance UUID. This UUID should persist even if the Kibana process restarts. + type: string + version: + additionalProperties: false + type: object + properties: + build_date: + description: The date and time of this build. + type: string + build_flavor: + description: The build flavour determines configuration and behavior of Kibana. On premise users will almost always run the "traditional" flavour, while other flavours are reserved for Elastic-specific use cases. + enum: + - serverless + - traditional + type: string + build_hash: + description: A unique hash value representing the git commit of this Kibana build. + type: string + build_number: + description: A monotonically increasing number, each subsequent build will have a higher number. + type: number + build_snapshot: + description: Whether this build is a snapshot build. + type: boolean + number: + description: A semantic version number. + type: string + required: + - number + - build_hash + - build_number + - build_snapshot + - build_flavor + - build_date + required: + - name + - uuid + - version + - status + - metrics diff --git a/compiler-rs/openapi_to_clients_schema/src/endpoints.rs b/compiler-rs/openapi_to_clients_schema/src/endpoints.rs index 468c24678e..6d07c11853 100644 --- a/compiler-rs/openapi_to_clients_schema/src/endpoints.rs +++ b/compiler-rs/openapi_to_clients_schema/src/endpoints.rs @@ -15,4 +15,173 @@ // specific language governing permissions and limitations // under the License. -// TODO +use clients_schema::{ + builtins, BaseType, Body, Endpoint, InstanceOf, NoBody, Property, Request, TypeDefinition, TypeName, UrlTemplate, + ValueOf, +}; +use openapiv3::{ReferenceOr, StatusCode}; + +use crate::types::{self, Types}; +use tracing::info; + +pub fn generate_endpoint( + id: &str, + path: &openapiv3::ReferenceOr, + types: &mut Types, +) -> anyhow::Result { + info!("Generating endpoint for {id}"); + match path { + ReferenceOr::Item(path_item) => { + if let Some(operation) = &path_item.get { + generate_get_endpoint(id, &operation, types) + } else { + Err(anyhow::anyhow!("No get operation found for endpoint {}", id)) + } + } + _ => Err(anyhow::anyhow!("No description found for endpoint {}", id)), + } +} + +fn generate_get_endpoint(id: &str, operation: &openapiv3::Operation, types: &mut Types) -> anyhow::Result { + use convert_case::{Case, Casing}; + + let default_name = operation.operation_id.as_deref().unwrap_or_default(); + let name = format!("_global.{}", default_name.to_case(Case::Snake)); + let description = operation.summary.as_deref().unwrap_or_default().to_string(); + + let response = generate_get_response(&operation); + let response_media_type = if response.is_some() { + vec!["application/json".to_string()] + } else { + vec![] + }; + let request = generate_get_request(&operation, types)?; + let urls = vec![UrlTemplate { + path: id.to_string(), + methods: vec!["GET".to_string()], + deprecation: None, + }]; + + Ok(Endpoint { + name, + description, + doc_url: None, + doc_id: None, + ext_doc_id: None, + ext_doc_url: None, + deprecation: None, + availability: None, + doc_tag: None, + request: Some(request), + request_body_required: false, + response, + urls, + request_media_type: vec![], + response_media_type, + privileges: None, + }) +} + +fn generate_get_response(operation: &openapiv3::Operation) -> Option { + let openapi_response: &ReferenceOr = + operation.responses.responses.get(&StatusCode::Code(200))?; + let response_typename = match openapi_response { + ReferenceOr::Reference { reference } => types::ref_to_typename(reference), + ReferenceOr::Item(response) => match response.content.values().next()?.schema.as_ref()? { + ReferenceOr::Reference { reference } => types::ref_to_typename(reference), + ReferenceOr::Item(schema) => panic!("complex schema not expected {:?}", schema.schema_kind), + }, + }; + Some(response_typename) +} + +fn generate_get_request(operation: &openapiv3::Operation, types: &mut Types) -> anyhow::Result { + let mut query = vec![]; + for parameter in &operation.parameters { + match parameter { + ReferenceOr::Reference { .. } => panic!("expected parameter to be inlined"), + ReferenceOr::Item(parameter) => { + match ¶meter { + openapiv3::Parameter::Query { parameter_data, .. } => { + let type_ = match ¶meter_data.format { + openapiv3::ParameterSchemaOrContent::Schema(ref_or_schema) => match ref_or_schema { + ReferenceOr::Item(item) => match &item.schema_kind { + openapiv3::SchemaKind::Type(type_) => convert_builtin_type(type_)?, + _ => return Err(anyhow::anyhow!("unexpected schema kind")), + }, + ReferenceOr::Reference { reference } => { + return Err(anyhow::anyhow!("unexpected ReferenceOr::Reference({})", reference)) + } + }, + openapiv3::ParameterSchemaOrContent::Content(content) => { + return Err(anyhow::anyhow!("unexpected Content({:?})", content)) + } + }; + + query.push(Property { + name: parameter_data.name.clone(), + typ: ValueOf::InstanceOf(InstanceOf::new(type_)), + description: parameter_data.description.clone(), + required: parameter_data.required, + doc_url: None, + doc_id: None, + ext_doc_url: None, + ext_doc_id: None, + server_default: None, + deprecation: None, + availability: None, + codegen_name: None, + aliases: vec![], + container_property: false, + es_quirk: None, + }); + } + _ => (), + }; + } + } + } + let request = Request { + base: BaseType { + name: TypeName { + namespace: "_global".into(), + name: "SystemStatusRequest".into(), + }, + description: None, + doc_url: None, + doc_id: None, + ext_doc_url: None, + ext_doc_id: None, + deprecation: None, + es_quirk: None, + variant_name: None, + codegen_names: vec![], + spec_location: None, + }, + generics: vec![], + inherits: None, + implements: vec![], + path: vec![], + query, + body: Body::NoBody(NoBody {}), + behaviors: vec![], + attached_behaviors: vec![], + }; + types.add("SystemStatusRequest", TypeDefinition::Request(request.clone())); + Ok(request.base.name.clone()) +} + +fn convert_builtin_type(type_: &openapiv3::Type) -> anyhow::Result { + Ok(match type_ { + openapiv3::Type::Boolean(_) => builtins::BOOLEAN.clone(), + openapiv3::Type::Integer(_) => builtins::INTEGER.clone(), + openapiv3::Type::Number(variant) => match &variant.format { + openapiv3::VariantOrUnknownOrEmpty::Item(number_type) => match number_type { + openapiv3::NumberFormat::Float => builtins::FLOAT.clone(), + openapiv3::NumberFormat::Double => builtins::DOUBLE.clone(), + }, + _ => builtins::DOUBLE.clone(), + }, + _ => return Err(anyhow::anyhow!("unexpected type {:?}", type_)), + }) +} diff --git a/compiler-rs/openapi_to_clients_schema/src/lib.rs b/compiler-rs/openapi_to_clients_schema/src/lib.rs index ca763ab2cc..2c4dfd0c7c 100644 --- a/compiler-rs/openapi_to_clients_schema/src/lib.rs +++ b/compiler-rs/openapi_to_clients_schema/src/lib.rs @@ -21,27 +21,30 @@ pub mod types; use std::convert::Into; +use anyhow::Error; use clients_schema::IndexedModel; use openapi::OpenAPI; use tracing::warn; +use types::Types; /// Generate a schema.json from an OpenAPI schema pub fn generate(open_api: &OpenAPI) -> anyhow::Result { let mut json_schema = clients_schema::IndexedModel::default(); - generate_types(open_api, &mut json_schema)?; + let mut schema_types = generate_types(open_api)?; + generate_endpoints(open_api, &mut json_schema, &mut schema_types)?; - // endpoints - // for (id, path) in &open_api.paths.paths { - // let endpoint = generate_endpoint(open_api, id, path)?; - // json_schema.endpoints.push(endpoint); - // } + json_schema.types = schema_types + .types() + .into_iter() + .map(|t| (t.name().clone(), t)) + .collect(); Ok(json_schema) } /// Generate all types from OpenAPI components -fn generate_types(open_api: &OpenAPI, model: &mut IndexedModel) -> anyhow::Result<()> { +fn generate_types(open_api: &OpenAPI) -> anyhow::Result { if let Some(ref components) = open_api.components { let mut types = types::Types::default(); for (id, schema) in &components.schemas { @@ -52,7 +55,16 @@ fn generate_types(open_api: &OpenAPI, model: &mut IndexedModel) -> anyhow::Resul } } let _ = types.check_tracker(); // TODO: actually fail - model.types = types.types().into_iter().map(|t| (t.name().clone(), t)).collect(); + Ok(types) + } else { + Err(Error::msg("No components found")) + } +} + +fn generate_endpoints(open_api: &OpenAPI, json_schema: &mut IndexedModel, types: &mut Types) -> anyhow::Result<()> { + for (id, path) in &open_api.paths.paths { + let endpoint = endpoints::generate_endpoint(id, path, types)?; + json_schema.endpoints.push(endpoint); } Ok(()) diff --git a/compiler-rs/openapi_to_clients_schema/src/main.rs b/compiler-rs/openapi_to_clients_schema/src/main.rs index 1f7c2be6d7..2b0fc349fe 100644 --- a/compiler-rs/openapi_to_clients_schema/src/main.rs +++ b/compiler-rs/openapi_to_clients_schema/src/main.rs @@ -34,6 +34,17 @@ fn main() -> anyhow::Result<()> { _ => return Err(anyhow::anyhow!("expected a single argument")), }; + let open_api = read_openapi_schema(path)?; + let sch_json = openapi_to_clients_schema::generate(&OpenAPI(open_api))?; + + let dest = PathBuf::from(path).with_extension("schema.json"); + let output = std::fs::File::create(dest)?; + serde_json::to_writer_pretty(output, &sch_json)?; + + Ok(()) +} + +fn read_openapi_schema(path: &str) -> anyhow::Result { info!("Loading OpenAPI from {path}"); let data = std::fs::read_to_string(path)?; @@ -46,27 +57,30 @@ fn main() -> anyhow::Result<()> { serde_ignored::deserialize(&mut deser, |path| { unused.insert(path.to_string()); }) - .map_err(From::from) + .map_err(Into::into) } Some(ext) if ext == "yml" || ext == "yaml" => { let deser = serde_yml::Deserializer::from_str(&data); serde_ignored::deserialize(deser, |path| { unused.insert(path.to_string()); }) - .map_err(From::from) + .map_err(Into::into) } _ => Err(anyhow::anyhow!(format!("Unsupported file extension {:?}", path))), - }?; + }; if !unused.is_empty() { - println!("Unused fields in the OpenAPI schema: {:?}", unused); + let message = format!("Unused fields in the OpenAPI schema: {:?}", unused); + return Err(anyhow::anyhow!(message)); } - let sch_json = openapi_to_clients_schema::generate(&OpenAPI(open_api))?; - - let dest = PathBuf::from(path).with_extension("schema.json"); - let output = std::fs::File::create(dest)?; - serde_json::to_writer_pretty(output, &sch_json)?; + open_api +} +#[test] +fn test_kibana_conversion() -> anyhow::Result<()> { + let open_api = read_openapi_schema("fixtures/kibana.serverless.yaml")?; + let sch_json = openapi_to_clients_schema::generate(&OpenAPI(open_api))?; + insta::assert_json_snapshot!(sch_json); Ok(()) } diff --git a/compiler-rs/openapi_to_clients_schema/src/snapshots/openapi_to_clients_schema__kibana_conversion.snap b/compiler-rs/openapi_to_clients_schema/src/snapshots/openapi_to_clients_schema__kibana_conversion.snap new file mode 100644 index 0000000000..162b51ddaf --- /dev/null +++ b/compiler-rs/openapi_to_clients_schema/src/snapshots/openapi_to_clients_schema__kibana_conversion.snap @@ -0,0 +1,1197 @@ +--- +source: openapi_to_clients_schema/src/main.rs +expression: sch_json +--- +{ + "endpoints": [ + { + "name": "_global.system_status", + "description": "Get Kibana's current status", + "request": { + "namespace": "_global", + "name": "SystemStatusRequest" + }, + "requestBodyRequired": false, + "response": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponse" + }, + "urls": [ + { + "path": "/api/status", + "methods": [ + "GET" + ] + } + ], + "responseMediaType": [ + "application/json" + ] + } + ], + "types": [ + { + "kind": "interface", + "name": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusRedactedResponse" + }, + "description": "A minimal representation of Kibana's operational status.", + "behaviors": [ + { + "type": { + "namespace": "_spec_utils", + "name": "AdditionalProperties" + }, + "generics": [ + { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "UserDefined" + } + } + ] + } + ], + "properties": [ + { + "name": "status", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusRedactedResponseStatus" + } + }, + "required": true + } + ] + }, + { + "kind": "interface", + "name": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusRedactedResponseStatus" + }, + "behaviors": [ + { + "type": { + "namespace": "_spec_utils", + "name": "AdditionalProperties" + }, + "generics": [ + { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "UserDefined" + } + } + ] + } + ], + "properties": [ + { + "name": "overall", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusRedactedResponseStatusOverall" + } + }, + "required": true + } + ] + }, + { + "kind": "interface", + "name": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusRedactedResponseStatusOverall" + }, + "behaviors": [ + { + "type": { + "namespace": "_spec_utils", + "name": "AdditionalProperties" + }, + "generics": [ + { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "UserDefined" + } + } + ] + } + ], + "properties": [ + { + "name": "level", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusRedactedResponseStatusOverallLevel" + } + }, + "required": true + } + ] + }, + { + "kind": "enum", + "name": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusRedactedResponseStatusOverallLevel" + }, + "description": "Service status levels as human and machine readable values.", + "isOpen": false, + "members": [ + { + "name": "available" + }, + { + "name": "degraded" + }, + { + "name": "unavailable" + }, + { + "name": "critical" + } + ] + }, + { + "kind": "interface", + "name": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponse" + }, + "description": "Kibana's operational status as well as a detailed breakdown of plugin statuses indication of various loads (like event loop utilization and network traffic) at time of request.", + "behaviors": [ + { + "type": { + "namespace": "_spec_utils", + "name": "AdditionalProperties" + }, + "generics": [ + { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "UserDefined" + } + } + ] + } + ], + "properties": [ + { + "name": "metrics", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponseMetrics" + } + }, + "required": true + }, + { + "name": "name", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "string" + } + }, + "required": true + }, + { + "name": "status", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponseStatus" + } + }, + "required": true + }, + { + "name": "uuid", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "string" + } + }, + "required": true + }, + { + "name": "version", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponseVersion" + } + }, + "required": true + } + ] + }, + { + "kind": "interface", + "name": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponseMetrics" + }, + "description": "Metric groups collected by Kibana.", + "behaviors": [ + { + "type": { + "namespace": "_spec_utils", + "name": "AdditionalProperties" + }, + "generics": [ + { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "UserDefined" + } + } + ] + } + ], + "properties": [ + { + "name": "collection_interval_in_millis", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "double" + } + }, + "required": true + }, + { + "name": "elasticsearch_client", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponseMetricsElasticsearchClient" + } + }, + "required": true + }, + { + "name": "last_updated", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "string" + } + }, + "required": true + } + ] + }, + { + "kind": "interface", + "name": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponseMetricsElasticsearchClient" + }, + "description": "Current network metrics of Kibana's Elasticsearch client.", + "behaviors": [ + { + "type": { + "namespace": "_spec_utils", + "name": "AdditionalProperties" + }, + "generics": [ + { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "UserDefined" + } + } + ] + } + ], + "properties": [ + { + "name": "totalActiveSockets", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "double" + } + }, + "required": true + }, + { + "name": "totalIdleSockets", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "double" + } + }, + "required": true + }, + { + "name": "totalQueuedRequests", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "double" + } + }, + "required": true + } + ] + }, + { + "kind": "interface", + "name": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponseStatus" + }, + "behaviors": [ + { + "type": { + "namespace": "_spec_utils", + "name": "AdditionalProperties" + }, + "generics": [ + { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "UserDefined" + } + } + ] + } + ], + "properties": [ + { + "name": "core", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponseStatusCore" + } + }, + "required": true + }, + { + "name": "overall", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponseStatusOverall" + } + }, + "required": true + }, + { + "name": "plugins", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponseStatusPlugins" + } + }, + "required": true + } + ] + }, + { + "kind": "interface", + "name": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponseStatusCore" + }, + "description": "Statuses of core Kibana services.", + "behaviors": [ + { + "type": { + "namespace": "_spec_utils", + "name": "AdditionalProperties" + }, + "generics": [ + { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "UserDefined" + } + } + ] + } + ], + "properties": [ + { + "name": "elasticsearch", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponseStatusCoreElasticsearch" + } + }, + "required": true + }, + { + "name": "savedObjects", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponseStatusCoreSavedObjects" + } + }, + "required": true + } + ] + }, + { + "kind": "interface", + "name": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponseStatusCoreElasticsearch" + }, + "behaviors": [ + { + "type": { + "namespace": "_spec_utils", + "name": "AdditionalProperties" + }, + "generics": [ + { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "UserDefined" + } + } + ] + } + ], + "properties": [ + { + "name": "detail", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "string" + } + }, + "required": false + }, + { + "name": "documentationUrl", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "string" + } + }, + "required": false + }, + { + "name": "level", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponseStatusCoreElasticsearchLevel" + } + }, + "required": true + }, + { + "name": "meta", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponseStatusCoreElasticsearchMeta" + } + }, + "required": true + }, + { + "name": "summary", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "string" + } + }, + "required": true + } + ] + }, + { + "kind": "enum", + "name": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponseStatusCoreElasticsearchLevel" + }, + "description": "Service status levels as human and machine readable values.", + "isOpen": false, + "members": [ + { + "name": "available" + }, + { + "name": "degraded" + }, + { + "name": "unavailable" + }, + { + "name": "critical" + } + ] + }, + { + "kind": "type_alias", + "name": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponseStatusCoreElasticsearchMeta" + }, + "description": "An unstructured set of extra metadata about this service.", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "Dictionary" + }, + "generics": [ + { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "string" + } + }, + { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "UserDefined" + } + } + ] + } + }, + { + "kind": "interface", + "name": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponseStatusCoreSavedObjects" + }, + "behaviors": [ + { + "type": { + "namespace": "_spec_utils", + "name": "AdditionalProperties" + }, + "generics": [ + { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "UserDefined" + } + } + ] + } + ], + "properties": [ + { + "name": "detail", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "string" + } + }, + "required": false + }, + { + "name": "documentationUrl", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "string" + } + }, + "required": false + }, + { + "name": "level", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponseStatusCoreSavedObjectsLevel" + } + }, + "required": true + }, + { + "name": "meta", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponseStatusCoreSavedObjectsMeta" + } + }, + "required": true + }, + { + "name": "summary", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "string" + } + }, + "required": true + } + ] + }, + { + "kind": "enum", + "name": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponseStatusCoreSavedObjectsLevel" + }, + "description": "Service status levels as human and machine readable values.", + "isOpen": false, + "members": [ + { + "name": "available" + }, + { + "name": "degraded" + }, + { + "name": "unavailable" + }, + { + "name": "critical" + } + ] + }, + { + "kind": "type_alias", + "name": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponseStatusCoreSavedObjectsMeta" + }, + "description": "An unstructured set of extra metadata about this service.", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "Dictionary" + }, + "generics": [ + { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "string" + } + }, + { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "UserDefined" + } + } + ] + } + }, + { + "kind": "interface", + "name": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponseStatusOverall" + }, + "behaviors": [ + { + "type": { + "namespace": "_spec_utils", + "name": "AdditionalProperties" + }, + "generics": [ + { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "UserDefined" + } + } + ] + } + ], + "properties": [ + { + "name": "detail", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "string" + } + }, + "required": false + }, + { + "name": "documentationUrl", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "string" + } + }, + "required": false + }, + { + "name": "level", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponseStatusOverallLevel" + } + }, + "required": true + }, + { + "name": "meta", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponseStatusOverallMeta" + } + }, + "required": true + }, + { + "name": "summary", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "string" + } + }, + "required": true + } + ] + }, + { + "kind": "enum", + "name": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponseStatusOverallLevel" + }, + "description": "Service status levels as human and machine readable values.", + "isOpen": false, + "members": [ + { + "name": "available" + }, + { + "name": "degraded" + }, + { + "name": "unavailable" + }, + { + "name": "critical" + } + ] + }, + { + "kind": "type_alias", + "name": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponseStatusOverallMeta" + }, + "description": "An unstructured set of extra metadata about this service.", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "Dictionary" + }, + "generics": [ + { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "string" + } + }, + { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "UserDefined" + } + } + ] + } + }, + { + "kind": "type_alias", + "name": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponseStatusPlugins" + }, + "description": "A dynamic mapping of plugin ID to plugin status.", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "Dictionary" + }, + "generics": [ + { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "string" + } + }, + { + "kind": "instance_of", + "type": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponseStatusPluginsValue" + } + } + ] + } + }, + { + "kind": "interface", + "name": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponseStatusPluginsValue" + }, + "behaviors": [ + { + "type": { + "namespace": "_spec_utils", + "name": "AdditionalProperties" + }, + "generics": [ + { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "UserDefined" + } + } + ] + } + ], + "properties": [ + { + "name": "detail", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "string" + } + }, + "required": false + }, + { + "name": "documentationUrl", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "string" + } + }, + "required": false + }, + { + "name": "level", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponseStatusPluginsValueLevel" + } + }, + "required": true + }, + { + "name": "meta", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponseStatusPluginsValueMeta" + } + }, + "required": true + }, + { + "name": "summary", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "string" + } + }, + "required": true + } + ] + }, + { + "kind": "enum", + "name": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponseStatusPluginsValueLevel" + }, + "description": "Service status levels as human and machine readable values.", + "isOpen": false, + "members": [ + { + "name": "available" + }, + { + "name": "degraded" + }, + { + "name": "unavailable" + }, + { + "name": "critical" + } + ] + }, + { + "kind": "type_alias", + "name": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponseStatusPluginsValueMeta" + }, + "description": "An unstructured set of extra metadata about this service.", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "Dictionary" + }, + "generics": [ + { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "string" + } + }, + { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "UserDefined" + } + } + ] + } + }, + { + "kind": "interface", + "name": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponseVersion" + }, + "behaviors": [ + { + "type": { + "namespace": "_spec_utils", + "name": "AdditionalProperties" + }, + "generics": [ + { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "UserDefined" + } + } + ] + } + ], + "properties": [ + { + "name": "build_date", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "string" + } + }, + "required": true + }, + { + "name": "build_flavor", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponseVersionBuildFlavor" + } + }, + "required": true + }, + { + "name": "build_hash", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "string" + } + }, + "required": true + }, + { + "name": "build_number", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "double" + } + }, + "required": true + }, + { + "name": "build_snapshot", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "boolean" + } + }, + "required": true + }, + { + "name": "number", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "string" + } + }, + "required": true + } + ] + }, + { + "kind": "enum", + "name": { + "namespace": "_global", + "name": "KibanaHttpApIsCoreStatusResponseVersionBuildFlavor" + }, + "description": "The build flavour determines configuration and behavior of Kibana. On premise users will almost always run the \"traditional\" flavour, while other flavours are reserved for Elastic-specific use cases.", + "isOpen": false, + "members": [ + { + "name": "serverless" + }, + { + "name": "traditional" + } + ] + }, + { + "kind": "request", + "name": { + "namespace": "_global", + "name": "SystemStatusRequest" + }, + "inherits": null, + "path": [], + "query": [ + { + "name": "v7format", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "boolean" + } + }, + "required": false, + "description": "Set to \"true\" to get the response in v7 format." + }, + { + "name": "v8format", + "type": { + "kind": "instance_of", + "type": { + "namespace": "_builtins", + "name": "boolean" + } + }, + "required": false, + "description": "Set to \"true\" to get the response in v8 format." + } + ], + "body": { + "kind": "no_body" + } + } + ] +} diff --git a/compiler-rs/openapi_to_clients_schema/src/types.rs b/compiler-rs/openapi_to_clients_schema/src/types.rs index 6d341465b3..d079626c94 100644 --- a/compiler-rs/openapi_to_clients_schema/src/types.rs +++ b/compiler-rs/openapi_to_clients_schema/src/types.rs @@ -55,7 +55,7 @@ impl Types { let mut failed = false; for id in self.tracker.iter() { if !self.types.contains_key(id) { - error!("Type '{id}' tracked but but not generated."); + error!("Type '{id}' tracked but not generated."); failed = true; } } @@ -532,7 +532,7 @@ fn id_to_typename(id: &str) -> TypeName { } } -fn ref_to_typename(ref_id: &str) -> TypeName { +pub fn ref_to_typename(ref_id: &str) -> TypeName { let id = ref_id.trim_start_matches("#/components/schemas/"); id_to_typename(id) }