Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
77 changes: 42 additions & 35 deletions internal/config/validation_errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,37 +35,44 @@ func (e *ValidationError) Error() string {
return sb.String()
}

// newValidationError logs logMsg and returns a ValidationError with the given fields.
// It centralises the repeated log+return pattern used by error constructor functions.
func newValidationError(logMsg, field, message, jsonPath, suggestion string) *ValidationError {
logValidation.Print(logMsg)
return &ValidationError{Field: field, Message: message, JSONPath: jsonPath, Suggestion: suggestion}
}

// UnsupportedType creates a ValidationError for unsupported type values
func UnsupportedType(fieldName, actualType, jsonPath, suggestion string) *ValidationError {
logValidation.Printf("Validation error: unsupported type at %s.%s, type=%s", jsonPath, fieldName, actualType)
return &ValidationError{
Field: fieldName,
Message: fmt.Sprintf("unsupported server type '%s'", actualType),
JSONPath: fmt.Sprintf("%s.%s", jsonPath, fieldName),
Suggestion: suggestion,
}
return newValidationError(
fmt.Sprintf("Validation error: unsupported type at %s.%s, type=%s", jsonPath, fieldName, actualType),
fieldName,
fmt.Sprintf("unsupported server type '%s'", actualType),
fmt.Sprintf("%s.%s", jsonPath, fieldName),
suggestion,
)
}

// UndefinedVariable creates a ValidationError for undefined environment variables
func UndefinedVariable(varName, jsonPath string) *ValidationError {
logValidation.Printf("Validation error: undefined environment variable at %s, var=%s", jsonPath, varName)
return &ValidationError{
Field: "env variable",
Message: fmt.Sprintf("undefined environment variable referenced: %s", varName),
JSONPath: jsonPath,
Suggestion: fmt.Sprintf("Set the environment variable %s before starting the gateway", varName),
}
return newValidationError(
fmt.Sprintf("Validation error: undefined environment variable at %s, var=%s", jsonPath, varName),
"env variable",
fmt.Sprintf("undefined environment variable referenced: %s", varName),
jsonPath,
fmt.Sprintf("Set the environment variable %s before starting the gateway", varName),
)
}

// MissingRequired creates a ValidationError for missing required fields
func MissingRequired(fieldName, serverType, jsonPath, suggestion string) *ValidationError {
logValidation.Printf("Validation error: missing required field at %s, field=%s, serverType=%s", jsonPath, fieldName, serverType)
return &ValidationError{
Field: fieldName,
Message: fmt.Sprintf("'%s' is required for %s servers", fieldName, serverType),
JSONPath: jsonPath,
Suggestion: suggestion,
}
return newValidationError(
fmt.Sprintf("Validation error: missing required field at %s, field=%s, serverType=%s", jsonPath, fieldName, serverType),
fieldName,
fmt.Sprintf("'%s' is required for %s servers", fieldName, serverType),
jsonPath,
suggestion,
)
}

// UnsupportedField creates a ValidationError for unsupported or unrecognized fields.
Expand All @@ -86,13 +93,13 @@ func AppendConfigDocsFooter(sb *strings.Builder) {
// InvalidPattern creates a ValidationError for values that don't match a required pattern.
// Used by validation_schema.go for container, mount, URL, and other pattern validations.
func InvalidPattern(fieldName, value, jsonPath, suggestion string) *ValidationError {
logValidation.Printf("Validation error: invalid pattern at %s, field=%s, value=%q", jsonPath, fieldName, value)
return &ValidationError{
Field: fieldName,
Message: fmt.Sprintf("%s '%s' does not match required pattern", fieldName, value),
JSONPath: jsonPath,
Suggestion: suggestion,
}
return newValidationError(
fmt.Sprintf("Validation error: invalid pattern at %s, field=%s, value=%q", jsonPath, fieldName, value),
fieldName,
fmt.Sprintf("%s '%s' does not match required pattern", fieldName, value),
jsonPath,
suggestion,
)
}

// InvalidValue creates a ValidationError for field values that violate a constraint.
Expand All @@ -109,11 +116,11 @@ func InvalidValue(fieldName, message, jsonPath, suggestion string) *ValidationEr
// SchemaValidationError creates a ValidationError for custom schema validation failures.
// Used by validation.go for the various stages of custom schema fetching, parsing, and validation.
func SchemaValidationError(serverType, message, jsonPath, suggestion string) *ValidationError {
logValidation.Printf("Validation error: schema validation failure at %s, serverType=%s, message=%q", jsonPath, serverType, message)
return &ValidationError{
Field: "type",
Message: fmt.Sprintf("%s for server type '%s'", message, serverType),
JSONPath: jsonPath,
Suggestion: suggestion,
}
return newValidationError(
fmt.Sprintf("Validation error: schema validation failure at %s, serverType=%s, message=%q", jsonPath, serverType, message),
"type",
fmt.Sprintf("%s for server type '%s'", message, serverType),
jsonPath,
suggestion,
)
}
84 changes: 42 additions & 42 deletions internal/config/validation_rules.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ var (
func PortRange(port int, jsonPath string) *ValidationError {
logValidation.Printf("Validating port range: port=%d, jsonPath=%s", port, jsonPath)
if port < 1 || port > 65535 {
logValidation.Printf("Port validation failed: port=%d out of range", port)
return &ValidationError{
Field: "port",
Message: fmt.Sprintf("port must be between 1 and 65535, got %d", port),
JSONPath: jsonPath,
Suggestion: "Use a valid port number (e.g., 8080)",
}
return newValidationError(
fmt.Sprintf("Port validation failed: port=%d out of range", port),
"port",
fmt.Sprintf("port must be between 1 and 65535, got %d", port),
jsonPath,
"Use a valid port number (e.g., 8080)",
)
}
return nil
}
Expand All @@ -49,13 +49,13 @@ func TimeoutPositive(timeout int, fieldName, jsonPath string) *ValidationError {
func PositiveInteger(value int, fieldName, jsonPath string) *ValidationError {
logValidation.Printf("Validating positive integer: field=%s, value=%d, jsonPath=%s", fieldName, value, jsonPath)
if value < 1 {
logValidation.Printf("Positive integer validation failed: %s=%d is not positive", fieldName, value)
return &ValidationError{
Field: fieldName,
Message: fmt.Sprintf("%s must be a positive integer (>= 1), got %d", fieldName, value),
JSONPath: jsonPath,
Suggestion: fmt.Sprintf("Use a positive integer (>= 1) for %s", fieldName),
}
return newValidationError(
fmt.Sprintf("Positive integer validation failed: %s=%d is not positive", fieldName, value),
fieldName,
fmt.Sprintf("%s must be a positive integer (>= 1), got %d", fieldName, value),
jsonPath,
fmt.Sprintf("Use a positive integer (>= 1) for %s", fieldName),
)
}
return nil
}
Expand All @@ -65,13 +65,13 @@ func PositiveInteger(value int, fieldName, jsonPath string) *ValidationError {
func TimeoutMinimum(timeout, min int, fieldName, jsonPath string) *ValidationError {
logValidation.Printf("Validating timeout minimum: field=%s, value=%d, min=%d, jsonPath=%s", fieldName, timeout, min, jsonPath)
if timeout < min {
logValidation.Printf("Timeout minimum validation failed: %s=%d is below minimum %d", fieldName, timeout, min)
return &ValidationError{
Field: fieldName,
Message: fmt.Sprintf("%s must be at least %d, got %d", fieldName, min, timeout),
JSONPath: jsonPath,
Suggestion: fmt.Sprintf("Use a value of at least %d seconds", min),
}
return newValidationError(
fmt.Sprintf("Timeout minimum validation failed: %s=%d is below minimum %d", fieldName, timeout, min),
fieldName,
fmt.Sprintf("%s must be at least %d, got %d", fieldName, min, timeout),
jsonPath,
fmt.Sprintf("Use a value of at least %d seconds", min),
)
}
return nil
}
Expand All @@ -81,14 +81,14 @@ func TimeoutMinimum(timeout, min int, fieldName, jsonPath string) *ValidationErr
func TimeoutRange(timeout, min, max int, fieldName, jsonPath string) *ValidationError {
logValidation.Printf("Validating timeout range: field=%s, value=%d, min=%d, max=%d, jsonPath=%s", fieldName, timeout, min, max, jsonPath)
if timeout < min || timeout > max {
logValidation.Printf("Timeout range validation failed: %s=%d is outside [%d, %d]", fieldName, timeout, min, max)
suggestedTimeout := min + (max-min)/2
return &ValidationError{
Field: fieldName,
Message: fmt.Sprintf("%s must be between %d and %d, got %d", fieldName, min, max, timeout),
JSONPath: jsonPath,
Suggestion: fmt.Sprintf("Use a value between %d and %d seconds (e.g., %d)", min, max, suggestedTimeout),
}
return newValidationError(
fmt.Sprintf("Timeout range validation failed: %s=%d is outside [%d, %d]", fieldName, timeout, min, max),
fieldName,
fmt.Sprintf("%s must be between %d and %d, got %d", fieldName, min, max, timeout),
jsonPath,
fmt.Sprintf("Use a value between %d and %d seconds (e.g., %d)", min, max, suggestedTimeout),
)
}
return nil
}
Expand Down Expand Up @@ -204,13 +204,13 @@ func NonEmptyString(value, fieldName, jsonPath string) *ValidationError {
func AbsolutePath(value, fieldName, jsonPath string) *ValidationError {
logValidation.Printf("Validating absolute path: field=%s, value=%s, jsonPath=%s", fieldName, value, jsonPath)
if value == "" {
logValidation.Printf("Absolute path validation failed: %s is empty", fieldName)
return &ValidationError{
Field: fieldName,
Message: fmt.Sprintf("%s cannot be empty", fieldName),
JSONPath: jsonPath,
Suggestion: fmt.Sprintf("Provide an absolute path for %s", fieldName),
}
return newValidationError(
fmt.Sprintf("Absolute path validation failed: %s is empty", fieldName),
fieldName,
fmt.Sprintf("%s cannot be empty", fieldName),
jsonPath,
fmt.Sprintf("Provide an absolute path for %s", fieldName),
)
}

// Check for Unix absolute path (starts with /)
Expand All @@ -228,11 +228,11 @@ func AbsolutePath(value, fieldName, jsonPath string) *ValidationError {
return nil
}

logValidation.Printf("Absolute path validation failed: %s=%s is not absolute", fieldName, value)
return &ValidationError{
Field: fieldName,
Message: fmt.Sprintf("%s must be an absolute path, got '%s'", fieldName, value),
JSONPath: jsonPath,
Suggestion: "Use an absolute path: Unix paths start with '/' (e.g., '/tmp/payloads'), Windows paths start with a drive letter (e.g., 'C:\\payloads')",
}
return newValidationError(
fmt.Sprintf("Absolute path validation failed: %s=%s is not absolute", fieldName, value),
fieldName,
fmt.Sprintf("%s must be an absolute path, got '%s'", fieldName, value),
jsonPath,
"Use an absolute path: Unix paths start with '/' (e.g., '/tmp/payloads'), Windows paths start with a drive letter (e.g., 'C:\\payloads')",
)
}
Loading