[TASK] add output prometheus-sd (service discovery) (#213)
This commit is contained in:
parent
1dbd52c5cd
commit
60639f2e63
|
@ -27,7 +27,7 @@ func TestReadConfig(t *testing.T) {
|
||||||
assert.Contains(config.Respondd.Sites["ffhb"].Domains, "city")
|
assert.Contains(config.Respondd.Sites["ffhb"].Domains, "city")
|
||||||
|
|
||||||
// Test output plugins
|
// Test output plugins
|
||||||
assert.Len(config.Nodes.Output, 5)
|
assert.Len(config.Nodes.Output, 6)
|
||||||
outputs := config.Nodes.Output["meshviewer"].([]map[string]interface{})
|
outputs := config.Nodes.Output["meshviewer"].([]map[string]interface{})
|
||||||
assert.Len(outputs, 1)
|
assert.Len(outputs, 1)
|
||||||
meshviewer := outputs[0]
|
meshviewer := outputs[0]
|
||||||
|
|
|
@ -158,6 +158,19 @@ path = "/var/www/html/meshviewer/data/nodelist.json"
|
||||||
# WARNING: if it is not set, it will publish contact information of other persons
|
# WARNING: if it is not set, it will publish contact information of other persons
|
||||||
no_owner = true
|
no_owner = true
|
||||||
|
|
||||||
|
# definition for prometheus-sd.json
|
||||||
|
[[nodes.output.prometheus-sd]]
|
||||||
|
enable = true
|
||||||
|
path = "/var/www/html/meshviewer/data/prometheus-sd.json"
|
||||||
|
# ip = lates recieved ip, node_id = node id from host
|
||||||
|
target_address = "ip"
|
||||||
|
|
||||||
|
# Labels of the data (optional)
|
||||||
|
[nodes.output.prometheus-sd.labels]
|
||||||
|
#labelname1 = "labelvalue 1"
|
||||||
|
## some useful e.g.:
|
||||||
|
#hosts = "ffhb"
|
||||||
|
#service = "yanic"
|
||||||
|
|
||||||
# definition for raw.json
|
# definition for raw.json
|
||||||
[[nodes.output.raw]]
|
[[nodes.output.raw]]
|
||||||
|
|
|
@ -545,6 +545,67 @@ path = "/var/www/html/meshviewer/data/nodelist.json"
|
||||||
```
|
```
|
||||||
{% endmethod %}
|
{% endmethod %}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [[nodes.output.prometheus-sd]]
|
||||||
|
{% method %}
|
||||||
|
The Prometheus Service Discovery (SD) output is a output with the list of addresses of the nodes to use them in later exporter by prometheus.
|
||||||
|
For usage in Prometheus read there Documentation [Use file-based service discovery to discover scrape targets](https://prometheus.io/docs/guides/file-sd/).
|
||||||
|
{% sample lang="toml" %}
|
||||||
|
```toml
|
||||||
|
[[nodes.output.prometheus-sd]]
|
||||||
|
enable = false
|
||||||
|
path = "/var/www/html/meshviewer/data/prometheus-sd.json"
|
||||||
|
target_address = "ip"
|
||||||
|
|
||||||
|
[nodes.output.prometheus-sd.labels]
|
||||||
|
labelname1 = "labelvalue 1"
|
||||||
|
# some useful e.g.:
|
||||||
|
hosts = "ffhb"
|
||||||
|
service = "yanic"
|
||||||
|
```
|
||||||
|
{% endmethod %}
|
||||||
|
|
||||||
|
|
||||||
|
### path
|
||||||
|
{% method %}
|
||||||
|
The path, where to store prometheus-sd.json
|
||||||
|
{% sample lang="toml" %}
|
||||||
|
```toml
|
||||||
|
path = "/var/www/html/meshviewer/data/prometheus-sd.json"
|
||||||
|
```
|
||||||
|
{% endmethod %}
|
||||||
|
|
||||||
|
### target_address
|
||||||
|
{% method %}
|
||||||
|
In the prometheus-sd.json the usage of which information of the node as targets (address).
|
||||||
|
|
||||||
|
Use the `node_id` as value, to put the Node ID into the target list as address.
|
||||||
|
Use the `ip` as value to put the last IP address into the target list from where the respondd message is recieved (maybe a link-local address).
|
||||||
|
Default value is `ip`.
|
||||||
|
|
||||||
|
{% sample lang="toml" %}
|
||||||
|
```toml
|
||||||
|
path = "/var/www/html/meshviewer/data/prometheus-sd.json"
|
||||||
|
```
|
||||||
|
{% endmethod %}
|
||||||
|
|
||||||
|
|
||||||
|
### [nodes.output.prometheus-sd.labels]
|
||||||
|
{% method %}
|
||||||
|
You could optional set manuelle labels with inserting into a prometheus-sd.json.
|
||||||
|
Useful if you want to identify the yanic instance when you use multiple own on the same prometheus database (e.g. multisites).
|
||||||
|
|
||||||
|
{% sample lang="toml" %}
|
||||||
|
```toml
|
||||||
|
labelname1 = "labelvalue 1"
|
||||||
|
# some useful e.g.:
|
||||||
|
hosts = "ffhb"
|
||||||
|
service = "yanic"
|
||||||
|
```
|
||||||
|
{% endmethod %}
|
||||||
|
|
||||||
|
|
||||||
## [[nodes.output.raw]]
|
## [[nodes.output.raw]]
|
||||||
{% method %}
|
{% method %}
|
||||||
This output takes the respondd response as sent by the node and includes it in a JSON document.
|
This output takes the respondd response as sent by the node and includes it in a JSON document.
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
_ "github.com/FreifunkBremen/yanic/output/meshviewer"
|
_ "github.com/FreifunkBremen/yanic/output/meshviewer"
|
||||||
_ "github.com/FreifunkBremen/yanic/output/meshviewer-ffrgb"
|
_ "github.com/FreifunkBremen/yanic/output/meshviewer-ffrgb"
|
||||||
_ "github.com/FreifunkBremen/yanic/output/nodelist"
|
_ "github.com/FreifunkBremen/yanic/output/nodelist"
|
||||||
|
_ "github.com/FreifunkBremen/yanic/output/prometheus-sd"
|
||||||
_ "github.com/FreifunkBremen/yanic/output/raw"
|
_ "github.com/FreifunkBremen/yanic/output/raw"
|
||||||
_ "github.com/FreifunkBremen/yanic/output/raw-jsonl"
|
_ "github.com/FreifunkBremen/yanic/output/raw-jsonl"
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
package prometheus_sd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"yanic/output"
|
||||||
|
"yanic/runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Output struct {
|
||||||
|
output.Output
|
||||||
|
path string
|
||||||
|
targetType TargetAddressType
|
||||||
|
labels map[string]interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Config map[string]interface{}
|
||||||
|
|
||||||
|
func (c Config) Path() string {
|
||||||
|
if path, ok := c["path"]; ok {
|
||||||
|
return path.(string)
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
type TargetAddressType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
TargetAddressIP TargetAddressType = "ip"
|
||||||
|
TargetAddressNodeID TargetAddressType = "node_id"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c Config) TargetAddress() TargetAddressType {
|
||||||
|
if v, ok := c["target_address"]; ok {
|
||||||
|
return TargetAddressType(v.(string))
|
||||||
|
}
|
||||||
|
return TargetAddressIP
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Config) Labels() map[string]interface{} {
|
||||||
|
if v, ok := c["labels"]; ok {
|
||||||
|
return v.(map[string]interface{})
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
output.RegisterAdapter("prometheus-sd", Register)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Register(configuration map[string]interface{}) (output.Output, error) {
|
||||||
|
config := Config(configuration)
|
||||||
|
|
||||||
|
if path := config.Path(); path != "" {
|
||||||
|
return &Output{
|
||||||
|
path: path,
|
||||||
|
targetType: config.TargetAddress(),
|
||||||
|
labels: config.Labels(),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("no path given")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
type Targets struct {
|
||||||
|
Targets []string `json:"targets"`
|
||||||
|
Labels map[string]interface{} `json:"labels,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Output) Save(nodes *runtime.Nodes) {
|
||||||
|
nodes.RLock()
|
||||||
|
defer nodes.RUnlock()
|
||||||
|
|
||||||
|
targets := &Targets{
|
||||||
|
Targets: []string{},
|
||||||
|
Labels: o.labels,
|
||||||
|
}
|
||||||
|
if o.targetType == TargetAddressNodeID {
|
||||||
|
for _, n := range nodes.List {
|
||||||
|
if ni := n.Nodeinfo; ni != nil {
|
||||||
|
targets.Targets = append(targets.Targets, ni.NodeID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for _, n := range nodes.List {
|
||||||
|
if addr := n.Address; addr != nil {
|
||||||
|
targets.Targets = append(targets.Targets, addr.IP.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
runtime.SaveJSON([]interface{}{targets}, o.path)
|
||||||
|
}
|
|
@ -0,0 +1,90 @@
|
||||||
|
package prometheus_sd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"yanic/data"
|
||||||
|
"yanic/runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestOutput(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
|
||||||
|
out, err := Register(map[string]interface{}{})
|
||||||
|
assert.Error(err)
|
||||||
|
assert.Nil(out)
|
||||||
|
|
||||||
|
nodes := runtime.NewNodes(&runtime.NodesConfig{})
|
||||||
|
ipAddress, err := net.ResolveUDPAddr("udp6", "[fe80::20de:a:3ac%eth0]:1001")
|
||||||
|
assert.NoError(err)
|
||||||
|
nodes.AddNode(&runtime.Node{
|
||||||
|
Online: true,
|
||||||
|
Address: ipAddress,
|
||||||
|
Nodeinfo: &data.Nodeinfo{
|
||||||
|
NodeID: "node_a",
|
||||||
|
Network: data.Network{
|
||||||
|
Mac: "node:a:mac",
|
||||||
|
Mesh: map[string]*data.NetworkInterface{
|
||||||
|
"bat0": {
|
||||||
|
Interfaces: struct {
|
||||||
|
Wireless []string `json:"wireless,omitempty"`
|
||||||
|
Other []string `json:"other,omitempty"`
|
||||||
|
Tunnel []string `json:"tunnel,omitempty"`
|
||||||
|
}{
|
||||||
|
Wireless: []string{"node:a:mac:wifi"},
|
||||||
|
Tunnel: []string{"node:a:mac:vpn"},
|
||||||
|
Other: []string{"node:a:mac:lan"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Neighbours: &data.Neighbours{
|
||||||
|
NodeID: "node_a",
|
||||||
|
Batadv: map[string]data.BatadvNeighbours{
|
||||||
|
"node:a:mac:wifi": {
|
||||||
|
Neighbours: map[string]data.BatmanLink{
|
||||||
|
"node:b:mac:wifi": {Tq: 153},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"node:a:mac:lan": {
|
||||||
|
Neighbours: map[string]data.BatmanLink{
|
||||||
|
"node:b:mac:lan": {Tq: 51},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// IP
|
||||||
|
out, err = Register(map[string]interface{}{
|
||||||
|
"path": "/tmp/prometheus_sd.json",
|
||||||
|
})
|
||||||
|
os.Remove("/tmp/prometheus_sd.json")
|
||||||
|
assert.NoError(err)
|
||||||
|
assert.NotNil(out)
|
||||||
|
|
||||||
|
out.Save(nodes)
|
||||||
|
_, err = os.Stat("/tmp/prometheus_sd.json")
|
||||||
|
assert.NoError(err)
|
||||||
|
|
||||||
|
// NodeID
|
||||||
|
out, err = Register(map[string]interface{}{
|
||||||
|
"target_address": "node_id",
|
||||||
|
"path": "/tmp/prometheus_sd.json",
|
||||||
|
"labels": map[string]interface{}{
|
||||||
|
"hosts": "ffhb",
|
||||||
|
"service": "yanic",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
os.Remove("/tmp/prometheus_sd.json")
|
||||||
|
assert.NoError(err)
|
||||||
|
assert.NotNil(out)
|
||||||
|
|
||||||
|
out.Save(nodes)
|
||||||
|
_, err = os.Stat("/tmp/prometheus_sd.json")
|
||||||
|
assert.NoError(err)
|
||||||
|
}
|
Loading…
Reference in New Issue