Files
akvorado/console/query.go
Vincent Bernat 50614cef5b console: add a bidirectional mode for graphs
It allows one to also display flows in the opposite direction.
2022-08-07 23:15:18 +02:00

99 lines
2.7 KiB
Go

// SPDX-FileCopyrightText: 2022 Free Mobile
// SPDX-License-Identifier: AGPL-3.0-only
package console
import (
"errors"
"fmt"
"strings"
"akvorado/common/helpers"
"akvorado/console/filter"
)
type queryColumn int
func (gc queryColumn) MarshalText() ([]byte, error) {
got, ok := queryColumnMap.LoadValue(gc)
if ok {
return []byte(got), nil
}
return nil, errors.New("unknown field")
}
func (gc queryColumn) String() string {
got, _ := queryColumnMap.LoadValue(gc)
return got
}
func (gc *queryColumn) UnmarshalText(input []byte) error {
got, ok := queryColumnMap.LoadKey(string(input))
if ok {
*gc = got
return nil
}
return errors.New("unknown field")
}
type queryFilter struct {
filter string
reverseFilter string
mainTableRequired bool
}
func (gf queryFilter) String() string {
return gf.filter
}
func (gf queryFilter) MarshalText() ([]byte, error) {
return []byte(gf.filter), nil
}
func (gf *queryFilter) UnmarshalText(input []byte) error {
if strings.TrimSpace(string(input)) == "" {
*gf = queryFilter{}
return nil
}
meta := &filter.Meta{}
direct, err := filter.Parse("", input, filter.GlobalStore("meta", meta))
if err != nil {
return fmt.Errorf("cannot parse filter: %s", filter.HumanError(err))
}
meta = &filter.Meta{ReverseDirection: true}
reverse, err := filter.Parse("", input, filter.GlobalStore("meta", meta))
*gf = queryFilter{
filter: direct.(string),
reverseFilter: reverse.(string),
mainTableRequired: meta.MainTableRequired,
}
return nil
}
// toSQLSelect transforms a column into an expression to use in SELECT
func (gc queryColumn) toSQLSelect() string {
var strValue string
switch gc {
case queryColumnExporterAddress, queryColumnSrcAddr, queryColumnDstAddr:
strValue = fmt.Sprintf("replaceRegexpOne(IPv6NumToString(%s), '^::ffff:', '')", gc)
case queryColumnSrcAS, queryColumnDstAS:
strValue = fmt.Sprintf(`concat(toString(%s), ': ', dictGetOrDefault('asns', 'name', %s, '???'))`,
gc, gc)
case queryColumnEType:
strValue = fmt.Sprintf(`if(EType = %d, 'IPv4', if(EType = %d, 'IPv6', '???'))`,
helpers.ETypeIPv4, helpers.ETypeIPv6)
case queryColumnProto:
strValue = `dictGetOrDefault('protocols', 'name', Proto, '???')`
case queryColumnInIfSpeed, queryColumnOutIfSpeed, queryColumnSrcPort, queryColumnDstPort, queryColumnForwardingStatus, queryColumnInIfBoundary, queryColumnOutIfBoundary:
strValue = fmt.Sprintf("toString(%s)", gc)
default:
strValue = gc.String()
}
return strValue
}
// reverseDirection reverse the direction of a column (src/dst, in/out)
func (gc queryColumn) reverseDirection() queryColumn {
value, ok := queryColumnMap.LoadKey(filter.ReverseColumnDirection(gc.String()))
if !ok {
panic("unknown reverse column")
}
return value
}