ast

package
v0.0.0-...-8b28c38 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 20, 2023 License: Apache-2.0 Imports: 7 Imported by: 0

Documentation

Overview

allocationfilterutil provides functionality for parsing V2 of the Kubecost filter language for Allocation types.

e.g. "filter=namespace:kubecost+controllerkind:deployment"

Index

Examples

Constants

View Source
const (
	// FilterOpEquals is the equality operator
	//
	// "kube-system" FilterOpEquals "kube-system" = true
	// "kube-syste" FilterOpEquals "kube-system" = false
	FilterOpEquals FilterOp = "equals"

	// FilterOpNotEquals is the inverse of equals.
	FilterOpNotEquals = "notequals"

	// FilterOpContains supports string fields, slice fields, and map fields.
	// For maps, this is equivalent to map.HasKey(x)
	//
	// "kube-system" FilterOpContains "e-s" = true
	// ["a", "b", "c"] FilterOpContains "a" = true
	// { "namespace": "kubecost", "cluster": "cluster-one" } FilterOpContains "namespace" = true
	FilterOpContains = "contains"

	// FilterOpNotContains is the inverse of contains.
	FilterOpNotContains = "notcontains"

	// FilterOpContainsPrefix is like FilterOpContains, but checks against the start of a string.
	// For maps, this checks to see if any of the keys start with the prefix
	//
	// "kube-system" ContainsPrefix "kube" = true
	// ["kube-system", "abc123"] ContainsPrefix "kube" = true
	// { "kube-label": "test", "abc": "123" } ContainsPrefix "ab" = true
	FilterOpContainsPrefix = "containsprefix"

	// FilterOpNotContainsPrefix is the inverse of FilterOpContainsPrefix
	FilterOpNotContainsPrefix = "notcontainsprefix"

	// FilterOpContainsSuffix is like FilterOpContains, but checks against the end of a string.
	// For maps, this checks to see if any of the keys end with the suffix
	//
	// "kube-system" ContainsSuffix "system" = true
	// ["kube-system", "abc123"] ContainsSuffix "system" = true
	// { "kube-label": "test", "abc": "123" } ContainsSuffix "-label" = true
	FilterOpContainsSuffix = "containssuffix"

	// FilterOpNotContainsSuffix is the inverse of FilterOpContainsSuffix
	FilterOpNotContainsSuffix = "notcontainssuffix"

	// FilterOpVoid is base-depth operator that is used for an empty filter
	FilterOpVoid = "void"

	// FilterOpContradiction is a base-depth operator that filters all data.
	FilterOpContradiction = "contradiction"

	// FilterOpAnd is an operator that succeeds if all parameters succeed.
	FilterOpAnd = "and"

	// FilterOpOr is an operator that succeeds if any parameter succeeds
	FilterOpOr = "or"

	// FilterOpNot is an operator that contains a single operand
	FilterOpNot = "not"
)

If you add a FilterOp, MAKE SURE TO UPDATE ALL FILTER IMPLEMENTATIONS! Go does not enforce exhaustive pattern matching on "enum" types.

Variables

This section is empty.

Functions

func OpStringFor

func OpStringFor(node FilterNode, traversalState TraversalState, depth int) string

OpStringFor returns a string for the provided leaf node, traversal state, and current depth.

func PreOrderTraversal

func PreOrderTraversal(node FilterNode, f func(FilterNode, TraversalState))

PreOrderTraversal accepts a root `FilterNode` and calls the f callback on each leaf node it traverses. When entering "group" leaf nodes (leaf nodes which contain other leaf nodes), a TraversalStateEnter/Exit will be includes to denote each depth. In short, the callback will be executed twice for each "group" op, once before entering, and once bofore exiting.

func ShortOpStringFor

func ShortOpStringFor(node FilterNode, traversalState TraversalState) string

ShortOpStringFor returns a condensed string for the provided leaf node, traversal state, and current depth.

func ToPreOrderShortString

func ToPreOrderShortString(node FilterNode) string

ToPreOrderShortString runs a PreOrderTraversal and generates a condensed tree structure string format for the provided tree root.

func ToPreOrderString

func ToPreOrderString(node FilterNode) string

ToPreOrderString runs a PreOrderTraversal and generates an indented tree structure string format for the provided tree root.

Types

type AndOp

type AndOp struct {
	Operands []FilterNode
}

AndOp is a filter operation that contains a flat list of nodes which should all resolve to true in order for the result to be true.

func (*AndOp) Add

func (ao *AndOp) Add(node FilterNode)

Add appends a filter node to the flat list of operands within the AND operator

func (*AndOp) Op

func (_ *AndOp) Op() FilterOp

Op returns the FilterOp enumeration value for the operator.

type ContainsOp

type ContainsOp struct {
	// Left contains a resolvable Identifier (property of an input type) which can be
	// used to query against using the Right value.
	Left Identifier

	// Right contains the value which we use to search the resolved Left identifier with.
	Right string
}

ContainsOp is a filter operation that checks to see if a resolvable identifier (Left) contains a string value (Right)

func (*ContainsOp) Op

func (_ *ContainsOp) Op() FilterOp

Op returns the FilterOp enumeration value for the operator.

type ContainsPrefixOp

type ContainsPrefixOp struct {
	// Left contains a resolvable Identifier (property of an input type) which can be
	// used to query against using the Right value.
	Left Identifier

	// Right contains the value which we use to search the resolved Left identifier with.
	Right string
}

ContainsPrefixOp is a filter operation that checks to see if a resolvable identifier (Left) starts with a string value (Right)

func (*ContainsPrefixOp) Op

func (_ *ContainsPrefixOp) Op() FilterOp

Op returns the FilterOp enumeration value for the operator.

type ContainsSuffixOp

type ContainsSuffixOp struct {
	// Left contains a resolvable Identifier (property of an input type) which can be
	// used to query against using the Right value.
	Left Identifier

	// Right contains the value which we use to search the resolved Left identifier with.
	Right string
}

ContainsSuffixOp is a filter operation that checks to see if a resolvable identifier (Left) ends with a string value (Right)

func (*ContainsSuffixOp) Op

func (_ *ContainsSuffixOp) Op() FilterOp

Op returns the FilterOp enumeration value for the operator.

type ContradictionOp

type ContradictionOp struct{}

ContradictionOp is a base-depth operator that filters all data.

func (*ContradictionOp) Op

func (_ *ContradictionOp) Op() FilterOp

Op returns the FilterOp enumeration value for the operator.

type EqualOp

type EqualOp struct {
	// Left contains a resolvable Identifier (property of an input type) which can be
	// used to compare against the Right value.
	Left Identifier

	// Right contains the value which we wish to compare the resolved identifier to.
	Right string
}

EqualOp is a filter operation that compares a resolvable identifier (Left) to a string value (Right)

func (*EqualOp) Op

func (_ *EqualOp) Op() FilterOp

Op returns the FilterOp enumeration value for the operator.

type Field

type Field struct {
	// Name contains the name of the specific field as it appears in language.
	Name string
	// contains filtered or unexported fields
}

Field is a Lexer input which acts as a mapping of identifiers used to lex/parse filters.

func Fields

func Fields(filter FilterNode) []Field

func NewAliasField

func NewAliasField[T ~string](name T) *Field

NewAliasField creates a new alias field using the provided name.

func NewField

func NewField[T ~string](name T) *Field

NewField creates a default string field using the provided name.

func NewMapField

func NewMapField[T ~string](name T) *Field

NewMapField creates a new map field using the provided name.

func NewSliceField

func NewSliceField[T ~string](name T) *Field

NewSliceField creates a slice field using the provided name.

func (*Field) Equal

func (f *Field) Equal(other *Field) bool

Field equivalence is determined by name and type.

func (*Field) IsAlias

func (f *Field) IsAlias() bool

IsAlias returns true if the field is an alias type. This instructs the lexer that the field is an alias for custom logical resolution by an external compiler.

func (*Field) IsMap

func (f *Field) IsMap() bool

IsMap returns true if the field is a map. This instructs the lexer that the field should allow keyed-access operations.

func (*Field) IsSlice

func (f *Field) IsSlice() bool

IsSlice returns true if the field is a slice. This instructs the lexer that the field should allow contains operations.

type FieldType

type FieldType int

FieldType is an enumeration of specific types relevant to lexing and parsing a filter.

const (
	FieldTypeDefault FieldType = iota
	FieldTypeSlice
	FieldTypeMap
	FieldTypeAlias
)

type FilterGroup

type FilterGroup interface {
	FilterNode

	// Adds a new leaf node to the FilterGroup
	Add(FilterNode)
}

FilterGroup is a specialized interface for ops which can collect N operands.

type FilterNode

type FilterNode interface {
	Op() FilterOp
}

FilterNode is the the base instance of a tree leaf node, which is a conditional operator which contains operands that may also be leaf nodes. A go type-switch should be used to reduce the FilterNode to a concrete type to operate on. If only the type of operator is required, the `Op()` field can be used.

func Clone

func Clone(filter FilterNode) FilterNode

Clone deep copies and returns the AST parameter.

func TransformLeaves

func TransformLeaves(node FilterNode, transformer func(FilterNode) FilterNode) FilterNode

TransformLeaves produces a new tree, leaving non-leaf nodes (e.g. And, Or) intact and replacing leaf nodes (e.g. Equals, Contains) with the result of calling leafTransformer(node).

Example
originalTree := &AndOp{
	Operands: []FilterNode{
		&EqualOp{
			Left: Identifier{
				Field: &Field{
					Name: "field1",
				},
				Key: "foo",
			},
			Right: "bar",
		},

		&EqualOp{
			Left: Identifier{
				Field: &Field{
					Name: "field2",
				},
			},
			Right: "bar",
		},
	},
}

// This transformer applies "Not" to all leaves
transformFunc := func(node FilterNode) FilterNode {
	switch concrete := node.(type) {
	case *AndOp, *OrOp, *NotOp:
		panic("Leaf transformer should not be called on non-leaf nodes")
	default:
		return &NotOp{Operand: concrete}
	}
}

newTree := TransformLeaves(originalTree, transformFunc)
fmt.Println(ToPreOrderString(newTree))
Output:

And {
  Not {
    Equals { Left: field1[foo], Right: bar }
  }
  Not {
    Equals { Left: field2, Right: bar }
  }
}

type FilterOp

type FilterOp string

FilterOp is an enum that represents operations that can be performed when filtering (equality, inequality, etc.)

type FilterParser

type FilterParser interface {
	// Parse parses a filter string into a FilterNode AST.
	Parse(filter string) (FilterNode, error)
}

FilterParser is an object capable of parsing a filter string into a `FilterNode` AST

func NewFilterParser

func NewFilterParser(fields []*Field) FilterParser

NewFilterParser creates a new `FilterParser` instance with the provided `Field` definitions to use when lexing and parsing.

type Identifier

type Identifier struct {
	Field *Field
	Key   string
}

Identifier is a struct that contains the data required to resolve a specific operand to a concrete value during operator compilation.

func (*Identifier) Equal

func (id *Identifier) Equal(ident Identifier) bool

Equal returns true if the identifiers are equal

func (*Identifier) String

func (id *Identifier) String() string

String returns the string representation for the Identifier

type NotOp

type NotOp struct {
	Operand FilterNode
}

NotOp is a filter operation that logically inverts result of the child operand.

func (*NotOp) Add

func (no *NotOp) Add(node FilterNode)

Add sets the not operand to the parameter

func (*NotOp) Op

func (_ *NotOp) Op() FilterOp

Op returns the FilterOp enumeration value for the operator.

type OrOp

type OrOp struct {
	Operands []FilterNode
}

OrOp is a filter operation that contains a flat list of nodes which at least one node should resolve to true in order for the result to be true.

func (*OrOp) Add

func (oo *OrOp) Add(node FilterNode)

Add appends a filter node to the flat list of operands within the OR operator

func (*OrOp) Op

func (_ *OrOp) Op() FilterOp

Op returns the FilterOp enumeration value for the operator.

type TraversalState

type TraversalState int

TraversalState represents the state of the current leaf node in a traversal of the filter Any grouping ops will include an Enter on their first occurence, and an Exit when leaving the op state.

const (
	// TraversalStateNone is used whenever a binary op leaf node is traversed.
	TraversalStateNone TraversalState = iota

	// TraversalStateEnter is used when a group op leaf node is traversed (and, or, not)
	TraversalStateEnter

	// TraversalStateExit is used wwhen a group op leaf node is popped (and, or, not).
	TraversalStateExit
)

type VoidOp

type VoidOp struct{}

VoidOp is base-depth operator that is used for an empty filter

func (*VoidOp) Op

func (_ *VoidOp) Op() FilterOp

Op returns the FilterOp enumeration value for the operator.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL