[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")
|
||||
|
||||
// Test output plugins
|
||||
assert.Len(config.Nodes.Output, 5)
|
||||
assert.Len(config.Nodes.Output, 6)
|
||||
outputs := config.Nodes.Output["meshviewer"].([]map[string]interface{})
|
||||
assert.Len(outputs, 1)
|
||||
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
|
||||
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
|
||||
[[nodes.output.raw]]
|
||||
|
|
|
@ -545,6 +545,67 @@ path = "/var/www/html/meshviewer/data/nodelist.json"
|
|||
```
|
||||
{% 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]]
|
||||
{% method %}
|
||||
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-ffrgb"
|
||||
_ "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-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