Documentation
¶
Overview ¶
Package errors provides structured error types and handling utilities for the Kure library and kurel tool.
Overview ¶
This package extends Go's standard error handling with domain-specific error types that provide structured information for Kubernetes resource validation, file operations, and configuration errors.
Error Types ¶
The package provides several specialized error constructors:
- ResourceValidationError: Validation failures for Kubernetes resources
- FileError: File operation failures (read, write, parse)
- ValidationError: General validation failures with field details
- ConfigError: Configuration-related errors
Predefined Errors ¶
A small set of sentinels is predefined, one for each error kure code actually returns; a sentinel no kure code returns is removed, not kept:
// Nil resource checks errors.ErrNilPodSpec errors.ErrNilContainer errors.ErrNilBundle errors.ErrNilObject errors.ErrNilRuntimeObject // GVK and kind errors errors.ErrGVKNotFound errors.ErrGVKNotAllowed errors.ErrUnsupportedKind
Error Wrapping ¶
The package provides wrappers compatible with Go's error unwrapping:
// Wrap with message
err := errors.Wrap(originalErr, "failed to load config")
// Wrap with formatted message
err := errors.Wrapf(originalErr, "failed to process %s", filename)
// Check wrapped errors with the standard library's errors.Is; this
// package does not re-export it, so import the two under distinct names
// (stderrors "errors", kerrors "github.com/go-kure/kure/pkg/errors")
if stderrors.Is(err, kerrors.ErrNilPodSpec) {
// handle nil pod spec
}
Resource Validation Errors ¶
Resource validation errors include structured fields:
err := errors.ResourceValidationError(
"Deployment", // resourceType
"my-app", // name
"spec.replicas", // field
"must be positive", // reason
originalErr, // cause (optional)
)
These errors can be introspected for automated handling:
var resErr *kerrors.ResourceError
if stderrors.As(err, &resErr) {
fmt.Printf("Resource: %s/%s\n", resErr.ResourceType, resErr.Name)
}
File Errors ¶
File operation errors include the operation type and path:
err := errors.NewFileError("read", "/path/to/file", "permission denied", nil)
Integration ¶
All error types implement the standard error interface and support Go 1.13+ error wrapping with errors.Is and errors.As.
Example (Sentinel) ¶
package main
import (
stderrors "errors"
"fmt"
kerrors "github.com/go-kure/kure/pkg/errors"
"github.com/go-kure/kure/pkg/kubernetes"
)
func main() {
// A PSA validator given no pod spec returns the ErrNilPodSpec sentinel.
err := kubernetes.ValidatePodSpecPSA(nil, kubernetes.PSARestricted)
if stderrors.Is(err, kerrors.ErrNilPodSpec) {
// handle nil pod spec
fmt.Println("nil pod spec:", err)
}
}
Output: nil pod spec: validation failed for PodSpec '' field 'spec': pod spec cannot be nil
Index ¶
- Variables
- func Errorf(format string, args ...any) error
- func IsKureError(err error) bool
- func IsType(err error, errType ErrorType) bool
- func New(message string) error
- func Wrap(err error, message string) error
- func Wrapf(err error, format string, args ...any) error
- type BaseError
- type ConfigError
- type ErrorType
- type FileError
- type KureError
- type PSAViolationError
- type ParseError
- type ParseErrors
- type PatchError
- type ResourceError
- type ValidationError
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( ErrGVKNotFound = errors.New("could not determine GroupVersionKind") ErrGVKNotAllowed = errors.New("GroupVersionKind is not allowed") ErrNilObject = errors.New("provided object is nil") )
Standard error variables using the standard library
var ( ErrNilPodSpec = ResourceValidationError("PodSpec", "", "spec", "pod spec cannot be nil", nil) ErrNilContainer = ResourceValidationError("Container", "", "container", "container cannot be nil", nil) ErrNilBundle = ResourceValidationError("Bundle", "", "bundle", "bundle cannot be nil", nil) )
Resource validation errors still returned by kure: the PSA validators in pkg/kubernetes and the stack's bundle checks. Sentinels no kure code returns are removed rather than kept exported; TestExportedSentinelsHaveProducers enforces that (go-kure/kure#758).
var ( ErrNilRuntimeObject = errors.New("nil runtime object provided") ErrUnsupportedKind = errors.New("unsupported object kind") )
Common parse/processing errors
Functions ¶
func Errorf ¶
Errorf creates a new formatted error using Go's standard error formatting.
Example ¶
package main
import (
"fmt"
"github.com/go-kure/kure/pkg/errors"
)
func main() {
// Simple error
simple := errors.New("invalid configuration")
// Formatted error
formatted := errors.Errorf("unknown generator: %s", "AppWorkload")
fmt.Println(simple)
fmt.Println(formatted)
}
Output: invalid configuration unknown generator: AppWorkload
func IsKureError ¶
IsKureError checks if an error is a Kure-specific error
Example ¶
package main
import (
"fmt"
"github.com/go-kure/kure/pkg/errors"
)
func main() {
err := errors.Wrap(
errors.NewValidationError("replicas", "-1", "Deployment", []string{"1", "3"}),
"load cluster config",
)
// Check if error is a Kure error
if errors.IsKureError(err) {
kErr := errors.GetKureError(err)
fmt.Println(kErr.Type())
fmt.Println(kErr.Suggestion())
}
// Check specific error type
if errors.IsType(err, errors.ErrorTypeValidation) {
// Handle validation error
fmt.Println("validation error:", err)
}
}
Output: validation Valid values are: 1, 3 validation error: load cluster config: invalid replicas for Deployment: -1
func Wrap ¶
Wrap wraps an error with a message using Go's standard error wrapping.
Example ¶
package main
import (
"fmt"
"github.com/go-kure/kure/pkg/errors"
)
func main() {
err := errors.New("connection refused")
// Wrap with context
wrapped := errors.Wrap(err, "failed to load cluster config")
// Wrap with formatted message
formatted := errors.Wrapf(err, "failed to fetch %s/%s", "Deployment", "my-app")
fmt.Println(wrapped)
fmt.Println(formatted)
}
Output: failed to load cluster config: connection refused failed to fetch Deployment/my-app: connection refused
Types ¶
type BaseError ¶
type BaseError struct {
ErrType ErrorType `json:"type"`
Message string `json:"message"`
Cause error `json:"cause,omitempty"`
ErrContext map[string]any `json:"context,omitempty"`
Help string `json:"suggestion,omitempty"`
}
BaseError provides common functionality for all Kure errors
func (*BaseError) Suggestion ¶
type ConfigError ¶
type ConfigError struct {
*BaseError
Source string `json:"source"`
Field string `json:"field"`
ValidValues []string `json:"validValues,omitempty"`
}
ConfigError represents configuration errors
func NewConfigError ¶
func NewConfigError(source, field, value, reason string, validValues []string) *ConfigError
type ErrorType ¶
type ErrorType string
ErrorType represents the category of error
const ( ErrorTypeValidation ErrorType = "validation" ErrorTypeResource ErrorType = "resource" ErrorTypePatch ErrorType = "patch" ErrorTypeParse ErrorType = "parse" ErrorTypeFile ErrorType = "file" ErrorTypeConfiguration ErrorType = "configuration" ErrorTypeInternal ErrorType = "internal" ErrorTypePSA ErrorType = "psa" )
type KureError ¶
KureError is the base interface for all Kure-specific errors
func GetKureError ¶
GetKureError extracts a KureError from an error chain
type PSAViolationError ¶
type PSAViolationError struct {
*BaseError
Field string `json:"field"` // path relative to PodSpec
Level string `json:"level"` // "baseline" or "restricted"
}
PSAViolationError represents a Pod Security Standards violation with field path information.
func NewPSAViolationError ¶
func NewPSAViolationError(field, level, message string) *PSAViolationError
type ParseError ¶
type ParseError struct {
*BaseError
Source string `json:"source"`
Line int `json:"line,omitempty"`
Column int `json:"column,omitempty"`
}
ParseError represents parsing errors with location information
func NewParseError ¶
func NewParseError(source, reason string, line, column int, cause error) *ParseError
type ParseErrors ¶
type ParseErrors struct {
Errors []error
}
ParseErrors aggregates multiple errors returned during YAML decoding. It implements the error interface and unwraps to the underlying errors.
func (*ParseErrors) Error ¶
func (pe *ParseErrors) Error() string
func (*ParseErrors) Unwrap ¶
func (pe *ParseErrors) Unwrap() []error
type PatchError ¶
type PatchError struct {
*BaseError
Operation string `json:"operation"`
Path string `json:"path"`
ResourceName string `json:"resourceName"`
}
PatchError represents patch-specific errors
func NewPatchError ¶
func NewPatchError(operation, path, resourceName, reason string, cause error) *PatchError
type ResourceError ¶
type ResourceError struct {
*BaseError
ResourceType string `json:"resourceType"`
Name string `json:"name"`
Namespace string `json:"namespace,omitempty"`
Available []string `json:"available,omitempty"`
}
ResourceError represents resource-related errors
func ResourceNotFoundError ¶
func ResourceNotFoundError(resourceType, name, namespace string, available []string) *ResourceError
func ResourceValidationError ¶
func ResourceValidationError(resourceType, name, field, reason string, cause error) *ResourceError
type ValidationError ¶
type ValidationError struct {
*BaseError
Field string `json:"field"`
Value string `json:"value"`
ValidValues []string `json:"validValues,omitempty"`
Component string `json:"component"`
}
ValidationError represents validation failures with suggestions
func NewValidationError ¶
func NewValidationError(field, value, component string, validValues []string) *ValidationError
Example ¶
package main
import (
"fmt"
"github.com/go-kure/kure/pkg/errors"
)
func main() {
originalErr := errors.New("original cause")
// Validation error with suggestion
validation := errors.NewValidationError(
"replicas", // field
"-1", // value
"Deployment", // component
[]string{"1", "3"}, // valid values
)
// Resource not found
notFound := errors.ResourceNotFoundError(
"Deployment", // resource type
"my-app", // name
"default", // namespace
[]string{"web-app", "api-app"}, // available resources
)
// Patch error
patch := errors.NewPatchError(
"set", // operation
"spec.replicas", // path
"my-deployment", // resource name
"field not found", // reason
originalErr, // cause
)
// Parse error with location
parse := errors.NewParseError(
"config.yaml", // source file
"invalid YAML", // reason
42, // line
10, // column
originalErr, // cause
)
// File error
file := errors.NewFileError("read", "/path/to/file", "permission denied", originalErr)
// Configuration error
config := errors.NewConfigError(
"mise.toml", // source
"go", // field
"1.21", // value
"version too old", // reason
[]string{"1.23", "1.24"}, // valid values
)
for _, err := range []error{validation, notFound, patch, parse, file, config} {
fmt.Println(err)
}
}
Output: invalid replicas for Deployment: -1 Deployment 'my-app' not found in namespace 'default' patch operation 'set' failed on resource 'my-deployment' at path 'spec.replicas': field not found: original cause parse error in config.yaml at line 42, column 10: invalid YAML: original cause file read failed for '/path/to/file': permission denied: original cause configuration error in mise.toml for field 'go' with value '1.21': version too old