Skip to content

Commit 1bd98cf

Browse files
committed
Fix template path including linked files
1 parent b9e2c04 commit 1bd98cf

File tree

5 files changed

+148
-11
lines changed

5 files changed

+148
-11
lines changed

code/go/internal/validator/semantic/validate_integration_policy_template_path.go

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import (
99
"fmt"
1010
"io/fs"
1111
"path"
12+
"path/filepath"
13+
"strings"
1214

1315
"gopkg.in/yaml.v3"
1416

@@ -148,18 +150,18 @@ func validateInputWithStreams(fsys fspath.FS, input string, dsMap map[string]dat
148150
stream.TemplatePath = defaultStreamTemplatePath
149151
}
150152

151-
_, err := fs.ReadFile(fsys, path.Join(dsDir, "agent", "stream", stream.TemplatePath))
153+
foundFile, err := findPathWithPattern(fsys, dsDir, stream.TemplatePath)
154+
if err != nil {
155+
return err
156+
}
157+
if foundFile == "" {
158+
return errTemplateNotFound
159+
}
160+
161+
_, err = fs.ReadFile(fsys, foundFile)
152162
if err != nil {
153163
if errors.Is(err, fs.ErrNotExist) {
154-
// fallback to glob pattern matching in case the default template path is customized with a prefix
155-
matches, err := fs.Glob(fsys, path.Join(dsDir, "agent", "stream", "*"+stream.TemplatePath))
156-
if err != nil {
157-
return err
158-
}
159-
if len(matches) == 0 {
160-
return errTemplateNotFound
161-
}
162-
continue
164+
return errTemplateNotFound
163165
}
164166
return err
165167
}
@@ -168,3 +170,33 @@ func validateInputWithStreams(fsys fspath.FS, input string, dsMap map[string]dat
168170

169171
return nil
170172
}
173+
174+
// findPathWithPattern looks for a file matching the templatePath in the given data stream directory
175+
// It checks for exact matches, files ending with the templatePath, or templatePath + ".link"
176+
func findPathWithPattern(fsys fspath.FS, dsDir, templatePath string) (string, error) {
177+
// Check for exact match, files ending with stream.TemplatePath, or stream.TemplatePath + ".link"
178+
pattern := path.Join(dsDir, "agent", "stream", "*"+templatePath+"*")
179+
matches, err := fs.Glob(fsys, pattern)
180+
if err != nil {
181+
return "", err
182+
}
183+
184+
// Filter matches to ensure they match our criteria:
185+
// 1. Exact name match
186+
// 2. Ends with stream.TemplatePath
187+
// 3. Equals stream.TemplatePath + ".link"
188+
var foundFile string
189+
for _, match := range matches {
190+
base := filepath.Base(match)
191+
if base == templatePath || base == templatePath+".link" {
192+
foundFile = match
193+
break
194+
}
195+
// fallbak to check for suffix match, in case the path is prefixed
196+
if strings.HasSuffix(match, templatePath) {
197+
foundFile = match
198+
break
199+
}
200+
}
201+
return foundFile, nil
202+
}

code/go/internal/validator/semantic/validate_integration_policy_template_path_test.go

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,3 +179,94 @@ streams:
179179
errs := ValidateIntegrationPolicyTemplates(fspath.DirFS(d))
180180
require.Empty(t, errs)
181181
}
182+
func TestFindPathWithPattern(t *testing.T) {
183+
d := t.TempDir()
184+
185+
dsDir := filepath.ToSlash(path.Join("data_stream", "logs"))
186+
err := os.MkdirAll(filepath.Join(d, "data_stream", "logs", "agent", "stream"), 0o755)
187+
require.NoError(t, err)
188+
189+
t.Run("exact match", func(t *testing.T) {
190+
templatePath := "exact.yml.hbs"
191+
err = os.WriteFile(filepath.Join(d, "data_stream", "logs", "agent", "stream", templatePath), []byte("content"), 0o644)
192+
require.NoError(t, err)
193+
defer os.Remove(filepath.Join(d, "data_stream", "logs", "agent", "stream", templatePath))
194+
195+
foundFile, err := findPathWithPattern(fspath.DirFS(d), dsDir, templatePath)
196+
require.NoError(t, err)
197+
require.NotEmpty(t, foundFile)
198+
require.Equal(t, filepath.ToSlash(path.Join(dsDir, "agent", "stream", templatePath)), foundFile)
199+
})
200+
201+
t.Run("match with .link extension", func(t *testing.T) {
202+
templatePath := "linked.yml.hbs"
203+
err = os.WriteFile(filepath.Join(d, "data_stream", "logs", "agent", "stream", templatePath+".link"), []byte("content"), 0o644)
204+
require.NoError(t, err)
205+
defer os.Remove(filepath.Join(d, "data_stream", "logs", "agent", "stream", templatePath+".link"))
206+
207+
foundFile, err := findPathWithPattern(fspath.DirFS(d), dsDir, templatePath)
208+
require.NoError(t, err)
209+
require.NotEmpty(t, foundFile)
210+
require.Equal(t, filepath.ToSlash(path.Join(dsDir, "agent", "stream", templatePath+".link")), foundFile)
211+
})
212+
213+
t.Run("match with prefix", func(t *testing.T) {
214+
templatePath := "stream.yml.hbs"
215+
prefixedFile := "prefixstream.yml.hbs"
216+
err = os.WriteFile(filepath.Join(d, "data_stream", "logs", "agent", "stream", prefixedFile), []byte("content"), 0o644)
217+
require.NoError(t, err)
218+
defer os.Remove(filepath.Join(d, "data_stream", "logs", "agent", "stream", prefixedFile))
219+
220+
foundFile, err := findPathWithPattern(fspath.DirFS(d), dsDir, templatePath)
221+
require.NoError(t, err)
222+
require.NotEmpty(t, foundFile)
223+
require.Equal(t, filepath.ToSlash(path.Join(dsDir, "agent", "stream", prefixedFile)), foundFile)
224+
})
225+
226+
t.Run("no match found", func(t *testing.T) {
227+
templatePath := "nonexistent.yml.hbs"
228+
229+
foundFile, err := findPathWithPattern(fspath.DirFS(d), dsDir, templatePath)
230+
require.NoError(t, err)
231+
require.Empty(t, foundFile)
232+
})
233+
234+
t.Run("multiple matches - exact match takes precedence", func(t *testing.T) {
235+
templatePath := "multi.yml.hbs"
236+
exactFile := "multi.yml.hbs"
237+
prefixedFile := "prefixmulti.yml.hbs"
238+
239+
err = os.WriteFile(filepath.Join(d, "data_stream", "logs", "agent", "stream", exactFile), []byte("exact"), 0o644)
240+
require.NoError(t, err)
241+
defer os.Remove(filepath.Join(d, "data_stream", "logs", "agent", "stream", exactFile))
242+
243+
err = os.WriteFile(filepath.Join(d, "data_stream", "logs", "agent", "stream", prefixedFile), []byte("prefixed"), 0o644)
244+
require.NoError(t, err)
245+
defer os.Remove(filepath.Join(d, "data_stream", "logs", "agent", "stream", prefixedFile))
246+
247+
foundFile, err := findPathWithPattern(fspath.DirFS(d), dsDir, templatePath)
248+
require.NoError(t, err)
249+
require.NotEmpty(t, foundFile)
250+
require.Equal(t, filepath.ToSlash(path.Join(dsDir, "agent", "stream", exactFile)), foundFile)
251+
})
252+
253+
t.Run("link file takes precedence over suffix match", func(t *testing.T) {
254+
templatePath := "link.yml.hbs"
255+
linkFile := "link.yml.hbs.link"
256+
suffixFile := "prefixlink.yml.hbs"
257+
258+
err = os.WriteFile(filepath.Join(d, "data_stream", "logs", "agent", "stream", linkFile), []byte("link"), 0o644)
259+
require.NoError(t, err)
260+
defer os.Remove(filepath.Join(d, "data_stream", "logs", "agent", "stream", linkFile))
261+
262+
err = os.WriteFile(filepath.Join(d, "data_stream", "logs", "agent", "stream", suffixFile), []byte("suffix"), 0o644)
263+
require.NoError(t, err)
264+
defer os.Remove(filepath.Join(d, "data_stream", "logs", "agent", "stream", suffixFile))
265+
266+
foundFile, err := findPathWithPattern(fspath.DirFS(d), dsDir, templatePath)
267+
require.NoError(t, err)
268+
require.NotEmpty(t, foundFile)
269+
require.Equal(t, filepath.ToSlash(path.Join(dsDir, "agent", "stream", linkFile)), foundFile)
270+
})
271+
}
272+

test/packages/with_links/data_stream/foo/manifest.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
title: Nginx access logs
22
type: logs
33
streams:
4-
- input: logfile
4+
- input: logfile-link
55
vars:
66
- name: empty_array
77
type: text

test/packages/with_links/manifest.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,20 @@ policy_templates:
1414
title: Apache logs and metrics
1515
description: Collect logs and metrics from Apache instances
1616
inputs:
17+
- type: logfile-link
18+
title: Collect logs from Apache instances
19+
description: Collecting Apache access and error logs
20+
multi: false
21+
vars:
22+
- name: paths
23+
type: text
24+
title: Paths
25+
multi: true
26+
required: true
27+
show_user: true
28+
default:
29+
- /var/log/apache2/access.log
30+
- /var/log/apache2/error.log
1731
- type: apache/metrics
1832
title: Collect metrics from Apache instances
1933
description: Collecting Apache status metrics

0 commit comments

Comments
 (0)