Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for passing the fieldValidation query parameter on patch #929

Merged
merged 7 commits into from
Jun 13, 2022
Merged
Show file tree
Hide file tree
Changes from 6 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
2 changes: 1 addition & 1 deletion kube-client/src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub use kube_core::{
Resource, ResourceExt,
};
pub use params::{
DeleteParams, ListParams, Patch, PatchParams, PostParams, Preconditions, PropagationPolicy,
DeleteParams, ListParams, Patch, PatchParams, PostParams, Preconditions, PropagationPolicy, ValidationDirective,
};

use crate::Client;
Expand Down
88 changes: 87 additions & 1 deletion kube-core/src/params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,39 @@ impl ListParams {
}
}

/// The validation directive to use for `fieldValidation` when using server-side apply.
#[derive(Clone, Debug)]
pub enum ValidationDirective {
phroggyy marked this conversation as resolved.
Show resolved Hide resolved
/// Strict mode will fail any invalid manifests.
///
/// This will fail the request with a BadRequest error if any unknown fields would be dropped from the
/// object, or if any duplicate fields are present. The error returned from the server will contain
/// all unknown and duplicate fields encountered.
clux marked this conversation as resolved.
Show resolved Hide resolved
Strict,
/// Warn mode will return a warning for invalid manifests.
///
/// This will send a warning via the standard warning response header for each unknown field that
/// is dropped from the object, and for each duplicate field that is encountered. The request will
/// still succeed if there are no other errors, and will only persist the last of any duplicate fields.
Warn,
/// Ignore mode will silently ignore any problems.
///
/// This will ignore any unknown fields that are silently dropped from the object, and will ignore
/// all but the last duplicate field that the decoder encounters.
Ignore,
clux marked this conversation as resolved.
Show resolved Hide resolved
}

impl ValidationDirective {
/// Returns the string format of the directive
pub fn as_str(self: &Self) -> &str {
match self {
Self::Strict => "Strict",
Self::Warn => "Warn",
Self::Ignore => "Ignore",
}
}
}

/// Common query parameters for put/post calls
#[derive(Default, Clone, Debug)]
pub struct PostParams {
Expand Down Expand Up @@ -270,6 +303,8 @@ pub struct PatchParams {
/// fieldManager is a name of the actor that is making changes. Required for [`Patch::Apply`]
/// optional for everything else.
pub field_manager: Option<String>,
/// The server-side validation directive to use. Applicable only to [`Patch::Apply`].
pub field_validation: Option<ValidationDirective>,
}

impl PatchParams {
Expand Down Expand Up @@ -301,6 +336,9 @@ impl PatchParams {
if let Some(ref fm) = self.field_manager {
qp.append_pair("fieldManager", fm);
}
if let Some(sv) = &self.field_validation {
qp.append_pair("fieldValidation", sv.as_str());
}
}

/// Construct `PatchParams` for server-side apply
Expand All @@ -327,6 +365,30 @@ impl PatchParams {
self.dry_run = true;
self
}

/// Set the validation directive for `fieldValidation` during server-side apply.
pub fn validation(mut self, vd: ValidationDirective) -> Self {
self.field_validation = Some(vd);
self
}

/// Set the validation directive to `Ignore`
#[must_use]
pub fn validation_ignore(self) -> Self {
self.validation(ValidationDirective::Ignore)
}

/// Set the validation directive to `Warn`
#[must_use]
pub fn validation_warn(self) -> Self {
self.validation(ValidationDirective::Warn)
}

/// Set the validation directive to `Strict`
#[must_use]
pub fn validation_strict(self) -> Self {
self.validation(ValidationDirective::Strict)
}
}

/// Common query parameters for delete calls
Expand Down Expand Up @@ -364,6 +426,7 @@ pub struct DeleteParams {

impl DeleteParams {
/// Construct `DeleteParams` with `PropagationPolicy::Background`.
///
/// This allows the garbage collector to delete the dependents in the background.
pub fn background() -> Self {
Self {
Expand All @@ -373,6 +436,7 @@ impl DeleteParams {
}

/// Construct `DeleteParams` with `PropagationPolicy::Foreground`.
///
/// This is a cascading policy that deletes all dependents in the foreground.
pub fn foreground() -> Self {
Self {
Expand All @@ -382,6 +446,7 @@ impl DeleteParams {
}

/// Construct `DeleteParams` with `PropagationPolicy::Orphan`.
///
/// This orpans the dependents.
pub fn orphan() -> Self {
Self {
Expand Down Expand Up @@ -435,7 +500,7 @@ where
}
#[cfg(test)]
mod test {
use super::DeleteParams;
use super::{DeleteParams, PatchParams, ValidationDirective};
#[test]
fn delete_param_serialize() {
let mut dp = DeleteParams::default();
Expand Down Expand Up @@ -463,6 +528,27 @@ mod test {
let ser = serde_json::to_value(&dp_orphan).unwrap();
assert_eq!(ser, serde_json::json!({"propagationPolicy": "Orphan"}));
}

#[test]
fn patch_param_serializes_field_validation() {
let pp = PatchParams::default().validation_ignore();
let mut qp = form_urlencoded::Serializer::new(String::from("some/resource?"));
pp.populate_qp(&mut qp);
let urlstr = qp.finish();
assert_eq!(String::from("some/resource?&fieldValidation=Ignore"), urlstr);

let pp = PatchParams::default().validation_warn();
let mut qp = form_urlencoded::Serializer::new(String::from("some/resource?"));
pp.populate_qp(&mut qp);
let urlstr = qp.finish();
assert_eq!(String::from("some/resource?&fieldValidation=Warn"), urlstr);

let pp = PatchParams::default().validation_strict();
let mut qp = form_urlencoded::Serializer::new(String::from("some/resource?"));
pp.populate_qp(&mut qp);
let urlstr = qp.finish();
assert_eq!(String::from("some/resource?&fieldValidation=Strict"), urlstr);
}
}

/// Preconditions must be fulfilled before an operation (update, delete, etc.) is carried out.
Expand Down