-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Expand file tree
/
Copy patherror.go
More file actions
137 lines (116 loc) · 3.57 KB
/
error.go
File metadata and controls
137 lines (116 loc) · 3.57 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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package dynamicparameters
import (
"fmt"
"net/http"
"slices"
"github.com/hashicorp/hcl/v2"
"github.com/coder/coder/v2/codersdk"
)
func parameterValidationError(diags hcl.Diagnostics) *DiagnosticError {
return &DiagnosticError{
Message: "Unable to validate parameters",
Diagnostics: diags,
KeyedDiagnostics: make(map[string]hcl.Diagnostics),
}
}
func tagValidationError(diags hcl.Diagnostics) *DiagnosticError {
return &DiagnosticError{
Message: "Unable to parse workspace tags",
Diagnostics: diags,
KeyedDiagnostics: make(map[string]hcl.Diagnostics),
}
}
func presetValidationError(diags hcl.Diagnostics) *DiagnosticError {
return &DiagnosticError{
Message: "Unable to validate presets",
Diagnostics: diags,
KeyedDiagnostics: make(map[string]hcl.Diagnostics),
}
}
type DiagnosticError struct {
// Message is the human-readable message that will be returned to the user.
Message string
// Diagnostics are top level diagnostics that will be returned as "Detail" in the response.
Diagnostics hcl.Diagnostics
// KeyedDiagnostics translate to Validation errors in the response. A key could
// be a parameter name, or a tag name. This allows diagnostics to be more closely
// associated with a specific index/parameter/tag.
KeyedDiagnostics map[string]hcl.Diagnostics
}
// Error is a pretty bad format for these errors. Try to avoid using this.
func (e *DiagnosticError) Error() string {
var diags hcl.Diagnostics
diags = diags.Extend(e.Diagnostics)
for _, d := range e.KeyedDiagnostics {
diags = diags.Extend(d)
}
return diags.Error()
}
func (e *DiagnosticError) HasError() bool {
if e.Diagnostics.HasErrors() {
return true
}
for _, diags := range e.KeyedDiagnostics {
if diags.HasErrors() {
return true
}
}
return false
}
func (e *DiagnosticError) Append(key string, diag *hcl.Diagnostic) {
e.Extend(key, hcl.Diagnostics{diag})
}
func (e *DiagnosticError) Extend(key string, diag hcl.Diagnostics) {
if e.KeyedDiagnostics == nil {
e.KeyedDiagnostics = make(map[string]hcl.Diagnostics)
}
if _, ok := e.KeyedDiagnostics[key]; !ok {
e.KeyedDiagnostics[key] = hcl.Diagnostics{}
}
e.KeyedDiagnostics[key] = e.KeyedDiagnostics[key].Extend(diag)
}
func (e *DiagnosticError) Response() (int, codersdk.Response) {
resp := codersdk.Response{
Message: e.Message,
Validations: nil,
}
// Sort the parameter names so that the order is consistent.
sortedNames := make([]string, 0, len(e.KeyedDiagnostics))
for name := range e.KeyedDiagnostics {
sortedNames = append(sortedNames, name)
}
slices.Sort(sortedNames)
for _, name := range sortedNames {
diag := e.KeyedDiagnostics[name]
resp.Validations = append(resp.Validations, codersdk.ValidationError{
Field: name,
Detail: DiagnosticsErrorString(diag),
})
}
if e.Diagnostics.HasErrors() {
resp.Detail = DiagnosticsErrorString(e.Diagnostics)
}
return http.StatusBadRequest, resp
}
func DiagnosticErrorString(d *hcl.Diagnostic) string {
return fmt.Sprintf("%s; %s", d.Summary, d.Detail)
}
func DiagnosticsErrorString(d hcl.Diagnostics) string {
count := len(d)
switch {
case count == 0:
return "no diagnostics"
case count == 1:
return DiagnosticErrorString(d[0])
default:
for _, d := range d {
// Render the first error diag.
// If there are warnings, do not priority them over errors.
if d.Severity == hcl.DiagError {
return fmt.Sprintf("%s, and %d other diagnostic(s)", DiagnosticErrorString(d), count-1)
}
}
// All warnings? ok...
return fmt.Sprintf("%s, and %d other diagnostic(s)", DiagnosticErrorString(d[0]), count-1)
}
}