Skip to content

Commit

Permalink
predicates: add Config predicate
Browse files Browse the repository at this point in the history
E.g. it could be used to let skipper instance know in which zone it is deployed:
```yaml
containers:
  - env:
      - name: TOPOLOGY_ZONE
        valueFrom:
          fieldRef:
            fieldPath: metadata.annotations['topology.kubernetes.io/zone']
    args:
      - skipper
      - -config-predicate-values=zone=$(TOPOLOGY_ZONE)
      - ...
```

such that it only enables specific route for that zone:
```
za: Path("/foo") && Config("zone", "a") -> "http://backend.zone-a.test";
zb: Path("/foo") && Config("zone", "b") -> "http://backend.zone-b.test";
zc: Path("/foo") && Config("zone", "c") -> "http://backend.zone-c.test";
```

Signed-off-by: Alexander Yastrebov <[email protected]>
  • Loading branch information
AlexanderYastrebov committed Jul 24, 2023
1 parent 1817eda commit 8dee3c7
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 0 deletions.
3 changes: 3 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ type Config struct {
DataclientPlugins *pluginFlag `yaml:"dataclient-plugin"`
MultiPlugins *pluginFlag `yaml:"multi-plugin"`
CompressEncodings *listFlag `yaml:"compress-encodings"`
ConfigPredicateValues mapFlags `yaml:"config-predicate-values"`

// logging, metrics, profiling, tracing:
EnablePrometheusMetrics bool `yaml:"enable-prometheus-metrics"`
Expand Down Expand Up @@ -348,6 +349,7 @@ func NewConfig() *Config {
flag.Var(cfg.DataclientPlugins, "dataclient-plugin", "set a custom dataclient plugins to load, a comma separated list of name and arguments")
flag.Var(cfg.MultiPlugins, "multi-plugin", "set a custom multitype plugins to load, a comma separated list of name and arguments")
flag.Var(cfg.CompressEncodings, "compress-encodings", "set encodings supported for compression, the order defines priority when Accept-Header has equal quality values, see RFC 7231 section 5.3.1")
flag.Var(&cfg.ConfigPredicateValues, "config-predicate-values", "sets name-value pairs for Config predicate")

// logging, metrics, tracing:
flag.BoolVar(&cfg.EnablePrometheusMetrics, "enable-prometheus-metrics", false, "*Deprecated*: use metrics-flavour. Switch to Prometheus metrics format to expose metrics")
Expand Down Expand Up @@ -704,6 +706,7 @@ func (c *Config) ToOptions() skipper.Options {
Plugins: c.MultiPlugins.values,
PluginDirs: []string{skipper.DefaultPluginDir},
CompressEncodings: c.CompressEncodings.values,
ConfigPredicateValues: c.ConfigPredicateValues.values,

// logging, metrics, profiling, tracing:
EnablePrometheusMetrics: c.EnablePrometheusMetrics,
Expand Down
1 change: 1 addition & 0 deletions predicates/predicates.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const (
TrueName = "True"
FalseName = "False"
ShutdownName = "Shutdown"
ConfigName = "Config"
MethodName = "Method"
MethodsName = "Methods"
HeaderName = "Header"
Expand Down
49 changes: 49 additions & 0 deletions predicates/primitive/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package primitive

import (
"regexp"

"github.com/zalando/skipper/predicates"
"github.com/zalando/skipper/routing"
)

type (
configSpec struct {
values map[string]string
}
)

// NewConfig provides a predicate spec to create predicates
// that evaluate to true if config value matches regular expression
func NewConfig(values map[string]string) routing.PredicateSpec {
return &configSpec{values}
}

func (*configSpec) Name() string { return predicates.ConfigName }

func (s *configSpec) Create(args []interface{}) (routing.Predicate, error) {
if len(args) != 2 {
return nil, predicates.ErrInvalidPredicateParameters
}

name, ok := args[0].(string)
if !ok {
return nil, predicates.ErrInvalidPredicateParameters
}

value, ok := args[1].(string)
if !ok {
return nil, predicates.ErrInvalidPredicateParameters
}

re, err := regexp.Compile(value)
if err != nil {
return nil, predicates.ErrInvalidPredicateParameters
}

if re.MatchString(s.values[name]) {
return &truePredicate{}, nil
} else {
return &falsePredicate{}, nil
}
}
4 changes: 4 additions & 0 deletions skipper.go
Original file line number Diff line number Diff line change
Expand Up @@ -806,6 +806,9 @@ type Options struct {
// CompressEncodings, if not empty replace default compression encodings
CompressEncodings []string

// ConfigPredicateValues sets name-value pairs for Config predicate
ConfigPredicateValues map[string]string

// OIDCSecretsFile path to the file containing key to encrypt OpenID token
OIDCSecretsFile string

Expand Down Expand Up @@ -1798,6 +1801,7 @@ func run(o Options, sig chan os.Signal, idleConnsCH chan struct{}) error {
primitive.NewTrue(),
primitive.NewFalse(),
primitive.NewShutdown(),
primitive.NewConfig(o.ConfigPredicateValues),
pauth.NewJWTPayloadAllKV(),
pauth.NewJWTPayloadAnyKV(),
pauth.NewJWTPayloadAllKVRegexp(),
Expand Down

0 comments on commit 8dee3c7

Please sign in to comment.