1
0
Fork 0

New constraints management.

Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
This commit is contained in:
Ludovic Fernandez 2019-06-21 09:24:04 +02:00 committed by Traefiker Bot
parent e9792b446f
commit fe68e9e243
40 changed files with 658 additions and 630 deletions

View file

@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2014 Ryan Uber
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -1,56 +0,0 @@
package glob
import "strings"
// The character which is treated like a glob
const GLOB = "*"
// Glob will test a string pattern, potentially containing globs, against a
// subject string. The result is a simple true/false, determining whether or
// not the glob pattern matched the subject text.
func Glob(pattern, subj string) bool {
// Empty pattern can only match empty subject
if pattern == "" {
return subj == pattern
}
// If the pattern _is_ a glob, it matches everything
if pattern == GLOB {
return true
}
parts := strings.Split(pattern, GLOB)
if len(parts) == 1 {
// No globs in pattern, so test for equality
return subj == pattern
}
leadingGlob := strings.HasPrefix(pattern, GLOB)
trailingGlob := strings.HasSuffix(pattern, GLOB)
end := len(parts) - 1
// Go over the leading parts and ensure they match.
for i := 0; i < end; i++ {
idx := strings.Index(subj, parts[i])
switch i {
case 0:
// Check the first section. Requires special handling.
if !leadingGlob && idx != 0 {
return false
}
default:
// Check that the middle parts match.
if idx < 0 {
return false
}
}
// Trim evaluated text from subj as we loop over the pattern.
subj = subj[idx+len(parts[i]):]
}
// Reached the last section. Requires special handling.
return trailingGlob || strings.HasSuffix(subj, parts[end])
}

View file

@ -119,6 +119,14 @@ func Or(a, b BoolPredicate) BoolPredicate {
}
}
// Not is a boolean predicate that calls a boolean predicate
// and returns negated result
func Not(a BoolPredicate) BoolPredicate {
return func() bool {
return !a()
}
}
// GetFieldByTag returns a field from the object based on the tag
func GetFieldByTag(ival interface{}, tagName string, fieldNames []string) (interface{}, error) {
if len(fieldNames) == 0 {

View file

@ -59,6 +59,16 @@ func (p *predicateParser) parseNode(node ast.Node) (interface{}, error) {
return callFunction(fn, arguments)
case *ast.ParenExpr:
return p.parseNode(n.X)
case *ast.UnaryExpr:
joinFn, err := p.getJoinFunction(n.Op)
if err != nil {
return nil, err
}
node, err := p.parseNode(n.X)
if err != nil {
return nil, err
}
return callFunction(joinFn, []interface{}{node})
}
return nil, trace.BadParameter("unsupported %T", node)
}
@ -122,6 +132,20 @@ func (p *predicateParser) evaluateExpr(n ast.Expr) (interface{}, error) {
return nil, trace.Wrap(err)
}
return val, nil
case *ast.CallExpr:
name, err := getIdentifier(l.Fun)
if err != nil {
return nil, err
}
fn, err := p.getFunction(name)
if err != nil {
return nil, err
}
arguments, err := p.evaluateArguments(l.Args)
if err != nil {
return nil, err
}
return callFunction(fn, arguments)
default:
return nil, trace.BadParameter("%T is not supported", n)
}
@ -161,6 +185,8 @@ func (p *predicateParser) joinPredicates(op token.Token, a, b interface{}) (inte
func (p *predicateParser) getJoinFunction(op token.Token) (interface{}, error) {
var fn interface{}
switch op {
case token.NOT:
fn = p.d.Operators.NOT
case token.LAND:
fn = p.d.Operators.AND
case token.LOR:

View file

@ -1,3 +1,20 @@
/*
Copyright 2014-2018 Vulcand Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Predicate package used to create interpreted mini languages with Go syntax - mostly to define
various predicates for configuration, e.g. Latency() > 40 || ErrorRate() > 0.5.
@ -76,6 +93,7 @@ type Operators struct {
OR interface{}
AND interface{}
NOT interface{}
}
// Parser takes the string with expression and calls the operators and functions.