Skip to content

Validation

Optional manifest validation utilities.

Usage

from k8smith.validation import validate_manifest, ValidationMode

result = validate_manifest(
    manifest,
    structural=ValidationMode.STRICT,
    cross_reference=ValidationMode.CHECK,
    best_practice=ValidationMode.NONE,
)

if result.errors:
    print("Errors:", result.errors)
if result.warnings:
    print("Warnings:", result.warnings)

Validation Modes

ValidationMode

Bases: Enum

Validation mode controlling how issues are reported.

Attributes:

Name Type Description
NONE

Silent - no warnings or errors raised

CHECK

Emit warnings for issues but don't raise exceptions

STRICT

Raise exception containing all detected issues

Source code in src/k8smith/validation/core.py
class ValidationMode(Enum):
    """Validation mode controlling how issues are reported.

    Attributes:
        NONE: Silent - no warnings or errors raised
        CHECK: Emit warnings for issues but don't raise exceptions
        STRICT: Raise exception containing all detected issues
    """

    NONE = "none"
    CHECK = "check"
    STRICT = "strict"

Functions

validate_manifest(manifest, *, structural=ValidationMode.STRICT, cross_reference=ValidationMode.NONE, best_practice=ValidationMode.NONE)

Validate a Kubernetes manifest.

Parameters:

Name Type Description Default
manifest dict[str, Any]

The Kubernetes resource dict to validate

required
structural ValidationMode

Mode for structural validation (required fields, valid combinations)

STRICT
cross_reference ValidationMode

Mode for cross-reference validation (volumes, ports, selectors)

NONE
best_practice ValidationMode

Mode for best practices validation (resources, probes)

NONE

Returns:

Type Description
ValidationResult

ValidationResult containing all issues found

Raises:

Type Description
ValidationError

In strict mode, if any issues are found in that category

Example

manifest = build_deployment(spec) result = validate_manifest( ... manifest, ... structural=ValidationMode.STRICT, ... cross_reference=ValidationMode.CHECK, ... best_practice=ValidationMode.NONE, ... )

Source code in src/k8smith/validation/validators.py
def validate_manifest(
    manifest: dict[str, Any],
    *,
    structural: ValidationMode = ValidationMode.STRICT,
    cross_reference: ValidationMode = ValidationMode.NONE,
    best_practice: ValidationMode = ValidationMode.NONE,
) -> ValidationResult:
    """Validate a Kubernetes manifest.

    Args:
        manifest: The Kubernetes resource dict to validate
        structural: Mode for structural validation (required fields, valid combinations)
        cross_reference: Mode for cross-reference validation (volumes, ports, selectors)
        best_practice: Mode for best practices validation (resources, probes)

    Returns:
        ValidationResult containing all issues found

    Raises:
        ValidationError: In strict mode, if any issues are found in that category

    Example:
        >>> manifest = build_deployment(spec)
        >>> result = validate_manifest(
        ...     manifest,
        ...     structural=ValidationMode.STRICT,
        ...     cross_reference=ValidationMode.CHECK,
        ...     best_practice=ValidationMode.NONE,
        ... )
    """
    result = ValidationResult()

    # Run validators based on mode
    if structural != ValidationMode.NONE:
        _validate_structural(manifest, result)
        _handle_mode(result, structural, "structural")

    if cross_reference != ValidationMode.NONE:
        _validate_cross_reference(manifest, result)
        _handle_mode(result, cross_reference, "cross_reference")

    if best_practice != ValidationMode.NONE:
        _validate_best_practice(manifest, result)
        _handle_mode(result, best_practice, "best_practice")

    return result

Result Types

ValidationResult dataclass

Collection of validation issues from a validation run.

Supports iteration and boolean checks

if result: # True if there are issues for issue in result: print(issue)

Source code in src/k8smith/validation/core.py
@dataclass
class ValidationResult:
    """Collection of validation issues from a validation run.

    Supports iteration and boolean checks:
        if result:  # True if there are issues
            for issue in result:
                print(issue)
    """

    issues: list[ValidationIssue] = field(default_factory=list)

    def add(
        self,
        path: str,
        message: str,
        severity: ValidationSeverity,
        category: Literal["structural", "cross_reference", "best_practice"],
    ) -> None:
        """Add a validation issue."""
        self.issues.append(ValidationIssue(path, message, severity, category))

    def error(
        self,
        path: str,
        message: str,
        category: Literal["structural", "cross_reference", "best_practice"],
    ) -> None:
        """Add an error-level issue."""
        self.add(path, message, ValidationSeverity.ERROR, category)

    def warning(
        self,
        path: str,
        message: str,
        category: Literal["structural", "cross_reference", "best_practice"],
    ) -> None:
        """Add a warning-level issue."""
        self.add(path, message, ValidationSeverity.WARNING, category)

    @property
    def errors(self) -> list[ValidationIssue]:
        """Get only error-level issues."""
        return [i for i in self.issues if i.severity == ValidationSeverity.ERROR]

    @property
    def warnings(self) -> list[ValidationIssue]:
        """Get only warning-level issues."""
        return [i for i in self.issues if i.severity == ValidationSeverity.WARNING]

    def __bool__(self) -> bool:
        """True if there are any issues."""
        return len(self.issues) > 0

    def __iter__(self) -> Iterator[ValidationIssue]:
        return iter(self.issues)

    def __len__(self) -> int:
        return len(self.issues)

    def merge(self, other: ValidationResult) -> None:
        """Merge issues from another result into this one."""
        self.issues.extend(other.issues)

errors property

Get only error-level issues.

warnings property

Get only warning-level issues.

add(path, message, severity, category)

Add a validation issue.

Source code in src/k8smith/validation/core.py
def add(
    self,
    path: str,
    message: str,
    severity: ValidationSeverity,
    category: Literal["structural", "cross_reference", "best_practice"],
) -> None:
    """Add a validation issue."""
    self.issues.append(ValidationIssue(path, message, severity, category))

error(path, message, category)

Add an error-level issue.

Source code in src/k8smith/validation/core.py
def error(
    self,
    path: str,
    message: str,
    category: Literal["structural", "cross_reference", "best_practice"],
) -> None:
    """Add an error-level issue."""
    self.add(path, message, ValidationSeverity.ERROR, category)

warning(path, message, category)

Add a warning-level issue.

Source code in src/k8smith/validation/core.py
def warning(
    self,
    path: str,
    message: str,
    category: Literal["structural", "cross_reference", "best_practice"],
) -> None:
    """Add a warning-level issue."""
    self.add(path, message, ValidationSeverity.WARNING, category)

__bool__()

True if there are any issues.

Source code in src/k8smith/validation/core.py
def __bool__(self) -> bool:
    """True if there are any issues."""
    return len(self.issues) > 0

merge(other)

Merge issues from another result into this one.

Source code in src/k8smith/validation/core.py
def merge(self, other: ValidationResult) -> None:
    """Merge issues from another result into this one."""
    self.issues.extend(other.issues)

ValidationIssue dataclass

A single validation issue found in a manifest.

Attributes:

Name Type Description
path str

JSON path to the problematic field (e.g., "spec.template.spec.containers[0]")

message str

Human-readable description of the issue

severity ValidationSeverity

Whether this is an error or warning

category Literal['structural', 'cross_reference', 'best_practice']

Type of validation that caught this (structural, cross_reference, best_practice)

Source code in src/k8smith/validation/core.py
@dataclass
class ValidationIssue:
    """A single validation issue found in a manifest.

    Attributes:
        path: JSON path to the problematic field (e.g., "spec.template.spec.containers[0]")
        message: Human-readable description of the issue
        severity: Whether this is an error or warning
        category: Type of validation that caught this (structural, cross_reference, best_practice)
    """

    path: str
    message: str
    severity: ValidationSeverity
    category: Literal["structural", "cross_reference", "best_practice"]

    def __str__(self) -> str:
        prefix = "ERROR" if self.severity == ValidationSeverity.ERROR else "WARNING"
        return f"[{prefix}] {self.path}: {self.message}"