Skip to content

Commit

Permalink
Add relaxed mode for partially invalid CRDs (#215)
Browse files Browse the repository at this point in the history
Signed-off-by: Daniel Poelzleithner <[email protected]>
Signed-off-by: Eirik A <[email protected]>
Co-authored-by: Eirik A <[email protected]>
  • Loading branch information
poelzi and clux authored Apr 1, 2024
1 parent 96035d0 commit d5d6864
Show file tree
Hide file tree
Showing 4 changed files with 19,181 additions and 2 deletions.
5 changes: 5 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ test-argo:
kubectl apply -f tests/app.yaml
cargo test --test runner -- --nocapture

test-argo-wf:
# argo workflows are hard to test since the full crd are not supposed to be installed in k8s
! cargo run --bin kopium -- --filename tests/argoproj.io_clusterworkflowtemplates.yaml > /dev/null
cargo run --bin kopium -- --relaxed --filename tests/argoproj.io_clusterworkflowtemplates.yaml > /dev/null

test-certmanager:
kubectl apply --force-conflicts --server-side -f https://github.com/jetstack/cert-manager/releases/download/v1.7.1/cert-manager.crds.yaml
cargo run --bin kopium -- -d certificates.cert-manager.io > tests/gen.rs
Expand Down
18 changes: 16 additions & 2 deletions src/analyzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const IGNORED_KEYS: [&str; 3] = ["metadata", "apiVersion", "kind"];
#[derive(Default)]
pub struct Config {
pub no_condition: bool,
pub relaxed: bool,
}

/// Scan a schema for structs and members, and recurse to find all structs
Expand Down Expand Up @@ -270,7 +271,7 @@ fn extract_container(
"integer" => extract_integer_type(value)?,
"array" => {
// recurse through repeated arrays until we find a concrete type (keep track of how deep we went)
let (mut array_type, recurse_level) = array_recurse_for_type(value, stack, key, 1)?;
let (mut array_type, recurse_level) = array_recurse_for_type(value, stack, key, 1, cfg)?;
trace!("got array {} for {} in level {}", array_type, key, recurse_level);
if !cfg.no_condition && key == "conditions" && is_conditions(value) {
array_type = "Vec<Condition>".into();
Expand All @@ -284,6 +285,9 @@ fn extract_container(
"IntOrString".into()
} else if value.x_kubernetes_preserve_unknown_fields == Some(true) {
"HashMap<String, serde_json::Value>".into()
} else if cfg.relaxed {
debug!("found empty object at {} key: {}", stack, key);
"HashMap<String, serde_json::Value>".into()
} else {
bail!("unknown empty dict type for {}", key)
}
Expand Down Expand Up @@ -405,6 +409,7 @@ fn array_recurse_for_type(
stack: &str,
key: &str,
level: u8,
cfg: &Config,
) -> Result<(String, u8)> {
if let Some(items) = &value.items {
match items {
Expand Down Expand Up @@ -435,7 +440,16 @@ fn array_recurse_for_type(
"date" => Ok((format!("Vec<{}>", extract_date_type(value)?), level)),
"number" => Ok((format!("Vec<{}>", extract_number_type(value)?), level)),
"integer" => Ok((format!("Vec<{}>", extract_integer_type(value)?), level)),
"array" => Ok(array_recurse_for_type(s, stack, key, level + 1)?),
"array" => {
if s.items.is_some() {
Ok(array_recurse_for_type(s, stack, key, level + 1, cfg)?)
} else if cfg.relaxed {
warn!("Empty inner array in: {} key: {}", stack, key);
Ok(("BTreeMap<String, serde_json::Value>".into(), level))
} else {
bail!("Empty inner array in: {} key: {}", stack, key);
}
},
unknown => {
bail!("unsupported recursive array type \"{unknown}\" for {key}")
}
Expand Down
8 changes: 8 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,13 @@ struct Kopium {
#[arg(long, short = 'e')]
elide: Vec<String>,

/// Relaxed interpretation
///
/// This allows certain invalid openapi specs to be interpreted as arbitrary objects as used by argo workflows for example.
/// the output first.
#[arg(long)]
relaxed: bool,

/// Enable generation of custom Condition APIs.
///
/// If false, it detects if a particular path is an array of Condition objects and uses a standard
Expand Down Expand Up @@ -192,6 +199,7 @@ impl Kopium {
log::debug!("schema: {}", serde_json::to_string_pretty(&schema)?);
let cfg = Config {
no_condition: self.no_condition,
relaxed: self.relaxed,
};
let structs = analyze(schema, kind, cfg)?
.rename()
Expand Down
Loading

0 comments on commit d5d6864

Please sign in to comment.