-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathworkspacetags.go
More file actions
110 lines (93 loc) · 2.89 KB
/
workspacetags.go
File metadata and controls
110 lines (93 loc) · 2.89 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
package preview
import (
"fmt"
"github.com/aquasecurity/trivy/pkg/iac/terraform"
"github.com/hashicorp/hcl/v2"
"github.com/zclconf/go-cty/cty"
"github.com/coder/preview/types"
)
func workspaceTags(modules terraform.Modules, files map[string]*hcl.File) (types.TagBlocks, hcl.Diagnostics) {
diags := make(hcl.Diagnostics, 0)
tagBlocks := make(types.TagBlocks, 0)
for _, mod := range modules {
blocks := mod.GetDatasByType("coder_workspace_tags")
for _, block := range blocks {
tagsAttr := block.GetAttribute("tags")
if tagsAttr.IsNil() {
// Nil tags block is valid, just skip it.
continue
}
tagsValue := tagsAttr.Value()
if !tagsValue.Type().IsObjectType() {
diags = diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Incorrect type for \"tags\" attribute",
// TODO: better error message for types
Detail: fmt.Sprintf(`"tags" attribute must be an 'Object', but got %q`, tagsValue.Type().FriendlyName()),
Subject: &tagsAttr.HCLAttribute().NameRange,
Context: &tagsAttr.HCLAttribute().Range,
Expression: tagsAttr.HCLAttribute().Expr,
EvalContext: block.Context().Inner(),
})
continue
}
var tags []types.Tag
tagsValue.ForEachElement(func(key cty.Value, val cty.Value) (stop bool) {
if val.IsNull() {
// null tags with null values are omitted
// This matches the behavior of `terraform apply``
return false
}
r := tagsAttr.HCLAttribute().Expr.Range()
tag, tagDiag := newTag(&r, files, key, val)
if tagDiag != nil {
diags = diags.Append(tagDiag)
return false
}
tags = append(tags, tag)
return false
})
tagBlocks = append(tagBlocks, types.TagBlock{
Tags: tags,
Block: block,
})
}
}
return tagBlocks, diags
}
// newTag creates a workspace tag from its hcl expression.
func newTag(srcRange *hcl.Range, _ map[string]*hcl.File, key, val cty.Value) (types.Tag, *hcl.Diagnostic) {
if key.IsKnown() && key.Type() != cty.String {
return types.Tag{}, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid key type for tags",
Detail: fmt.Sprintf("Key must be a string, but got %s", key.Type().FriendlyName()),
Context: srcRange,
}
}
tag := types.Tag{
Key: types.HCLString{
Value: key,
},
Value: types.HCLString{
Value: val,
},
}
switch val.Type() {
case cty.String, cty.Bool, cty.Number:
// These types are supported and can be safely converted to a string.
default:
fr := "<nil>"
if !val.Type().Equals(cty.NilType) {
fr = val.Type().FriendlyName()
}
// Unsupported types will be treated as errors.
tag.Value.ValueDiags = tag.Value.ValueDiags.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: fmt.Sprintf("Invalid value type for tag %q", tag.KeyString()),
Detail: fmt.Sprintf("Value must be a string, but got %s.", fr),
Context: srcRange,
})
}
return tag, nil
}