Skip to content

Commit 56ec679

Browse files
committed
Parse HCL
1 parent 6097029 commit 56ec679

File tree

1 file changed

+75
-4
lines changed

1 file changed

+75
-4
lines changed

cli/templatevariables.go

Lines changed: 75 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
package cli
22

33
import (
4+
"encoding/json"
5+
"fmt"
46
"os"
57
"path/filepath"
8+
"sort"
69
"strings"
710

811
"golang.org/x/xerrors"
912
"gopkg.in/yaml.v3"
1013

14+
"github.com/hashicorp/hcl/v2/hclparse"
15+
"github.com/zclconf/go-cty/cty"
16+
1117
"github.com/coder/coder/v2/codersdk"
1218
)
1319

@@ -94,12 +100,77 @@ func parseVariableValuesFromVarsFiles(varsFiles []string) ([]codersdk.VariableVa
94100
return parsed, nil
95101
}
96102

97-
func parseVariableValuesFromHCL(hcl []byte) ([]codersdk.VariableValue, error) {
98-
panic("not implemented yet")
103+
func parseVariableValuesFromHCL(content []byte) ([]codersdk.VariableValue, error) {
104+
parser := hclparse.NewParser()
105+
hclFile, diags := parser.ParseHCL(content, "file.hcl")
106+
if diags.HasErrors() {
107+
return nil, diags
108+
}
109+
110+
attrs, diags := hclFile.Body.JustAttributes()
111+
if diags.HasErrors() {
112+
return nil, diags
113+
}
114+
115+
var stringData map[string]string
116+
for _, attribute := range attrs {
117+
ctyValue, diags := attribute.Expr.Value(nil)
118+
if diags.HasErrors() {
119+
return nil, diags
120+
}
121+
122+
ctyType := ctyValue.Type()
123+
if ctyType.Equals(cty.String) {
124+
stringData[attribute.Name] = ctyValue.AsString()
125+
} else if ctyType.Equals(cty.Number) {
126+
stringData[attribute.Name] = ctyValue.AsBigFloat().String()
127+
} else if ctyType.IsListType() {
128+
stringData[attribute.Name] = "TODO list(string)"
129+
}
130+
}
131+
132+
return convertMapIntoVariableValues(stringData), nil
133+
}
134+
135+
// parseVariableValuesFromJSON converts the .tfvars.json content into template variables.
136+
// The function visits only root-level properties as template variables do not support nested
137+
// structures.
138+
func parseVariableValuesFromJSON(content []byte) ([]codersdk.VariableValue, error) {
139+
var data map[string]interface{}
140+
err := json.Unmarshal(content, &data)
141+
if err != nil {
142+
return nil, err
143+
}
144+
145+
stringData := make(map[string]string)
146+
for key, value := range data {
147+
switch value.(type) {
148+
case string, int, bool:
149+
stringData[key] = fmt.Sprintf("%v", value)
150+
default:
151+
m, err := json.Marshal(value)
152+
if err != nil {
153+
return nil, err
154+
}
155+
stringData[key] = string(m)
156+
}
157+
}
158+
159+
return convertMapIntoVariableValues(stringData), nil
99160
}
100161

101-
func parseVariableValuesFromJSON(json []byte) ([]codersdk.VariableValue, error) {
102-
panic("not implemented yet")
162+
func convertMapIntoVariableValues(m map[string]string) []codersdk.VariableValue {
163+
var parsed []codersdk.VariableValue
164+
for key, value := range m {
165+
parsed = append(parsed, codersdk.VariableValue{
166+
Name: key,
167+
Value: value,
168+
})
169+
}
170+
sort.Slice(parsed, func(i, j int) bool {
171+
return parsed[i].Name < parsed[j].Name
172+
})
173+
return parsed
103174
}
104175

105176
func parseVariableValuesFromFile(variablesFile string) ([]codersdk.VariableValue, error) {

0 commit comments

Comments
 (0)