in internal/fields/dependency_manager.go [201:262]
func (dm *DependencyManager) injectFieldsWithOptions(defs []common.MapStr, options InjectFieldsOptions) ([]common.MapStr, bool, error) {
var updated []common.MapStr
var changed bool
for _, def := range defs {
fieldPath := buildFieldPath(options.root, def)
external, _ := def.GetValue("external")
if external != nil {
imported, err := dm.importField(external.(string), fieldPath)
if err != nil {
return nil, false, fmt.Errorf("can't import field: %w", err)
}
if imported.disallowAtTopLevel && options.DisallowReusableECSFieldsAtTopLevel {
return nil, false, fmt.Errorf("field %s cannot be reused at top level", fieldPath)
}
transformed := transformImportedField(imported, options)
// Allow overrides of everything, except the imported type, for consistency.
transformed.DeepUpdate(def)
if !options.KeepExternal {
transformed.Delete("external")
}
// Set the type back to the one imported, unless it is one of the allowed overrides.
if ttype, _ := transformed["type"].(string); !allowedTypeOverride(imported.Type, ttype) {
transformed["type"] = imported.Type
}
def = transformed
changed = true
} else {
fields, _ := def.GetValue("fields")
if fields != nil {
fieldsMs, err := common.ToMapStrSlice(fields)
if err != nil {
return nil, false, fmt.Errorf("can't convert fields: %w", err)
}
childrenOptions := options
childrenOptions.root = fieldPath
updatedFields, fieldsChanged, err := dm.injectFieldsWithOptions(fieldsMs, childrenOptions)
if err != nil {
return nil, false, err
}
if fieldsChanged {
changed = true
}
def.Put("fields", updatedFields)
}
}
if options.SkipEmptyFields && skipField(def) {
changed = true
continue
}
updated = append(updated, def)
}
return updated, changed, nil
}