예제 #1
0
파일: eval.go 프로젝트: wutaizeng/kapacitor
func evalTypeDeclaration(node *ast.TypeDeclarationNode, scope *stateful.Scope, predefinedVars, defaultVars map[string]Var, ignoreMissingVars bool) error {
	var actualType ast.ValueType
	switch node.Type.Ident {
	case "int":
		actualType = ast.TInt
	case "float":
		actualType = ast.TFloat
	case "bool":
		actualType = ast.TBool
	case "string":
		actualType = ast.TString
	case "regex":
		actualType = ast.TRegex
	case "duration":
		actualType = ast.TDuration
	case "lambda":
		actualType = ast.TLambda
	case "list":
		actualType = ast.TList
	case "star":
		actualType = ast.TStar
	default:
		return fmt.Errorf("invalid var type %q", node.Type.Ident)
	}
	name := node.Node.Ident
	desc := ""
	if node.Comment != nil {
		desc = node.Comment.CommentString()
	}
	defaultVars[name] = Var{
		Type:        actualType,
		Value:       nil,
		Description: desc,
	}

	if predefinedValue, ok := predefinedVars[name]; ok {
		if predefinedValue.Type != actualType {
			return fmt.Errorf("invalid type supplied for %s, got %v exp %v", name, predefinedValue.Type, actualType)
		}
		v, err := convertVarToValue(Var{Value: predefinedValue.Value, Type: actualType})
		if err != nil {
			return err
		}
		scope.Set(name, v)
	} else if ignoreMissingVars {
		// Set zero value on scope, so execution can continue
		scope.Set(name, ast.ZeroValue(actualType))
	} else {
		return fmt.Errorf("missing value for var %q.", name)
	}

	return nil
}
예제 #2
0
func createPipelineAndVars(
	script string,
	sourceEdge EdgeType,
	scope *stateful.Scope,
	deadman DeadmanService,
	predefinedVars map[string]tick.Var,
	ignoreMissingVars bool,
) (*Pipeline, map[string]tick.Var, error) {
	p := &Pipeline{
		deadman: deadman,
	}
	var src Node
	switch sourceEdge {
	case StreamEdge:
		src = newStreamNode()
		scope.Set("stream", src)
	case BatchEdge:
		src = newBatchNode()
		scope.Set("batch", src)
	default:
		return nil, nil, fmt.Errorf("source edge type must be either Stream or Batch not %s", sourceEdge)
	}
	p.addSource(src)

	vars, err := tick.Evaluate(script, scope, predefinedVars, ignoreMissingVars)
	if err != nil {
		return nil, nil, err
	}
	if deadman.Global() {
		switch s := src.(type) {
		case *StreamNode:
			s.Deadman(deadman.Threshold(), deadman.Interval())
		case *BatchNode:
			s.Deadman(deadman.Threshold(), deadman.Interval())
		default:
			return nil, nil, fmt.Errorf("source edge type must be either Stream or Batch not %s", sourceEdge)
		}
	}
	if err = p.Walk(
		func(n Node) error {
			return n.validate()
		}); err != nil {
		return nil, nil, err
	}
	return p, vars, nil
}
예제 #3
0
파일: eval.go 프로젝트: wutaizeng/kapacitor
func evalDeclaration(node *ast.DeclarationNode, scope *stateful.Scope, stck *stack, predefinedVars, defaultVars map[string]Var) error {
	name := node.Left.Ident
	if v, _ := scope.Get(name); v != nil {
		return fmt.Errorf("attempted to redefine %s, vars are immutable", name)
	}
	value := stck.Pop()
	if i, ok := value.(*ast.IdentifierNode); ok {
		// Resolve identifier
		v, err := scope.Get(i.Ident)
		if err != nil {
			return err
		}
		value = v
	}
	actualType := ast.TypeOf(value)
	// Populate set of default vars
	if actualType != ast.InvalidType {
		desc := ""
		if node.Comment != nil {
			desc = node.Comment.CommentString()
		}

		v, err := convertValueToVar(value, actualType, desc)
		if err != nil {
			return err
		}
		defaultVars[name] = v
	}
	// Populate scope, first check for predefined var
	if predefinedValue, ok := predefinedVars[name]; ok {
		if predefinedValue.Type != actualType {
			return fmt.Errorf("invalid type supplied for %s, got %v exp %v", name, predefinedValue.Type, actualType)
		}
		v, err := convertVarToValue(Var{Value: predefinedValue.Value, Type: actualType})
		if err != nil {
			return err
		}
		value = v
	}
	scope.Set(name, value)
	return nil
}
예제 #4
0
파일: expr.go 프로젝트: wutaizeng/kapacitor
// fillScope - given a scope and reference variables, we fill the exact variables from the now, fields and tags.
func fillScope(vars *stateful.Scope, referenceVariables []string, now time.Time, fields models.Fields, tags models.Tags) error {
	for _, refVariableName := range referenceVariables {
		if refVariableName == "time" {
			vars.Set("time", now.Local())
			continue
		}

		// Support the error with tags/fields collision
		var fieldValue interface{}
		var isFieldExists bool
		var tagValue interface{}
		var isTagExists bool

		if fieldValue, isFieldExists = fields[refVariableName]; isFieldExists {
			vars.Set(refVariableName, fieldValue)
		}

		if tagValue, isTagExists = tags[refVariableName]; isTagExists {
			if isFieldExists {
				return fmt.Errorf("cannot have field and tags with same name %q", refVariableName)
			}
			vars.Set(refVariableName, tagValue)
		}
		if !isFieldExists && !isTagExists {
			if !vars.Has(refVariableName) {
				return fmt.Errorf("no field or tag exists for %s", refVariableName)
			}
		}
	}

	return nil
}