Skip to content

Commit

Permalink
Breaking: Refactored parameters to a list to make ordering stable.
Browse files Browse the repository at this point in the history
  • Loading branch information
kristofferahl committed Jan 21, 2024
1 parent 682706b commit 7814629
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 31 deletions.
2 changes: 1 addition & 1 deletion internal/command/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func newContext(c *cli.Context, metadata config.AppMetadata, validateParams bool
}
}

ctx.Parameters = p
ctx.Parameters = p.Ordered(ctx.Manifest.Config.Parameters)
ctx.Context = c.Context

return ctx, nil
Expand Down
2 changes: 1 addition & 1 deletion internal/config/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type AppContext struct {
Log *logrus.Logger
Metadata AppMetadata
Manifest Manifest
Parameters Parameters
Parameters OrderedParameterList
}

type AppMetadata struct {
Expand Down
26 changes: 18 additions & 8 deletions internal/config/manifest.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,8 @@ func (m Manifest) Filepath() string {
}

type Config struct {
Parameters ParameterConfig `yaml:"parameters"`
Sources SourceConfig `yaml:"sources"`
Parameters ParameterConfigList `yaml:"parameters"`
Sources SourceConfig `yaml:"sources"`
}

type LayerList []LayerConfig
Expand Down Expand Up @@ -215,9 +215,19 @@ func (l PropertyList) Remove(pl PropertyList) (properties PropertyList) {
})
}

type ParameterConfig map[string]ParameterRule
type ParameterConfigList []ParameterConfig

type ParameterRule struct {
func (p ParameterConfigList) HasKey(k string) bool {
for _, r := range p {
if r.Key == k {
return true
}
}
return false
}

type ParameterConfig struct {
Key string `yaml:"key"`
Required bool `yaml:"required"`
Regexp string `yaml:"regexp"`
}
Expand Down Expand Up @@ -374,7 +384,7 @@ func (m *Manifest) GetLayers(ctx AppContext) (layers []LayerConfig, err error) {
return
}

func (l *LayerConfig) Matches(p Parameters, ctx AppContext) (match bool, err error) {
func (l *LayerConfig) Matches(op OrderedParameterList, ctx AppContext) (match bool, err error) {
match = true

for _, expr := range l.Match {
Expand All @@ -384,7 +394,7 @@ func (l *LayerConfig) Matches(p Parameters, ctx AppContext) (match bool, err err
err = fmt.Errorf("matching layer %s against parameters failed, %v", l.Name, e)
break
}
if pv, ok := p[k]; ok {
if pv, ok := op.Value(k); ok {
if !m.Match(pv) {
match = false
break
Expand All @@ -396,9 +406,9 @@ func (l *LayerConfig) Matches(p Parameters, ctx AppContext) (match bool, err err
}

if match {
ctx.Log.Debugf("matched layer %s against parameters (conditions=%v parameters=%v)", l.Name, l.Match, p)
ctx.Log.Debugf("matched layer %s against parameters (conditions=%v parameters=%v)", l.Name, l.Match, op)
} else {
ctx.Log.Debugf("layer %s did not match parameters (conditions=%v parameters=%v)", l.Name, l.Match, p)
ctx.Log.Debugf("layer %s did not match parameters (conditions=%v parameters=%v)", l.Name, l.Match, op)
}

return
Expand Down
60 changes: 44 additions & 16 deletions internal/config/parameter.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,17 @@ import (
"strings"
)

type Parameters map[string]string
type parameters map[string]string

func ParseParams(ls []string) (Parameters, error) {
p := Parameters{}
type OrderedParameterList []Parameter

type Parameter struct {
Key string
Value string
}

func ParseParams(ls []string) (parameters, error) {
p := parameters{}
for _, l := range ls {
parts := strings.SplitN(l, "=", 2)
if len(parts) != 2 {
Expand All @@ -25,33 +32,33 @@ func ParseParams(ls []string) (Parameters, error) {
return p, nil
}

func (p Parameters) ValidateParams(c ParameterConfig) error {
func (p parameters) ValidateParams(pl ParameterConfigList) error {
// validate parameters are defined by manifest
for k := range p {
if _, ok := c[k]; !ok {
if ok := pl.HasKey(k); !ok {
return fmt.Errorf("parameter %s, provided but not defined", k)
}
}

// validate parameters
for k, v := range c {
pv, ok := p[k]
for _, pc := range pl {
pv, ok := p[pc.Key]

if v.Required {
if pc.Required {
if !ok {
return fmt.Errorf("required parameter must be set, parameter: %s", k)
return fmt.Errorf("required parameter must be set, parameter: %s", pc.Key)
}
}

if ok {
if len(v.Regexp) > 0 {
re, err := regexp.Compile(v.Regexp)
if len(pc.Regexp) > 0 {
re, err := regexp.Compile(pc.Regexp)
if err != nil {
return fmt.Errorf("invalid regular expression for parameter %s, err: %w", k, err)
return fmt.Errorf("invalid regular expression for parameter %s, err: %w", pc.Key, err)
}

if !re.MatchString(pv) {
return fmt.Errorf("parameter %s, regular expression validation failed (value=%s regexp=%s)", k, pv, v.Regexp)
return fmt.Errorf("parameter %s, regular expression validation failed (value=%s regexp=%s)", pc.Key, pv, pc.Regexp)
}
}
}
Expand All @@ -60,9 +67,30 @@ func (p Parameters) ValidateParams(c ParameterConfig) error {
return nil
}

func (p Parameters) Replace(s string) string {
for k, v := range p {
s = strings.ReplaceAll(s, fmt.Sprintf("{%s}", k), v)
func (p parameters) Ordered(pl ParameterConfigList) (ordered OrderedParameterList) {
for _, pc := range pl {
if v, ok := p[pc.Key]; ok {
ordered = append(ordered, Parameter{
Key: pc.Key,
Value: v,
})
}
}
return ordered
}

func (op OrderedParameterList) Replace(s string) string {
for _, p := range op {
s = strings.ReplaceAll(s, fmt.Sprintf("{%s}", p.Key), p.Value)
}
return s
}

func (op OrderedParameterList) Value(key string) (string, bool) {
for _, p := range op {
if p.Key == key {
return p.Value, true
}
}
return "", false
}
6 changes: 3 additions & 3 deletions internal/store/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ func (vs *ValueStore) Read(layer api.Layer, key string, sensitive bool, source *
case config.SourceTypeParameter:
if len(*source.Parameter) > 0 {
key := *source.Parameter
if v, ok := vs.context.Parameters[key]; ok {
return api.NewValue(api.NewValueSource(layer, api.SourceTypeParameter), key, v, nil, sensitive)
if pv, ok := vs.context.Parameters.Value(key); ok {
return api.NewValue(api.NewValueSource(layer, api.SourceTypeParameter), key, pv, nil, sensitive)
} else {
return api.NewValue(api.NewValueSource(layer, api.SourceTypeParameter), key, v, api.NewNotFoundError(nil, key, api.SourceTypeParameter), sensitive)
return api.NewValue(api.NewValueSource(layer, api.SourceTypeParameter), key, pv, api.NewNotFoundError(nil, key, api.SourceTypeParameter), sensitive)
}
}

Expand Down
6 changes: 4 additions & 2 deletions testdata/racoon.base.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
config:
parameters:
context:
- key: context
required: true
tenant:
- key: user
required: false
- key: tenant
required: false
sources:
awsParameterStore:
Expand Down
1 change: 1 addition & 0 deletions testdata/racoon.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
extends: ./racoon.base.yaml

name: racoon-e2e-tests

labels:
Environment: "{context}"
ManagedBy: racoon
Expand Down

0 comments on commit 7814629

Please sign in to comment.