-
Notifications
You must be signed in to change notification settings - Fork 73
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add compliance tests for 3.1.0 #709
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
Feature: Field types | ||
Check support for field types that have been added since Fleet exists. | ||
|
||
@3.1.0 | ||
Scenario: Package uses the "counted_keyword" type | ||
Given the "counted_keyword" package is installed | ||
And a policy is created with "counted_keyword" package | ||
Then index template "metrics-counted_keyword.foo" has a field "foo.count" with "type:counted_keyword" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
Feature: Subobjects | ||
Support to disable subobjects in object fields. | ||
|
||
@3.1.0 | ||
Scenario: Installer leverages subobjects false | ||
Given the "subobjects_false" package is installed | ||
And a policy is created with "subobjects_false" package | ||
Then index template "metrics-subobjects_false.foo" has a field "foo.object" with "subobjects:false" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the main reason to stop using the typed API, with this one there is no way to check if a property has the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be great to be able to use the typed API, but it's true that not using it give us more flexibility. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, the typed API is quite nice, but limited for some things, and complicated for dynamic objects in responses. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,22 +5,94 @@ | |
package main | ||
|
||
import ( | ||
"encoding/json" | ||
"errors" | ||
"fmt" | ||
"reflect" | ||
"strconv" | ||
"strings" | ||
|
||
"github.com/elastic/go-elasticsearch/v8/typedapi/types" | ||
) | ||
|
||
// IndexTemplate contains the result of getting an index template, decoded | ||
// from json into a map. | ||
type IndexTemplate struct { | ||
IndexPatterns []string `json:"index_patterns"` | ||
} | ||
|
||
// SimulatedIndexTemplate contains the result of simulating an index template, | ||
// with the component templates resolved. | ||
type SimulatedIndexTemplate struct { | ||
types.Template | ||
Mappings struct { | ||
Runtime map[string]MappingProperty `json:"runtime"` | ||
Properties map[string]MappingProperty `json:"properties"` | ||
} `json:"mappings"` | ||
} | ||
|
||
// MappingProperty is the definition of a property in an index template. | ||
type MappingProperty map[string]any | ||
|
||
// CheckCondition checks if a property satisfies a condition. Conditions are in the | ||
// form key:value, where the key and the value are compared with attributes of the | ||
// property. | ||
func (p MappingProperty) CheckCondition(condition string) bool { | ||
key, value, ok := strings.Cut(condition, ":") | ||
if !ok { | ||
panic("cannot understand condition " + condition) | ||
} | ||
|
||
v, ok := p[strings.TrimSpace(key)] | ||
if !ok { | ||
return false | ||
} | ||
|
||
switch v := v.(type) { | ||
case string: | ||
return strings.TrimSpace(value) == strings.TrimSpace(v) | ||
case bool: | ||
expected, err := strconv.ParseBool(value) | ||
return err != nil || expected == v | ||
case json.Number: | ||
expected, err := strconv.ParseInt(value, 10, 64) | ||
if err != nil { | ||
return false | ||
} | ||
n, err := v.Int64() | ||
if err != nil { | ||
return false | ||
} | ||
return expected == n | ||
} | ||
|
||
return false | ||
} | ||
|
||
// Properties returns the child properties of this property. | ||
func (p MappingProperty) Properties() (map[string]MappingProperty, error) { | ||
properties, ok := p["properties"] | ||
if !ok { | ||
return nil, nil | ||
} | ||
mapProperties, ok := properties.(map[string]any) | ||
if !ok { | ||
return nil, errors.New("not a map") | ||
} | ||
|
||
result := make(map[string]MappingProperty) | ||
for k, v := range mapProperties { | ||
anyMap, ok := v.(map[string]any) | ||
if !ok { | ||
return nil, errors.New("not a map") | ||
} | ||
result[k] = MappingProperty(anyMap) | ||
} | ||
|
||
return result, nil | ||
} | ||
|
||
// FieldMapping looks for the definition of a field in the simulated index template. | ||
func (t *SimulatedIndexTemplate) FieldMapping(name string) (any, error) { | ||
func (t *SimulatedIndexTemplate) FieldMapping(name string) (MappingProperty, error) { | ||
if runtimeField, isRuntime := t.Mappings.Runtime[name]; isRuntime { | ||
// TODO: Look for some solution to don't need to modify the properties. | ||
runtimeField["runtime"] = true | ||
return runtimeField, nil | ||
} | ||
|
||
|
@@ -35,19 +107,9 @@ func (t *SimulatedIndexTemplate) FieldMapping(name string) (any, error) { | |
return property, nil | ||
} | ||
|
||
// Using reflect because Property type is defined as any and there are too many | ||
// possible matching types. | ||
value := reflect.ValueOf(property).Elem() | ||
if value.Kind() != reflect.Struct { | ||
return nil, fmt.Errorf("property %q not found in index template, unexpected parent kind %s", name, value.Kind()) | ||
} | ||
nextPropertiesValue := value.FieldByName("Properties") | ||
if nextPropertiesValue.IsZero() { | ||
return nil, fmt.Errorf("property %q not found in index template, zero properties", name) | ||
} | ||
nextProperties, ok := nextPropertiesValue.Interface().(map[string]types.Property) | ||
if !ok { | ||
return nil, fmt.Errorf("property %q not found in index template, cannot convert properties", name) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Another problem of the typed API is that we ended up relying on reflection for some things. |
||
nextProperties, err := property.Properties() | ||
if err != nil { | ||
return nil, fmt.Errorf("property %q not found in index template: %w", name, err) | ||
} | ||
properties = nextProperties | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could it be used a non released spec version here too ? Would it make sense ?
I was thinking of adding here also the current
3.0.5-next
version as a version to comply too (so we have the stable and the next one).Or just use
compliance_test 8.12.0 3.0.5-next
?It's also true that there is no test package with version
3.0.*
currentlyThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Umm, actually I did some changes to be able to test with unreleased versions, in principle we could have tested 3.0.5 without the
next
suffix, as is done with3.1.0
.