@@ -26,6 +26,8 @@ import (
2626 "github.com/elastic/elastic-package/internal/packages/buildmanifest"
2727)
2828
29+ var semver2_0_0 = semver .MustParse ("2.0.0" )
30+
2931// Validator is responsible for fields validation.
3032type Validator struct {
3133 // Schema contains definition records.
@@ -195,31 +197,27 @@ func (v *Validator) ValidateDocumentBody(body json.RawMessage) multierror.Error
195197 return errs
196198 }
197199
198- errs := v .validateMapElement ("" , c )
199- if len (errs ) == 0 {
200- return nil
201- }
202- return errs
200+ return v .ValidateDocumentMap (c )
203201}
204202
205203// ValidateDocumentMap validates the provided document as common.MapStr.
206204func (v * Validator ) ValidateDocumentMap (body common.MapStr ) multierror.Error {
207- errs := v .validateMapElement ("" , body )
205+ errs := v .validateMapElement ("" , body , body )
208206 if len (errs ) == 0 {
209207 return nil
210208 }
211209 return errs
212210}
213211
214- func (v * Validator ) validateMapElement (root string , elem common.MapStr ) multierror.Error {
212+ func (v * Validator ) validateMapElement (root string , elem common.MapStr , doc common. MapStr ) multierror.Error {
215213 var errs multierror.Error
216214 for name , val := range elem {
217215 key := strings .TrimLeft (root + "." + name , "." )
218216
219217 switch val := val .(type ) {
220218 case []map [string ]interface {}:
221219 for _ , m := range val {
222- err := v .validateMapElement (key , m )
220+ err := v .validateMapElement (key , m , doc )
223221 if err != nil {
224222 errs = append (errs , err ... )
225223 }
@@ -230,12 +228,12 @@ func (v *Validator) validateMapElement(root string, elem common.MapStr) multierr
230228 // because the entire object is mapped as a single field.
231229 continue
232230 }
233- err := v .validateMapElement (key , val )
231+ err := v .validateMapElement (key , val , doc )
234232 if err != nil {
235233 errs = append (errs , err ... )
236234 }
237235 default :
238- err := v .validateScalarElement (key , val )
236+ err := v .validateScalarElement (key , val , doc )
239237 if err != nil {
240238 errs = append (errs , err )
241239 }
@@ -244,7 +242,7 @@ func (v *Validator) validateMapElement(root string, elem common.MapStr) multierr
244242 return errs
245243}
246244
247- func (v * Validator ) validateScalarElement (key string , val interface {}) error {
245+ func (v * Validator ) validateScalarElement (key string , val interface {}, doc common. MapStr ) error {
248246 if key == "" {
249247 return nil // root key is always valid
250248 }
@@ -276,7 +274,7 @@ func (v *Validator) validateScalarElement(key string, val interface{}) error {
276274 return errors .Wrapf (err , "field %q is not normalized as expected" , key )
277275 }
278276
279- err = v .parseElementValue (key , * definition , val )
277+ err = v .parseElementValue (key , * definition , val , doc )
280278 if err != nil {
281279 return errors .Wrap (err , "parsing field value failed" )
282280 }
@@ -384,7 +382,7 @@ func compareKeys(key string, def FieldDefinition, searchedKey string) bool {
384382
385383func (v * Validator ) validateExpectedNormalization (definition FieldDefinition , val interface {}) error {
386384 // Validate expected normalization starting with packages following spec v2 format.
387- if v .specVersion .LessThan (semver . MustParse ( "2.0.0" ) ) {
385+ if v .specVersion .LessThan (semver2_0_0 ) {
388386 return nil
389387 }
390388 for _ , normalize := range definition .Normalize {
@@ -433,11 +431,11 @@ func validSubField(def FieldDefinition, extraPart string) bool {
433431
434432// parseElementValue checks that the value stored in a field matches the field definition. For
435433// arrays it checks it for each Element.
436- func (v * Validator ) parseElementValue (key string , definition FieldDefinition , val interface {}) error {
437- return forEachElementValue (key , definition , val , v .parseSingleElementValue )
434+ func (v * Validator ) parseElementValue (key string , definition FieldDefinition , val interface {}, doc common. MapStr ) error {
435+ return forEachElementValue (key , definition , val , doc , v .parseSingleElementValue )
438436}
439437
440- func (v * Validator ) parseSingleElementValue (key string , definition FieldDefinition , val interface {}) error {
438+ func (v * Validator ) parseSingleElementValue (key string , definition FieldDefinition , val interface {}, doc common. MapStr ) error {
441439 invalidTypeError := func () error {
442440 return fmt .Errorf ("field %q's Go type, %T, does not match the expected field type: %s (field value: %v)" , key , val , definition .Type , val )
443441 }
@@ -461,6 +459,11 @@ func (v *Validator) parseSingleElementValue(key string, definition FieldDefiniti
461459 if err := ensureAllowedValues (key , valStr , definition ); err != nil {
462460 return err
463461 }
462+ if ! v .specVersion .LessThan (semver2_0_0 ) {
463+ if err := ensureExpectedEventType (key , valStr , definition , doc ); err != nil {
464+ return err
465+ }
466+ }
464467 // Normal text fields should be of type string.
465468 // If a pattern is provided, it checks if the value matches.
466469 case "keyword" , "text" :
@@ -475,6 +478,11 @@ func (v *Validator) parseSingleElementValue(key string, definition FieldDefiniti
475478 if err := ensureAllowedValues (key , valStr , definition ); err != nil {
476479 return err
477480 }
481+ if ! v .specVersion .LessThan (semver2_0_0 ) {
482+ if err := ensureExpectedEventType (key , valStr , definition , doc ); err != nil {
483+ return err
484+ }
485+ }
478486 // Dates are expected to be formatted as strings or as seconds or milliseconds
479487 // since epoch.
480488 // If it is a string and a pattern is provided, it checks if the value matches.
@@ -563,13 +571,13 @@ func (v *Validator) isAllowedIPValue(s string) bool {
563571
564572// forEachElementValue visits a function for each element in the given value if
565573// it is an array. If it is not an array, it calls the function with it.
566- func forEachElementValue (key string , definition FieldDefinition , val interface {}, fn func (string , FieldDefinition , interface {}) error ) error {
574+ func forEachElementValue (key string , definition FieldDefinition , val interface {}, doc common. MapStr , fn func (string , FieldDefinition , interface {}, common. MapStr ) error ) error {
567575 arr , isArray := val .([]interface {})
568576 if ! isArray {
569- return fn (key , definition , val )
577+ return fn (key , definition , val , doc )
570578 }
571579 for _ , element := range arr {
572- err := fn (key , definition , element )
580+ err := fn (key , definition , element , doc )
573581 if err != nil {
574582 return err
575583 }
@@ -616,3 +624,14 @@ func ensureAllowedValues(key, value string, definition FieldDefinition) error {
616624 }
617625 return nil
618626}
627+
628+ // ensureExpectedEventType validates that the document's `event.type` field is one of the expected
629+ // one for the given value.
630+ func ensureExpectedEventType (key , value string , definition FieldDefinition , doc common.MapStr ) error {
631+ eventType , _ := doc .GetValue ("event.type" )
632+ if ! definition .AllowedValues .IsExpectedEventType (value , eventType ) {
633+ expected := definition .AllowedValues .ExpectedEventTypes (value )
634+ return fmt .Errorf ("field \" event.type\" value \" %v\" (%T) is not one of the expected values (%s) for %s=%q" , eventType , eventType , strings .Join (expected , ", " ), key , value )
635+ }
636+ return nil
637+ }
0 commit comments