feature

package
v0.2.14 Latest Latest
Warning

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

Go to latest
Published: Mar 31, 2023 License: Apache-2.0 Imports: 21 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 (
	ErrDeprecatedVersion error = errors.New("namespace version is deprecated, please upgrade")
	ErrUnknownVersion    error = errors.New("namespace version is unknown")
)
View Source
var ErrTypeMismatch = fmt.Errorf("type mismatch")

Functions

func AnyToVal

func AnyToVal(a *anypb.Any, fType FeatureType, registry *protoregistry.Types) (interface{}, error)

Translates the pb any object to a go-native object based on the given type. Also takes an optional protbuf type registry, in case the value depends on a user-defined protobuf type.

func FeatureTypes added in v0.2.3

func FeatureTypes() []string

func ParseFeaturePath

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

func ProtoToJSON

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

func ValToAny

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

Takes a go value and an associated type, and converts the value to a language-agnostic protobuf any type.

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)
	// Returns the feature type (bool, string, json, proto, etc)
	// or "" if the type is not supported
	Type() FeatureType
}

type Feature

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

	Rules     []*Rule
	UnitTests []*UnitTest
}

func FromProto

func FromProto(fProto *featurev1beta1.Feature, registry *protoregistry.Types) (*Feature, error)

Converts a feature from its protobuf representation into a go-native representation. Takes an optional proto registry in case we require user-defined types in order to parse the feature.

func NewBoolFeature

func NewBoolFeature(value bool) *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 NewProtoFeature added in v0.2.6

func NewProtoFeature(value protoreflect.ProtoMessage) *Feature

func NewStringFeature

func NewStringFeature(value string) *Feature

func (*Feature) AddBoolRule

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

func (*Feature) AddFloatRule

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

func (*Feature) AddIntRule

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

func (*Feature) AddJSONRule

func (f *Feature) AddJSONRule(rule string, ast *rulesv1beta2.Rule, astNew *rulesv1beta3.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, astNew *rulesv1beta3.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() (*featurev1beta1.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 FeatureTypeFromProto added in v0.2.6

func FeatureTypeFromProto(ft featurev1beta1.FeatureType) FeatureType

func (FeatureType) IsPrimitive added in v0.2.12

func (ft FeatureType) IsPrimitive() bool

func (FeatureType) ToProto added in v0.2.6

func (ft FeatureType) ToProto() featurev1beta1.FeatureType

type NamespaceVersion added in v0.2.8

type NamespaceVersion string
const (
	NamespaceVersionV1Beta1 NamespaceVersion = "v1beta1"
	NamespaceVersionV1Beta2 NamespaceVersion = "v1beta2"
	NamespaceVersionV1Beta3 NamespaceVersion = "v1beta3"
	// Supports generating n-ary rules AST
	NamespaceVersionV1Beta4 NamespaceVersion = "v1beta4"
	// Supports != operator
	NamespaceVersionV1Beta5 NamespaceVersion = "v1beta5"
)

func AllNamespaceVersions added in v0.2.8

func AllNamespaceVersions() []NamespaceVersion

Returns all namespace versions in the order that they were released

func LatestNamespaceVersion added in v0.2.8

func LatestNamespaceVersion() NamespaceVersion

Returns the latest namespace version.

func NewNamespaceVersion added in v0.2.8

func NewNamespaceVersion(v string) NamespaceVersion

func SupportedNamespaceVersions added in v0.2.8

func SupportedNamespaceVersions() []NamespaceVersion

Returns the list of namespace versions that are supported.

func (NamespaceVersion) Before added in v0.2.8

func (nv NamespaceVersion) Before(cmp NamespaceVersion) bool

func (NamespaceVersion) IsLatest added in v0.2.8

func (nv NamespaceVersion) IsLatest() bool

func (NamespaceVersion) String added in v0.2.8

func (nv NamespaceVersion) String() string

func (NamespaceVersion) Supported added in v0.2.8

func (nv NamespaceVersion) Supported() 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
	ConditionASTV3 *rulesv1beta3.Rule
	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