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.",
|
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() {
|
func init() {
|
||||||
@ -105,6 +113,7 @@ func init() {
|
|||||||
prometheus.MustRegister(deprecatedRegistryErrors)
|
prometheus.MustRegister(deprecatedRegistryErrors)
|
||||||
prometheus.MustRegister(deprecatedSourceErrors)
|
prometheus.MustRegister(deprecatedSourceErrors)
|
||||||
prometheus.MustRegister(controllerNoChangesTotal)
|
prometheus.MustRegister(controllerNoChangesTotal)
|
||||||
|
prometheus.MustRegister(verifiedARecords)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Controller is responsible for orchestrating the different components.
|
// Controller is responsible for orchestrating the different components.
|
||||||
@ -151,7 +160,8 @@ func (c *Controller) RunOnce(ctx context.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
sourceEndpointsTotal.Set(float64(len(endpoints)))
|
sourceEndpointsTotal.Set(float64(len(endpoints)))
|
||||||
|
vRecords := fetchMatchingARecords(endpoints, records)
|
||||||
|
verifiedARecords.Set(float64(len(vRecords)))
|
||||||
endpoints = c.Registry.AdjustEndpoints(endpoints)
|
endpoints = c.Registry.AdjustEndpoints(endpoints)
|
||||||
|
|
||||||
plan := &plan.Plan{
|
plan := &plan.Plan{
|
||||||
@ -181,6 +191,32 @@ func (c *Controller) RunOnce(ctx context.Context) error {
|
|||||||
return nil
|
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.
|
// ScheduleRunOnce makes sure execution happens at most once per interval.
|
||||||
func (c *Controller) ScheduleRunOnce(now time.Time) {
|
func (c *Controller) ScheduleRunOnce(now time.Time) {
|
||||||
c.nextRunAtMux.Lock()
|
c.nextRunAtMux.Lock()
|
||||||
|
@ -19,6 +19,8 @@ package controller
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
"math"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@ -49,6 +51,10 @@ type filteredMockProvider struct {
|
|||||||
ApplyChangesCalls []*plan.Changes
|
ApplyChangesCalls []*plan.Changes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type errorMockProvider struct {
|
||||||
|
mockProvider
|
||||||
|
}
|
||||||
|
|
||||||
func (p *filteredMockProvider) GetDomainFilter() endpoint.DomainFilterInterface {
|
func (p *filteredMockProvider) GetDomainFilter() endpoint.DomainFilterInterface {
|
||||||
return p.domainFilter
|
return p.domainFilter
|
||||||
}
|
}
|
||||||
@ -70,6 +76,10 @@ func (p *mockProvider) Records(ctx context.Context) ([]*endpoint.Endpoint, error
|
|||||||
return p.RecordsStore, nil
|
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.
|
// ApplyChanges validates that the passed in changes satisfy the assumptions.
|
||||||
func (p *mockProvider) ApplyChanges(ctx context.Context, changes *plan.Changes) error {
|
func (p *mockProvider) ApplyChanges(ctx context.Context, changes *plan.Changes) error {
|
||||||
if len(changes.Create) != len(p.ExpectChanges.Create) {
|
if len(changes.Create) != len(p.ExpectChanges.Create) {
|
||||||
@ -180,6 +190,13 @@ func TestRunOnce(t *testing.T) {
|
|||||||
|
|
||||||
// Validate that the mock source was called.
|
// Validate that the mock source was called.
|
||||||
source.AssertExpectations(t)
|
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) {
|
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_registry_errors_total | Number of Registry errors | Counter |
|
||||||
| external_dns_source_endpoints_total | Number of Endpoints in the registry | Gauge |
|
| external_dns_source_endpoints_total | Number of Endpoints in the registry | Gauge |
|
||||||
| external_dns_source_errors_total | Number of Source errors | Counter |
|
| 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?
|
### 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