mirror of
https://github.com/kubernetes-sigs/external-dns.git
synced 2025-08-06 17:46:57 +02:00
Changes to add metric to external-dns.
1. external_dns_controller_verified_records - No of DNS A-records that exists both in source and registry - Gauge Metric
This commit is contained in:
parent
fed5dd26b5
commit
39d5b39e18
@ -94,6 +94,14 @@ var (
|
||||
Help: "Number of Source errors.",
|
||||
},
|
||||
)
|
||||
verifiedARecords = prometheus.NewGauge(
|
||||
prometheus.GaugeOpts{
|
||||
Namespace: "external_dns",
|
||||
Subsystem: "controller",
|
||||
Name: "verified_a_records",
|
||||
Help: "Number of DNS A-records that exists both in source and registry.",
|
||||
},
|
||||
)
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -105,6 +113,7 @@ func init() {
|
||||
prometheus.MustRegister(deprecatedRegistryErrors)
|
||||
prometheus.MustRegister(deprecatedSourceErrors)
|
||||
prometheus.MustRegister(controllerNoChangesTotal)
|
||||
prometheus.MustRegister(verifiedARecords)
|
||||
}
|
||||
|
||||
// Controller is responsible for orchestrating the different components.
|
||||
@ -151,7 +160,8 @@ func (c *Controller) RunOnce(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
sourceEndpointsTotal.Set(float64(len(endpoints)))
|
||||
|
||||
vRecords := fetchMatchingARecords(endpoints, records)
|
||||
verifiedARecords.Set(float64(len(vRecords)))
|
||||
endpoints = c.Registry.AdjustEndpoints(endpoints)
|
||||
|
||||
plan := &plan.Plan{
|
||||
@ -181,6 +191,32 @@ func (c *Controller) RunOnce(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Checks and returns the intersection of A records in endpoint and registry.
|
||||
func fetchMatchingARecords(endpoints []*endpoint.Endpoint, registryRecords []*endpoint.Endpoint) []string {
|
||||
aRecords := filterARecords(endpoints)
|
||||
recordsMap := make(map[string]struct{})
|
||||
for _, regRecord := range registryRecords {
|
||||
recordsMap[regRecord.DNSName] = struct{}{}
|
||||
}
|
||||
var cm []string
|
||||
for _, sourceRecord := range aRecords {
|
||||
if _, found := recordsMap[sourceRecord]; found {
|
||||
cm = append(cm, sourceRecord)
|
||||
}
|
||||
}
|
||||
return cm
|
||||
}
|
||||
|
||||
func filterARecords(endpoints []*endpoint.Endpoint) []string {
|
||||
var aRecords []string
|
||||
for _, endPoint := range endpoints {
|
||||
if endPoint.RecordType == endpoint.RecordTypeA {
|
||||
aRecords = append(aRecords, endPoint.DNSName)
|
||||
}
|
||||
}
|
||||
return aRecords
|
||||
}
|
||||
|
||||
// ScheduleRunOnce makes sure execution happens at most once per interval.
|
||||
func (c *Controller) ScheduleRunOnce(now time.Time) {
|
||||
c.nextRunAtMux.Lock()
|
||||
|
@ -19,6 +19,8 @@ package controller
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"math"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
@ -49,6 +51,10 @@ type filteredMockProvider struct {
|
||||
ApplyChangesCalls []*plan.Changes
|
||||
}
|
||||
|
||||
type errorMockProvider struct {
|
||||
mockProvider
|
||||
}
|
||||
|
||||
func (p *filteredMockProvider) GetDomainFilter() endpoint.DomainFilterInterface {
|
||||
return p.domainFilter
|
||||
}
|
||||
@ -70,6 +76,10 @@ func (p *mockProvider) Records(ctx context.Context) ([]*endpoint.Endpoint, error
|
||||
return p.RecordsStore, nil
|
||||
}
|
||||
|
||||
func (p *errorMockProvider) Records(ctx context.Context) ([]*endpoint.Endpoint, error) {
|
||||
return nil, errors.New("error for testing")
|
||||
}
|
||||
|
||||
// ApplyChanges validates that the passed in changes satisfy the assumptions.
|
||||
func (p *mockProvider) ApplyChanges(ctx context.Context, changes *plan.Changes) error {
|
||||
if len(changes.Create) != len(p.ExpectChanges.Create) {
|
||||
@ -180,6 +190,13 @@ func TestRunOnce(t *testing.T) {
|
||||
|
||||
// Validate that the mock source was called.
|
||||
source.AssertExpectations(t)
|
||||
// check the verified records
|
||||
assert.Equal(t, math.Float64bits(1), valueFromMetric(verifiedARecords))
|
||||
}
|
||||
|
||||
func valueFromMetric(metric prometheus.Gauge) uint64 {
|
||||
ref := reflect.ValueOf(metric)
|
||||
return reflect.Indirect(ref).FieldByName("valBits").Uint()
|
||||
}
|
||||
|
||||
func TestShouldRunOnce(t *testing.T) {
|
||||
@ -376,3 +393,80 @@ func TestWhenMultipleControllerConsidersAllFilteredComain(t *testing.T) {
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func TestVerifyARecords(t *testing.T) {
|
||||
testControllerFiltersDomains(
|
||||
t,
|
||||
[]*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "create-record.used.tld",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"1.2.3.4"},
|
||||
},
|
||||
{
|
||||
DNSName: "some-record.used.tld",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
},
|
||||
},
|
||||
endpoint.NewDomainFilter([]string{"used.tld"}),
|
||||
[]*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "some-record.used.tld",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
},
|
||||
{
|
||||
DNSName: "create-record.used.tld",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"1.2.3.4"},
|
||||
},
|
||||
},
|
||||
[]*plan.Changes{},
|
||||
)
|
||||
assert.Equal(t, math.Float64bits(2), valueFromMetric(verifiedARecords))
|
||||
|
||||
testControllerFiltersDomains(
|
||||
t,
|
||||
[]*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "some-record.1.used.tld",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"1.2.3.4"},
|
||||
},
|
||||
{
|
||||
DNSName: "some-record.2.used.tld",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
},
|
||||
{
|
||||
DNSName: "some-record.3.used.tld",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"24.24.24.24"},
|
||||
},
|
||||
},
|
||||
endpoint.NewDomainFilter([]string{"used.tld"}),
|
||||
[]*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "some-record.1.used.tld",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"1.2.3.4"},
|
||||
},
|
||||
{
|
||||
DNSName: "some-record.2.used.tld",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
},
|
||||
},
|
||||
[]*plan.Changes{{
|
||||
Create: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "some-record.3.used.tld",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"24.24.24.24"},
|
||||
},
|
||||
},
|
||||
}},
|
||||
)
|
||||
assert.Equal(t, math.Float64bits(2), valueFromMetric(verifiedARecords))
|
||||
}
|
||||
|
@ -185,6 +185,8 @@ Here is the full list of available metrics provided by ExternalDNS:
|
||||
| external_dns_registry_errors_total | Number of Registry errors | Counter |
|
||||
| external_dns_source_endpoints_total | Number of Endpoints in the registry | Gauge |
|
||||
| external_dns_source_errors_total | Number of Source errors | Counter |
|
||||
| external_dns_controller_verified_records | Number of DNS A-records that exists both in | Gauge |
|
||||
| | source & registry | |
|
||||
|
||||
### How can I run ExternalDNS under a specific GCP Service Account, e.g. to access DNS records in other projects?
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user