Skip to content

Commit fdb4ec1

Browse files
committed
feat: standalone targeting, fractional shorthand
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
1 parent 1ba4b03 commit fdb4ec1

File tree

6 files changed

+120
-10
lines changed

6 files changed

+120
-10
lines changed

json/flagd_definitions_test.go

+25-8
Original file line numberDiff line numberDiff line change
@@ -13,34 +13,51 @@ import (
1313
"github.com/xeipuuv/gojsonschema"
1414
)
1515

16-
var compiledSchema *gojsonschema.Schema
16+
var compiledFlagDefinitionSchema *gojsonschema.Schema
17+
var compiledTargetingSchema *gojsonschema.Schema
1718

1819
func init() {
19-
schemaLoader := gojsonschema.NewSchemaLoader()
20-
schemaLoader.AddSchemas(gojsonschema.NewStringLoader(flagd_definitions.TargetingSchema))
20+
flagDefinitionSchemaLoader := gojsonschema.NewSchemaLoader()
21+
flagDefinitionSchemaLoader.AddSchemas(gojsonschema.NewStringLoader(flagd_definitions.TargetingSchema))
22+
targetingSchemaLoader := gojsonschema.NewSchemaLoader()
2123
var err error
22-
compiledSchema, err = schemaLoader.Compile(gojsonschema.NewStringLoader(flagd_definitions.FlagSchema))
24+
compiledFlagDefinitionSchema, err = flagDefinitionSchemaLoader.Compile(gojsonschema.NewStringLoader(flagd_definitions.FlagSchema))
25+
compiledTargetingSchema, err = targetingSchemaLoader.Compile(gojsonschema.NewStringLoader(flagd_definitions.TargetingSchema))
2326
if err != nil {
2427
message := fmt.Errorf("err: %v", err)
2528
log.Fatal(message)
2629
}
2730
}
2831

2932
func TestPositiveParsing(t *testing.T) {
30-
if err := walkPath(true, "./test/positive"); err != nil {
33+
if err := walkPath(true, "./test/positive", compiledFlagDefinitionSchema); err != nil {
3134
t.Error(err)
3235
t.FailNow()
3336
}
3437
}
3538

3639
func TestNegativeParsing(t *testing.T) {
37-
if err := walkPath(false, "./test/negative"); err != nil {
40+
if err := walkPath(false, "./test/negative", compiledFlagDefinitionSchema); err != nil {
3841
t.Error(err)
3942
t.FailNow()
4043
}
4144
}
4245

43-
func walkPath(shouldPass bool, root string) error {
46+
func TestPositiveTargetingParsing(t *testing.T) {
47+
if err := walkPath(true, "./test/targeting-only/positive", compiledTargetingSchema); err != nil {
48+
t.Error(err)
49+
t.FailNow()
50+
}
51+
}
52+
53+
func TestNegativeTargetingParsing(t *testing.T) {
54+
if err := walkPath(false, "./test/targeting-only/negative", compiledTargetingSchema); err != nil {
55+
t.Error(err)
56+
t.FailNow()
57+
}
58+
}
59+
60+
func walkPath(shouldPass bool, root string, schema *gojsonschema.Schema) error {
4461
return filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
4562
if err != nil {
4663
return err
@@ -56,7 +73,7 @@ func walkPath(shouldPass bool, root string) error {
5673

5774
flagStringLoader := gojsonschema.NewStringLoader(string(file))
5875

59-
p, err := compiledSchema.Validate(flagStringLoader)
76+
p, err := schema.Validate(flagStringLoader)
6077
if err != nil {
6178
return err
6279
}

json/targeting.json

+6-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44
"title": "flagd Targeting",
55
"description": "Defines targeting logic for flagd; a extension of JSONLogic, including purpose-built feature-flagging operations.",
66
"type": "object",
7+
"properties": {
8+
"targeting": {
9+
"$ref": "#/definitions/targeting"
10+
}
11+
},
712
"definitions": {
813
"targeting": {
914
"title": "Targeting",
@@ -462,7 +467,7 @@
462467
"$comment": "if we remove the \"sum to 100\" restriction, update the descriptions below!",
463468
"description": "Distribution for all possible variants, with their associated weighting out of 100.",
464469
"type": "array",
465-
"minItems": 2,
470+
"minItems": 1,
466471
"maxItems": 2,
467472
"items": [
468473
{

json/targeting.yaml

+4-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ title: flagd Targeting
44
description: Defines targeting logic for flagd; a extension of JSONLogic, including
55
purpose-built feature-flagging operations.
66
type: object
7+
properties:
8+
targeting:
9+
$ref: "#/definitions/targeting"
710
definitions:
811
targeting:
912
title: Targeting
@@ -363,7 +366,7 @@ definitions:
363366
description: Distribution for all possible variants, with their associated weighting
364367
out of 100.
365368
type: array
366-
minItems: 2
369+
minItems: 1
367370
maxItems: 2
368371
items:
369372
- description: If this bucket is randomly selected, this string is used to as

json/test/positive/custom-ops.json

+15
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,21 @@
2525
]
2626
}
2727
},
28+
"fractional-flag-shorthand": {
29+
"state": "ENABLED",
30+
"variants": {
31+
"heads": "heads",
32+
"tails": "tails",
33+
"draw": "draw"
34+
},
35+
"defaultVariant": "draw",
36+
"targeting": {
37+
"fractional": [
38+
[ "heads" ],
39+
[ "tails", 1 ]
40+
]
41+
}
42+
},
2843
"shorthand-fractional-flag": {
2944
"state": "ENABLED",
3045
"variants": {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"$schema": "../../../targeting.json",
3+
"targeting": {
4+
"not-a-valid-rule": "lol"
5+
}
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
{
2+
"$schema": "../../../targeting.json",
3+
"targeting": {
4+
"*" : [
5+
{"if" : [false, "false", false, "false", true, "true"] },
6+
{"if" : [ true, "yes", "no" ]},
7+
{"if" : [ true, "yes" ]},
8+
{"if" : [ true ]},
9+
{"==" : [1, 1]},
10+
{"===" : [1, 1]},
11+
{"!=" : [1, 2]},
12+
{"!==" : [1, 2]},
13+
{"!": [true]},
14+
{"!": true},
15+
{"!!": ["0"] },
16+
{"or": [true, false]},
17+
{"or":[false, 0, "a"]},
18+
{"and": [true, true]},
19+
{"and":[true, "a", 3]},
20+
{">" : [2, 1]},
21+
{">=" : [1, 1]},
22+
{"<" : [1, 2]},
23+
{"<=" : [1, 1]},
24+
{"<" : [1, 2, 3]},
25+
{"<" : [1, 4, 3]},
26+
{"<=" : [1, 2, 3]},
27+
{"<=" : [1, 1, 3]},
28+
{"max":[1,2,3]},
29+
{"min":[1,2,3]},
30+
{"+":[4,2]},
31+
{"+":[2,2,2,2,2]},
32+
{"+" : [ "3.14" ]},
33+
{"/":[4,2]},
34+
{"*":[2,2,2,2,2]},
35+
{"-": [ 2 ]},
36+
{"-":[4, 2]},
37+
{"%": [101,2]},
38+
{"map":[
39+
{"var":"integers"},
40+
{"*":[{"var":""},2]}
41+
]},
42+
{"filter":[
43+
{"var":"integers"},
44+
{"%":[{"var":""},2]}
45+
]},
46+
{"reduce":[
47+
{"var":"integers"},
48+
{"+":[{"var":"current"}, {"var":"accumulator"}]},
49+
0
50+
]},
51+
{"all" : [ [1,2,3], {">":[{"var":""}, 0]} ]},
52+
{"some" : [ [-1,0,1], {">":[{"var":""}, 0]} ]},
53+
{"none" : [ [-3,-2,-1], {">":[{"var":""}, 0]} ]},
54+
{"some" : [ {"var":"pies"}, {"==":[{"var":"filling"}, "apple"]} ]},
55+
{"merge":[ [1,2], [3,4] ]},
56+
{"merge":[ 1, 2, [3,4] ]},
57+
{"in":[ "Ringo", ["John", "Paul", "George", "Ringo"] ]},
58+
{"in":["Spring", "Springfield"]},
59+
{"cat": ["I love", " pie"]},
60+
{"substr": ["jsonlogic", 4]},
61+
{"substr": ["jsonlogic", 1, 3]}
62+
]
63+
}
64+
}

0 commit comments

Comments
 (0)