- Added lock file exclusions for pnpm in .gitignore. - Removed obsolete package-lock.json from the api and portal directories. - Enhanced Cloudflare adapter with additional interfaces for zones and tunnels. - Improved Proxmox adapter error handling and logging for API requests. - Updated Proxmox VM parameters with validation rules in the API schema. - Enhanced documentation for Proxmox VM specifications and examples.
253 lines
6.0 KiB
Go
253 lines
6.0 KiB
Go
package virtualmachine
|
|
|
|
import "testing"
|
|
|
|
func TestCategorizeError(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
errorStr string
|
|
wantType string
|
|
wantReason string
|
|
}{
|
|
// API not supported errors
|
|
{
|
|
name: "501 error",
|
|
errorStr: "501 Not Implemented",
|
|
wantType: "APINotSupported",
|
|
wantReason: "ImportDiskAPINotImplemented",
|
|
},
|
|
{
|
|
name: "not implemented",
|
|
errorStr: "importdisk API is not implemented",
|
|
wantType: "APINotSupported",
|
|
wantReason: "ImportDiskAPINotImplemented",
|
|
},
|
|
{
|
|
name: "importdisk error",
|
|
errorStr: "failed to use importdisk",
|
|
wantType: "APINotSupported",
|
|
wantReason: "ImportDiskAPINotImplemented",
|
|
},
|
|
|
|
// Configuration errors
|
|
{
|
|
name: "cannot get provider config",
|
|
errorStr: "cannot get provider config",
|
|
wantType: "ConfigurationError",
|
|
wantReason: "InvalidConfiguration",
|
|
},
|
|
{
|
|
name: "cannot get credentials",
|
|
errorStr: "cannot get credentials",
|
|
wantType: "ConfigurationError",
|
|
wantReason: "InvalidConfiguration",
|
|
},
|
|
{
|
|
name: "cannot find site",
|
|
errorStr: "cannot find site",
|
|
wantType: "ConfigurationError",
|
|
wantReason: "InvalidConfiguration",
|
|
},
|
|
{
|
|
name: "cannot create proxmox client",
|
|
errorStr: "cannot create Proxmox client",
|
|
wantType: "ConfigurationError",
|
|
wantReason: "InvalidConfiguration",
|
|
},
|
|
|
|
// Quota errors
|
|
{
|
|
name: "quota exceeded",
|
|
errorStr: "quota exceeded",
|
|
wantType: "QuotaExceeded",
|
|
wantReason: "ResourceQuotaExceeded",
|
|
},
|
|
{
|
|
name: "resource exceeded",
|
|
errorStr: "resource exceeded",
|
|
wantType: "QuotaExceeded",
|
|
wantReason: "ResourceQuotaExceeded",
|
|
},
|
|
|
|
// Node health errors
|
|
{
|
|
name: "node unhealthy",
|
|
errorStr: "node is unhealthy",
|
|
wantType: "NodeUnhealthy",
|
|
wantReason: "NodeHealthCheckFailed",
|
|
},
|
|
{
|
|
name: "node not reachable",
|
|
errorStr: "node is not reachable",
|
|
wantType: "NodeUnhealthy",
|
|
wantReason: "NodeHealthCheckFailed",
|
|
},
|
|
{
|
|
name: "node offline",
|
|
errorStr: "node is offline",
|
|
wantType: "NodeUnhealthy",
|
|
wantReason: "NodeHealthCheckFailed",
|
|
},
|
|
|
|
// Image errors
|
|
{
|
|
name: "image not found",
|
|
errorStr: "image not found in storage",
|
|
wantType: "ImageNotFound",
|
|
wantReason: "ImageNotFoundInStorage",
|
|
},
|
|
{
|
|
name: "cannot find image",
|
|
errorStr: "cannot find image",
|
|
wantType: "ImageNotFound",
|
|
wantReason: "ImageNotFoundInStorage",
|
|
},
|
|
|
|
// Lock errors
|
|
{
|
|
name: "lock file error",
|
|
errorStr: "lock file timeout",
|
|
wantType: "LockError",
|
|
wantReason: "LockFileTimeout",
|
|
},
|
|
{
|
|
name: "timeout error",
|
|
errorStr: "operation timeout",
|
|
wantType: "LockError",
|
|
wantReason: "LockFileTimeout",
|
|
},
|
|
|
|
// Authentication errors
|
|
{
|
|
name: "authentication error",
|
|
errorStr: "authentication failed",
|
|
wantType: "AuthenticationError",
|
|
wantReason: "AuthenticationFailed",
|
|
},
|
|
{
|
|
name: "unauthorized",
|
|
errorStr: "unauthorized access",
|
|
wantType: "AuthenticationError",
|
|
wantReason: "AuthenticationFailed",
|
|
},
|
|
{
|
|
name: "401 error",
|
|
errorStr: "401 Unauthorized",
|
|
wantType: "AuthenticationError",
|
|
wantReason: "AuthenticationFailed",
|
|
},
|
|
{
|
|
name: "invalid credentials",
|
|
errorStr: "invalid credentials",
|
|
wantType: "AuthenticationError",
|
|
wantReason: "AuthenticationFailed",
|
|
},
|
|
{
|
|
name: "forbidden",
|
|
errorStr: "forbidden",
|
|
wantType: "AuthenticationError",
|
|
wantReason: "AuthenticationFailed",
|
|
},
|
|
{
|
|
name: "403 error",
|
|
errorStr: "403 Forbidden",
|
|
wantType: "AuthenticationError",
|
|
wantReason: "AuthenticationFailed",
|
|
},
|
|
|
|
// Network errors
|
|
{
|
|
name: "network error",
|
|
errorStr: "network connection failed",
|
|
wantType: "NetworkError",
|
|
wantReason: "TransientNetworkFailure",
|
|
},
|
|
{
|
|
name: "connection error",
|
|
errorStr: "connection refused",
|
|
wantType: "NetworkError",
|
|
wantReason: "TransientNetworkFailure",
|
|
},
|
|
{
|
|
name: "connection reset",
|
|
errorStr: "connection reset",
|
|
wantType: "NetworkError",
|
|
wantReason: "TransientNetworkFailure",
|
|
},
|
|
{
|
|
name: "502 error",
|
|
errorStr: "502 Bad Gateway",
|
|
wantType: "NetworkError",
|
|
wantReason: "TransientNetworkFailure",
|
|
},
|
|
{
|
|
name: "503 error",
|
|
errorStr: "503 Service Unavailable",
|
|
wantType: "NetworkError",
|
|
wantReason: "TransientNetworkFailure",
|
|
},
|
|
|
|
// Creation failures
|
|
{
|
|
name: "cannot create vm",
|
|
errorStr: "cannot create VM",
|
|
wantType: "CreationFailed",
|
|
wantReason: "VMCreationFailed",
|
|
},
|
|
{
|
|
name: "failed to create",
|
|
errorStr: "failed to create VM",
|
|
wantType: "CreationFailed",
|
|
wantReason: "VMCreationFailed",
|
|
},
|
|
|
|
// Unknown errors
|
|
{
|
|
name: "unknown error",
|
|
errorStr: "something went wrong",
|
|
wantType: "Failed",
|
|
wantReason: "UnknownError",
|
|
},
|
|
{
|
|
name: "empty error",
|
|
errorStr: "",
|
|
wantType: "Failed",
|
|
wantReason: "UnknownError",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result := categorizeError(tt.errorStr)
|
|
if result.Type != tt.wantType {
|
|
t.Errorf("categorizeError(%q).Type = %q, want %q", tt.errorStr, result.Type, tt.wantType)
|
|
}
|
|
if result.Reason != tt.wantReason {
|
|
t.Errorf("categorizeError(%q).Reason = %q, want %q", tt.errorStr, result.Reason, tt.wantReason)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCategorizeError_CaseInsensitive(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
errorStr string
|
|
wantType string
|
|
}{
|
|
{"uppercase", "AUTHENTICATION FAILED", "AuthenticationError"},
|
|
{"mixed case", "AuThEnTiCaTiOn FaIlEd", "AuthenticationError"},
|
|
{"lowercase", "authentication failed", "AuthenticationError"},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result := categorizeError(tt.errorStr)
|
|
if result.Type != tt.wantType {
|
|
t.Errorf("categorizeError(%q).Type = %q, want %q", tt.errorStr, result.Type, tt.wantType)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|