Skip to content

Commit 09f5c9c

Browse files
Merge branch 'main' into feat/validate-unique-tags
2 parents a594f6a + edad324 commit 09f5c9c

File tree

37 files changed

+845
-61
lines changed

37 files changed

+845
-61
lines changed

code/go/internal/validator/semantic/types.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ type field struct {
151151

152152
type fieldFileMetadata struct {
153153
dataStream string
154+
transform string
154155
filePath string
155156
fullFilePath string
156157
}
@@ -230,6 +231,7 @@ func listFieldsFiles(fsys fspath.FS) ([]fieldFileMetadata, error) {
230231
filePath: file,
231232
fullFilePath: fsys.Path(file),
232233
dataStream: dataStream,
234+
transform: "",
233235
})
234236
}
235237
}
@@ -247,9 +249,35 @@ func listFieldsFiles(fsys fspath.FS) ([]fieldFileMetadata, error) {
247249
filePath: file,
248250
fullFilePath: fsys.Path(file),
249251
dataStream: "",
252+
transform: "",
250253
})
251254
}
252255

256+
// transform definitions
257+
transforms, err := listTransforms(fsys)
258+
if err != nil {
259+
return nil, err
260+
}
261+
262+
for _, transform := range transforms {
263+
fieldsDir := path.Join("elasticsearch", "transform", transform, "fields")
264+
transformFieldsFiles, err := readFieldsFolder(fsys, fieldsDir)
265+
if err != nil {
266+
return nil, fmt.Errorf("cannot read fields file from integration packages: %w", err)
267+
}
268+
269+
for _, file := range transformFieldsFiles {
270+
fieldsFilesMetadata = append(
271+
fieldsFilesMetadata,
272+
fieldFileMetadata{
273+
filePath: file,
274+
fullFilePath: fsys.Path(file),
275+
dataStream: "",
276+
transform: transform,
277+
})
278+
}
279+
}
280+
253281
return fieldsFilesMetadata, nil
254282
}
255283

@@ -316,6 +344,24 @@ func listDataStreams(fsys fspath.FS) ([]string, error) {
316344
return list, nil
317345
}
318346

347+
func listTransforms(fsys fspath.FS) ([]string, error) {
348+
transformDirectory := path.Join("elasticsearch", "transform")
349+
transforms, err := fs.ReadDir(fsys, transformDirectory)
350+
if errors.Is(err, os.ErrNotExist) {
351+
return nil, nil
352+
}
353+
if err != nil {
354+
return nil, fmt.Errorf("can't list transforms directory: %w", err)
355+
}
356+
357+
list := make([]string, len(transforms))
358+
for i, transform := range transforms {
359+
list[i] = transform.Name()
360+
}
361+
return list, nil
362+
363+
}
364+
319365
func listPipelineFiles(fsys fspath.FS, dataStream string) ([]pipelineFileMetadata, error) {
320366
var pipelineFileMetadatas []pipelineFileMetadata
321367

code/go/internal/validator/semantic/types_test.go

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,87 +25,103 @@ func TestListFieldsFiles(t *testing.T) {
2525
{
2626
pkgName: "good_v2",
2727
expected: []fieldFileMetadata{
28-
fieldFileMetadata{
28+
{
2929
filePath: "data_stream/foo/fields/base-fields.yml",
3030
fullFilePath: filepath.FromSlash("../../../../../test/packages/good_v2/data_stream/foo/fields/base-fields.yml"),
3131
dataStream: "foo",
3232
},
33-
fieldFileMetadata{
33+
{
3434
filePath: "data_stream/foo/fields/external-fields.yml",
3535
fullFilePath: filepath.FromSlash("../../../../../test/packages/good_v2/data_stream/foo/fields/external-fields.yml"),
3636
dataStream: "foo",
3737
},
38-
fieldFileMetadata{
38+
{
3939
filePath: "data_stream/foo/fields/some_fields.yml",
4040
fullFilePath: filepath.FromSlash("../../../../../test/packages/good_v2/data_stream/foo/fields/some_fields.yml"),
4141
dataStream: "foo",
4242
},
43-
fieldFileMetadata{
43+
{
4444
filePath: "data_stream/hidden_data_stream/fields/base-fields.yml",
4545
fullFilePath: filepath.FromSlash("../../../../../test/packages/good_v2/data_stream/hidden_data_stream/fields/base-fields.yml"),
4646
dataStream: "hidden_data_stream",
4747
},
48-
fieldFileMetadata{
48+
{
4949
filePath: "data_stream/hidden_data_stream/fields/some_fields.yml",
5050
fullFilePath: filepath.FromSlash("../../../../../test/packages/good_v2/data_stream/hidden_data_stream/fields/some_fields.yml"),
5151
dataStream: "hidden_data_stream",
5252
},
53-
fieldFileMetadata{
53+
{
5454
filePath: "data_stream/ilm_policy/fields/base-fields.yml",
5555
fullFilePath: filepath.FromSlash("../../../../../test/packages/good_v2/data_stream/ilm_policy/fields/base-fields.yml"),
5656
dataStream: "ilm_policy",
5757
},
58-
fieldFileMetadata{
58+
{
5959
filePath: "data_stream/ilm_policy/fields/some_fields.yml",
6060
fullFilePath: filepath.FromSlash("../../../../../test/packages/good_v2/data_stream/ilm_policy/fields/some_fields.yml"),
6161
dataStream: "ilm_policy",
6262
},
63-
fieldFileMetadata{
63+
{
6464
filePath: "data_stream/k8s_data_stream/fields/base-fields.yml",
6565
fullFilePath: filepath.FromSlash("../../../../../test/packages/good_v2/data_stream/k8s_data_stream/fields/base-fields.yml"),
6666
dataStream: "k8s_data_stream",
6767
},
68-
fieldFileMetadata{
68+
{
6969
filePath: "data_stream/k8s_data_stream_no_definitions/fields/base-fields.yml",
7070
fullFilePath: filepath.FromSlash("../../../../../test/packages/good_v2/data_stream/k8s_data_stream_no_definitions/fields/base-fields.yml"),
7171
dataStream: "k8s_data_stream_no_definitions",
7272
},
73-
fieldFileMetadata{
73+
{
7474
filePath: "data_stream/pe/fields/base-fields.yml",
7575
fullFilePath: filepath.FromSlash("../../../../../test/packages/good_v2/data_stream/pe/fields/base-fields.yml"),
7676
dataStream: "pe",
7777
},
78-
fieldFileMetadata{
78+
{
7979
filePath: "data_stream/pe/fields/some_fields.yml",
8080
fullFilePath: filepath.FromSlash("../../../../../test/packages/good_v2/data_stream/pe/fields/some_fields.yml"),
8181
dataStream: "pe",
8282
},
83-
fieldFileMetadata{
83+
{
8484
filePath: "data_stream/routing_rules/fields/base-fields.yml",
8585
fullFilePath: filepath.FromSlash("../../../../../test/packages/good_v2/data_stream/routing_rules/fields/base-fields.yml"),
8686
dataStream: "routing_rules",
8787
},
88-
fieldFileMetadata{
88+
{
8989
filePath: "data_stream/skipped_tests/fields/base-fields.yml",
9090
fullFilePath: filepath.FromSlash("../../../../../test/packages/good_v2/data_stream/skipped_tests/fields/base-fields.yml"),
9191
dataStream: "skipped_tests",
9292
},
93-
fieldFileMetadata{
93+
{
9494
filePath: "data_stream/skipped_tests/fields/some_fields.yml",
9595
fullFilePath: filepath.FromSlash("../../../../../test/packages/good_v2/data_stream/skipped_tests/fields/some_fields.yml"),
9696
dataStream: "skipped_tests",
9797
},
98+
// transforms
99+
{
100+
filePath: "elasticsearch/transform/metadata_current/fields/fields.yml",
101+
fullFilePath: filepath.FromSlash("../../../../../test/packages/good_v2/elasticsearch/transform/metadata_current/fields/fields.yml"),
102+
transform: "metadata_current",
103+
},
104+
{
105+
filePath: "elasticsearch/transform/metadata_united/fields/base-fields.yml",
106+
fullFilePath: filepath.FromSlash("../../../../../test/packages/good_v2/elasticsearch/transform/metadata_united/fields/base-fields.yml"),
107+
transform: "metadata_united",
108+
},
109+
{
110+
filePath: "elasticsearch/transform/metadata_united/fields/fields.yml",
111+
fullFilePath: filepath.FromSlash("../../../../../test/packages/good_v2/elasticsearch/transform/metadata_united/fields/fields.yml"),
112+
transform: "metadata_united",
113+
},
98114
},
99115
},
100116
{
101117
pkgName: "good_input",
102118
expected: []fieldFileMetadata{
103-
fieldFileMetadata{
119+
{
104120
filePath: "fields/base-fields.yml",
105121
fullFilePath: filepath.FromSlash("../../../../../test/packages/good_input/fields/base-fields.yml"),
106122
dataStream: "",
107123
},
108-
fieldFileMetadata{
124+
{
109125
filePath: "fields/input.yml",
110126
fullFilePath: filepath.FromSlash("../../../../../test/packages/good_input/fields/input.yml"),
111127
dataStream: "",

code/go/internal/validator/semantic/validate_fields_limits.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,20 @@ func ValidateFieldsLimits(limit int) func(fspath.FS) specerrors.ValidationErrors
1818

1919
func validateFieldsLimits(fsys fspath.FS, limit int) specerrors.ValidationErrors {
2020
counts := make(map[string]int)
21+
// Created a new map to avoid collisions with data stream names
22+
transformCounts := make(map[string]int)
2123
countField := func(metadata fieldFileMetadata, f field) specerrors.ValidationErrors {
2224
if len(f.Fields) > 0 {
2325
// Don't count groups
2426
return nil
2527
}
2628

29+
if metadata.transform != "" {
30+
count := transformCounts[metadata.transform]
31+
transformCounts[metadata.transform] = count + 1
32+
return nil
33+
}
34+
2735
count := counts[metadata.dataStream]
2836
counts[metadata.dataStream] = count + 1
2937
return nil
@@ -33,11 +41,19 @@ func validateFieldsLimits(fsys fspath.FS, limit int) specerrors.ValidationErrors
3341
if err != nil {
3442
return err
3543
}
36-
3744
var errs specerrors.ValidationErrors
3845
for id, count := range counts {
3946
if count > limit {
40-
errs = append(errs, specerrors.NewStructuredErrorf("data stream %s has more than %d fields (%d)", id, limit, count))
47+
if id != "" {
48+
errs = append(errs, specerrors.NewStructuredErrorf("data stream %s has more than %d fields (%d)", id, limit, count))
49+
} else {
50+
errs = append(errs, specerrors.NewStructuredErrorf("input package has more than %d fields (%d)", limit, count))
51+
}
52+
}
53+
}
54+
for id, count := range transformCounts {
55+
if count > limit {
56+
errs = append(errs, specerrors.NewStructuredErrorf("transform %s has more than %d fields (%d)", id, limit, count))
4157
}
4258
}
4359
return errs
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
2+
// or more contributor license agreements. Licensed under the Elastic License;
3+
// you may not use this file except in compliance with the Elastic License.
4+
5+
package semantic
6+
7+
import (
8+
"os"
9+
"path/filepath"
10+
"testing"
11+
12+
"github.com/stretchr/testify/assert"
13+
"github.com/stretchr/testify/require"
14+
15+
"github.com/elastic/package-spec/v3/code/go/internal/fspath"
16+
)
17+
18+
func TestValidateFieldsLimits(t *testing.T) {
19+
t.Run("one data stream with too many fields", func(t *testing.T) {
20+
d := t.TempDir()
21+
22+
err := os.MkdirAll(filepath.Join(d, "data_stream", "test", "fields"), 0o755)
23+
require.NoError(t, err)
24+
err = os.MkdirAll(filepath.Join(d, "data_stream", "foo", "fields"), 0o755)
25+
require.NoError(t, err)
26+
err = os.WriteFile(filepath.Join(d, "data_stream", "foo", "fields", "fields.yml"), []byte(`
27+
- name: field1
28+
type: keyword
29+
- name: field2
30+
type: keyword
31+
- name: field3
32+
type: keyword
33+
`), 0o644)
34+
require.NoError(t, err)
35+
err = os.WriteFile(filepath.Join(d, "data_stream", "foo", "fields", "more-fields.yml"), []byte(`
36+
- name: field1
37+
type: keyword
38+
`), 0o644)
39+
require.NoError(t, err)
40+
err = os.WriteFile(filepath.Join(d, "data_stream", "test", "fields", "fields.yml"), []byte(`
41+
- name: field1
42+
type: keyword
43+
`), 0o644)
44+
require.NoError(t, err)
45+
46+
errs := validateFieldsLimits(fspath.DirFS(d), 1)
47+
require.Len(t, errs, 1)
48+
assert.EqualError(t, errs[0], "data stream foo has more than 1 fields (4)")
49+
})
50+
t.Run("one transform with too many fields", func(t *testing.T) {
51+
d := t.TempDir()
52+
53+
err := os.MkdirAll(filepath.Join(d, "elasticsearch", "transform", "foo", "fields"), 0o755)
54+
require.NoError(t, err)
55+
err = os.MkdirAll(filepath.Join(d, "elasticsearch", "transform", "bar", "fields"), 0o755)
56+
require.NoError(t, err)
57+
err = os.WriteFile(filepath.Join(d, "elasticsearch", "transform", "foo", "fields", "fields.yml"), []byte(`
58+
- name: field1
59+
type: keyword
60+
- name: field2
61+
type: keyword
62+
- name: field3
63+
type: keyword
64+
`), 0o644)
65+
require.NoError(t, err)
66+
err = os.WriteFile(filepath.Join(d, "elasticsearch", "transform", "foo", "fields", "more-fields.yml"), []byte(`
67+
- name: field1
68+
type: keyword
69+
`), 0o644)
70+
require.NoError(t, err)
71+
err = os.WriteFile(filepath.Join(d, "elasticsearch", "transform", "bar", "fields", "fields.yml"), []byte(`
72+
- name: field1
73+
type: keyword
74+
`), 0o644)
75+
require.NoError(t, err)
76+
77+
errs := validateFieldsLimits(fspath.DirFS(d), 1)
78+
require.Len(t, errs, 1)
79+
assert.EqualError(t, errs[0], "transform foo has more than 1 fields (4)")
80+
})
81+
t.Run("input package with too many fields", func(t *testing.T) {
82+
d := t.TempDir()
83+
84+
err := os.MkdirAll(filepath.Join(d, "fields"), 0o755)
85+
require.NoError(t, err)
86+
err = os.WriteFile(filepath.Join(d, "fields", "fields.yml"), []byte(`
87+
- name: field1
88+
type: keyword
89+
- name: field2
90+
type: keyword
91+
- name: field3
92+
type: keyword
93+
`), 0o644)
94+
require.NoError(t, err)
95+
err = os.WriteFile(filepath.Join(d, "fields", "more-fields.yml"), []byte(`
96+
- name: field1
97+
type: keyword
98+
`), 0o644)
99+
require.NoError(t, err)
100+
101+
errs := validateFieldsLimits(fspath.DirFS(d), 1)
102+
require.Len(t, errs, 1)
103+
assert.EqualError(t, errs[0], "input package has more than 1 fields (4)")
104+
})
105+
}

0 commit comments

Comments
 (0)