feat: add targeting validation (#1146)
- adds targeting validation - updates sample json files - updates schemas modules to most recent release Closes #1140 Signed-off-by: Best Olunusi <olunusibest@gmail.com> Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
This commit is contained in:
parent
2adfa573a2
commit
b727dd00c5
|
|
@ -12,7 +12,7 @@ require (
|
|||
github.com/fsnotify/fsnotify v1.7.0
|
||||
github.com/golang/mock v1.6.0
|
||||
github.com/open-feature/open-feature-operator/apis v0.2.38-0.20231117101310-726a7f714906
|
||||
github.com/open-feature/schemas v0.2.8
|
||||
github.com/open-feature/schemas v0.2.9-0.20240115143711-4a0be4f48816
|
||||
github.com/prometheus/client_golang v1.18.0
|
||||
github.com/robfig/cron v1.2.0
|
||||
github.com/rs/cors v1.10.1
|
||||
|
|
|
|||
|
|
@ -640,6 +640,8 @@ github.com/open-feature/open-feature-operator/apis v0.2.38-0.20231117101310-726a
|
|||
github.com/open-feature/open-feature-operator/apis v0.2.38-0.20231117101310-726a7f714906/go.mod h1:YtdYEXJHo9iKwmchxbwGGsmu33FbugMQ8lKGarA9UYM=
|
||||
github.com/open-feature/schemas v0.2.8 h1:oA75hJXpOd9SFgmNI2IAxWZkwzQPUDm7Jyyh3q489wM=
|
||||
github.com/open-feature/schemas v0.2.8/go.mod h1:vj+rfTsOLlh5PtGGkAbitnJmFPYuTHXTjOy13kzNgKQ=
|
||||
github.com/open-feature/schemas v0.2.9-0.20240115143711-4a0be4f48816 h1:8F+uUDbw/Qa192HXfxfoLf/RkVAhFLImTH6uYzhaLz8=
|
||||
github.com/open-feature/schemas v0.2.9-0.20240115143711-4a0be4f48816/go.mod h1:5tZlsJkdP1CiBHWrGUbDQxpCAVNTG851yAbmUrfji1M=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
|
|
|
|||
|
|
@ -400,16 +400,38 @@ func getFlagdProperties(context map[string]any) (flagdProperties, bool) {
|
|||
return p, true
|
||||
}
|
||||
|
||||
func (je *JSON) loadAndCompileSchema() *gojsonschema.Schema {
|
||||
schemaLoader := gojsonschema.NewSchemaLoader()
|
||||
|
||||
// compile dependency schema
|
||||
targetingSchemaLoader := gojsonschema.NewStringLoader(schema.Targeting)
|
||||
if err := schemaLoader.AddSchemas(targetingSchemaLoader); err != nil {
|
||||
je.Logger.Warn(fmt.Sprintf("error adding Targeting schema: %s", err))
|
||||
}
|
||||
|
||||
// compile root schema
|
||||
flagdDefinitionsLoader := gojsonschema.NewStringLoader(schema.FlagdDefinitions)
|
||||
compiledSchema, err := schemaLoader.Compile(flagdDefinitionsLoader)
|
||||
if err != nil {
|
||||
je.Logger.Warn(fmt.Sprintf("error compiling FlagdDefinitions schema: %s", err))
|
||||
}
|
||||
|
||||
return compiledSchema
|
||||
}
|
||||
|
||||
// configToFlags convert string configurations to flags and store them to pointer newFlags
|
||||
func (je *JSON) configToFlags(config string, newFlags *Flags) error {
|
||||
schemaLoader := gojsonschema.NewStringLoader(schema.FlagdDefinitions)
|
||||
compiledSchema := je.loadAndCompileSchema()
|
||||
|
||||
flagStringLoader := gojsonschema.NewStringLoader(config)
|
||||
|
||||
result, err := gojsonschema.Validate(schemaLoader, flagStringLoader)
|
||||
result, err := compiledSchema.Validate(flagStringLoader)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error validating json schema: %w", err)
|
||||
je.Logger.Warn(fmt.Sprintf("failed to execute JSON schema validation: %s", err))
|
||||
} else if !result.Valid() {
|
||||
return fmt.Errorf("JSON schema validation failed: %s", buildErrorString(result.Errors()))
|
||||
je.Logger.Warn(fmt.Sprintf(
|
||||
"flag definition does not conform to the schema; validation errors: %s", buildErrorString(result.Errors()),
|
||||
))
|
||||
}
|
||||
|
||||
transposedConfig, err := je.transposeEvaluators(config)
|
||||
|
|
|
|||
|
|
@ -973,6 +973,112 @@ func TestState_Evaluator(t *testing.T) {
|
|||
inputSyncType: sync.ALL,
|
||||
expectedError: true,
|
||||
},
|
||||
"invalid targeting": {
|
||||
inputState: `
|
||||
{
|
||||
"flags": {
|
||||
"fibAlgo": {
|
||||
"variants": {
|
||||
"recursive": "recursive",
|
||||
"memo": "memo",
|
||||
"loop": "loop",
|
||||
"binet": "binet"
|
||||
},
|
||||
"defaultVariant": "recursive",
|
||||
"state": "ENABLED",
|
||||
"source":"",
|
||||
"targeting": {
|
||||
"if": [
|
||||
{
|
||||
"in": ["@faas.com", {
|
||||
"var": ["email"]
|
||||
}]
|
||||
}, "binet", "null", "loop"
|
||||
]
|
||||
}
|
||||
},
|
||||
"isColorYellow": {
|
||||
"state": "ENABLED",
|
||||
"variants": {
|
||||
"on": true,
|
||||
"off": false
|
||||
},
|
||||
"defaultVariant": "off",
|
||||
"source":"",
|
||||
"targeting": {
|
||||
"if": [
|
||||
{
|
||||
"==": [
|
||||
{
|
||||
"varr": ["color"]
|
||||
},
|
||||
"yellow"
|
||||
]
|
||||
},
|
||||
"on",
|
||||
"off",
|
||||
"none"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"flagSources":null
|
||||
}
|
||||
`,
|
||||
inputSyncType: sync.ALL,
|
||||
expectedError: false,
|
||||
expectedOutputState: `
|
||||
{
|
||||
"flags": {
|
||||
"fibAlgo": {
|
||||
"variants": {
|
||||
"recursive": "recursive",
|
||||
"memo": "memo",
|
||||
"loop": "loop",
|
||||
"binet": "binet"
|
||||
},
|
||||
"defaultVariant": "recursive",
|
||||
"state": "ENABLED",
|
||||
"source":"",
|
||||
"targeting": {
|
||||
"if": [
|
||||
{
|
||||
"in": ["@faas.com", {
|
||||
"var": ["email"]
|
||||
}]
|
||||
}, "binet", "null", "loop"
|
||||
]
|
||||
}
|
||||
},
|
||||
"isColorYellow": {
|
||||
"state": "ENABLED",
|
||||
"variants": {
|
||||
"on": true,
|
||||
"off": false
|
||||
},
|
||||
"defaultVariant": "off",
|
||||
"source":"",
|
||||
"targeting": {
|
||||
"if": [
|
||||
{
|
||||
"==": [
|
||||
{
|
||||
"varr": ["color"]
|
||||
},
|
||||
"yellow"
|
||||
]
|
||||
},
|
||||
"on",
|
||||
"off",
|
||||
"none"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"flagSources":null
|
||||
}
|
||||
`,
|
||||
},
|
||||
"empty evaluator": {
|
||||
inputState: `
|
||||
{
|
||||
|
|
|
|||
|
|
@ -56,9 +56,7 @@
|
|||
{
|
||||
"==": [
|
||||
{
|
||||
"var": [
|
||||
"color"
|
||||
]
|
||||
"var": ["color"]
|
||||
},
|
||||
"yellow"
|
||||
]
|
||||
|
|
@ -81,7 +79,9 @@
|
|||
"if": [
|
||||
{
|
||||
"$ref": "emailWithFaas"
|
||||
}, "binet", null
|
||||
},
|
||||
"binet",
|
||||
null
|
||||
]
|
||||
}
|
||||
},
|
||||
|
|
@ -100,35 +100,27 @@
|
|||
"$ref": "emailWithFaas"
|
||||
},
|
||||
{
|
||||
"fractionalEvaluation": [
|
||||
"email",
|
||||
[
|
||||
"red",
|
||||
25
|
||||
],
|
||||
[
|
||||
"blue",
|
||||
25
|
||||
],
|
||||
[
|
||||
"green",
|
||||
25
|
||||
],
|
||||
[
|
||||
"yellow",
|
||||
25
|
||||
]
|
||||
"fractional": [
|
||||
{ "var": "email" },
|
||||
["red", 25],
|
||||
["blue", 25],
|
||||
["green", 25],
|
||||
["yellow", 25]
|
||||
]
|
||||
}, null
|
||||
},
|
||||
null
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"$evaluators": {
|
||||
"emailWithFaas": {
|
||||
"in": ["@faas.com", {
|
||||
"var": ["email"]
|
||||
}]
|
||||
"in": [
|
||||
"@faas.com",
|
||||
{
|
||||
"var": ["email"]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,8 +69,9 @@ flags:
|
|||
targeting:
|
||||
if:
|
||||
- "$ref": emailWithFaas
|
||||
- fractionalEvaluation:
|
||||
- email
|
||||
- fractional:
|
||||
- var:
|
||||
- email
|
||||
- - red
|
||||
- 25
|
||||
- - blue
|
||||
|
|
|
|||
|
|
@ -56,9 +56,7 @@
|
|||
{
|
||||
"==": [
|
||||
{
|
||||
"var": [
|
||||
"color"
|
||||
]
|
||||
"var": ["color"]
|
||||
},
|
||||
"yellow"
|
||||
]
|
||||
|
|
@ -81,7 +79,9 @@
|
|||
"if": [
|
||||
{
|
||||
"$ref": "emailWithFaas"
|
||||
}, "binet", null
|
||||
},
|
||||
"binet",
|
||||
null
|
||||
]
|
||||
}
|
||||
},
|
||||
|
|
@ -100,35 +100,27 @@
|
|||
"$ref": "emailWithFaas"
|
||||
},
|
||||
{
|
||||
"fractionalEvaluation": [
|
||||
"email",
|
||||
[
|
||||
"red",
|
||||
25
|
||||
],
|
||||
[
|
||||
"blue",
|
||||
25
|
||||
],
|
||||
[
|
||||
"green",
|
||||
25
|
||||
],
|
||||
[
|
||||
"yellow",
|
||||
25
|
||||
]
|
||||
"fractional": [
|
||||
{ "var": "email" },
|
||||
["red", 25],
|
||||
["blue", 25],
|
||||
["green", 25],
|
||||
["yellow", 25]
|
||||
]
|
||||
}, null
|
||||
},
|
||||
null
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"$evaluators": {
|
||||
"emailWithFaas": {
|
||||
"in": ["@faas.com", {
|
||||
"var": ["email"]
|
||||
}]
|
||||
"in": [
|
||||
"@faas.com",
|
||||
{
|
||||
"var": ["email"]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,8 +69,9 @@ flags:
|
|||
targeting:
|
||||
if:
|
||||
- "$ref": emailWithFaas
|
||||
- fractionalEvaluation:
|
||||
- email
|
||||
- fractional:
|
||||
- var:
|
||||
- email
|
||||
- - red
|
||||
- 25
|
||||
- - blue
|
||||
|
|
|
|||
2
schemas
2
schemas
|
|
@ -1 +1 @@
|
|||
Subproject commit f3e419c5ea676b6e0a4384b1ba3c9ad43b047eed
|
||||
Subproject commit 4a0be4f48816ea0ac83d909ae58b8dcf5acda4b8
|
||||
Loading…
Reference in New Issue