feature

package
v0.0.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 21, 2023 License: Apache-2.0 Imports: 20 Imported by: 0

README

Feature Tree

Feature flags are stored as n-ary trees, with each non-root node having a rule and an optional default value. The root node has no rule, and has a non-optional default value.

Feature evaluation traverses the n-ary in depth-first search fashion, starting at the root, and ending as soon as a leaf node evaluates to true or there are no further paths to traverse. The algorithm returns the last non-null value it visited.

Feature Name: illustration
Description: Complex feature tree to illustrate node paths


                                            *Root*
                                            Path: []
                                            Value: 12
                                            /   |   \
                           -----------------    |    -------------------
                          /                     |                        \
                    Rule: a == 1            Rule: a > 10             Rule: a > 5
                    Path: [0]               Path: [1]                Path: [2]
                    Value: 38               Value: NULL              Value: 23
                        /                       |
             -----------                        |
            /                                   |
    Rule: x IN ["a", "b"]                   Rule: x == "c"
    Path: [0,0]                             Path: [1,0]
    Value: 108                              Value: 21
   

*** Tests ***

Context: {}
Value: 12
Path: []

Context: {"a": 1}
Value: 38
Path: [0]

Context: {"a": 11}
Value: 12
Path: []

Context: {"a": 11, "x": "c"}
Value: 21
Path: [1,0]

Context: {"a": 8}
Value: 23
Path: [2]

Context: {"a": 8}
Value: 108
Path: [0,0]

Documentation

Overview

This package governs the specifics of a feature, like what individual files make up a feature.

Index

Constants

This section is empty.

Variables

View Source
var ErrTypeMismatch = fmt.Errorf("type mismatch")

Functions

func ParseFeaturePath

func ParseFeaturePath(featurePath string) (namespaceName string, featureName string, err error)

func ProtoToJSON

func ProtoToJSON(fProto *lekkov1beta1.Feature, registry *protoregistry.Types) ([]byte, error)

func ValToAny

func ValToAny(value interface{}) (*anypb.Any, error)

Types

type CompiledFeature

type CompiledFeature struct {
	Feature          *Feature
	TestResults      []*TestResult
	ValidatorResults []*ValidatorResult
}

Contains the compiled feature model, along with any validator results and unit test results that were collected as part of compilation.

type EvaluableFeature

type EvaluableFeature interface {
	// Evaluate Feature returns a protobuf.Any.
	// For user defined protos, we shouldn't attempt to Unmarshal
	// this unless we know the type. For primitive types, we can
	// safely unmarshal into BoolValue, StringValue, etc.
	Evaluate(evalContext map[string]interface{}) (*anypb.Any, ResultPath, error)
}

type Feature

type Feature struct {
	Key, Description string
	Value            interface{}
	FeatureType      FeatureType

	Rules     []*Rule
	UnitTests []*UnitTest
}

func FromProto

func FromProto(fProto *lekkov1beta1.Feature) (*Feature, error)

func NewBoolFeature

func NewBoolFeature(value bool) *Feature

func NewComplexFeature

func NewComplexFeature(value protoreflect.ProtoMessage) *Feature

func NewEncodedJSONFeature

func NewEncodedJSONFeature(encodedJSON []byte) (*Feature, error)

func NewFloatFeature

func NewFloatFeature(value float64) *Feature

func NewIntFeature

func NewIntFeature(value int64) *Feature

func NewJSONFeature

func NewJSONFeature(value *structpb.Value) *Feature

func NewStringFeature

func NewStringFeature(value string) *Feature

func (*Feature) AddBoolRule

func (f *Feature) AddBoolRule(rule string, ast *rulesv1beta2.Rule, val bool) error

func (*Feature) AddFloatRule

func (f *Feature) AddFloatRule(rule string, ast *rulesv1beta2.Rule, val float64) error

func (*Feature) AddIntRule

func (f *Feature) AddIntRule(rule string, ast *rulesv1beta2.Rule, val int64) error

func (*Feature) AddJSONRule

func (f *Feature) AddJSONRule(rule string, ast *rulesv1beta2.Rule, val *structpb.Value) error

func (*Feature) AddJSONUnitTest

func (f *Feature) AddJSONUnitTest(context map[string]interface{}, val *structpb.Value, starCtx, starVal string) error

func (*Feature) AddStringRule

func (f *Feature) AddStringRule(rule string, ast *rulesv1beta2.Rule, val string) error

func (*Feature) PrintJSON

func (f *Feature) PrintJSON(registry *protoregistry.Types)

func (*Feature) RunUnitTests

func (f *Feature) RunUnitTests() ([]*TestResult, error)

func (*Feature) ToEvaluableFeature

func (f *Feature) ToEvaluableFeature() (EvaluableFeature, error)

func (*Feature) ToJSON

func (f *Feature) ToJSON(registry *protoregistry.Types) ([]byte, error)

func (*Feature) ToProto

func (f *Feature) ToProto() (*lekkov1beta1.Feature, error)

type FeatureContents

type FeatureContents struct {
	File *FeatureFile

	Star  []byte
	JSON  []byte
	Proto []byte
	SHA   string
}

type FeatureFile

type FeatureFile struct {
	Name string
	// Filename of the featureName.star file.
	StarlarkFileName string
	// Filename of an featureName.proto file.
	// This is optional.
	ProtoFileName string
	// Filename of a compiled .json file.
	CompiledJSONFileName string
	// Filename of a compiled .proto.bin file.
	CompiledProtoBinFileName string
	// name of the namespace directory
	NamespaceName string
}

FeatureFile is a parsed feature from an on desk representation. This is intended to remain stable across feature versions.

func GroupFeatureFiles

func GroupFeatureFiles(
	ctx context.Context,
	pathToNamespace string,
	fsProvider fs.Provider,
) ([]FeatureFile, error)

This groups feature files in a way that is governed by the namespace metadata. TODO naming conventions.

func NewFeatureFile

func NewFeatureFile(nsName, featureName string) FeatureFile

func (FeatureFile) RootPath

func (ff FeatureFile) RootPath(filename string) string

func (FeatureFile) Verify

func (ff FeatureFile) Verify() error

type FeatureType

type FeatureType string

Indicates the lekko-specific types that are allowed in feature flags.

const (
	FeatureTypeBool   FeatureType = "bool"
	FeatureTypeInt    FeatureType = "int"
	FeatureTypeFloat  FeatureType = "float"
	FeatureTypeString FeatureType = "string"
	FeatureTypeProto  FeatureType = "proto"
	FeatureTypeJSON   FeatureType = "json"
)

func AnyToVal

func AnyToVal(a *anypb.Any) (interface{}, FeatureType, error)

type ResultPath

type ResultPath []int

Stores the path of the tree node that returned the final value after successful evaluation. See the readme for an illustration.

type Rule

type Rule struct {
	Condition    string             // source of truth
	ConditionAST *rulesv1beta2.Rule // by-product of Condition
	Value        interface{}
}

type TestResult

type TestResult struct {
	Test      string // a string representation of the test, as written in starlark
	TestIndex int    // The index of the test in the list of tests.
	Error     error  // human-readable error
}

This struct holds information about a test run.

func NewTestResult

func NewTestResult(testStar string, testIndex int) *TestResult

func (*TestResult) DebugString

func (tr *TestResult) DebugString() string

func (*TestResult) Identifier

func (tr *TestResult) Identifier() string

Creates a short string - a human-readable version of this unit test that is helpful for debugging and printing errors. e.g. 'test 1 ["{"org"...]' idx refers to the index of the unit test in the list of unit tests written in starlark.

func (*TestResult) Passed

func (tr *TestResult) Passed() bool

func (*TestResult) WithError

func (tr *TestResult) WithError(err error) *TestResult

type UnitTest

type UnitTest struct {
	Context       map[string]interface{}
	ExpectedValue interface{}
	// The starlark textual representation of the context and expected value.
	// These fields are helpful for print statements.
	ContextStar, ExpectedValueStar string
}

func NewUnitTest

func NewUnitTest(context map[string]interface{}, val interface{}, starCtx, starVal string) *UnitTest

func (UnitTest) Run

func (ut UnitTest) Run(idx int, eval EvaluableFeature) *TestResult

type ValidatorResult

type ValidatorResult struct {
	// Indicates whether this validator result applies on a rule value, the default value, or a test value.
	Type ValidatorResultType
	// If this is a rule value validator result, specifies the index of the rule that this result applies to.
	// If this is a test value validator result, specifies the index of the unit test that this result applies to.
	Index int
	// A string representation of the starlark value that was invalid
	Value string
	Error error // human-readable error describing what the validation error was
}

Holds the results of validation checks performed on the compiled feature. Since a validation check is done on a single final feature value, There will be 1 validator result for the default value and 1 for each subsequent rule.

func NewValidatorResult

func NewValidatorResult(t ValidatorResultType, index int, starVal string) *ValidatorResult

func (*ValidatorResult) DebugString

func (vr *ValidatorResult) DebugString() string

func (*ValidatorResult) Identifier

func (vr *ValidatorResult) Identifier() string

func (*ValidatorResult) Passed

func (vr *ValidatorResult) Passed() bool

func (*ValidatorResult) WithError

func (vr *ValidatorResult) WithError(err error) *ValidatorResult

type ValidatorResultType

type ValidatorResultType int
const (
	ValidatorResultTypeDefault ValidatorResultType = iota
	ValidatorResultTypeRule
	ValidatorResultTypeTest
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL