[TASK] refactoring of filters (#114)
This commit is contained in:
parent
0d186677e4
commit
6b522c629c
@ -31,6 +31,9 @@ func TestReadConfig(t *testing.T) {
|
|||||||
"enable": false,
|
"enable": false,
|
||||||
"nodes_path": "/var/www/html/meshviewer/data/nodes.json",
|
"nodes_path": "/var/www/html/meshviewer/data/nodes.json",
|
||||||
"graph_path": "/var/www/html/meshviewer/data/graph.json",
|
"graph_path": "/var/www/html/meshviewer/data/graph.json",
|
||||||
|
"filter": map[string]interface{}{
|
||||||
|
"no_owner": true,
|
||||||
|
},
|
||||||
}, meshviewer)
|
}, meshviewer)
|
||||||
|
|
||||||
_, err = ReadConfigFile("testdata/config_invalid.toml")
|
_, err = ReadConfigFile("testdata/config_invalid.toml")
|
||||||
|
@ -46,12 +46,16 @@ offline_after = "10m"
|
|||||||
# For each output format there can be set different filters
|
# For each output format there can be set different filters
|
||||||
#[nodes.output.example.filter]
|
#[nodes.output.example.filter]
|
||||||
#
|
#
|
||||||
# Set to false, if you want the json files to contain the owner information
|
# WARNING: if it is not set, it will publish contact information of other persons
|
||||||
|
# Set to true, if you did not want the json files to contain the owner information
|
||||||
#no_owner = true
|
#no_owner = true
|
||||||
#
|
#
|
||||||
# List of nodeids of nodes that should be filtered out, so they won't appear in output
|
# List of nodeids of nodes that should be filtered out, so they won't appear in output
|
||||||
#blacklist = ["00112233445566", "1337f0badead"]
|
#blacklist = ["00112233445566", "1337f0badead"]
|
||||||
#
|
#
|
||||||
|
# List of site_codes of nodes that should be included in the output
|
||||||
|
#sites = ["ffhb"]
|
||||||
|
#
|
||||||
# set has_location to true if you want to include only nodes that have geo-coordinates set
|
# set has_location to true if you want to include only nodes that have geo-coordinates set
|
||||||
# (setting this to false has no sensible effect, unless you'd want to hide nodes that have coordinates)
|
# (setting this to false has no sensible effect, unless you'd want to hide nodes that have coordinates)
|
||||||
#has_location = true
|
#has_location = true
|
||||||
@ -69,9 +73,11 @@ offline_after = "10m"
|
|||||||
enable = true
|
enable = true
|
||||||
path = "/var/www/html/meshviewer/data/meshviewer.json"
|
path = "/var/www/html/meshviewer/data/meshviewer.json"
|
||||||
|
|
||||||
#[nodes.output.meshviewer-ffrgb.filter]
|
[nodes.output.meshviewer-ffrgb.filter]
|
||||||
#no_owner = false
|
# WARNING: if it is not set, it will publish contact information of other persons
|
||||||
|
no_owner = false
|
||||||
#blacklist = ["00112233445566", "1337f0badead"]
|
#blacklist = ["00112233445566", "1337f0badead"]
|
||||||
|
#sites = ["ffhb"]
|
||||||
#has_location = true
|
#has_location = true
|
||||||
|
|
||||||
#[nodes.output.meshviewer-ffrgb.filter.in_area]
|
#[nodes.output.meshviewer-ffrgb.filter.in_area]
|
||||||
@ -96,8 +102,9 @@ nodes_path = "/var/www/html/meshviewer/data/nodes.json"
|
|||||||
# path where to store graph.json
|
# path where to store graph.json
|
||||||
graph_path = "/var/www/html/meshviewer/data/graph.json"
|
graph_path = "/var/www/html/meshviewer/data/graph.json"
|
||||||
|
|
||||||
#[nodes.output.meshviewer.filter]
|
[nodes.output.meshviewer.filter]
|
||||||
#no_owner = false
|
# WARNING: if it is not set, it will publish contact information of other persons
|
||||||
|
no_owner = true
|
||||||
|
|
||||||
|
|
||||||
# definition for nodelist.json
|
# definition for nodelist.json
|
||||||
@ -105,8 +112,9 @@ graph_path = "/var/www/html/meshviewer/data/graph.json"
|
|||||||
enable = true
|
enable = true
|
||||||
path = "/var/www/html/meshviewer/data/nodelist.json"
|
path = "/var/www/html/meshviewer/data/nodelist.json"
|
||||||
|
|
||||||
#[nodes.output.nodelist.filter]
|
[nodes.output.nodelist.filter]
|
||||||
#no_owner = false
|
# WARNING: if it is not set, it will publish contact information of other persons
|
||||||
|
no_owner = true
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -196,6 +196,7 @@ enable = true
|
|||||||
[nodes.output.example.filter]
|
[nodes.output.example.filter]
|
||||||
no_owner = true
|
no_owner = true
|
||||||
blacklist = ["00112233445566", "1337f0badead"]
|
blacklist = ["00112233445566", "1337f0badead"]
|
||||||
|
sites = ["ffhb"]
|
||||||
has_location = true
|
has_location = true
|
||||||
[nodes.output.example.filter.in_area]
|
[nodes.output.example.filter.in_area]
|
||||||
latitude_min = 34.30
|
latitude_min = 34.30
|
||||||
@ -222,6 +223,7 @@ For each output format there can be set different filters
|
|||||||
[nodes.output.example.filter]
|
[nodes.output.example.filter]
|
||||||
no_owner = true
|
no_owner = true
|
||||||
blacklist = ["00112233445566", "1337f0badead"]
|
blacklist = ["00112233445566", "1337f0badead"]
|
||||||
|
sites = ["ffhb"]
|
||||||
has_location = true
|
has_location = true
|
||||||
[nodes.output.example.filter.in_area]
|
[nodes.output.example.filter.in_area]
|
||||||
latitude_min = 34.30
|
latitude_min = 34.30
|
||||||
@ -235,6 +237,10 @@ longitude_max = 39.72
|
|||||||
### no_owner
|
### no_owner
|
||||||
{% method %}
|
{% method %}
|
||||||
Set to false, if you want the json files to contain the owner information
|
Set to false, if you want the json files to contain the owner information
|
||||||
|
|
||||||
|
|
||||||
|
**WARNING: if it is not set, it will publish contact information of other persons.**
|
||||||
|
|
||||||
{% sample lang="toml" %}
|
{% sample lang="toml" %}
|
||||||
```toml
|
```toml
|
||||||
no_owner = true
|
no_owner = true
|
||||||
@ -252,6 +258,16 @@ blacklist = ["00112233445566", "1337f0badead"]
|
|||||||
{% endmethod %}
|
{% endmethod %}
|
||||||
|
|
||||||
|
|
||||||
|
### sites
|
||||||
|
{% method %}
|
||||||
|
List of site_codes of nodes that should be included in output
|
||||||
|
{% sample lang="toml" %}
|
||||||
|
```toml
|
||||||
|
sites = ["ffhb"]
|
||||||
|
```
|
||||||
|
{% endmethod %}
|
||||||
|
|
||||||
|
|
||||||
### has_location
|
### has_location
|
||||||
{% method %}
|
{% method %}
|
||||||
set has_location to true if you want to include only nodes that have geo-coordinates set
|
set has_location to true if you want to include only nodes that have geo-coordinates set
|
||||||
|
@ -1,44 +1,9 @@
|
|||||||
package all
|
package all
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/FreifunkBremen/yanic/runtime"
|
_ "github.com/FreifunkBremen/yanic/output/filter/blacklist"
|
||||||
|
_ "github.com/FreifunkBremen/yanic/output/filter/haslocation"
|
||||||
|
_ "github.com/FreifunkBremen/yanic/output/filter/inarea"
|
||||||
|
_ "github.com/FreifunkBremen/yanic/output/filter/noowner"
|
||||||
|
_ "github.com/FreifunkBremen/yanic/output/filter/site"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Config Filter
|
|
||||||
type filterConfig map[string]interface{}
|
|
||||||
|
|
||||||
type filterFunc func(*runtime.Node) *runtime.Node
|
|
||||||
|
|
||||||
func noFilter(node *runtime.Node) *runtime.Node {
|
|
||||||
return node
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create Filter
|
|
||||||
func (f filterConfig) filtering(nodesOrigin *runtime.Nodes) *runtime.Nodes {
|
|
||||||
nodes := runtime.NewNodes(&runtime.NodesConfig{})
|
|
||||||
filterfuncs := []filterFunc{
|
|
||||||
f.HasLocation(),
|
|
||||||
f.Blacklist(),
|
|
||||||
f.InArea(),
|
|
||||||
f.NoOwner(),
|
|
||||||
}
|
|
||||||
|
|
||||||
nodesOrigin.Lock()
|
|
||||||
defer nodesOrigin.Unlock()
|
|
||||||
|
|
||||||
for _, nodeOrigin := range nodesOrigin.List {
|
|
||||||
//maybe cloning of this object is better?
|
|
||||||
node := nodeOrigin
|
|
||||||
for _, f := range filterfuncs {
|
|
||||||
node = f(node)
|
|
||||||
if node == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if node != nil {
|
|
||||||
nodes.AddNode(node)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nodes
|
|
||||||
}
|
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
package all
|
|
||||||
|
|
||||||
import "github.com/FreifunkBremen/yanic/runtime"
|
|
||||||
|
|
||||||
func (f filterConfig) Blacklist() filterFunc {
|
|
||||||
v, ok := f["blacklist"]
|
|
||||||
if !ok {
|
|
||||||
return noFilter
|
|
||||||
}
|
|
||||||
|
|
||||||
list := make(map[string]interface{})
|
|
||||||
for _, nodeid := range v.([]interface{}) {
|
|
||||||
list[nodeid.(string)] = true
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(node *runtime.Node) *runtime.Node {
|
|
||||||
if nodeinfo := node.Nodeinfo; nodeinfo != nil {
|
|
||||||
if _, ok := list[nodeinfo.NodeID]; ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return node
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
package all
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/FreifunkBremen/yanic/data"
|
|
||||||
"github.com/FreifunkBremen/yanic/runtime"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestFilterBlacklist(t *testing.T) {
|
|
||||||
assert := assert.New(t)
|
|
||||||
var config filterConfig
|
|
||||||
|
|
||||||
config = map[string]interface{}{}
|
|
||||||
|
|
||||||
filterBlacklist := config.Blacklist()
|
|
||||||
|
|
||||||
n := filterBlacklist(&runtime.Node{Nodeinfo: &data.NodeInfo{}})
|
|
||||||
assert.NotNil(n)
|
|
||||||
|
|
||||||
config["blacklist"] = []interface{}{"a", "c"}
|
|
||||||
filterBlacklist = config.Blacklist()
|
|
||||||
|
|
||||||
n = filterBlacklist(&runtime.Node{Nodeinfo: &data.NodeInfo{NodeID: "a"}})
|
|
||||||
assert.Nil(n)
|
|
||||||
|
|
||||||
n = filterBlacklist(&runtime.Node{Nodeinfo: &data.NodeInfo{}})
|
|
||||||
assert.NotNil(n)
|
|
||||||
|
|
||||||
n = filterBlacklist(&runtime.Node{})
|
|
||||||
assert.NotNil(n)
|
|
||||||
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
package all
|
|
||||||
|
|
||||||
import "github.com/FreifunkBremen/yanic/runtime"
|
|
||||||
|
|
||||||
func (f filterConfig) HasLocation() filterFunc {
|
|
||||||
withLocation, ok := f["has_location"].(bool)
|
|
||||||
if !ok {
|
|
||||||
return noFilter
|
|
||||||
}
|
|
||||||
return func(node *runtime.Node) *runtime.Node {
|
|
||||||
if nodeinfo := node.Nodeinfo; nodeinfo != nil {
|
|
||||||
if withLocation {
|
|
||||||
if location := nodeinfo.Location; location != nil {
|
|
||||||
return node
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if location := nodeinfo.Location; location == nil {
|
|
||||||
return node
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if !withLocation {
|
|
||||||
return node
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,50 +0,0 @@
|
|||||||
package all
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/FreifunkBremen/yanic/data"
|
|
||||||
"github.com/FreifunkBremen/yanic/runtime"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestFilterHasLocation(t *testing.T) {
|
|
||||||
assert := assert.New(t)
|
|
||||||
var config filterConfig
|
|
||||||
|
|
||||||
config = map[string]interface{}{}
|
|
||||||
|
|
||||||
filterHasLocation := config.HasLocation()
|
|
||||||
n := filterHasLocation(&runtime.Node{Nodeinfo: &data.NodeInfo{
|
|
||||||
Location: &data.Location{},
|
|
||||||
}})
|
|
||||||
assert.NotNil(n)
|
|
||||||
|
|
||||||
config["has_location"] = true
|
|
||||||
filterHasLocation = config.HasLocation()
|
|
||||||
|
|
||||||
n = filterHasLocation(&runtime.Node{Nodeinfo: &data.NodeInfo{
|
|
||||||
Location: &data.Location{},
|
|
||||||
}})
|
|
||||||
assert.NotNil(n)
|
|
||||||
|
|
||||||
n = filterHasLocation(&runtime.Node{Nodeinfo: &data.NodeInfo{}})
|
|
||||||
assert.Nil(n)
|
|
||||||
|
|
||||||
n = filterHasLocation(&runtime.Node{})
|
|
||||||
assert.Nil(n)
|
|
||||||
|
|
||||||
config["has_location"] = false
|
|
||||||
filterHasLocation = config.HasLocation()
|
|
||||||
|
|
||||||
n = filterHasLocation(&runtime.Node{Nodeinfo: &data.NodeInfo{
|
|
||||||
Location: &data.Location{},
|
|
||||||
}})
|
|
||||||
assert.Nil(n)
|
|
||||||
|
|
||||||
n = filterHasLocation(&runtime.Node{Nodeinfo: &data.NodeInfo{}})
|
|
||||||
assert.NotNil(n)
|
|
||||||
|
|
||||||
n = filterHasLocation(&runtime.Node{})
|
|
||||||
assert.NotNil(n)
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
package all
|
|
||||||
|
|
||||||
import "github.com/FreifunkBremen/yanic/runtime"
|
|
||||||
|
|
||||||
type area struct {
|
|
||||||
latitudeMin float64
|
|
||||||
latitudeMax float64
|
|
||||||
longitudeMin float64
|
|
||||||
longitudeMax float64
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f filterConfig) InArea() filterFunc {
|
|
||||||
if areaConfigInt, ok := f["in_area"]; ok {
|
|
||||||
areaConfig := areaConfigInt.(map[string]interface{})
|
|
||||||
a := area{}
|
|
||||||
if v, ok := areaConfig["latitude_min"]; ok {
|
|
||||||
a.latitudeMin = v.(float64)
|
|
||||||
}
|
|
||||||
if v, ok := areaConfig["latitude_max"]; ok {
|
|
||||||
a.latitudeMax = v.(float64)
|
|
||||||
}
|
|
||||||
if v, ok := areaConfig["longitude_min"]; ok {
|
|
||||||
a.longitudeMin = v.(float64)
|
|
||||||
}
|
|
||||||
if v, ok := areaConfig["longitude_max"]; ok {
|
|
||||||
a.longitudeMax = v.(float64)
|
|
||||||
}
|
|
||||||
return func(node *runtime.Node) *runtime.Node {
|
|
||||||
if nodeinfo := node.Nodeinfo; nodeinfo != nil {
|
|
||||||
location := nodeinfo.Location
|
|
||||||
if location == nil {
|
|
||||||
return node
|
|
||||||
}
|
|
||||||
if location.Latitude >= a.latitudeMin && location.Latitude <= a.latitudeMax && location.Longitude >= a.longitudeMin && location.Longitude <= a.longitudeMax {
|
|
||||||
return node
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return noFilter
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
package all
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/FreifunkBremen/yanic/data"
|
|
||||||
"github.com/FreifunkBremen/yanic/runtime"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestFilterInArea(t *testing.T) {
|
|
||||||
assert := assert.New(t)
|
|
||||||
var config filterConfig
|
|
||||||
areaConfig := map[string]interface{}{
|
|
||||||
"latitude_min": 3.0,
|
|
||||||
"latitude_max": 5.0,
|
|
||||||
"longitude_min": 10.0,
|
|
||||||
"longitude_max": 12.0,
|
|
||||||
}
|
|
||||||
config = map[string]interface{}{}
|
|
||||||
|
|
||||||
filterLocationInArea := config.InArea()
|
|
||||||
n := filterLocationInArea(&runtime.Node{Nodeinfo: &data.NodeInfo{
|
|
||||||
Location: &data.Location{Latitude: 4.0, Longitude: 11.0},
|
|
||||||
}})
|
|
||||||
assert.NotNil(n)
|
|
||||||
|
|
||||||
config["in_area"] = areaConfig
|
|
||||||
filterLocationInArea = config.InArea()
|
|
||||||
|
|
||||||
// drop area without nodeinfo
|
|
||||||
n = filterLocationInArea(&runtime.Node{})
|
|
||||||
assert.Nil(n)
|
|
||||||
|
|
||||||
// keep without location
|
|
||||||
n = filterLocationInArea(&runtime.Node{Nodeinfo: &data.NodeInfo{}})
|
|
||||||
assert.NotNil(n)
|
|
||||||
|
|
||||||
// zeros not in area (0, 0)
|
|
||||||
n = filterLocationInArea(&runtime.Node{Nodeinfo: &data.NodeInfo{
|
|
||||||
Location: &data.Location{},
|
|
||||||
}})
|
|
||||||
assert.Nil(n)
|
|
||||||
|
|
||||||
// in area
|
|
||||||
n = filterLocationInArea(&runtime.Node{Nodeinfo: &data.NodeInfo{
|
|
||||||
Location: &data.Location{Latitude: 4.0, Longitude: 11.0},
|
|
||||||
}})
|
|
||||||
assert.NotNil(n)
|
|
||||||
|
|
||||||
n = filterLocationInArea(&runtime.Node{Nodeinfo: &data.NodeInfo{
|
|
||||||
Location: &data.Location{Latitude: 4.0, Longitude: 13.0},
|
|
||||||
}})
|
|
||||||
assert.Nil(n)
|
|
||||||
|
|
||||||
n = filterLocationInArea(&runtime.Node{Nodeinfo: &data.NodeInfo{
|
|
||||||
Location: &data.Location{Latitude: 6.0, Longitude: 11.0},
|
|
||||||
}})
|
|
||||||
assert.Nil(n)
|
|
||||||
|
|
||||||
n = filterLocationInArea(&runtime.Node{Nodeinfo: &data.NodeInfo{
|
|
||||||
Location: &data.Location{Latitude: 1.0, Longitude: 2.0},
|
|
||||||
}})
|
|
||||||
assert.Nil(n)
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
package all
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/FreifunkBremen/yanic/data"
|
|
||||||
"github.com/FreifunkBremen/yanic/runtime"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (f filterConfig) NoOwner() filterFunc {
|
|
||||||
if v, ok := f["no_owner"]; ok && v.(bool) == false {
|
|
||||||
return noFilter
|
|
||||||
}
|
|
||||||
return func(node *runtime.Node) *runtime.Node {
|
|
||||||
if nodeinfo := node.Nodeinfo; nodeinfo != nil {
|
|
||||||
return &runtime.Node{
|
|
||||||
Address: node.Address,
|
|
||||||
Firstseen: node.Firstseen,
|
|
||||||
Lastseen: node.Lastseen,
|
|
||||||
Online: node.Online,
|
|
||||||
Statistics: node.Statistics,
|
|
||||||
Nodeinfo: &data.NodeInfo{
|
|
||||||
NodeID: nodeinfo.NodeID,
|
|
||||||
Network: nodeinfo.Network,
|
|
||||||
System: nodeinfo.System,
|
|
||||||
Owner: nil,
|
|
||||||
Hostname: nodeinfo.Hostname,
|
|
||||||
Location: nodeinfo.Location,
|
|
||||||
Software: nodeinfo.Software,
|
|
||||||
Hardware: nodeinfo.Hardware,
|
|
||||||
VPN: nodeinfo.VPN,
|
|
||||||
Wireless: nodeinfo.Wireless,
|
|
||||||
},
|
|
||||||
Neighbours: node.Neighbours,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return node
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,49 +0,0 @@
|
|||||||
package all
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/FreifunkBremen/yanic/data"
|
|
||||||
"github.com/FreifunkBremen/yanic/runtime"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestFilterNoOwner(t *testing.T) {
|
|
||||||
assert := assert.New(t)
|
|
||||||
var config filterConfig
|
|
||||||
|
|
||||||
config = map[string]interface{}{}
|
|
||||||
|
|
||||||
filterNoOwner := config.NoOwner()
|
|
||||||
n := filterNoOwner(&runtime.Node{Nodeinfo: &data.NodeInfo{
|
|
||||||
Owner: &data.Owner{
|
|
||||||
Contact: "blub",
|
|
||||||
},
|
|
||||||
}})
|
|
||||||
assert.NotNil(n)
|
|
||||||
assert.Nil(n.Nodeinfo.Owner)
|
|
||||||
|
|
||||||
n = filterNoOwner(&runtime.Node{})
|
|
||||||
assert.NotNil(n)
|
|
||||||
|
|
||||||
config["no_owner"] = true
|
|
||||||
filterNoOwner = config.NoOwner()
|
|
||||||
n = filterNoOwner(&runtime.Node{Nodeinfo: &data.NodeInfo{
|
|
||||||
Owner: &data.Owner{
|
|
||||||
Contact: "blub",
|
|
||||||
},
|
|
||||||
}})
|
|
||||||
assert.NotNil(n)
|
|
||||||
assert.Nil(n.Nodeinfo.Owner)
|
|
||||||
|
|
||||||
config["no_owner"] = false
|
|
||||||
filterNoOwner = config.NoOwner()
|
|
||||||
|
|
||||||
n = filterNoOwner(&runtime.Node{Nodeinfo: &data.NodeInfo{
|
|
||||||
Owner: &data.Owner{
|
|
||||||
Contact: "blub",
|
|
||||||
},
|
|
||||||
}})
|
|
||||||
assert.NotNil(n)
|
|
||||||
assert.NotNil(n.Nodeinfo.Owner)
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
package all
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/FreifunkBremen/yanic/data"
|
|
||||||
"github.com/FreifunkBremen/yanic/runtime"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestFilter(t *testing.T) {
|
|
||||||
assert := assert.New(t)
|
|
||||||
|
|
||||||
// filtered - do not run all
|
|
||||||
nodes := &runtime.Nodes{
|
|
||||||
List: map[string]*runtime.Node{
|
|
||||||
"a": {
|
|
||||||
Nodeinfo: &data.NodeInfo{NodeID: "a"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
config := filterConfig{
|
|
||||||
"has_location": true,
|
|
||||||
}
|
|
||||||
nodes = config.filtering(nodes)
|
|
||||||
assert.Len(nodes.List, 0)
|
|
||||||
|
|
||||||
// run to end
|
|
||||||
nodes = &runtime.Nodes{
|
|
||||||
List: map[string]*runtime.Node{
|
|
||||||
"a": {
|
|
||||||
Nodeinfo: &data.NodeInfo{NodeID: "a"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
config = filterConfig{
|
|
||||||
"has_location": false,
|
|
||||||
}
|
|
||||||
nodes = config.filtering(nodes)
|
|
||||||
assert.Len(nodes.List, 1)
|
|
||||||
}
|
|
@ -5,18 +5,19 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
|
|
||||||
"github.com/FreifunkBremen/yanic/output"
|
"github.com/FreifunkBremen/yanic/output"
|
||||||
|
"github.com/FreifunkBremen/yanic/output/filter"
|
||||||
"github.com/FreifunkBremen/yanic/runtime"
|
"github.com/FreifunkBremen/yanic/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Output struct {
|
type Output struct {
|
||||||
output.Output
|
output.Output
|
||||||
list map[int]output.Output
|
list map[int]output.Output
|
||||||
filter map[int]filterConfig
|
outputFilter map[int]filter.Set
|
||||||
}
|
}
|
||||||
|
|
||||||
func Register(configuration map[string]interface{}) (output.Output, error) {
|
func Register(configuration map[string]interface{}) (output.Output, error) {
|
||||||
list := make(map[int]output.Output)
|
list := make(map[int]output.Output)
|
||||||
filter := make(map[int]filterConfig)
|
outputFilter := make(map[int]filter.Set)
|
||||||
i := 1
|
i := 1
|
||||||
allOutputs := configuration
|
allOutputs := configuration
|
||||||
for outputType, outputRegister := range output.Adapters {
|
for outputType, outputRegister := range output.Adapters {
|
||||||
@ -44,25 +45,26 @@ func Register(configuration map[string]interface{}) (output.Output, error) {
|
|||||||
if output == nil {
|
if output == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
list[i] = output
|
var errs []error
|
||||||
|
var filterSet filter.Set
|
||||||
if c := config["filter"]; c != nil {
|
if c := config["filter"]; c != nil {
|
||||||
filter[i] = config["filter"].(map[string]interface{})
|
if filterConf, ok := c.(map[string]interface{}); ok {
|
||||||
|
filterSet, errs = filter.New(filterConf)
|
||||||
|
}
|
||||||
|
if len(errs) > 0 {
|
||||||
|
return nil, fmt.Errorf("filter configuration errors: %v", errs)
|
||||||
|
}
|
||||||
|
outputFilter[i] = filterSet
|
||||||
}
|
}
|
||||||
|
list[i] = output
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &Output{list: list, filter: filter}, nil
|
return &Output{list: list, outputFilter: outputFilter}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Output) Save(nodes *runtime.Nodes) {
|
func (o *Output) Save(nodes *runtime.Nodes) {
|
||||||
for i, item := range o.list {
|
for i, item := range o.list {
|
||||||
var filteredNodes *runtime.Nodes
|
item.Save(o.outputFilter[i].Apply(nodes))
|
||||||
if config := o.filter[i]; config != nil {
|
|
||||||
filteredNodes = config.filtering(nodes)
|
|
||||||
} else {
|
|
||||||
filteredNodes = filterConfig{}.filtering(nodes)
|
|
||||||
}
|
|
||||||
|
|
||||||
item.Save(filteredNodes)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,16 +82,40 @@ func TestStart(t *testing.T) {
|
|||||||
allOutput.Save(nodes)
|
allOutput.Save(nodes)
|
||||||
assert.Equal(3, globalOutput.Get())
|
assert.Equal(3, globalOutput.Get())
|
||||||
|
|
||||||
|
// wrong format - map
|
||||||
_, err = Register(map[string]interface{}{
|
_, err = Register(map[string]interface{}{
|
||||||
"e": []map[string]interface{}{
|
"e": []interface{}{
|
||||||
{},
|
false,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
assert.Error(err)
|
assert.Error(err)
|
||||||
|
|
||||||
// wrong format
|
// wrong format - array
|
||||||
_, err = Register(map[string]interface{}{
|
_, err = Register(map[string]interface{}{
|
||||||
"e": true,
|
"e": true,
|
||||||
})
|
})
|
||||||
assert.Error(err)
|
assert.Error(err)
|
||||||
|
|
||||||
|
// output error
|
||||||
|
_, err = Register(map[string]interface{}{
|
||||||
|
"e": []interface{}{
|
||||||
|
map[string]interface{}{
|
||||||
|
"enable": true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
assert.Error(err)
|
||||||
|
|
||||||
|
// output error invalid config of filter
|
||||||
|
_, err = Register(map[string]interface{}{
|
||||||
|
"a": []interface{}{
|
||||||
|
map[string]interface{}{
|
||||||
|
"enable": true,
|
||||||
|
"filter": map[string]interface{}{
|
||||||
|
"blacklist": true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
assert.Error(err)
|
||||||
}
|
}
|
||||||
|
36
output/filter/blacklist/blacklist.go
Normal file
36
output/filter/blacklist/blacklist.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package blacklist
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/FreifunkBremen/yanic/output/filter"
|
||||||
|
"github.com/FreifunkBremen/yanic/runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
type blacklist map[string]interface{}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
filter.Register("blacklist", build)
|
||||||
|
}
|
||||||
|
|
||||||
|
func build(config interface{}) (filter.Filter, error) {
|
||||||
|
values, ok := config.([]string)
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("invalid configuration, array of strings expected")
|
||||||
|
}
|
||||||
|
|
||||||
|
list := make(blacklist)
|
||||||
|
for _, nodeid := range values {
|
||||||
|
list[nodeid] = struct{}{}
|
||||||
|
}
|
||||||
|
return &list, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (list blacklist) Apply(node *runtime.Node) *runtime.Node {
|
||||||
|
if nodeinfo := node.Nodeinfo; nodeinfo != nil {
|
||||||
|
if _, ok := list[nodeinfo.NodeID]; ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return node
|
||||||
|
}
|
38
output/filter/blacklist/blacklist_test.go
Normal file
38
output/filter/blacklist/blacklist_test.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package blacklist
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/FreifunkBremen/yanic/data"
|
||||||
|
"github.com/FreifunkBremen/yanic/runtime"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFilterBlacklist(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
|
||||||
|
// invalid config
|
||||||
|
filter, err := build(3)
|
||||||
|
assert.Error(err)
|
||||||
|
|
||||||
|
// tests with empty list
|
||||||
|
filter, err = build([]string{})
|
||||||
|
|
||||||
|
// keep node without nodeid
|
||||||
|
n := filter.Apply(&runtime.Node{Nodeinfo: &data.NodeInfo{}})
|
||||||
|
assert.NotNil(n)
|
||||||
|
|
||||||
|
// tests with blacklist
|
||||||
|
filter, _ = build([]string{"a", "c"})
|
||||||
|
|
||||||
|
// blacklist contains node with nodeid -> drop it
|
||||||
|
n = filter.Apply(&runtime.Node{Nodeinfo: &data.NodeInfo{NodeID: "a"}})
|
||||||
|
assert.Nil(n)
|
||||||
|
|
||||||
|
// blacklist does not contains node without nodeid -> keep it
|
||||||
|
n = filter.Apply(&runtime.Node{Nodeinfo: &data.NodeInfo{}})
|
||||||
|
assert.NotNil(n)
|
||||||
|
|
||||||
|
n = filter.Apply(&runtime.Node{})
|
||||||
|
assert.NotNil(n)
|
||||||
|
}
|
73
output/filter/filter.go
Normal file
73
output/filter/filter.go
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
package filter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/FreifunkBremen/yanic/runtime"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// factory function for building a filter
|
||||||
|
// may return nil if the filter never applies
|
||||||
|
type factory func(interface{}) (Filter, error)
|
||||||
|
|
||||||
|
// Filter is a filter instance
|
||||||
|
type Filter interface {
|
||||||
|
Apply(*runtime.Node) *runtime.Node
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set is a list of configured filters
|
||||||
|
type Set []Filter
|
||||||
|
|
||||||
|
var filters = make(map[string]factory)
|
||||||
|
|
||||||
|
// Register registers a new filter
|
||||||
|
func Register(name string, f factory) {
|
||||||
|
if _, ok := filters[name]; ok {
|
||||||
|
panic("already registered: " + name)
|
||||||
|
}
|
||||||
|
filters[name] = f
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns and initializes a set of filters
|
||||||
|
func New(configs map[string]interface{}) (set Set, errs []error) {
|
||||||
|
for name, config := range configs {
|
||||||
|
if config == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
f, _ := filters[name]
|
||||||
|
if f == nil {
|
||||||
|
errs = append(errs, fmt.Errorf("unknown filter: %s", name))
|
||||||
|
} else if filter, err := f(config); err != nil {
|
||||||
|
errs = append(errs, errors.Wrapf(err, "unable to initialize filter %s", name))
|
||||||
|
} else if filter != nil {
|
||||||
|
set = append(set, filter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply applies the filter set to the given node list and returns a new node list
|
||||||
|
func (set Set) Apply(nodesOrigin *runtime.Nodes) *runtime.Nodes {
|
||||||
|
nodes := runtime.NewNodes(&runtime.NodesConfig{})
|
||||||
|
|
||||||
|
nodesOrigin.Lock()
|
||||||
|
defer nodesOrigin.Unlock()
|
||||||
|
|
||||||
|
for _, nodeOrigin := range nodesOrigin.List {
|
||||||
|
//maybe cloning of this object is better?
|
||||||
|
node := nodeOrigin
|
||||||
|
for _, filter := range set {
|
||||||
|
node = filter.Apply(node)
|
||||||
|
if node == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if node != nil {
|
||||||
|
nodes.AddNode(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nodes
|
||||||
|
}
|
96
output/filter/filter_test.go
Normal file
96
output/filter/filter_test.go
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
package filter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/FreifunkBremen/yanic/data"
|
||||||
|
"github.com/FreifunkBremen/yanic/runtime"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
type filterBool struct{ bool }
|
||||||
|
|
||||||
|
func (f filterBool) Apply(node *runtime.Node) *runtime.Node {
|
||||||
|
if f.bool {
|
||||||
|
return node
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func build(v interface{}) (Filter, error) {
|
||||||
|
if config, ok := v.(bool); ok {
|
||||||
|
return &filterBool{config}, nil
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildNil(v interface{}) (Filter, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildError(v interface{}) (Filter, error) {
|
||||||
|
if v != nil {
|
||||||
|
return nil, errors.New("some errors")
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilter(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
|
||||||
|
Register("test_nil", buildNil)
|
||||||
|
Register("test_err", buildError)
|
||||||
|
Register("test", build)
|
||||||
|
|
||||||
|
// filter still exists
|
||||||
|
filter, err := New(map[string]interface{}{
|
||||||
|
"adsa": true,
|
||||||
|
})
|
||||||
|
assert.Len(err, 1)
|
||||||
|
assert.Nil(filter)
|
||||||
|
|
||||||
|
// no filter
|
||||||
|
filter, err = New(map[string]interface{}{
|
||||||
|
"test_nil": 3,
|
||||||
|
})
|
||||||
|
assert.Len(err, 0)
|
||||||
|
assert.Len(filter, 0)
|
||||||
|
|
||||||
|
// filter error
|
||||||
|
filter, err = New(map[string]interface{}{
|
||||||
|
"test_err": false,
|
||||||
|
})
|
||||||
|
assert.Len(err, 1)
|
||||||
|
assert.Nil(filter)
|
||||||
|
|
||||||
|
// filter a node
|
||||||
|
nodes := &runtime.Nodes{
|
||||||
|
List: map[string]*runtime.Node{
|
||||||
|
"a": {
|
||||||
|
Nodeinfo: &data.NodeInfo{NodeID: "a"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
filter, err = New(map[string]interface{}{
|
||||||
|
"test": false,
|
||||||
|
})
|
||||||
|
assert.Len(err, 0)
|
||||||
|
nodes = filter.Apply(nodes)
|
||||||
|
assert.Len(nodes.List, 0)
|
||||||
|
|
||||||
|
// keep a node
|
||||||
|
nodes = &runtime.Nodes{
|
||||||
|
List: map[string]*runtime.Node{
|
||||||
|
"a": {
|
||||||
|
Nodeinfo: &data.NodeInfo{NodeID: "a"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
filter, err = New(map[string]interface{}{
|
||||||
|
"test": true,
|
||||||
|
})
|
||||||
|
assert.Len(err, 0)
|
||||||
|
nodes = filter.Apply(nodes)
|
||||||
|
assert.Len(nodes.List, 1)
|
||||||
|
}
|
40
output/filter/haslocation/haslocation.go
Normal file
40
output/filter/haslocation/haslocation.go
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
package haslocation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/FreifunkBremen/yanic/output/filter"
|
||||||
|
"github.com/FreifunkBremen/yanic/runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
type haslocation struct {
|
||||||
|
has bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
filter.Register("has_location", build)
|
||||||
|
}
|
||||||
|
|
||||||
|
func build(config interface{}) (filter.Filter, error) {
|
||||||
|
if value, ok := config.(bool); ok {
|
||||||
|
return &haslocation{has: value}, nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("invalid configuration, bool expected")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *haslocation) Apply(node *runtime.Node) *runtime.Node {
|
||||||
|
if nodeinfo := node.Nodeinfo; nodeinfo != nil {
|
||||||
|
if h.has {
|
||||||
|
if location := nodeinfo.Location; location != nil {
|
||||||
|
return node
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if location := nodeinfo.Location; location == nil {
|
||||||
|
return node
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if !h.has {
|
||||||
|
return node
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
53
output/filter/haslocation/haslocation_test.go
Normal file
53
output/filter/haslocation/haslocation_test.go
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
package haslocation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/FreifunkBremen/yanic/data"
|
||||||
|
"github.com/FreifunkBremen/yanic/runtime"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFilterHasLocation(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
|
||||||
|
// invalid config
|
||||||
|
filter, err := build(3)
|
||||||
|
assert.Error(err)
|
||||||
|
|
||||||
|
// test to drop nodes without location
|
||||||
|
filter, err = build(true)
|
||||||
|
assert.NoError(err)
|
||||||
|
|
||||||
|
// node has location (with 0,0) -> keep it
|
||||||
|
n := filter.Apply(&runtime.Node{Nodeinfo: &data.NodeInfo{
|
||||||
|
Location: &data.Location{},
|
||||||
|
}})
|
||||||
|
assert.NotNil(n)
|
||||||
|
|
||||||
|
// node without location has no location -> drop it
|
||||||
|
n = filter.Apply(&runtime.Node{Nodeinfo: &data.NodeInfo{}})
|
||||||
|
assert.Nil(n)
|
||||||
|
|
||||||
|
// node without nodeinfo has no location -> drop it
|
||||||
|
n = filter.Apply(&runtime.Node{})
|
||||||
|
assert.Nil(n)
|
||||||
|
|
||||||
|
// test to drop nodes without location
|
||||||
|
filter, err = build(false)
|
||||||
|
assert.NoError(err)
|
||||||
|
|
||||||
|
// node has location (with 0,0) -> drop it
|
||||||
|
n = filter.Apply(&runtime.Node{Nodeinfo: &data.NodeInfo{
|
||||||
|
Location: &data.Location{},
|
||||||
|
}})
|
||||||
|
assert.Nil(n)
|
||||||
|
|
||||||
|
// node without location has no location -> keep it
|
||||||
|
n = filter.Apply(&runtime.Node{Nodeinfo: &data.NodeInfo{}})
|
||||||
|
assert.NotNil(n)
|
||||||
|
|
||||||
|
// node without nodeinfo has no location -> keep it
|
||||||
|
n = filter.Apply(&runtime.Node{})
|
||||||
|
assert.NotNil(n)
|
||||||
|
}
|
65
output/filter/inarea/inarea.go
Normal file
65
output/filter/inarea/inarea.go
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
package inarea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/FreifunkBremen/yanic/output/filter"
|
||||||
|
"github.com/FreifunkBremen/yanic/runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
type area struct {
|
||||||
|
latitudeMin float64
|
||||||
|
latitudeMax float64
|
||||||
|
longitudeMin float64
|
||||||
|
longitudeMax float64
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
filter.Register("in_area", build)
|
||||||
|
}
|
||||||
|
|
||||||
|
func build(config interface{}) (filter.Filter, error) {
|
||||||
|
values, ok := config.(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("invalid configuration, map expected")
|
||||||
|
}
|
||||||
|
|
||||||
|
a := area{}
|
||||||
|
if v, ok := values["latitude_min"]; ok {
|
||||||
|
a.latitudeMin = v.(float64)
|
||||||
|
}
|
||||||
|
if v, ok := values["latitude_max"]; ok {
|
||||||
|
a.latitudeMax = v.(float64)
|
||||||
|
}
|
||||||
|
if v, ok := values["longitude_min"]; ok {
|
||||||
|
a.longitudeMin = v.(float64)
|
||||||
|
}
|
||||||
|
if v, ok := values["longitude_max"]; ok {
|
||||||
|
a.longitudeMax = v.(float64)
|
||||||
|
}
|
||||||
|
|
||||||
|
if a.latitudeMin >= a.latitudeMax {
|
||||||
|
return nil, errors.New("invalid latitude: max is bigger then min")
|
||||||
|
}
|
||||||
|
if a.longitudeMin >= a.longitudeMax {
|
||||||
|
return nil, errors.New("invalid longitude: max is bigger then min")
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO bessere Fehlerbehandlung!
|
||||||
|
|
||||||
|
return &a, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *area) Apply(node *runtime.Node) *runtime.Node {
|
||||||
|
if nodeinfo := node.Nodeinfo; nodeinfo != nil {
|
||||||
|
location := nodeinfo.Location
|
||||||
|
if location == nil {
|
||||||
|
return node
|
||||||
|
}
|
||||||
|
if location.Latitude >= a.latitudeMin && location.Latitude <= a.latitudeMax && location.Longitude >= a.longitudeMin && location.Longitude <= a.longitudeMax {
|
||||||
|
return node
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return node
|
||||||
|
}
|
86
output/filter/inarea/inarea_test.go
Normal file
86
output/filter/inarea/inarea_test.go
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
package inarea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/FreifunkBremen/yanic/data"
|
||||||
|
"github.com/FreifunkBremen/yanic/runtime"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFilterInArea(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
|
||||||
|
filter, _ := build(map[string]interface{}{
|
||||||
|
"latitude_min": 3.0,
|
||||||
|
"latitude_max": 5.0,
|
||||||
|
"longitude_min": 10.0,
|
||||||
|
"longitude_max": 12.0,
|
||||||
|
})
|
||||||
|
|
||||||
|
n := filter.Apply(&runtime.Node{Nodeinfo: &data.NodeInfo{
|
||||||
|
Location: &data.Location{Latitude: 4.0, Longitude: 11.0},
|
||||||
|
}})
|
||||||
|
assert.NotNil(n)
|
||||||
|
|
||||||
|
// keep without nodeinfo -> use has_location for it
|
||||||
|
n = filter.Apply(&runtime.Node{})
|
||||||
|
assert.NotNil(n)
|
||||||
|
|
||||||
|
// keep without location -> use has_location for it
|
||||||
|
n = filter.Apply(&runtime.Node{Nodeinfo: &data.NodeInfo{}})
|
||||||
|
assert.NotNil(n)
|
||||||
|
|
||||||
|
// zeros not in area (0, 0)
|
||||||
|
n = filter.Apply(&runtime.Node{Nodeinfo: &data.NodeInfo{
|
||||||
|
Location: &data.Location{},
|
||||||
|
}})
|
||||||
|
assert.Nil(n)
|
||||||
|
|
||||||
|
// in area
|
||||||
|
n = filter.Apply(&runtime.Node{Nodeinfo: &data.NodeInfo{
|
||||||
|
Location: &data.Location{Latitude: 4.0, Longitude: 11.0},
|
||||||
|
}})
|
||||||
|
assert.NotNil(n)
|
||||||
|
|
||||||
|
// over max longitude -> dropped
|
||||||
|
n = filter.Apply(&runtime.Node{Nodeinfo: &data.NodeInfo{
|
||||||
|
Location: &data.Location{Latitude: 4.0, Longitude: 13.0},
|
||||||
|
}})
|
||||||
|
assert.Nil(n)
|
||||||
|
|
||||||
|
// over max latitude -> dropped
|
||||||
|
n = filter.Apply(&runtime.Node{Nodeinfo: &data.NodeInfo{
|
||||||
|
Location: &data.Location{Latitude: 6.0, Longitude: 11.0},
|
||||||
|
}})
|
||||||
|
assert.Nil(n)
|
||||||
|
|
||||||
|
// lower then mix latitde -> dropped
|
||||||
|
n = filter.Apply(&runtime.Node{Nodeinfo: &data.NodeInfo{
|
||||||
|
Location: &data.Location{Latitude: 1.0, Longitude: 2.0},
|
||||||
|
}})
|
||||||
|
assert.Nil(n)
|
||||||
|
|
||||||
|
// invalid config format
|
||||||
|
_, err := build(true)
|
||||||
|
assert.Error(err)
|
||||||
|
|
||||||
|
// invalid config latitude switched max and min
|
||||||
|
_, err = build(map[string]interface{}{
|
||||||
|
"latitude_min": 5.0,
|
||||||
|
"latitude_max": 3.0,
|
||||||
|
"longitude_min": 10.0,
|
||||||
|
"longitude_max": 12.0,
|
||||||
|
})
|
||||||
|
assert.Error(err)
|
||||||
|
|
||||||
|
// invalid config longitude switched max and min
|
||||||
|
_, err = build(map[string]interface{}{
|
||||||
|
"latitude_min": 3.0,
|
||||||
|
"latitude_max": 5.0,
|
||||||
|
"longitude_min": 15.0,
|
||||||
|
"longitude_max": 10.0,
|
||||||
|
})
|
||||||
|
assert.Error(err)
|
||||||
|
|
||||||
|
}
|
48
output/filter/noowner/noowner.go
Normal file
48
output/filter/noowner/noowner.go
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
package noowner
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/FreifunkBremen/yanic/data"
|
||||||
|
"github.com/FreifunkBremen/yanic/output/filter"
|
||||||
|
"github.com/FreifunkBremen/yanic/runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
type noowner struct{ has bool }
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
filter.Register("noowner", build)
|
||||||
|
}
|
||||||
|
|
||||||
|
func build(config interface{}) (filter.Filter, error) {
|
||||||
|
if value, ok := config.(bool); ok {
|
||||||
|
return &noowner{has: value}, nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("invalid configuration, boolean expected")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (no *noowner) Apply(node *runtime.Node) *runtime.Node {
|
||||||
|
if nodeinfo := node.Nodeinfo; nodeinfo != nil && no.has {
|
||||||
|
node = &runtime.Node{
|
||||||
|
Address: node.Address,
|
||||||
|
Firstseen: node.Firstseen,
|
||||||
|
Lastseen: node.Lastseen,
|
||||||
|
Online: node.Online,
|
||||||
|
Statistics: node.Statistics,
|
||||||
|
Nodeinfo: &data.NodeInfo{
|
||||||
|
NodeID: nodeinfo.NodeID,
|
||||||
|
Network: nodeinfo.Network,
|
||||||
|
System: nodeinfo.System,
|
||||||
|
Owner: nil,
|
||||||
|
Hostname: nodeinfo.Hostname,
|
||||||
|
Location: nodeinfo.Location,
|
||||||
|
Software: nodeinfo.Software,
|
||||||
|
Hardware: nodeinfo.Hardware,
|
||||||
|
VPN: nodeinfo.VPN,
|
||||||
|
Wireless: nodeinfo.Wireless,
|
||||||
|
},
|
||||||
|
Neighbours: node.Neighbours,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return node
|
||||||
|
}
|
39
output/filter/noowner/noowner_test.go
Normal file
39
output/filter/noowner/noowner_test.go
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
package noowner
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/FreifunkBremen/yanic/data"
|
||||||
|
"github.com/FreifunkBremen/yanic/runtime"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFilter(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
|
||||||
|
// invalid config
|
||||||
|
filter, err := build("nope")
|
||||||
|
assert.Error(err)
|
||||||
|
|
||||||
|
// delete owner by configuration
|
||||||
|
filter, _ = build(true)
|
||||||
|
n := filter.Apply(&runtime.Node{Nodeinfo: &data.NodeInfo{
|
||||||
|
Owner: &data.Owner{
|
||||||
|
Contact: "blub",
|
||||||
|
},
|
||||||
|
}})
|
||||||
|
|
||||||
|
assert.NotNil(n)
|
||||||
|
assert.Nil(n.Nodeinfo.Owner)
|
||||||
|
|
||||||
|
// keep owner configuration
|
||||||
|
filter, _ = build(false)
|
||||||
|
n = filter.Apply(&runtime.Node{Nodeinfo: &data.NodeInfo{
|
||||||
|
Owner: &data.Owner{
|
||||||
|
Contact: "blub",
|
||||||
|
},
|
||||||
|
}})
|
||||||
|
|
||||||
|
assert.NotNil(n)
|
||||||
|
assert.NotNil(n.Nodeinfo.Owner)
|
||||||
|
}
|
36
output/filter/site/site.go
Normal file
36
output/filter/site/site.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package site
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/FreifunkBremen/yanic/output/filter"
|
||||||
|
"github.com/FreifunkBremen/yanic/runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
type sites map[string]interface{}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
filter.Register("sites", build)
|
||||||
|
}
|
||||||
|
|
||||||
|
func build(config interface{}) (filter.Filter, error) {
|
||||||
|
values, ok := config.([]string)
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("invalid configuration, array of strings expected")
|
||||||
|
}
|
||||||
|
|
||||||
|
list := make(sites)
|
||||||
|
for _, nodeid := range values {
|
||||||
|
list[nodeid] = struct{}{}
|
||||||
|
}
|
||||||
|
return &list, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (list sites) Apply(node *runtime.Node) *runtime.Node {
|
||||||
|
if nodeinfo := node.Nodeinfo; nodeinfo != nil {
|
||||||
|
if _, ok := list[nodeinfo.System.SiteCode]; ok {
|
||||||
|
return node
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
32
output/filter/site/site_test.go
Normal file
32
output/filter/site/site_test.go
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package site
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/FreifunkBremen/yanic/data"
|
||||||
|
"github.com/FreifunkBremen/yanic/runtime"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFilterSite(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
|
||||||
|
// invalid config
|
||||||
|
filter, err := build("ffhb")
|
||||||
|
assert.Error(err)
|
||||||
|
|
||||||
|
filter, err = build([]string{"ffhb"})
|
||||||
|
assert.NoError(err)
|
||||||
|
|
||||||
|
// wronge node
|
||||||
|
n := filter.Apply(&runtime.Node{Nodeinfo: &data.NodeInfo{System: data.System{SiteCode: "ffxx"}}})
|
||||||
|
assert.Nil(n)
|
||||||
|
|
||||||
|
// right node
|
||||||
|
n = filter.Apply(&runtime.Node{Nodeinfo: &data.NodeInfo{System: data.System{SiteCode: "ffhb"}}})
|
||||||
|
assert.NotNil(n)
|
||||||
|
|
||||||
|
// node without data -> wrong node
|
||||||
|
n = filter.Apply(&runtime.Node{})
|
||||||
|
assert.Nil(n)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user