-
Notifications
You must be signed in to change notification settings - Fork 40
/
upstream_bugs.rs
189 lines (168 loc) · 7.1 KB
/
upstream_bugs.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#![deny(unused)]
//! These fixups correspond to bugs in the upstream swagger spec.
// Path operation annotated with a "x-kubernetes-group-version-kind" that references a type that doesn't exist in the schema.
//
// Ref: https://github.com/kubernetes/kubernetes/pull/66807
#[allow(clippy::if_same_then_else)]
pub(crate) fn connect_options_gvk(spec: &mut crate::swagger20::Spec) -> Result<(), crate::Error> {
let mut found = false;
for operation in &mut spec.operations {
if let Some(kubernetes_group_kind_version) = &mut operation.kubernetes_group_kind_version {
if kubernetes_group_kind_version.group.is_empty() && kubernetes_group_kind_version.version == "v1" {
let kind = &mut kubernetes_group_kind_version.kind;
if &*kind == "NodeProxyOptions" {
*kind = "Node".to_string();
found = true;
}
else if &*kind == "PodAttachOptions" {
*kind = "Pod".to_string();
found = true;
}
else if &*kind == "PodExecOptions" {
*kind = "Pod".to_string();
found = true;
}
else if &*kind == "PodPortForwardOptions" {
*kind = "Pod".to_string();
found = true;
}
else if &*kind == "PodProxyOptions" {
*kind = "Pod".to_string();
found = true;
}
else if &*kind == "ServiceProxyOptions" {
*kind = "Service".to_string();
found = true;
}
}
}
}
if found {
Ok(())
}
else {
Err("never applied connect options kubernetes_group_kind_version override".into())
}
}
// The spec says that `createAppsV1beta1NamespacedDeploymentRollback` returns `DeploymentRollback`, but it returns `Status`.
//
// Ref: https://github.com/kubernetes/kubernetes/pull/63837
pub(crate) fn deployment_rollback_create_response_type(spec: &mut crate::swagger20::Spec) -> Result<(), crate::Error> {
let mut found = false;
if let Some(operation) = spec.operations.iter_mut().find(|o| o.id == "createAppsV1beta1NamespacedDeploymentRollback") {
if let crate::swagger20::OperationResponses::Map(responses) = &mut operation.responses {
for response in responses.values_mut() {
if let crate::swagger20::Schema { kind: crate::swagger20::SchemaKind::Ref(crate::swagger20::RefPath { path, .. }), .. } = response {
if path == "io.k8s.api.apps.v1beta1.DeploymentRollback" {
*path = "io.k8s.apimachinery.pkg.apis.meta.v1.Status".to_owned();
found = true;
}
}
}
}
}
if found {
Ok(())
}
else {
Err("never applied createAppsV1beta1NamespacedDeploymentRollback response type override".into())
}
}
// The spec says that this property is an array, but it can be null.
//
// Override it to be optional to achieve the same effect.
pub(crate) mod optional_properties {
// `ContainerImage::names`
//
// Ref: https://github.com/kubernetes/kubernetes/issues/93606
pub(crate) fn containerimage(spec: &mut crate::swagger20::Spec) -> Result<(), crate::Error> {
let definition_path = crate::swagger20::DefinitionPath("io.k8s.api.core.v1.ContainerImage".to_owned());
if let Some(definition) = spec.definitions.get_mut(&definition_path) {
if let crate::swagger20::SchemaKind::Properties(properties) = &mut definition.kind {
if let Some(property) = properties.get_mut(&crate::swagger20::PropertyName("names".to_string())) {
if property.1 {
property.1 = false;
return Ok(());
}
}
}
}
Err("never applied ContainerImage optional properties override".into())
}
// `CustomResourceDefinitionStatus::conditions`
//
// Ref: https://github.com/kubernetes/kubernetes/pull/64996
pub(crate) fn crdstatus(spec: &mut crate::swagger20::Spec) -> Result<(), crate::Error> {
let definition_path = crate::swagger20::DefinitionPath("io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionStatus".to_owned());
if let Some(definition) = spec.definitions.get_mut(&definition_path) {
if let crate::swagger20::SchemaKind::Properties(properties) = &mut definition.kind {
if let Some(property) = properties.get_mut(&crate::swagger20::PropertyName("conditions".to_string())) {
if property.1 {
property.1 = false;
return Ok(());
}
}
}
}
Err("never applied CustomResourceDefinitionStatus optional properties override".into())
}
// `PodDisruptionBudgetStatus::disruptedPods`
//
// Ref: https://github.com/kubernetes/kubernetes/pull/65041
pub(crate) fn poddisruptionbudgetstatus(spec: &mut crate::swagger20::Spec) -> Result<(), crate::Error> {
let definition_path = crate::swagger20::DefinitionPath("io.k8s.api.policy.v1beta1.PodDisruptionBudgetStatus".to_owned());
if let Some(definition) = spec.definitions.get_mut(&definition_path) {
if let crate::swagger20::SchemaKind::Properties(properties) = &mut definition.kind {
if let Some(property) = properties.get_mut(&crate::swagger20::PropertyName("disruptedPods".to_string())) {
if property.1 {
property.1 = false;
return Ok(());
}
}
}
}
Err("never applied PodDisruptionBudgetStatus optional properties override".into())
}
}
// The spec says that `RawExtension` is an object with a property `raw` that's a byte-formatted string.
// While the golang type is indeed a struct with a `Raw []byte` field, the type is serialized by just emitting the value of that field.
// The value of that field is itself a JSON-serialized value. For example, a `WatchEvent` of `Pod`s has the `Pod` object serialized as
// the value of the `WatchEvent::object` property.
//
// Thus `RawExtension` is really an arbitrary JSON value, and should be represented by `serde_json::Value`
//
// Ref: https://github.com/kubernetes/kubernetes/issues/55890
//
// https://github.com/kubernetes/kubernetes/pull/56434 will remove RawExtension and replace it with `{ type: "object" }`,
// which would've already been mapped to `Ty(Any)` by `Ty::parse`, so just replicate that for `RawExtension` here.
pub(crate) fn raw_extension_ty(spec: &mut crate::swagger20::Spec) -> Result<(), crate::Error> {
let definition_path = crate::swagger20::DefinitionPath("io.k8s.apimachinery.pkg.runtime.RawExtension".to_owned());
if let Some(definition) = spec.definitions.get_mut(&definition_path) {
if !matches!(definition.kind, crate::swagger20::SchemaKind::Ty(crate::swagger20::Type::Any)) {
definition.kind = crate::swagger20::SchemaKind::Ty(crate::swagger20::Type::Any);
return Ok(());
}
}
Err("never applied RawExtension override".into())
}
// Remove `$ref`s under `io.k8s.kubernetes.pkg` since these are marked deprecated and point to corresponding definitions under `io.k8s.api`.
// They only exist for backward-compatibility with 1.7's spec.
pub(crate) fn remove_compat_refs(spec: &mut crate::swagger20::Spec) -> Result<(), crate::Error> {
const COMPAT_NAMESPACE: &[&str] = &["io", "k8s", "kubernetes", "pkg"];
let mut to_remove = vec![];
for (definition_path, definition) in &spec.definitions {
if let crate::swagger20::SchemaKind::Ref(_) = definition.kind {
let parts: Vec<_> = definition_path.split('.').collect();
if parts.starts_with(COMPAT_NAMESPACE) {
to_remove.push(definition_path.clone());
}
}
}
if to_remove.is_empty() {
return Err("never removed compat refs".into());
}
for to_remove in to_remove {
spec.definitions.remove(&to_remove);
}
Ok(())
}