Skip to content

Commit

Permalink
support config metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
passichenko committed Oct 19, 2023
1 parent 8687d0a commit 867ec3e
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 2 deletions.
18 changes: 18 additions & 0 deletions pkg/star/feature.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const (
ResultVariableName string = "result"
DefaultValueAttrName string = "default"
DescriptionAttrName string = "description"
MetadataAttrName string = "metadata"
// TODO: Fully migrate to overrides over rules
RulesAttrName string = "rules"
OverridesAttrName string = "overrides"
Expand All @@ -54,6 +55,7 @@ var (
OverridesAttrName: {},
validatorAttrName: {},
unitTestsAttrName: {},
MetadataAttrName: {},
}
)

Expand Down Expand Up @@ -295,6 +297,22 @@ func (fb *featureBuilder) getDescription(featureVal *starlarkstruct.Struct) (str
return dsc.GoString(), nil
}

func (fb *featureBuilder) getMetadata(featureVal *starlarkstruct.Struct) (*structpb.Value, error) {
metadataVal, err := featureVal.Attr(MetadataAttrName)
if err != nil {
return nil, errors.Wrap(err, "metadata attribute")
}
metadataDict, ok := metadataVal.(*starlark.Dict)
if !ok {
return nil, fmt.Errorf("metadata must be a dict (got a %s)", metadataVal.Type())
}
metadataMap, err := translateContext(metadataDict)
if err != nil {
return nil, errors.Wrap(err, "translate metadata attribute")
}
return structpb.NewValue(metadataMap)
}

func (fb *featureBuilder) addOverrides(f *feature.Feature, featureVal *starlarkstruct.Struct) ([]starlark.Value, error) {
overridesVal, err := featureVal.Attr(OverridesAttrName)
if err != nil {
Expand Down
17 changes: 17 additions & 0 deletions pkg/star/static/traverse.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const (
ResultVariableName string = "result"
DefaultValueAttrName string = "default"
DescriptionAttrName string = "description"
MetadataAttrName string = "metadata"
// TODO: Fully migrate to overrides over rules
RulesAttrName string = "rules"
OverridesAttrName string = "overrides"
Expand All @@ -40,11 +41,13 @@ func defaultNoop(v *build.Expr) error { return nil }
func descriptionNoop(v *build.StringExpr) error { return nil }
func rulesNoop(rules *overridesWrapper) error { return nil }
func importsNoop(imports *importsWrapper) error { return nil }
func metadataNoop(ast *starFeatureAST) error { return nil}

type defaultFn func(v *build.Expr) error
type descriptionFn func(v *build.StringExpr) error
type overridesFn func(rules *overridesWrapper) error
type importsFn func(imports *importsWrapper) error
type metadataFn func(ast *starFeatureAST) error

// Traverses a lekko starlark file, running methods on various
// components of the file. Methods can be provided to read the
Expand All @@ -57,6 +60,7 @@ type traverser struct {
descriptionFn descriptionFn
overridesFn overridesFn
protoImportsFn importsFn
metadataFn metadataFn
}

func newTraverser(f *build.File, nv feature.NamespaceVersion) *traverser {
Expand All @@ -67,6 +71,7 @@ func newTraverser(f *build.File, nv feature.NamespaceVersion) *traverser {
descriptionFn: descriptionNoop,
overridesFn: rulesNoop,
protoImportsFn: importsNoop,
metadataFn: metadataNoop,
}
}

Expand All @@ -90,6 +95,11 @@ func (t *traverser) withProtoImportsFn(fn importsFn) *traverser {
return t
}

func (t *traverser) withMetadataFn(fn metadataFn) *traverser {
t.metadataFn = fn
return t
}

func (t *traverser) traverse() error {
imports := t.getProtoImports()
if err := t.protoImportsFn(imports); err != nil {
Expand Down Expand Up @@ -118,6 +128,9 @@ func (t *traverser) traverse() error {
if err := t.descriptionFn(descriptionStr); err != nil {
return errors.Wrap(err, "description fn")
}
if err := t.metadataFn(ast); err != nil {
return errors.Wrap(err, "metadata fn")
}
// rules
if err := ast.parseOverrides(t.overridesFn, t.nv); err != nil {
return err
Expand Down Expand Up @@ -326,6 +339,10 @@ type importVal struct {
assignExpr *build.AssignExpr
}

type metadataWrapper struct {
metadataExpr *build.DictExpr
}

func newOverride(li build.Expr) (*override, error) {
tupleV, ok := li.(*build.TupleExpr)
if !ok {
Expand Down
42 changes: 40 additions & 2 deletions pkg/star/static/walk.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ func (w *walker) Build() (*featurev1beta1.StaticFeature, error) {
withDefaultFn(w.buildDefaultFn(ret)).
withDescriptionFn(w.buildDescriptionFn(ret)).
withOverridesFn(w.buildRulesFn(ret)).
withProtoImportsFn(w.buildProtoImportsFn(ret))
withProtoImportsFn(w.buildProtoImportsFn(ret)).
withMetadataFn(w.buildMetadataFn(ret))

if err := t.traverse(); err != nil {
return nil, errors.Wrap(err, "traverse")
Expand All @@ -101,7 +102,8 @@ func (w *walker) Mutate(f *featurev1beta1.StaticFeature) ([]byte, error) {
t := newTraverser(ast, w.nv).
withDefaultFn(w.mutateDefaultFn(f)).
withDescriptionFn(w.mutateDescriptionFn(f)).
withOverridesFn(w.mutateOverridesFn(f))
withOverridesFn(w.mutateOverridesFn(f)).
withMetadataFn(w.mutateMetadataFn(f))

if err := t.traverse(); err != nil {
return nil, errors.Wrap(err, "traverse")
Expand Down Expand Up @@ -240,6 +242,27 @@ func (w *walker) buildDescriptionFn(f *featurev1beta1.StaticFeature) description
}
}

func (w *walker) buildMetadataFn(f *featurev1beta1.StaticFeature) metadataFn {
return func(ast *starFeatureAST) error {
metadataExprPtr, found := ast.get(MetadataAttrName)
if !found {
return nil
}
metadataExpr := *metadataExprPtr
metadataDict, ok := metadataExpr.(*build.DictExpr)
if !ok {
return errors.Wrapf(ErrUnsupportedStaticParsing, "metadata kwarg: expected dict, got %T", metadataExpr)
}
metadataValue, err := w.extractJSONValue(metadataDict)
if err != nil {
return errors.Wrap(err, "extract metadata")
}
f.Feature.Metadata = metadataValue
f.FeatureOld.Metadata = metadataValue
return nil
}
}

func (w *walker) buildRulesFn(f *featurev1beta1.StaticFeature) overridesFn {
return func(overridesW *overridesWrapper) error {
for i, o := range overridesW.overrides {
Expand Down Expand Up @@ -485,6 +508,21 @@ func (w *walker) mutateDescriptionFn(f *featurev1beta1.StaticFeature) descriptio
}
}

func (w *walker) mutateMetadataFn(f *featurev1beta1.StaticFeature) metadataFn {
return func(ast *starFeatureAST) error {
metadataProto := f.FeatureOld.GetMetadata()
if metadataProto == nil {
return nil
}
metadataStarDict, err := w.genJSONValue(metadataProto, nil)
if err != nil {
return err
}
ast.set(MetadataAttrName, metadataStarDict)
return nil
}
}

func (w *walker) mutateOverridesFn(f *featurev1beta1.StaticFeature) overridesFn {
return func(overridesW *overridesWrapper) error {
var newOverrides []override
Expand Down
2 changes: 2 additions & 0 deletions proto/lekko/feature/v1beta1/static.proto
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ syntax = "proto3";

package lekko.feature.v1beta1;

import "google/protobuf/struct.proto";
import "lekko/feature/v1beta1/feature.proto";

// Represents a statically parsed feature.
Expand Down Expand Up @@ -47,6 +48,7 @@ message FeatureStruct {
string description = 2;
StarExpr default = 3;
Rules rules = 4;
google.protobuf.Value metadata = 7;
}

message Rules {
Expand Down

0 comments on commit 867ec3e

Please sign in to comment.