Skip to content

Commit bc69d1e

Browse files
committed
avoid too much caching, allow caller to bring their own parser
1 parent 14a5901 commit bc69d1e

File tree

3 files changed

+20
-20
lines changed

3 files changed

+20
-20
lines changed

provisioner/terraform/parse.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ func (s *server) Parse(sess *provisionersdk.Session, _ *proto.ParseRequest, _ <-
2626
return provisionersdk.ParseErrorf("load module: %s", formatDiagnostics(sess.WorkDirectory, diags))
2727
}
2828

29-
workspaceTags, err := tfparse.WorkspaceTags(module)
29+
workspaceTags, err := tfparse.WorkspaceTags(nil, module)
3030
if err != nil {
3131
return provisionersdk.ParseErrorf("can't load workspace tags: %v", err)
3232
}

provisioner/terraform/tfparse/tfextract.go

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,24 +31,22 @@ import (
3131
// introducing a circular dependency
3232
const maxFileSizeBytes = 10 * (10 << 20) // 10 MB
3333

34-
// hclparse.Parser by default keeps track of all files it has ever parsed
35-
// by filename. By re-using the same parser instance we can avoid repeating
36-
// previous work.
37-
// NOTE: we can only do this if we _just_ use ParseHCLFile().
38-
// The ParseHCL() method allows specifying the filename directly, which allows
39-
// easily getting previously cached results. Whenever we parse HCL files from disk
40-
// we do so in a unique file path.
41-
// See: provisionersdk/session.go#L51
42-
var hclFileParser ParseHCLFiler = hclparse.NewParser()
43-
44-
type ParseHCLFiler interface {
34+
// ParseHCLFile() is only method of hclparse.Parser we use in this package.
35+
// hclparse.Parser will by default cache all previous files it has ever
36+
// parsed. While leveraging this caching behavior is nice, we _never_ want
37+
// to end up in a situation where we end up returning stale values.
38+
type Parser interface {
4539
ParseHCLFile(filename string) (*hcl.File, hcl.Diagnostics)
4640
}
4741

4842
// WorkspaceTags extracts tags from coder_workspace_tags data sources defined in module.
4943
// Note that this only returns the lexical values of the data source, and does not
5044
// evaluate variables and such. To do this, see evalProvisionerTags below.
51-
func WorkspaceTags(module *tfconfig.Module) (map[string]string, error) {
45+
// If the provided Parser is nil, a new instance of hclparse.Parser will be used instead.
46+
func WorkspaceTags(parser Parser, module *tfconfig.Module) (map[string]string, error) {
47+
if parser == nil {
48+
parser = hclparse.NewParser()
49+
}
5250
tags := map[string]string{}
5351

5452
for _, dataResource := range module.DataResources {
@@ -63,7 +61,7 @@ func WorkspaceTags(module *tfconfig.Module) (map[string]string, error) {
6361
continue
6462
}
6563
// We know in which HCL file is the data resource defined.
66-
file, diags = hclFileParser.ParseHCLFile(dataResource.Pos.Filename)
64+
file, diags = parser.ParseHCLFile(dataResource.Pos.Filename)
6765
if diags.HasErrors() {
6866
return nil, xerrors.Errorf("can't parse the resource file: %s", diags.Error())
6967
}
@@ -143,9 +141,11 @@ func WorkspaceTagDefaultsFromFile(ctx context.Context, logger slog.Logger, file
143141
}
144142
}()
145143

144+
parser := hclparse.NewParser()
145+
146146
// This only gets us the expressions. We need to evaluate them.
147147
// Example: var.region -> "us"
148-
tags, err = WorkspaceTags(module)
148+
tags, err = WorkspaceTags(parser, module)
149149
if err != nil {
150150
return nil, xerrors.Errorf("extract workspace tags: %w", err)
151151
}
@@ -156,7 +156,7 @@ func WorkspaceTagDefaultsFromFile(ctx context.Context, logger slog.Logger, file
156156
if err != nil {
157157
return nil, xerrors.Errorf("load variable defaults: %w", err)
158158
}
159-
paramsDefaults, err := loadParamsDefaults(maps.Values(module.DataResources))
159+
paramsDefaults, err := loadParamsDefaults(parser, maps.Values(module.DataResources))
160160
if err != nil {
161161
return nil, xerrors.Errorf("load parameter defaults: %w", err)
162162
}
@@ -242,7 +242,7 @@ func loadVarsDefaults(variables []*tfconfig.Variable) (map[string]string, error)
242242
}
243243

244244
// loadParamsDefaults returns the default values of all coder_parameter data sources data sources provided.
245-
func loadParamsDefaults(dataSources []*tfconfig.Resource) (map[string]string, error) {
245+
func loadParamsDefaults(parser Parser, dataSources []*tfconfig.Resource) (map[string]string, error) {
246246
defaultsM := make(map[string]string)
247247
for _, dataResource := range dataSources {
248248
if dataResource == nil {
@@ -261,7 +261,7 @@ func loadParamsDefaults(dataSources []*tfconfig.Resource) (map[string]string, er
261261
}
262262

263263
// We know in which HCL file is the data resource defined.
264-
file, diags = hclFileParser.ParseHCLFile(dataResource.Pos.Filename)
264+
file, diags = parser.ParseHCLFile(dataResource.Pos.Filename)
265265
if diags.HasErrors() {
266266
return nil, xerrors.Errorf("can't parse the resource file %q: %s", dataResource.Pos.Filename, diags.Error())
267267
}

provisioner/terraform/tfparse/tfparse_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -395,8 +395,8 @@ func createZip(t testing.TB, files map[string]string) []byte {
395395
// goarch: amd64
396396
// pkg: github.com/coder/coder/v2/provisioner/terraform/tfparse
397397
// cpu: AMD EPYC 7502P 32-Core Processor
398-
// BenchmarkWorkspaceTagDefaultsFromFile/Tar-16 1147 1073487 ns/op 200266 B/op 1309 allocs/op
399-
// BenchmarkWorkspaceTagDefaultsFromFile/Zip-16 991 1030536 ns/op 248063 B/op 1364 allocs/op
398+
// BenchmarkWorkspaceTagDefaultsFromFile/Tar-16 1077 1081951 ns/op 200754 B/op 1312 allocs/op
399+
// BenchmarkWorkspaceTagDefaultsFromFile/Zip-16 984 1187299 ns/op 249574 B/op 1369 allocs/op
400400
// PASS
401401
func BenchmarkWorkspaceTagDefaultsFromFile(b *testing.B) {
402402
files := map[string]string{

0 commit comments

Comments
 (0)