diff --git a/CHANGELOG.md b/CHANGELOG.md index 76e4c2f5e..ea8948e85 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ Unreleased changes are available as `avenga/couper:edge` container. * **Added** * [`can()` function](https://docs.couper.io/configuration/functions) ([#699](https://github.com/avenga/couper/pull/699)) * `bearer = true` attribute for [`jwt` block](https://docs.couper.io/configuration/block/jwt#attributes) to indicate retrieving token from `Authorization: Bearer ...`. This is the new default token source indicator. `header = "Authorization"` is now _deprecated_ in favour of this new attribute. ([#724](https://github.com/avenga/couper/pull/724)) + * If Couper starts with `-watch` CLI flag, watch referenced files, too ([#747](https://github.com/avenga/couper/pull/747)) * **Fixed** * Erroneously sending an empty [`Server-Timing` header](https://docs.couper.io/configuration/command-line#oberservation-options) ([#700](https://github.com/avenga/couper/pull/700)) diff --git a/config/configload/load.go b/config/configload/load.go index 0dcf27ec7..22910dc6c 100644 --- a/config/configload/load.go +++ b/config/configload/load.go @@ -108,7 +108,8 @@ func LoadFiles(filesList []string, env string) (*config.Couper, error) { if err != nil { return nil, err } - conf.Files = configFiles + + conf.Files = append(configFiles, conf.Files...) return conf, nil } @@ -170,8 +171,12 @@ func loadConfig(body *hclsyntax.Body) (*config.Couper, error) { return helper.config, nil } -func absolutizePaths(fileBody *hclsyntax.Body) error { +func absolutizePaths(fileBody *hclsyntax.Body) ([]configfile.File, error) { + const watchFilePrefix = "COUPER-WATCH-FILE: " + visitor := func(node hclsyntax.Node) hcl.Diagnostics { + var watchFile string + attribute, ok := node.(*hclsyntax.Attribute) if !ok { return nil @@ -197,30 +202,57 @@ func absolutizePaths(fileBody *hclsyntax.Body) error { filePath = strings.TrimPrefix(filePath, "file:") if path.IsAbs(filePath) { - return nil - } + watchFile = filePath + } else { + watchFile = filepath.ToSlash(path.Join(filepath.Dir(basePath), filePath)) - absolutePath = "file:" + filepath.ToSlash(path.Join(filepath.Dir(basePath), filePath)) + absolutePath = "file:" + watchFile + } } else { if filepath.IsAbs(filePath) { - return nil + watchFile = filePath + } else { + watchFile = filepath.Join(filepath.Dir(basePath), filePath) + + absolutePath = watchFile } - absolutePath = filepath.Join(filepath.Dir(basePath), filePath) } - attribute.Expr = &hclsyntax.LiteralValueExpr{ - Val: cty.StringVal(absolutePath), - SrcRange: attribute.SrcRange, + if absolutePath != "" { + attribute.Expr = &hclsyntax.LiteralValueExpr{ + Val: cty.StringVal(absolutePath), + SrcRange: attribute.SrcRange, + } } - return nil + return hcl.Diagnostics{&hcl.Diagnostic{ + Severity: hcl.DiagWarning, + Summary: fmt.Sprintf("%s%s", watchFilePrefix, watchFile), + }} } diags := hclsyntax.VisitAll(fileBody, visitor) - if diags.HasErrors() { - return diags + + var ( + newDiags hcl.Diagnostics + watchFiles []configfile.File + ) + + for _, diag := range diags { + if diag.Severity == hcl.DiagWarning && strings.HasPrefix(diag.Summary, watchFilePrefix) { + watchFiles = append(watchFiles, configfile.File{ + Path: strings.TrimPrefix(diag.Summary, watchFilePrefix), + }) + } else { + newDiags.Append(diag) + } } - return nil + + if newDiags.HasErrors() { + return nil, newDiags + } + + return watchFiles, nil } func updateContext(body hcl.Body, srcBytes [][]byte, environment string) hcl.Diagnostics { @@ -253,14 +285,19 @@ func bodiesToConfig(parsedBodies []*hclsyntax.Body, srcBytes [][]byte, env strin return nil, diags } + var watchFiles configfile.Files + for _, body := range parsedBodies { - if err = absolutizePaths(body); err != nil { + files, err := absolutizePaths(body) + if err != nil { return nil, err } if err = validateBody(body, false); err != nil { return nil, err } + + watchFiles = append(watchFiles, files...) } settingsBlock := mergeSettings(parsedBodies) @@ -293,5 +330,7 @@ func bodiesToConfig(parsedBodies []*hclsyntax.Body, srcBytes [][]byte, env strin return nil, err } + conf.Files = append(conf.Files, watchFiles...) + return conf, nil }