Skip to content

Commit 6211e3a

Browse files
authored
feat: standalone targeting, fractional shorthand (#168)
This PR does 2 things: - Allows for fractional targeting shorthand where no weight (assumes weight = 1) - Allows the targeting.json schema to be used alone, not just as part of the flag definition schema Non functionally, it restructures our testing so that tests pertaining to `targeting.json` exist in the `test/targeting/` dir, while tests pertaining to the `flags.json` exist in the `test/flags` dir. Fixes: #165 --------- Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
1 parent 1ba4b03 commit 6211e3a

35 files changed

+530
-650
lines changed

json/flagd_definitions_test.go

+27-10
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

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

36-
func TestNegativeParsing(t *testing.T) {
37-
if err := walkPath(false, "./test/negative"); err != nil {
39+
func TestNegativeFlagParsing(t *testing.T) {
40+
if err := walkPath(false, "./test/flags/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/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/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/flags.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"$id": "https://flagd.dev/schema/v0/flags.json",
33
"$schema": "http://json-schema.org/draft-07/schema#",
44
"title": "flagd Flag Configuration",
5-
"description": "Defines flags for use in flagd, including typed variants and rules",
5+
"description": "Defines flags for use in flagd, including typed variants and rules.",
66
"type": "object",
77
"properties": {
88
"flags": {
@@ -46,7 +46,7 @@
4646
"patternProperties": {
4747
"^.{1,}$": {
4848
"$comment": "this relative ref means that targeting.json MUST be in the same dir, or available on the same HTTP path",
49-
"$ref": "./targeting.json#/definitions/targeting"
49+
"$ref": "./targeting.json"
5050
}
5151
}
5252
}
@@ -71,7 +71,7 @@
7171
"type": "string"
7272
},
7373
"targeting": {
74-
"$ref": "./targeting.json#/definitions/targeting"
74+
"$ref": "./targeting.json"
7575
}
7676
},
7777
"required": [

json/flags.yaml

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
$id: "https://flagd.dev/schema/v0/flags.json"
22
$schema: http://json-schema.org/draft-07/schema#
33
title: flagd Flag Configuration
4-
description: Defines flags for use in flagd, including typed variants and rules
4+
description: Defines flags for use in flagd, including typed variants and rules.
55
type: object
66
properties:
77
flags:
@@ -35,7 +35,7 @@ properties:
3535
"^.{1,}$":
3636
$comment: this relative ref means that targeting.json MUST be in the same
3737
dir, or available on the same HTTP path
38-
$ref: "./targeting.json#/definitions/targeting"
38+
$ref: "./targeting.json"
3939
definitions:
4040
flag:
4141
$comment: base flag object; no title/description here, allows for better UX,
@@ -56,7 +56,7 @@ definitions:
5656
if the targeting returns null).
5757
type: string
5858
targeting:
59-
$ref: "./targeting.json#/definitions/targeting"
59+
$ref: "./targeting.json"
6060
required:
6161
- state
6262
- defaultVariant

json/targeting.json

+13-17
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,20 @@
22
"$id": "https://flagd.dev/schema/v0/targeting.json",
33
"$schema": "http://json-schema.org/draft-07/schema#",
44
"title": "flagd Targeting",
5-
"description": "Defines targeting logic for flagd; a extension of JSONLogic, including purpose-built feature-flagging operations.",
5+
"description": "Defines targeting logic for flagd; a extension of JSONLogic, including purpose-built feature-flagging operations. Note that this schema applies to top-level objects; no additional properties are supported, including \"$schema\", which means built-in JSON-schema support is not possible in editors. Please use flags.json (which imports this schema) for a rich editor experience.",
66
"type": "object",
7-
"definitions": {
8-
"targeting": {
9-
"title": "Targeting",
10-
"description": "An expression returning a value which is coerced to a string to be used as a targeting key, or null (to fall back to defaultVariant). If targeting returns a value which is not a variant key, it's considered an error.",
11-
"anyOf": [
12-
{
13-
"$comment": "we need this to support empty targeting",
14-
"type": "object",
15-
"additionalProperties": false,
16-
"properties": {}
17-
},
18-
{
19-
"$ref": "#/definitions/anyRule"
20-
}
21-
]
7+
"anyOf": [
8+
{
9+
"$comment": "we need this to support empty targeting",
10+
"type": "object",
11+
"additionalProperties": false,
12+
"properties": {}
2213
},
14+
{
15+
"$ref": "#/definitions/anyRule"
16+
}
17+
],
18+
"definitions": {
2319
"primitive": {
2420
"oneOf": [
2521
{
@@ -462,7 +458,7 @@
462458
"$comment": "if we remove the \"sum to 100\" restriction, update the descriptions below!",
463459
"description": "Distribution for all possible variants, with their associated weighting out of 100.",
464460
"type": "array",
465-
"minItems": 2,
461+
"minItems": 1,
466462
"maxItems": 2,
467463
"items": [
468464
{

0 commit comments

Comments
 (0)