Skip to content

Commit

Permalink
feat: wip pass yaml as filetype to FilePathSync
Browse files Browse the repository at this point in the history
- check `yaml.Unmarshal` not able to `Unmarshal` to `json.rawMessage` which is just `[]byte` with `MarshalJSON` and `UnmarshalJSON`
- `FileTypeEvaluator` didn't turn out to be such a good idea because we are reliant on `gojsonschema` to test json schema
- add `example_flags.yaml` file based on `examples_flags.json`
refactor: remove traces of `FileTypeEvaluator`

Signed-off-by: Suraj Banakar <surajrbanakar@gmail.com>
  • Loading branch information
vadasambar committed Nov 11, 2022
1 parent 7aa703f commit cef8463
Show file tree
Hide file tree
Showing 7 changed files with 136 additions and 34 deletions.
88 changes: 88 additions & 0 deletions config/samples/example_flags.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
flags:
myBoolFlag:
state: ENABLED
variants:
'on': true
'off': false
defaultVariant: 'on'
myStringFlag:
state: ENABLED
variants:
key1: val1
key2: val2
defaultVariant: key1
myFloatFlag:
state: ENABLED
variants:
one: 1.23
two: 2.34
defaultVariant: one
myIntFlag:
state: ENABLED
variants:
one: 1
two: 2
defaultVariant: one
myObjectFlag:
state: ENABLED
variants:
object1:
key: val
object2:
key: true
defaultVariant: object1
isColorYellow:
state: ENABLED
variants:
'on': true
'off': false
defaultVariant: 'off'
targeting:
if:
- "==":
- var:
- color
- yellow
- 'on'
- 'off'
fibAlgo:
variants:
recursive: recursive
memo: memo
loop: loop
binet: binet
defaultVariant: recursive
state: ENABLED
targeting:
if:
- "$ref": emailWithFaas
- binet
- null
headerColor:
variants:
red: "#FF0000"
blue: "#0000FF"
green: "#00FF00"
yellow: "#FFFF00"
defaultVariant: red
state: ENABLED
targeting:
if:
- "$ref": emailWithFaas
- fractionalEvaluation:
- email
- - red
- 25
- - blue
- 25
- - green
- 25
- - yellow
- 25
- null
"$evaluators":
emailWithFaas:
in:
- "@faas.com"
- var:
- email
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ require (
golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0
google.golang.org/grpc v1.49.0
google.golang.org/protobuf v1.28.1
gopkg.in/yaml.v2 v2.4.0
k8s.io/api v0.25.2
k8s.io/apimachinery v0.25.2
k8s.io/client-go v0.25.2
Expand Down Expand Up @@ -89,7 +90,6 @@ require (
google.golang.org/genproto v0.0.0-20220930163606-c98284e70a91 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/klog/v2 v2.80.1 // indirect
k8s.io/kube-openapi v0.0.0-20220928191237-829ce0c27909 // indirect
Expand Down
27 changes: 10 additions & 17 deletions pkg/eval/filetype_evaluator.go → pkg/eval/json_evaluator.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,9 @@ import (
"google.golang.org/protobuf/types/known/structpb"
)

type FileTypeEvaluator struct {
type JSONEvaluator struct {
state Flags
Logger *log.Entry
MUaler interface{}
}

// MUaler is short for `MarshalerUnmarshaler`
type MUaler interface {
Marshal(v interface{}) ([]byte, error)
Unmarshal(data []byte, v interface{}) error
}

type constraints interface {
Expand All @@ -36,15 +29,15 @@ const (
Disabled = "DISABLED"
)

func (je *FileTypeEvaluator) GetState() (string, error) {
func (je *JSONEvaluator) GetState() (string, error) {
data, err := json.Marshal(&je.state)
if err != nil {
return "", err
}
return string(data), nil
}

func (je *FileTypeEvaluator) SetState(source string, state string) ([]StateChangeNotification, error) {
func (je *JSONEvaluator) SetState(source string, state string) ([]StateChangeNotification, error) {
schemaLoader := gojsonschema.NewStringLoader(schema.FlagdDefinitions)
flagStringLoader := gojsonschema.NewStringLoader(state)
result, err := gojsonschema.Validate(schemaLoader, flagStringLoader)
Expand Down Expand Up @@ -98,7 +91,7 @@ func resolve[T constraints](key string, context *structpb.Struct,
return value, variant, reason, nil
}

func (je *FileTypeEvaluator) ResolveBooleanValue(flagKey string, context *structpb.Struct) (
func (je *JSONEvaluator) ResolveBooleanValue(flagKey string, context *structpb.Struct) (
value bool,
variant string,
reason string,
Expand All @@ -107,7 +100,7 @@ func (je *FileTypeEvaluator) ResolveBooleanValue(flagKey string, context *struct
return resolve[bool](flagKey, context, je.evaluateVariant, je.state.Flags[flagKey].Variants)
}

func (je *FileTypeEvaluator) ResolveStringValue(flagKey string, context *structpb.Struct) (
func (je *JSONEvaluator) ResolveStringValue(flagKey string, context *structpb.Struct) (
value string,
variant string,
reason string,
Expand All @@ -116,7 +109,7 @@ func (je *FileTypeEvaluator) ResolveStringValue(flagKey string, context *structp
return resolve[string](flagKey, context, je.evaluateVariant, je.state.Flags[flagKey].Variants)
}

func (je *FileTypeEvaluator) ResolveFloatValue(flagKey string, context *structpb.Struct) (
func (je *JSONEvaluator) ResolveFloatValue(flagKey string, context *structpb.Struct) (
value float64,
variant string,
reason string,
Expand All @@ -126,7 +119,7 @@ func (je *FileTypeEvaluator) ResolveFloatValue(flagKey string, context *structpb
return
}

func (je *FileTypeEvaluator) ResolveIntValue(flagKey string, context *structpb.Struct) (
func (je *JSONEvaluator) ResolveIntValue(flagKey string, context *structpb.Struct) (
value int64,
variant string,
reason string,
Expand All @@ -138,7 +131,7 @@ func (je *FileTypeEvaluator) ResolveIntValue(flagKey string, context *structpb.S
return
}

func (je *FileTypeEvaluator) ResolveObjectValue(flagKey string, context *structpb.Struct) (
func (je *JSONEvaluator) ResolveObjectValue(flagKey string, context *structpb.Struct) (
value map[string]any,
variant string,
reason string,
Expand All @@ -148,7 +141,7 @@ func (je *FileTypeEvaluator) ResolveObjectValue(flagKey string, context *structp
}

// runs the rules (if defined) to determine the variant, otherwise falling through to the default
func (je *FileTypeEvaluator) evaluateVariant(
func (je *JSONEvaluator) evaluateVariant(
flagKey string,
context *structpb.Struct,
) (variant string, reason string, err error) {
Expand Down Expand Up @@ -211,7 +204,7 @@ func validateDefaultVariants(flags Flags) error {
return nil
}

func (je *FileTypeEvaluator) transposeEvaluators(state string) (string, error) {
func (je *JSONEvaluator) transposeEvaluators(state string) (string, error) {
var evaluators Evaluators
if err := json.Unmarshal([]byte(state), &evaluators); err != nil {
return "", fmt.Errorf("unmarshal: %w", err)
Expand Down
19 changes: 12 additions & 7 deletions pkg/eval/json_evaluator_model.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,17 @@ import (
"reflect"
)

type FlagsAndEvaluators struct {
Flags map[string]Flag `json:"flags" yaml:"flags"`
Evaluators map[string]json.RawMessage `json:"$evaluators" yaml:"$evaluators"`
}

type Flags struct {
Flags map[string]Flag `json:"flags"`
Flags map[string]Flag `json:"flags" yaml:"flags"`
}

type Evaluators struct {
Evaluators map[string]json.RawMessage `json:"$evaluators"`
Evaluators map[string]json.RawMessage `json:"$evaluators" yaml:"$evaluators"`
}

func (f Flags) Merge(source string, ff Flags) (Flags, []StateChangeNotification) {
Expand Down Expand Up @@ -52,9 +57,9 @@ func (f Flags) Merge(source string, ff Flags) (Flags, []StateChangeNotification)
}

type Flag struct {
State string `json:"state"`
DefaultVariant string `json:"defaultVariant"`
Variants map[string]any `json:"variants"`
Targeting json.RawMessage `json:"targeting"`
Source string `json:"source"`
State string `json:"state" yaml:"state"`
DefaultVariant string `json:"defaultVariant" yaml:"defaultVariant"`
Variants map[string]any `json:"variants" yaml:"variants"`
Targeting json.RawMessage `json:"targeting" yaml:"targeting"`
Source string `json:"source" yaml:"source"`
}
File renamed without changes.
11 changes: 3 additions & 8 deletions pkg/runtime/from_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,19 +52,12 @@ func (r *Runtime) setEvaluatorFromConfig() error {
switch r.config.Evaluator {
case "json":

r.Evaluator = &eval.FileTypeEvaluator{
r.Evaluator = &eval.JSONEvaluator{
Logger: log.WithFields(log.Fields{
"evaluator": "json",
"component": "evaluator",
}),
}
case "yaml":
r.Evaluator = &eval.FileTypeEvaluator{
Logger: log.WithFields(log.Fields{
"evaluator": "yaml",
"component": "evaluator",
}),
}
default:
return errors.New("no evaluator set")
}
Expand All @@ -84,6 +77,8 @@ func (r *Runtime) setSyncImplFromConfig() error {
"component": "sync",
}),
ProviderArgs: r.config.ProviderArgs,
// evaluator here is file type: `json`, `yaml` etc.,
FileType: r.config.Evaluator,
})
log.Debugf("Using %s sync-provider on %q\n", r.config.SyncProvider, u)
}
Expand Down
23 changes: 22 additions & 1 deletion pkg/sync/filepath_sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@ package sync

import (
"context"
"encoding/json"
"errors"
"fmt"
"os"

"github.com/open-feature/flagd/pkg/eval"
log "github.com/sirupsen/logrus"
"gopkg.in/yaml.v2"

"github.com/fsnotify/fsnotify"
)
Expand All @@ -14,6 +18,9 @@ type FilePathSync struct {
URI string
Logger *log.Entry
ProviderArgs ProviderArgs
// FileType indicates the file type e.g., json, yaml etc.,
// TODO: limit this to `json` or `yaml only?`
FileType string
}

func (fs *FilePathSync) Source() string {
Expand All @@ -28,7 +35,21 @@ func (fs *FilePathSync) Fetch(_ context.Context) (string, error) {
if err != nil {
return "", err
}
return string(rawFile), nil

var config eval.FlagsAndEvaluators
err = yaml.Unmarshal(rawFile, &config)
if err != nil {
return "", fmt.Errorf("unmarshal yaml: %w", err)
}

fmt.Println("config", config)

r, err := json.Marshal(config)
if err != nil {
return "", fmt.Errorf("marshal json: %w", err)
}

return string(r), nil
}

func (fs *FilePathSync) Notify(ctx context.Context, w chan<- INotify) {
Expand Down

0 comments on commit cef8463

Please sign in to comment.