helm-schema-k8s 0.0.4

Generate an accurate JSON schema for any helm chart
Documentation
use helm_schema_core::{CapabilityOracle, ResourceRef, live_literals};

use crate::ordered_api_versions_for_resource;

pub(crate) fn resource_lookup_candidates<O: CapabilityOracle + ?Sized>(
    resource: &ResourceRef,
    oracle: &O,
) -> Vec<ResourceRef> {
    let api_versions = candidate_api_versions(resource, oracle);
    resource_candidates_with_api_versions(resource, api_versions)
}

pub(crate) fn missing_schema_attribution_candidates<O: CapabilityOracle + ?Sized>(
    resource: &ResourceRef,
    oracle: &O,
) -> Vec<ResourceRef> {
    let api_versions = missing_schema_attribution_api_versions(resource, oracle);
    resource_candidates_with_api_versions(resource, api_versions)
}

fn candidate_api_versions<O: CapabilityOracle + ?Sized>(
    resource: &ResourceRef,
    oracle: &O,
) -> Vec<String> {
    if !resource.api_version_branches.is_empty() {
        let live = live_literals(&resource.api_version_branches, oracle);
        if !live.is_empty() {
            return live;
        }
    }

    ordered_api_versions_for_resource(resource)
        .into_iter()
        .map(str::to_string)
        .collect()
}

fn missing_schema_attribution_api_versions<O: CapabilityOracle + ?Sized>(
    resource: &ResourceRef,
    oracle: &O,
) -> Vec<String> {
    if !resource.api_version_branches.is_empty() {
        let live = live_literals(&resource.api_version_branches, oracle);
        return match live.first().cloned() {
            Some(api_version) => vec![api_version],
            None if resource.api_version.is_empty()
                && !resource.api_version_candidates.is_empty() =>
            {
                resource.api_version_candidates.clone()
            }
            None => vec![resource.api_version.clone()],
        };
    }

    if resource.api_version.is_empty() && !resource.api_version_candidates.is_empty() {
        return resource.api_version_candidates.clone();
    }

    vec![resource.api_version.clone()]
}

fn resource_candidates_with_api_versions(
    resource: &ResourceRef,
    api_versions: Vec<String>,
) -> Vec<ResourceRef> {
    let mut kinds = vec![resource.kind.clone()];
    for kind in &resource.kind_candidates {
        if !kind.is_empty() && !kinds.contains(kind) {
            kinds.push(kind.clone());
        }
    }
    api_versions
        .into_iter()
        .flat_map(|api_version| {
            kinds
                .iter()
                .cloned()
                .map(move |kind| ResourceRef::concrete(api_version.clone(), kind))
        })
        .collect()
}

#[cfg(test)]
#[path = "tests/resource_lookup_plan.rs"]
mod tests;