k8s_openapi_codegen_common/swagger20/
mod.rs

1//! This module contains types related to the OpenAPI types used in the Kubernetes spec.
2
3mod definitions;
4pub use self::definitions::*;
5
6mod info;
7pub use self::info::*;
8
9mod paths;
10pub use self::paths::*;
11
12/// The value of an `x-kubernetes-group-version-kind` annotation on a type or an operation.
13#[derive(Clone, Debug, Eq, PartialEq)]
14#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
15pub struct KubernetesGroupKindVersion {
16    pub group: String,
17    pub kind: String,
18    pub version: String,
19}
20
21impl std::cmp::Ord for KubernetesGroupKindVersion {
22    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
23        self.group.cmp(&other.group)
24        .then_with(|| self.version.cmp(&other.version))
25        .then_with(|| self.kind.cmp(&other.kind))
26    }
27}
28
29impl std::cmp::PartialOrd for KubernetesGroupKindVersion {
30    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
31        Some(self.cmp(other))
32    }
33}
34
35/// The whole `Spec` object. An OpenAPI spec JSON file can be deserialized into this type.
36#[derive(Debug)]
37pub struct Spec {
38    pub info: Info,
39    pub definitions: std::collections::BTreeMap<DefinitionPath, Schema>,
40    pub operations: Vec<Operation>,
41}
42
43#[cfg(feature = "serde")]
44#[allow(clippy::use_self)]
45impl<'de> serde::Deserialize<'de> for Spec {
46    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: serde::Deserializer<'de> {
47        #[derive(Debug, serde::Deserialize)]
48        pub struct InnerSpec {
49            info: Info,
50            definitions: std::collections::BTreeMap<DefinitionPath, Schema>,
51            paths: std::collections::BTreeMap<Path, InnerPathItem>,
52            swagger: String,
53        }
54
55        #[derive(Debug, serde::Deserialize)]
56        struct InnerPathItem {
57            delete: Option<InnerOperation>,
58            get: Option<InnerOperation>,
59            patch: Option<InnerOperation>,
60            post: Option<InnerOperation>,
61            put: Option<InnerOperation>,
62        }
63
64        #[derive(Debug, serde::Deserialize)]
65        struct InnerOperation {
66            #[serde(rename = "operationId")]
67            id: String,
68            #[serde(rename = "x-kubernetes-action")]
69            kubernetes_action: Option<KubernetesAction>,
70            #[serde(rename = "x-kubernetes-group-version-kind")]
71            kubernetes_group_kind_version: Option<KubernetesGroupKindVersion>,
72        }
73
74        let result: InnerSpec = serde::Deserialize::deserialize(deserializer)?;
75
76        if result.swagger != "2.0" {
77            return Err(serde::de::Error::invalid_value(serde::de::Unexpected::Str(&result.swagger), &"2.0"));
78        }
79
80        let mut operations = vec![];
81
82        for (path, path_item) in result.paths {
83            if let Some(delete) = path_item.delete {
84                operations.push(Operation {
85                    id: delete.id,
86                    kubernetes_action: delete.kubernetes_action,
87                    kubernetes_group_kind_version: delete.kubernetes_group_kind_version,
88                    path: path.clone(),
89                });
90            }
91
92            if let Some(get) = path_item.get {
93                operations.push(Operation {
94                    id: get.id,
95                    kubernetes_action: get.kubernetes_action,
96                    kubernetes_group_kind_version: get.kubernetes_group_kind_version,
97                    path: path.clone(),
98                });
99            }
100
101            if let Some(patch) = path_item.patch {
102                operations.push(Operation {
103                    id: patch.id,
104                    kubernetes_action: patch.kubernetes_action,
105                    kubernetes_group_kind_version: patch.kubernetes_group_kind_version,
106                    path: path.clone(),
107                });
108            }
109
110            if let Some(post) = path_item.post {
111                operations.push(Operation {
112                    id: post.id,
113                    kubernetes_action: post.kubernetes_action,
114                    kubernetes_group_kind_version: post.kubernetes_group_kind_version,
115                    path: path.clone(),
116                });
117            }
118
119            if let Some(put) = path_item.put {
120                operations.push(Operation {
121                    id: put.id,
122                    kubernetes_action: put.kubernetes_action,
123                    kubernetes_group_kind_version: put.kubernetes_group_kind_version,
124                    path,
125                });
126            }
127        }
128
129        let mut operation_ids: std::collections::BTreeSet<_> = Default::default();
130        for operation in &operations {
131            assert!(operation_ids.insert(&operation.id));
132        }
133
134        Ok(Spec {
135            info: result.info,
136            definitions: result.definitions,
137            operations,
138        })
139    }
140}