1#[derive(Clone, Debug, Default, PartialEq)]
5pub struct ValidatingWebhook {
6 pub admission_review_versions: Vec<String>,
8
9 pub client_config: crate::api::admissionregistration::v1::WebhookClientConfig,
11
12 pub failure_policy: Option<String>,
14
15 pub match_conditions: Option<Vec<crate::api::admissionregistration::v1::MatchCondition>>,
24
25 pub match_policy: Option<String>,
33
34 pub name: String,
36
37 pub namespace_selector: Option<crate::apimachinery::pkg::apis::meta::v1::LabelSelector>,
69
70 pub object_selector: Option<crate::apimachinery::pkg::apis::meta::v1::LabelSelector>,
72
73 pub rules: Option<Vec<crate::api::admissionregistration::v1::RuleWithOperations>>,
75
76 pub side_effects: String,
78
79 pub timeout_seconds: Option<i32>,
81}
82
83impl crate::DeepMerge for ValidatingWebhook {
84 fn merge_from(&mut self, other: Self) {
85 crate::merge_strategies::list::atomic(&mut self.admission_review_versions, other.admission_review_versions);
86 crate::DeepMerge::merge_from(&mut self.client_config, other.client_config);
87 crate::DeepMerge::merge_from(&mut self.failure_policy, other.failure_policy);
88 crate::merge_strategies::list::map(
89 &mut self.match_conditions,
90 other.match_conditions,
91 &[|lhs, rhs| lhs.name == rhs.name],
92 |current_item, other_item| {
93 crate::DeepMerge::merge_from(current_item, other_item);
94 },
95 );
96 crate::DeepMerge::merge_from(&mut self.match_policy, other.match_policy);
97 crate::DeepMerge::merge_from(&mut self.name, other.name);
98 crate::DeepMerge::merge_from(&mut self.namespace_selector, other.namespace_selector);
99 crate::DeepMerge::merge_from(&mut self.object_selector, other.object_selector);
100 crate::merge_strategies::list::atomic(&mut self.rules, other.rules);
101 crate::DeepMerge::merge_from(&mut self.side_effects, other.side_effects);
102 crate::DeepMerge::merge_from(&mut self.timeout_seconds, other.timeout_seconds);
103 }
104}
105
106impl<'de> crate::serde::Deserialize<'de> for ValidatingWebhook {
107 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: crate::serde::Deserializer<'de> {
108 #[allow(non_camel_case_types)]
109 enum Field {
110 Key_admission_review_versions,
111 Key_client_config,
112 Key_failure_policy,
113 Key_match_conditions,
114 Key_match_policy,
115 Key_name,
116 Key_namespace_selector,
117 Key_object_selector,
118 Key_rules,
119 Key_side_effects,
120 Key_timeout_seconds,
121 Other,
122 }
123
124 impl<'de> crate::serde::Deserialize<'de> for Field {
125 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: crate::serde::Deserializer<'de> {
126 struct Visitor;
127
128 impl crate::serde::de::Visitor<'_> for Visitor {
129 type Value = Field;
130
131 fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
132 f.write_str("field identifier")
133 }
134
135 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> where E: crate::serde::de::Error {
136 Ok(match v {
137 "admissionReviewVersions" => Field::Key_admission_review_versions,
138 "clientConfig" => Field::Key_client_config,
139 "failurePolicy" => Field::Key_failure_policy,
140 "matchConditions" => Field::Key_match_conditions,
141 "matchPolicy" => Field::Key_match_policy,
142 "name" => Field::Key_name,
143 "namespaceSelector" => Field::Key_namespace_selector,
144 "objectSelector" => Field::Key_object_selector,
145 "rules" => Field::Key_rules,
146 "sideEffects" => Field::Key_side_effects,
147 "timeoutSeconds" => Field::Key_timeout_seconds,
148 _ => Field::Other,
149 })
150 }
151 }
152
153 deserializer.deserialize_identifier(Visitor)
154 }
155 }
156
157 struct Visitor;
158
159 impl<'de> crate::serde::de::Visitor<'de> for Visitor {
160 type Value = ValidatingWebhook;
161
162 fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
163 f.write_str("ValidatingWebhook")
164 }
165
166 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error> where A: crate::serde::de::MapAccess<'de> {
167 let mut value_admission_review_versions: Option<Vec<String>> = None;
168 let mut value_client_config: Option<crate::api::admissionregistration::v1::WebhookClientConfig> = None;
169 let mut value_failure_policy: Option<String> = None;
170 let mut value_match_conditions: Option<Vec<crate::api::admissionregistration::v1::MatchCondition>> = None;
171 let mut value_match_policy: Option<String> = None;
172 let mut value_name: Option<String> = None;
173 let mut value_namespace_selector: Option<crate::apimachinery::pkg::apis::meta::v1::LabelSelector> = None;
174 let mut value_object_selector: Option<crate::apimachinery::pkg::apis::meta::v1::LabelSelector> = None;
175 let mut value_rules: Option<Vec<crate::api::admissionregistration::v1::RuleWithOperations>> = None;
176 let mut value_side_effects: Option<String> = None;
177 let mut value_timeout_seconds: Option<i32> = None;
178
179 while let Some(key) = crate::serde::de::MapAccess::next_key::<Field>(&mut map)? {
180 match key {
181 Field::Key_admission_review_versions => value_admission_review_versions = crate::serde::de::MapAccess::next_value(&mut map)?,
182 Field::Key_client_config => value_client_config = crate::serde::de::MapAccess::next_value(&mut map)?,
183 Field::Key_failure_policy => value_failure_policy = crate::serde::de::MapAccess::next_value(&mut map)?,
184 Field::Key_match_conditions => value_match_conditions = crate::serde::de::MapAccess::next_value(&mut map)?,
185 Field::Key_match_policy => value_match_policy = crate::serde::de::MapAccess::next_value(&mut map)?,
186 Field::Key_name => value_name = crate::serde::de::MapAccess::next_value(&mut map)?,
187 Field::Key_namespace_selector => value_namespace_selector = crate::serde::de::MapAccess::next_value(&mut map)?,
188 Field::Key_object_selector => value_object_selector = crate::serde::de::MapAccess::next_value(&mut map)?,
189 Field::Key_rules => value_rules = crate::serde::de::MapAccess::next_value(&mut map)?,
190 Field::Key_side_effects => value_side_effects = crate::serde::de::MapAccess::next_value(&mut map)?,
191 Field::Key_timeout_seconds => value_timeout_seconds = crate::serde::de::MapAccess::next_value(&mut map)?,
192 Field::Other => { let _: crate::serde::de::IgnoredAny = crate::serde::de::MapAccess::next_value(&mut map)?; },
193 }
194 }
195
196 Ok(ValidatingWebhook {
197 admission_review_versions: value_admission_review_versions.unwrap_or_default(),
198 client_config: value_client_config.unwrap_or_default(),
199 failure_policy: value_failure_policy,
200 match_conditions: value_match_conditions,
201 match_policy: value_match_policy,
202 name: value_name.unwrap_or_default(),
203 namespace_selector: value_namespace_selector,
204 object_selector: value_object_selector,
205 rules: value_rules,
206 side_effects: value_side_effects.unwrap_or_default(),
207 timeout_seconds: value_timeout_seconds,
208 })
209 }
210 }
211
212 deserializer.deserialize_struct(
213 "ValidatingWebhook",
214 &[
215 "admissionReviewVersions",
216 "clientConfig",
217 "failurePolicy",
218 "matchConditions",
219 "matchPolicy",
220 "name",
221 "namespaceSelector",
222 "objectSelector",
223 "rules",
224 "sideEffects",
225 "timeoutSeconds",
226 ],
227 Visitor,
228 )
229 }
230}
231
232impl crate::serde::Serialize for ValidatingWebhook {
233 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: crate::serde::Serializer {
234 let mut state = serializer.serialize_struct(
235 "ValidatingWebhook",
236 4 +
237 self.failure_policy.as_ref().map_or(0, |_| 1) +
238 self.match_conditions.as_ref().map_or(0, |_| 1) +
239 self.match_policy.as_ref().map_or(0, |_| 1) +
240 self.namespace_selector.as_ref().map_or(0, |_| 1) +
241 self.object_selector.as_ref().map_or(0, |_| 1) +
242 self.rules.as_ref().map_or(0, |_| 1) +
243 self.timeout_seconds.as_ref().map_or(0, |_| 1),
244 )?;
245 crate::serde::ser::SerializeStruct::serialize_field(&mut state, "admissionReviewVersions", &self.admission_review_versions)?;
246 crate::serde::ser::SerializeStruct::serialize_field(&mut state, "clientConfig", &self.client_config)?;
247 if let Some(value) = &self.failure_policy {
248 crate::serde::ser::SerializeStruct::serialize_field(&mut state, "failurePolicy", value)?;
249 }
250 if let Some(value) = &self.match_conditions {
251 crate::serde::ser::SerializeStruct::serialize_field(&mut state, "matchConditions", value)?;
252 }
253 if let Some(value) = &self.match_policy {
254 crate::serde::ser::SerializeStruct::serialize_field(&mut state, "matchPolicy", value)?;
255 }
256 crate::serde::ser::SerializeStruct::serialize_field(&mut state, "name", &self.name)?;
257 if let Some(value) = &self.namespace_selector {
258 crate::serde::ser::SerializeStruct::serialize_field(&mut state, "namespaceSelector", value)?;
259 }
260 if let Some(value) = &self.object_selector {
261 crate::serde::ser::SerializeStruct::serialize_field(&mut state, "objectSelector", value)?;
262 }
263 if let Some(value) = &self.rules {
264 crate::serde::ser::SerializeStruct::serialize_field(&mut state, "rules", value)?;
265 }
266 crate::serde::ser::SerializeStruct::serialize_field(&mut state, "sideEffects", &self.side_effects)?;
267 if let Some(value) = &self.timeout_seconds {
268 crate::serde::ser::SerializeStruct::serialize_field(&mut state, "timeoutSeconds", value)?;
269 }
270 crate::serde::ser::SerializeStruct::end(state)
271 }
272}
273
274#[cfg(feature = "schemars")]
275impl crate::schemars::JsonSchema for ValidatingWebhook {
276 fn schema_name() -> String {
277 "io.k8s.api.admissionregistration.v1.ValidatingWebhook".to_owned()
278 }
279
280 fn json_schema(__gen: &mut crate::schemars::gen::SchemaGenerator) -> crate::schemars::schema::Schema {
281 crate::schemars::schema::Schema::Object(crate::schemars::schema::SchemaObject {
282 metadata: Some(Box::new(crate::schemars::schema::Metadata {
283 description: Some("ValidatingWebhook describes an admission webhook and the resources and operations it applies to.".to_owned()),
284 ..Default::default()
285 })),
286 instance_type: Some(crate::schemars::schema::SingleOrVec::Single(Box::new(crate::schemars::schema::InstanceType::Object))),
287 object: Some(Box::new(crate::schemars::schema::ObjectValidation {
288 properties: [
289 (
290 "admissionReviewVersions".to_owned(),
291 crate::schemars::schema::Schema::Object(crate::schemars::schema::SchemaObject {
292 metadata: Some(Box::new(crate::schemars::schema::Metadata {
293 description: Some("AdmissionReviewVersions is an ordered list of preferred `AdmissionReview` versions the Webhook expects. API server will try to use first version in the list which it supports. If none of the versions specified in this list supported by API server, validation will fail for this object. If a persisted webhook configuration specifies allowed versions and does not include any versions known to the API Server, calls to the webhook will fail and be subject to the failure policy.".to_owned()),
294 ..Default::default()
295 })),
296 instance_type: Some(crate::schemars::schema::SingleOrVec::Single(Box::new(crate::schemars::schema::InstanceType::Array))),
297 array: Some(Box::new(crate::schemars::schema::ArrayValidation {
298 items: Some(crate::schemars::schema::SingleOrVec::Single(Box::new(
299 crate::schemars::schema::Schema::Object(crate::schemars::schema::SchemaObject {
300 instance_type: Some(crate::schemars::schema::SingleOrVec::Single(Box::new(crate::schemars::schema::InstanceType::String))),
301 ..Default::default()
302 })
303 ))),
304 ..Default::default()
305 })),
306 ..Default::default()
307 }),
308 ),
309 (
310 "clientConfig".to_owned(),
311 {
312 let mut schema_obj = __gen.subschema_for::<crate::api::admissionregistration::v1::WebhookClientConfig>().into_object();
313 schema_obj.metadata = Some(Box::new(crate::schemars::schema::Metadata {
314 description: Some("ClientConfig defines how to communicate with the hook. Required".to_owned()),
315 ..Default::default()
316 }));
317 crate::schemars::schema::Schema::Object(schema_obj)
318 },
319 ),
320 (
321 "failurePolicy".to_owned(),
322 crate::schemars::schema::Schema::Object(crate::schemars::schema::SchemaObject {
323 metadata: Some(Box::new(crate::schemars::schema::Metadata {
324 description: Some("FailurePolicy defines how unrecognized errors from the admission endpoint are handled - allowed values are Ignore or Fail. Defaults to Fail.".to_owned()),
325 ..Default::default()
326 })),
327 instance_type: Some(crate::schemars::schema::SingleOrVec::Single(Box::new(crate::schemars::schema::InstanceType::String))),
328 ..Default::default()
329 }),
330 ),
331 (
332 "matchConditions".to_owned(),
333 crate::schemars::schema::Schema::Object(crate::schemars::schema::SchemaObject {
334 metadata: Some(Box::new(crate::schemars::schema::Metadata {
335 description: Some("MatchConditions is a list of conditions that must be met for a request to be sent to this webhook. Match conditions filter requests that have already been matched by the rules, namespaceSelector, and objectSelector. An empty list of matchConditions matches all requests. There are a maximum of 64 match conditions allowed.\n\nThe exact matching logic is (in order):\n 1. If ANY matchCondition evaluates to FALSE, the webhook is skipped.\n 2. If ALL matchConditions evaluate to TRUE, the webhook is called.\n 3. If any matchCondition evaluates to an error (but none are FALSE):\n - If failurePolicy=Fail, reject the request\n - If failurePolicy=Ignore, the error is ignored and the webhook is skipped".to_owned()),
336 ..Default::default()
337 })),
338 instance_type: Some(crate::schemars::schema::SingleOrVec::Single(Box::new(crate::schemars::schema::InstanceType::Array))),
339 array: Some(Box::new(crate::schemars::schema::ArrayValidation {
340 items: Some(crate::schemars::schema::SingleOrVec::Single(Box::new(__gen.subschema_for::<crate::api::admissionregistration::v1::MatchCondition>()))),
341 ..Default::default()
342 })),
343 ..Default::default()
344 }),
345 ),
346 (
347 "matchPolicy".to_owned(),
348 crate::schemars::schema::Schema::Object(crate::schemars::schema::SchemaObject {
349 metadata: Some(Box::new(crate::schemars::schema::Metadata {
350 description: Some("matchPolicy defines how the \"rules\" list is used to match incoming requests. Allowed values are \"Exact\" or \"Equivalent\".\n\n- Exact: match a request only if it exactly matches a specified rule. For example, if deployments can be modified via apps/v1, apps/v1beta1, and extensions/v1beta1, but \"rules\" only included `apiGroups:[\"apps\"], apiVersions:[\"v1\"], resources: [\"deployments\"]`, a request to apps/v1beta1 or extensions/v1beta1 would not be sent to the webhook.\n\n- Equivalent: match a request if modifies a resource listed in rules, even via another API group or version. For example, if deployments can be modified via apps/v1, apps/v1beta1, and extensions/v1beta1, and \"rules\" only included `apiGroups:[\"apps\"], apiVersions:[\"v1\"], resources: [\"deployments\"]`, a request to apps/v1beta1 or extensions/v1beta1 would be converted to apps/v1 and sent to the webhook.\n\nDefaults to \"Equivalent\"".to_owned()),
351 ..Default::default()
352 })),
353 instance_type: Some(crate::schemars::schema::SingleOrVec::Single(Box::new(crate::schemars::schema::InstanceType::String))),
354 ..Default::default()
355 }),
356 ),
357 (
358 "name".to_owned(),
359 crate::schemars::schema::Schema::Object(crate::schemars::schema::SchemaObject {
360 metadata: Some(Box::new(crate::schemars::schema::Metadata {
361 description: Some("The name of the admission webhook. Name should be fully qualified, e.g., imagepolicy.kubernetes.io, where \"imagepolicy\" is the name of the webhook, and kubernetes.io is the name of the organization. Required.".to_owned()),
362 ..Default::default()
363 })),
364 instance_type: Some(crate::schemars::schema::SingleOrVec::Single(Box::new(crate::schemars::schema::InstanceType::String))),
365 ..Default::default()
366 }),
367 ),
368 (
369 "namespaceSelector".to_owned(),
370 {
371 let mut schema_obj = __gen.subschema_for::<crate::apimachinery::pkg::apis::meta::v1::LabelSelector>().into_object();
372 schema_obj.metadata = Some(Box::new(crate::schemars::schema::Metadata {
373 description: Some("NamespaceSelector decides whether to run the webhook on an object based on whether the namespace for that object matches the selector. If the object itself is a namespace, the matching is performed on object.metadata.labels. If the object is another cluster scoped resource, it never skips the webhook.\n\nFor example, to run the webhook on any objects whose namespace is not associated with \"runlevel\" of \"0\" or \"1\"; you will set the selector as follows: \"namespaceSelector\": {\n \"matchExpressions\": [\n {\n \"key\": \"runlevel\",\n \"operator\": \"NotIn\",\n \"values\": [\n \"0\",\n \"1\"\n ]\n }\n ]\n}\n\nIf instead you want to only run the webhook on any objects whose namespace is associated with the \"environment\" of \"prod\" or \"staging\"; you will set the selector as follows: \"namespaceSelector\": {\n \"matchExpressions\": [\n {\n \"key\": \"environment\",\n \"operator\": \"In\",\n \"values\": [\n \"prod\",\n \"staging\"\n ]\n }\n ]\n}\n\nSee https://kubernetes.io/docs/concepts/overview/working-with-objects/labels for more examples of label selectors.\n\nDefault to the empty LabelSelector, which matches everything.".to_owned()),
374 ..Default::default()
375 }));
376 crate::schemars::schema::Schema::Object(schema_obj)
377 },
378 ),
379 (
380 "objectSelector".to_owned(),
381 {
382 let mut schema_obj = __gen.subschema_for::<crate::apimachinery::pkg::apis::meta::v1::LabelSelector>().into_object();
383 schema_obj.metadata = Some(Box::new(crate::schemars::schema::Metadata {
384 description: Some("ObjectSelector decides whether to run the webhook based on if the object has matching labels. objectSelector is evaluated against both the oldObject and newObject that would be sent to the webhook, and is considered to match if either object matches the selector. A null object (oldObject in the case of create, or newObject in the case of delete) or an object that cannot have labels (like a DeploymentRollback or a PodProxyOptions object) is not considered to match. Use the object selector only if the webhook is opt-in, because end users may skip the admission webhook by setting the labels. Default to the empty LabelSelector, which matches everything.".to_owned()),
385 ..Default::default()
386 }));
387 crate::schemars::schema::Schema::Object(schema_obj)
388 },
389 ),
390 (
391 "rules".to_owned(),
392 crate::schemars::schema::Schema::Object(crate::schemars::schema::SchemaObject {
393 metadata: Some(Box::new(crate::schemars::schema::Metadata {
394 description: Some("Rules describes what operations on what resources/subresources the webhook cares about. The webhook cares about an operation if it matches _any_ Rule. However, in order to prevent ValidatingAdmissionWebhooks and MutatingAdmissionWebhooks from putting the cluster in a state which cannot be recovered from without completely disabling the plugin, ValidatingAdmissionWebhooks and MutatingAdmissionWebhooks are never called on admission requests for ValidatingWebhookConfiguration and MutatingWebhookConfiguration objects.".to_owned()),
395 ..Default::default()
396 })),
397 instance_type: Some(crate::schemars::schema::SingleOrVec::Single(Box::new(crate::schemars::schema::InstanceType::Array))),
398 array: Some(Box::new(crate::schemars::schema::ArrayValidation {
399 items: Some(crate::schemars::schema::SingleOrVec::Single(Box::new(__gen.subschema_for::<crate::api::admissionregistration::v1::RuleWithOperations>()))),
400 ..Default::default()
401 })),
402 ..Default::default()
403 }),
404 ),
405 (
406 "sideEffects".to_owned(),
407 crate::schemars::schema::Schema::Object(crate::schemars::schema::SchemaObject {
408 metadata: Some(Box::new(crate::schemars::schema::Metadata {
409 description: Some("SideEffects states whether this webhook has side effects. Acceptable values are: None, NoneOnDryRun (webhooks created via v1beta1 may also specify Some or Unknown). Webhooks with side effects MUST implement a reconciliation system, since a request may be rejected by a future step in the admission chain and the side effects therefore need to be undone. Requests with the dryRun attribute will be auto-rejected if they match a webhook with sideEffects == Unknown or Some.".to_owned()),
410 ..Default::default()
411 })),
412 instance_type: Some(crate::schemars::schema::SingleOrVec::Single(Box::new(crate::schemars::schema::InstanceType::String))),
413 ..Default::default()
414 }),
415 ),
416 (
417 "timeoutSeconds".to_owned(),
418 crate::schemars::schema::Schema::Object(crate::schemars::schema::SchemaObject {
419 metadata: Some(Box::new(crate::schemars::schema::Metadata {
420 description: Some("TimeoutSeconds specifies the timeout for this webhook. After the timeout passes, the webhook call will be ignored or the API call will fail based on the failure policy. The timeout value must be between 1 and 30 seconds. Default to 10 seconds.".to_owned()),
421 ..Default::default()
422 })),
423 instance_type: Some(crate::schemars::schema::SingleOrVec::Single(Box::new(crate::schemars::schema::InstanceType::Integer))),
424 format: Some("int32".to_owned()),
425 ..Default::default()
426 }),
427 ),
428 ].into(),
429 required: [
430 "admissionReviewVersions".to_owned(),
431 "clientConfig".to_owned(),
432 "name".to_owned(),
433 "sideEffects".to_owned(),
434 ].into(),
435 ..Default::default()
436 })),
437 ..Default::default()
438 })
439 }
440}