Skip to content

Commit

Permalink
feat: add ability to configure registry entities with config map
Browse files Browse the repository at this point in the history
  • Loading branch information
mikhailswift committed Jul 16, 2024
1 parent adbf7b0 commit 9dd38be
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 4 deletions.
2 changes: 1 addition & 1 deletion attestation/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ func GetAttestors(nameOrTypes []string) ([]Attestor, error) {

attestor := factory()
opts := AttestorOptions(nameOrType)
attestor, err := attestorRegistry.SetDefaultVals(attestor, opts)
attestor, err := registry.SetDefaultVals(attestor, opts)
if err != nil {
return nil, err
}
Expand Down
80 changes: 77 additions & 3 deletions registry/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ package registry
import (
"fmt"
"time"

"github.com/in-toto/go-witness/log"
)

// Registry is a way for the library to expose details about available configuration options
Expand Down Expand Up @@ -91,14 +93,31 @@ func (r Registry[T]) NewEntity(name string, optSetters ...func(T) (T, error)) (T
return result, fmt.Errorf("could not find entry with name %v", name)
}

result, err := r.SetDefaultVals(entry.Factory(), entry.Options)
result, err := SetDefaultVals(entry.Factory(), entry.Options)
if err != nil {
return result, err
return result, fmt.Errorf("could not set default values: %w", err)
}

return SetOptions(result, optSetters...)
}

// NewEntityFromConfigMap creates a new entity with options provided by a config map.
// Values in the config map will be used to set options on the entity by the key of the config map.
func (r Registry[T]) NewEntityFromConfigMap(name string, configMap map[string]any) (T, error) {
var result T
entry, ok := r.Entry(name)
if !ok {
return result, fmt.Errorf("could not find entry with name %v", name)
}

result, err := SetDefaultVals(entry.Factory(), entry.Options)
if err != nil {
return result, fmt.Errorf("could not set default values: %w", err)
}

return SetOptionsFromConfigMap(result, entry.Options, configMap)
}

func SetOptions[T any](entity T, optSetters ...func(T) (T, error)) (T, error) {
var err error
result := entity
Expand All @@ -113,7 +132,7 @@ func SetOptions[T any](entity T, optSetters ...func(T) (T, error)) (T, error) {
}

// SetDefaultVals will take an Entity and call Setter for every option with that option's defaultVal.
func (r Registry[T]) SetDefaultVals(entity T, opts []Configurer) (T, error) {
func SetDefaultVals[T any](entity T, opts []Configurer) (T, error) {
var err error

for _, opt := range opts {
Expand All @@ -137,3 +156,58 @@ func (r Registry[T]) SetDefaultVals(entity T, opts []Configurer) (T, error) {

return entity, nil
}

func SetOptionsFromConfigMap[T any](entity T, configurers []Configurer, configMap map[string]any) (T, error) {
optsByName := make(map[string]Configurer)
for _, opt := range configurers {
optsByName[opt.Name()] = opt
}

var err error
for name, value := range configMap {
opt, ok := optsByName[name]
if !ok {
log.Debugf("unknown option name in config map: %v", name)
continue
}

switch o := opt.(type) {
case *ConfigOption[T, int]:
val, ok := value.(int)
if !ok {
return entity, fmt.Errorf("expected value for option %v to be an int but got %T", name, value)
}
entity, err = o.Setter()(entity, val)
case *ConfigOption[T, string]:
val, ok := value.(string)
if !ok {
return entity, fmt.Errorf("expected value for option %v to be an int but got %T", name, value)
}
entity, err = o.Setter()(entity, val)
case *ConfigOption[T, []string]:
val, ok := value.([]string)
if !ok {
return entity, fmt.Errorf("expected value for option %v to be an int but got %T", name, value)
}
entity, err = o.Setter()(entity, val)
case *ConfigOption[T, bool]:
val, ok := value.(bool)
if !ok {
return entity, fmt.Errorf("expected value for option %v to be an int but got %T", name, value)
}
entity, err = o.Setter()(entity, val)
case *ConfigOption[T, time.Duration]:
val, ok := value.(time.Duration)
if !ok {
return entity, fmt.Errorf("expected value for option %v to be an int but got %T", name, value)
}
entity, err = o.Setter()(entity, val)
}

if err != nil {
return entity, err
}
}

return entity, nil
}
4 changes: 4 additions & 0 deletions signer/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ func NewSignerProvider(name string, opts ...func(SignerProvider) (SignerProvider
return signerRegistry.NewEntity(name, opts...)
}

func NewSignerProviderFromConfigMap(name string, configMap map[string]any) (SignerProvider, error) {
return signerRegistry.NewEntityFromConfigMap(name, configMap)
}

// NOTE: This is a temporary interface, and should not be used. It will be deprecated in a future release.
// The same applies to the functions that use this interface.
type VerifierProvider interface {
Expand Down

0 comments on commit 9dd38be

Please sign in to comment.