Skip to content

Commit 6c1fdf5

Browse files
committed
feat: use preview to compute workspace tags from terraform
1 parent 15a6ca1 commit 6c1fdf5

File tree

5 files changed

+838
-13
lines changed

5 files changed

+838
-13
lines changed

coderd/dynamicparameters/tags.go

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package dynamicparameters
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/hashicorp/hcl/v2"
7+
8+
"github.com/coder/preview"
9+
previewtypes "github.com/coder/preview/types"
10+
)
11+
12+
func CheckTags(output *preview.Output, diags hcl.Diagnostics) *DiagnosticError {
13+
de := TagValidationError(diags)
14+
failedTags := output.WorkspaceTags.UnusableTags()
15+
if len(failedTags) == 0 && !de.HasError() {
16+
return nil // No errors, all is good!
17+
}
18+
19+
for _, tag := range failedTags {
20+
name := tag.KeyString()
21+
if name == previewtypes.UnknownStringValue {
22+
name = "unknown" // Best effort to get a name for the tag
23+
}
24+
de.Extend(name, FailedTagDiagnostic(tag))
25+
}
26+
return de
27+
}
28+
29+
// FailedTagDiagnostic is a helper function that takes an invalid tag and
30+
// returns an appropriate hcl diagnostic for it.
31+
func FailedTagDiagnostic(tag previewtypes.Tag) hcl.Diagnostics {
32+
const (
33+
key = "key"
34+
value = "value"
35+
)
36+
37+
diags := hcl.Diagnostics{}
38+
39+
// TODO: It would be really nice to pull out the variable references to help identify the source of
40+
// the unknown or invalid tag.
41+
unknownErr := "Tag %s is not known, it likely refers to a variable that is not set or has no default."
42+
invalidErr := "Tag %s is not valid, it must be a non-null string value."
43+
44+
if !tag.Key.Value.IsWhollyKnown() {
45+
diags = diags.Append(&hcl.Diagnostic{
46+
Severity: hcl.DiagError,
47+
Summary: fmt.Sprintf(unknownErr, key),
48+
})
49+
} else if !tag.Key.Valid() {
50+
diags = diags.Append(&hcl.Diagnostic{
51+
Severity: hcl.DiagError,
52+
Summary: fmt.Sprintf(invalidErr, key),
53+
})
54+
}
55+
56+
if !tag.Value.Value.IsWhollyKnown() {
57+
diags = diags.Append(&hcl.Diagnostic{
58+
Severity: hcl.DiagError,
59+
Summary: fmt.Sprintf(unknownErr, value),
60+
})
61+
} else if !tag.Value.Valid() {
62+
diags = diags.Append(&hcl.Diagnostic{
63+
Severity: hcl.DiagError,
64+
Summary: fmt.Sprintf(invalidErr, value),
65+
})
66+
}
67+
68+
if diags.HasErrors() {
69+
// Stop here if there are diags, as the diags manually created above are more
70+
// informative than the original tag's diagnostics.
71+
return diags
72+
}
73+
74+
// If we reach here, decorate the original tag's diagnostics
75+
diagErr := "Tag %s: %s"
76+
if tag.Key.ValueDiags.HasErrors() {
77+
// add 'Tag key' prefix to each diagnostic
78+
for _, d := range tag.Key.ValueDiags {
79+
d.Summary = fmt.Sprintf(diagErr, key, d.Summary)
80+
}
81+
}
82+
diags = diags.Extend(tag.Key.ValueDiags)
83+
84+
if tag.Value.ValueDiags.HasErrors() {
85+
// add 'Tag value' prefix to each diagnostic
86+
for _, d := range tag.Value.ValueDiags {
87+
d.Summary = fmt.Sprintf(diagErr, value, d.Summary)
88+
}
89+
}
90+
diags = diags.Extend(tag.Value.ValueDiags)
91+
92+
if !diags.HasErrors() {
93+
diags = diags.Append(&hcl.Diagnostic{
94+
Severity: hcl.DiagError,
95+
Summary: "Tag is invalid for some unknown reason. Please check the tag's value and key.",
96+
})
97+
}
98+
99+
return diags
100+
}

0 commit comments

Comments
 (0)