* feat(source): pods added support for annotation filter and label selectors
* feat(source/pods): support for annotation and label filter
Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
---------
Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
* feat(traefik)!: disable legacy listeners on traefik.containo.us API Group
* update docs accordingly
* update test accordingly
* type argument is infered
* fix rebase
* chore(store*): add reduce complexity and improve code coverage
* docs(store.go): reasoning for helper function
* style(store): standardized order of args
* chore: gofmt auto-format source/store.go for lint compliance
* feat(source/pod): add support for fqdn templating
Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
* feat(source/pod): add support for fqdn templating
Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
* feat(source/pod): add support for fqdn templating
Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
* feat(source/pod): add support for fqdn templating
Co-authored-by: vflaux <38909103+vflaux@users.noreply.github.com>
* feat(source/pod): add support for fqdn templating
Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
* feat(source/pod): add support for fqdn templating
Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
* feat(source/pod): add support for fqdn templating
Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
* feat(source/pod): add support for fqdn templating
Co-authored-by: Michel Loiseleur <97035654+mloiseleur@users.noreply.github.com>
---------
Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
Co-authored-by: vflaux <38909103+vflaux@users.noreply.github.com>
Co-authored-by: Michel Loiseleur <97035654+mloiseleur@users.noreply.github.com>
* feat(source/node): Make exclusion of unschedulable Nodes configurable
This fixes a behavioral regression introduced in #4761, where
nodes that were previously added to DNS are removed when they are considered
unschedulable, for example due to automated maintenance tasks.
This change will introduce a new flag called `exclude-unschedulable`, which
defaults to `true` in order to keep in line with the current behavior.
However, it would also be reasonable to restore the initial behavior before
* Allow testing for expected log entries in testNodeSourceEndpoints
This commit adds the required logic to be able to test for
the existence (and absence) of certain log messages
in testNodeSourceEndpoints. As an example, this is implemented
for the tests around excludeUnschedulable.
A side effect of using LogsToBuffer is that tests can't run in
parallel due to the log buffer being shared across all
parallel test cases. As such, these specific tests are now executed
one after another.
* Ensure logging is only hooked for tests that require it
* Document new exclude-unschedulable flag for nodes source
Add two new options:
- --ignore-non-host-network-pods
- --pod-source-domain
Combined toghether, they can be used to register the IPs
of all pods with their associated PTR record.
Co-authored-by: Michel Loiseleur <97035654+mloiseleur@users.noreply.github.com>
* Add annotation filter to Ambassador Host Source
This change makes the Ambassador Host source respect the External-DNS annotationFilter allowing for an Ambassador Host resource to specify what External-DNS deployment to use when there are multiple External-DNS deployments within the same cluster. Before this change if you had two External-DNS deployments within the cluster and used the Ambassador Host source the first External-DNS to process the resource will create the record and not the one that was specified in the filter annotation.
I added the `filterByAnnotations` function so that it matched the same way the other sources have implemented annotation filtering. I didn't add the controller check only because I wanted to keep this change to implementing the annotationFilter.
Example: Create two External-DNS deployments 1 public and 1 private and set the Ambassador Host to use the public External-DNS using the annotation filter.
```
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: external-dns-private
spec:
strategy:
type: Recreate
selector:
matchLabels:
app: external-dns-private
template:
metadata:
labels:
app: external-dns-private
annotations:
iam.amazonaws.com/role: {ARN} # AWS ARN role
spec:
serviceAccountName: external-dns
containers:
- name: external-dns
image: k8s.gcr.io/external-dns/external-dns:latest
args:
- --source=ambassador-host
- --domain-filter=example.net # will make ExternalDNS see only the hosted zones matching provided domain, omit to process all available hosted zones
- --provider=aws
- --policy=upsert-only # would prevent ExternalDNS from deleting any records, omit to enable full synchronization
- --aws-zone-type=private # only look at public hosted zones (valid values are public, private or no value for both)
- --registry=txt
- --txt-owner-id= {Hosted Zone ID} # Insert Route53 Hosted Zone ID here
- --annotation-filter=kubernetes.io/ingress.class in (private)
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: external-dns-public
spec:
strategy:
type: Recreate
selector:
matchLabels:
app: external-dns-public
template:
metadata:
labels:
app: external-dns-public
annotations:
iam.amazonaws.com/role: {ARN} # AWS ARN role
spec:
serviceAccountName: external-dns
containers:
- name: external-dns
image: k8s.gcr.io/external-dns/external-dns:latest
args:
- --source=ambassador-host
- --domain-filter=example.net # will make ExternalDNS see only the hosted zones matching provided domain, omit to process all available hosted zones
- --provider=aws
- --policy=upsert-only # would prevent ExternalDNS from deleting any records, omit to enable full synchronization
- --aws-zone-type= # only look at public hosted zones (valid values are public, private or no value for both)
- --registry=txt
- --txt-owner-id= {Hosted Zone ID} # Insert Route53 Hosted Zone ID here
- --annotation-filter=kubernetes.io/ingress.class in (public)
---
apiVersion: getambassador.io/v3alpha1
kind: Host
metadata:
name: your-hostname
annotations:
external-dns.ambassador-service: emissary-ingress/emissary
kubernetes.io/ingress.class: public
spec:
acmeProvider:
authority: none
hostname: your-hostname.example.com
```
Fixeskubernetes-sigs/external-dns#2632
* Add Label filltering for Ambassador Host source
Currently the `--label-filter` flag can only be used to filter CRDs, Ingress, Service and Openshift Route objects which match the label selector passed through that flag. This change extends the functionality to the Ambassador Host type object.
When the flag is not specified the default value is `labels.Everything()` which is an empty string, the same as before. An annotation based filter is inefficient because the filtering has to be done in the controller instead of the API server like with label filtering. The Annotation based filtering has been left in for legacy reasons so the Ambassador Host source can be used inconjunction with the other sources that don't yet support label filltering.
It is possible to use label based filltering with annotation based filltering so you can initially filter by label then filter the returned hosts by annotation. This is not recomended
* Update Ambassador Host source docs
Add that the Ambassador Host source now supports both annotation and label filltering.
mgruener suggested that the --events flag could be wired to control whether or
not the CRD source created and started its informer. This commit makes that
change; good idea!
This change disables the CRD source's informer during tests. I made the mistake
of not running `make test` before the previous commit, and thus didn't realize
that leaving the informer enabled during the tests introduced a race condition:
WARNING: DATA RACE
Write at 0x00c0005aa130 by goroutine 59:
k8s.io/client-go/rest/fake.(*RESTClient).do()
/Users/erath/go/pkg/mod/k8s.io/client-go@v0.18.8/rest/fake/fake.go:113 +0x69
k8s.io/client-go/rest/fake.(*RESTClient).do-fm()
/Users/erath/go/pkg/mod/k8s.io/client-go@v0.18.8/rest/fake/fake.go:109 +0x64
k8s.io/client-go/rest/fake.roundTripperFunc.RoundTrip()
/Users/erath/go/pkg/mod/k8s.io/client-go@v0.18.8/rest/fake/fake.go:43 +0x3d
net/http.send()
/usr/local/go/src/net/http/client.go:251 +0x6da
net/http.(*Client).send()
/usr/local/go/src/net/http/client.go:175 +0x1d5
net/http.(*Client).do()
/usr/local/go/src/net/http/client.go:717 +0x2cb
net/http.(*Client).Do()
/usr/local/go/src/net/http/client.go:585 +0x68b
k8s.io/client-go/rest.(*Request).request()
/Users/erath/go/pkg/mod/k8s.io/client-go@v0.18.8/rest/request.go:855 +0x209
k8s.io/client-go/rest.(*Request).Do()
/Users/erath/go/pkg/mod/k8s.io/client-go@v0.18.8/rest/request.go:928 +0xf0
sigs.k8s.io/external-dns/source.(*crdSource).List()
/Users/erath/go/src/github.com/ericrrath/external-dns/source/crd.go:250 +0x28c
sigs.k8s.io/external-dns/source.NewCRDSource.func1()
/Users/erath/go/src/github.com/ericrrath/external-dns/source/crd.go:125 +0x10a
k8s.io/client-go/tools/cache.(*ListWatch).List()
/Users/erath/go/pkg/mod/k8s.io/client-go@v0.18.8/tools/cache/listwatch.go:106 +0x94
k8s.io/client-go/tools/cache.(*Reflector).ListAndWatch.func1.1.2()
/Users/erath/go/pkg/mod/k8s.io/client-go@v0.18.8/tools/cache/reflector.go:233 +0xf4
k8s.io/client-go/tools/pager.SimplePageFunc.func1()
/Users/erath/go/pkg/mod/k8s.io/client-go@v0.18.8/tools/pager/pager.go:40 +0x94
k8s.io/client-go/tools/pager.(*ListPager).List()
/Users/erath/go/pkg/mod/k8s.io/client-go@v0.18.8/tools/pager/pager.go:91 +0x1f4
k8s.io/client-go/tools/cache.(*Reflector).ListAndWatch.func1.1()
/Users/erath/go/pkg/mod/k8s.io/client-go@v0.18.8/tools/cache/reflector.go:258 +0x2b7
Previous write at 0x00c0005aa130 by goroutine 37:
k8s.io/client-go/rest/fake.(*RESTClient).do()
/Users/erath/go/pkg/mod/k8s.io/client-go@v0.18.8/rest/fake/fake.go:113 +0x69
k8s.io/client-go/rest/fake.(*RESTClient).do-fm()
/Users/erath/go/pkg/mod/k8s.io/client-go@v0.18.8/rest/fake/fake.go:109 +0x64
k8s.io/client-go/rest/fake.roundTripperFunc.RoundTrip()
/Users/erath/go/pkg/mod/k8s.io/client-go@v0.18.8/rest/fake/fake.go:43 +0x3d
net/http.send()
/usr/local/go/src/net/http/client.go:251 +0x6da
net/http.(*Client).send()
/usr/local/go/src/net/http/client.go:175 +0x1d5
net/http.(*Client).do()
/usr/local/go/src/net/http/client.go:717 +0x2cb
net/http.(*Client).Do()
/usr/local/go/src/net/http/client.go:585 +0x68b
k8s.io/client-go/rest.(*Request).request()
/Users/erath/go/pkg/mod/k8s.io/client-go@v0.18.8/rest/request.go:855 +0x209
k8s.io/client-go/rest.(*Request).Do()
/Users/erath/go/pkg/mod/k8s.io/client-go@v0.18.8/rest/request.go:928 +0xf0
sigs.k8s.io/external-dns/source.(*crdSource).List()
/Users/erath/go/src/github.com/ericrrath/external-dns/source/crd.go:250 +0x28c
sigs.k8s.io/external-dns/source.(*crdSource).Endpoints()
/Users/erath/go/src/github.com/ericrrath/external-dns/source/crd.go:171 +0x13c4
sigs.k8s.io/external-dns/source.testCRDSourceEndpoints.func1()
/Users/erath/go/src/github.com/ericrrath/external-dns/source/crd_test.go:388 +0x4f6
testing.tRunner()
/usr/local/go/src/testing/testing.go:1193 +0x202
Goroutine 59 (running) created at:
k8s.io/client-go/tools/cache.(*Reflector).ListAndWatch.func1()
/Users/erath/go/pkg/mod/k8s.io/client-go@v0.18.8/tools/cache/reflector.go:224 +0x36f
k8s.io/client-go/tools/cache.(*Reflector).ListAndWatch()
/Users/erath/go/pkg/mod/k8s.io/client-go@v0.18.8/tools/cache/reflector.go:316 +0x1ab
k8s.io/client-go/tools/cache.(*Reflector).Run.func1()
/Users/erath/go/pkg/mod/k8s.io/client-go@v0.18.8/tools/cache/reflector.go:177 +0x4a
k8s.io/apimachinery/pkg/util/wait.BackoffUntil.func1()
/Users/erath/go/pkg/mod/k8s.io/apimachinery@v0.18.8/pkg/util/wait/wait.go:155 +0x75
k8s.io/apimachinery/pkg/util/wait.BackoffUntil()
/Users/erath/go/pkg/mod/k8s.io/apimachinery@v0.18.8/pkg/util/wait/wait.go:156 +0xba
k8s.io/client-go/tools/cache.(*Reflector).Run()
/Users/erath/go/pkg/mod/k8s.io/client-go@v0.18.8/tools/cache/reflector.go:176 +0xee
k8s.io/client-go/tools/cache.(*Reflector).Run-fm()
/Users/erath/go/pkg/mod/k8s.io/client-go@v0.18.8/tools/cache/reflector.go:174 +0x54
k8s.io/apimachinery/pkg/util/wait.(*Group).StartWithChannel.func1()
/Users/erath/go/pkg/mod/k8s.io/apimachinery@v0.18.8/pkg/util/wait/wait.go:56 +0x45
k8s.io/apimachinery/pkg/util/wait.(*Group).Start.func1()
/Users/erath/go/pkg/mod/k8s.io/apimachinery@v0.18.8/pkg/util/wait/wait.go:73 +0x6d
Goroutine 37 (running) created at:
testing.(*T).Run()
/usr/local/go/src/testing/testing.go:1238 +0x5d7
sigs.k8s.io/external-dns/source.testCRDSourceEndpoints()
/Users/erath/go/src/github.com/ericrrath/external-dns/source/crd_test.go:376 +0x1fcf
testing.tRunner()
/usr/local/go/src/testing/testing.go:1193 +0x202
It looks like client-go's fake.RESTClient (used by crd_test.go) is known to
cause race conditions when used with informers:
<https://github.com/kubernetes/kubernetes/issues/95372>. None of the CRD tests
_depend_ on the informer yet, so disabling the informer at least allows the
existing tests to pass without race conditions. I'll look into further changes
that 1) test the new event-handler behavior, and 2) allow all tests to pass
without race conditions.
This feature adds a router field to the OCP Route Source so that a user can add an ingress controller name in flag --ocp-router-name which will be used to pick up the respective routerCanonicalHostname from Route's Status Ingress Object.
Signed-off-by: Miheer Salunke <miheer.salunke@gmail.com>
Currently the `--label-filter` flag can only be used to filter CRDs
which match the label selector passed through that flag. This change
extends the functionality to the Ingress, Service and Openshift Route
type objects. When the flag is not specified the default value is
`labels.Everything()` which is an empty string, the same as before.
Annotation based filter is inefficient because the filtering has to be
done in the controller instead of the API server like with label
filtering.