-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy patherrors.go
More file actions
84 lines (72 loc) · 3.59 KB
/
Copy patherrors.go
File metadata and controls
84 lines (72 loc) · 3.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
package xshellz
import (
"errors"
"fmt"
)
// Sentinel errors, usable with errors.Is. API-originated errors additionally
// carry an *APIError (usable with errors.As) that wraps the matching sentinel.
var (
// ErrNoAPIKey is returned when no API key was supplied — neither in the
// options nor via the XSHELLZ_API_KEY environment variable. Create a
// personal access token with "read" and "write" scopes in your xShellz
// account settings and export it as XSHELLZ_API_KEY.
ErrNoAPIKey = errors.New("xshellz: missing API key: set XSHELLZ_API_KEY (or pass APIKey) to a personal access token with read+write scopes — create one in your xShellz account settings")
// ErrAuth covers authentication and permission failures (HTTP 401/403):
// an invalid or expired token, missing scopes, an account that is not
// entitled to Agent Shells, or verification-required gates. Inspect the
// wrapped *APIError's Code/Message for the specific reason.
ErrAuth = errors.New("xshellz: authentication or permission denied")
// ErrQuota is returned when the plan's concurrent sandbox limit is
// reached (the API answers 403 "You've reached your plan's agent shell
// limit (N)."). The free tier allows one box — Connect to the existing
// box instead of creating another, or Close it first.
ErrQuota = errors.New("xshellz: sandbox quota reached: your plan's concurrent box limit is used up — Connect() to the existing sandbox or Close() it first")
// ErrNotFound is returned when the API answers 404 — the sandbox UUID
// does not exist, is not yours, or is not in the state the call needs
// (e.g. Start on a box that is not stopped).
ErrNotFound = errors.New("xshellz: sandbox not found")
// ErrNotRunning is returned by Run and the file helpers when the sandbox
// is not in the "running" state (or has no SSH endpoint yet). Call
// Start(ctx) to resume an idle-stopped box.
ErrNotRunning = errors.New("xshellz: sandbox is not running (call Start to resume a stopped box)")
// ErrMissingKey is returned by GetOrCreate when the named sandbox already
// exists but no SSH private key for it can be found — neither an explicit
// PrivateKeyPEM nor a keystore file. The wrapping error says where a key
// was expected.
ErrMissingKey = errors.New("xshellz: missing private key for existing sandbox")
// ErrUnsupportedLanguage is returned by RunCode for a language it does
// not know how to execute. The wrapping error lists the supported ones
// (see SupportedLanguages).
ErrUnsupportedLanguage = errors.New("xshellz: unsupported RunCode language")
)
// APIError is a control-plane error: any non-2xx response from the xShellz
// API. It wraps the matching sentinel (ErrAuth, ErrQuota, ErrNotFound) where
// one applies, so both errors.Is(err, xshellz.ErrQuota) and
// errors.As(err, &apiErr) work.
type APIError struct {
// StatusCode is the HTTP status of the response.
StatusCode int
// Code is the machine-readable error code when the API provides one
// (e.g. "verification_required"); empty otherwise.
Code string
// Message is the human-readable message from the API response.
Message string
// Body is the raw response body, for anything the typed fields miss.
Body string
sentinel error
}
// Error implements the error interface.
func (e *APIError) Error() string {
msg := e.Message
if msg == "" {
msg = e.Body
}
if e.Code != "" {
return fmt.Sprintf("xshellz: API error %d (%s): %s", e.StatusCode, e.Code, msg)
}
return fmt.Sprintf("xshellz: API error %d: %s", e.StatusCode, msg)
}
// Unwrap exposes the matching sentinel error (if any) to errors.Is.
func (e *APIError) Unwrap() error {
return e.sentinel
}