Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/contributing/sources-and-providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ When creating a new source, add the following annotations above the source struc
// +externaldns:source:filters=
// +externaldns:source:namespace=all,single
// +externaldns:source:fqdn-template=false
// +externaldns:source:events=false|true
Copy link
Copy Markdown
Contributor

@vflaux vflaux Jan 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you also add this in the Annotation Reference section?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added. Will think of how to make sure docs and code is in sync for this section

type myNewSource struct {
// ... fields
}
Expand All @@ -64,6 +65,7 @@ type myNewSource struct {
* `+externaldns:source:filters` - Supported filter types (annotation, label)
* `+externaldns:source:namespace` - Namespace support: comma-separated values (all, single, multiple)
* `+externaldns:source:fqdn-template` - FQDN template support (true, false)
* `+externaldns:source:events` - Kubernetes [`events`](https://kubernetes.io/docs/reference/kubectl/generated/kubectl_events/) support (true, false)

After adding annotations, run `make generate-sources-documentation` to update sources file.

Expand Down
52 changes: 26 additions & 26 deletions docs/sources/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,32 +22,32 @@ Sources are responsible for:

## Available Sources

| **Source Name** | Resources | Filters | Namespace | FQDN Template | Category |
|:----------------|:----------|:--------|:----------|:--------------|:---------|
| **ambassador-host** | Host.getambassador.io | annotation,label | all,single | false | ingress controllers |
| **connector** | Remote TCP Server | | | false | special |
| **contour-httpproxy** | HTTPProxy.projectcontour.io | annotation | all,single | true | ingress controllers |
| **crd** | DNSEndpoint.k8s.io | annotation,label | all,single | false | externaldns |
| **empty** | None | | | false | testing |
| **f5-transportserver** | TransportServer.cis.f5.com | annotation | all,single | false | load balancers |
| **f5-virtualserver** | VirtualServer.cis.f5.com | annotation | all,single | false | load balancers |
| **fake** | Fake Endpoints | | | true | testing |
| **gateway-grpcroute** | GRPCRoute.gateway.networking.k8s.io | annotation,label | all,single | false | gateway api |
| **gateway-httproute** | HTTPRoute.gateway.networking.k8s.io | annotation,label | all,single | false | gateway api |
| **gateway-tcproute** | TCPRoute.gateway.networking.k8s.io | annotation,label | all,single | false | gateway api |
| **gateway-tlsroute** | TLSRoute.gateway.networking.k8s.io | annotation,label | all,single | false | gateway api |
| **gateway-udproute** | UDPRoute.gateway.networking.k8s.io | annotation,label | all,single | true | gateway api |
| **gloo-proxy** | Proxy.gloo.solo.io | | all,single | false | service mesh |
| **ingress** | Ingress | annotation,label | all,single | true | kubernetes core |
| **istio-gateway** | Gateway.networking.istio.io | annotation | all,single | true | service mesh |
| **istio-virtualservice** | VirtualService.networking.istio.io | annotation | all,single | true | service mesh |
| **kong-tcpingress** | TCPIngress.configuration.konghq.com | annotation | all,single | false | ingress controllers |
| **node** | Node | annotation,label | all | true | kubernetes core |
| **openshift-route** | Route.route.openshift.io | annotation,label | all,single | true | openshift |
| **pod** | Pod | annotation,label | all,single | true | kubernetes core |
| **service** | Service | annotation,label | all,single | true | kubernetes core |
| **skipper-routegroup** | RouteGroup.zalando.org | annotation | all,single | true | ingress controllers |
| **traefik-proxy** | IngressRoute.traefik.io<br/>IngressRouteTCP.traefik.io<br/>IngressRouteUDP.traefik.io | annotation | all,single | false | ingress controllers |
| **Source Name** | Resources | Filters | Namespace | FQDN Template | Events | Category |
|:----------------|:----------|:--------|:----------|:--------------|:---------|:---------|
| **ambassador-host** | Host.getambassador.io | annotation,label | all,single | false | false | ingress controllers |
| **connector** | Remote TCP Server | | | false | false | special |
| **contour-httpproxy** | HTTPProxy.projectcontour.io | annotation | all,single | true | false | ingress controllers |
| **crd** | DNSEndpoint.externaldns.k8s.io | annotation,label | all,single | false | false | externaldns |
| **empty** | None | | | false | false | testing |
| **f5-transportserver** | TransportServer.cis.f5.com | annotation | all,single | false | false | load balancers |
| **f5-virtualserver** | VirtualServer.cis.f5.com | annotation | all,single | false | false | load balancers |
| **fake** | Fake Endpoints | | | true | true | testing |
| **gateway-grpcroute** | GRPCRoute.gateway.networking.k8s.io | annotation,label | all,single | false | false | gateway api |
| **gateway-httproute** | HTTPRoute.gateway.networking.k8s.io | annotation,label | all,single | false | false | gateway api |
| **gateway-tcproute** | TCPRoute.gateway.networking.k8s.io | annotation,label | all,single | false | false | gateway api |
| **gateway-tlsroute** | TLSRoute.gateway.networking.k8s.io | annotation,label | all,single | false | false | gateway api |
| **gateway-udproute** | UDPRoute.gateway.networking.k8s.io | annotation,label | all,single | true | false | gateway api |
| **gloo-proxy** | Proxy.gloo.solo.io | | all,single | false | false | service mesh |
| **ingress** | Ingress | annotation,label | all,single | true | false | kubernetes core |
| **istio-gateway** | Gateway.networking.istio.io | annotation | all,single | true | false | service mesh |
| **istio-virtualservice** | VirtualService.networking.istio.io | annotation | all,single | true | false | service mesh |
| **kong-tcpingress** | TCPIngress.configuration.konghq.com | annotation | all,single | false | false | ingress controllers |
| **node** | Node | annotation,label | all | true | false | kubernetes core |
| **openshift-route** | Route.route.openshift.io | annotation,label | all,single | true | false | openshift |
| **pod** | Pod | annotation,label | all,single | true | false | kubernetes core |
| **service** | Service | annotation,label | all,single | true | false | kubernetes core |
| **skipper-routegroup** | RouteGroup.zalando.org | annotation | all,single | true | false | ingress controllers |
| **traefik-proxy** | IngressRoute.traefik.io<br/>IngressRouteTCP.traefik.io<br/>IngressRouteUDP.traefik.io | annotation | all,single | false | false | ingress controllers |

## Usage

Expand Down
11 changes: 8 additions & 3 deletions internal/gen/docs/sources/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ const (
annotationFilters = annotationPrefix + "filters="
annotationNamespace = annotationPrefix + "namespace="
annotationFQDNTemplate = annotationPrefix + "fqdn-template="
annotationEvents = annotationPrefix + "events="
)

var (
Expand All @@ -62,6 +63,7 @@ type Source struct {
Filters string // Supported filters, e.g., "annotation,label"
Namespace string // Namespace support: "all", "single", "multiple"
FQDNTemplate string // FQDN template support: "true", "false"
Events string // Events support: "true", "false"
}

type Sources []Source
Expand Down Expand Up @@ -254,9 +256,10 @@ func extractSourcesFromComments(comments, typeName, filePath string) (Sources, e

// Start new source
currentSource = &Source{
Type: typeName,
File: filePath,
Name: strings.TrimPrefix(line, annotationName),
Type: typeName,
File: filePath,
Name: strings.TrimPrefix(line, annotationName),
Events: "false",
}
case currentSource == nil:
return nil, fmt.Errorf("found annotation line without preceding source name in type %s: %s", typeName, line)
Expand All @@ -272,6 +275,8 @@ func extractSourcesFromComments(comments, typeName, filePath string) (Sources, e
currentSource.Namespace = strings.TrimPrefix(line, annotationNamespace)
case strings.HasPrefix(line, annotationFQDNTemplate):
currentSource.FQDNTemplate = strings.TrimPrefix(line, annotationFQDNTemplate)
case strings.HasPrefix(line, annotationEvents):
currentSource.Events = strings.TrimPrefix(line, annotationEvents)
}
}

Expand Down
4 changes: 4 additions & 0 deletions internal/gen/docs/sources/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ type testSource struct {
assert.Equal(t, "annotation,label", source.Filters)
assert.Equal(t, "all,single", source.Namespace)
assert.Equal(t, "true", source.FQDNTemplate)
assert.Equal(t, "false", source.Events)
}

func TestParseSourceAnnotations_SkipsTestFiles(t *testing.T) {
Expand Down Expand Up @@ -168,6 +169,7 @@ type firstSource struct {}
// +externaldns:source:name=second
// +externaldns:source:category=Testing
// +externaldns:source:description=Second source
// +externaldns:source:events=true
type secondSource struct {}
`
err := os.WriteFile(testFile, []byte(content), 0644)
Expand All @@ -177,7 +179,9 @@ type secondSource struct {}
require.NoError(t, err)
assert.Len(t, sources, 2)
assert.Equal(t, "first", sources[0].Name)
assert.Equal(t, "false", sources[0].Events)
assert.Equal(t, "second", sources[1].Name)
assert.Equal(t, "true", sources[1].Events)
}

func TestParseFile_IgnoresNonSourceTypes(t *testing.T) {
Expand Down
6 changes: 3 additions & 3 deletions internal/gen/docs/sources/templates/sources.gotpl
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ Sources are responsible for:

## Available Sources

| **Source Name** | Resources | Filters | Namespace | FQDN Template | Category |
|:----------------|:----------|:--------|:----------|:--------------|:---------|
| **Source Name** | Resources | Filters | Namespace | FQDN Template | Events | Category |
|:----------------|:----------|:--------|:----------|:--------------|:---------|:---------|
{{- range . }}
| **{{ .Name }}** | {{ replace .Resources "," "<br/>" }} | {{ .Filters }} | {{ .Namespace }} | {{ .FQDNTemplate }} | {{ lower .Category }} |
| **{{ .Name }}** | {{ replace .Resources "," "<br/>" }} | {{ .Filters }} | {{ .Namespace }} | {{ .FQDNTemplate }} | {{ .Events }} | {{ lower .Category }} |
{{- end }}

## Usage
Expand Down
1 change: 1 addition & 0 deletions source/ambassador_host.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ var (
// +externaldns:source:filters=annotation,label
// +externaldns:source:namespace=all,single
// +externaldns:source:fqdn-template=false
// +externaldns:source:events=false
type ambassadorHostSource struct {
dynamicKubeClient dynamic.Interface
kubeClient kubernetes.Interface
Expand Down
3 changes: 2 additions & 1 deletion source/crd.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,11 @@ import (
// +externaldns:source:name=crd
// +externaldns:source:category=ExternalDNS
// +externaldns:source:description=Creates DNS entries from DNSEndpoint CRD resources
// +externaldns:source:resources=DNSEndpoint.k8s.io
// +externaldns:source:resources=DNSEndpoint.externaldns.k8s.io
// +externaldns:source:filters=annotation,label
// +externaldns:source:namespace=all,single
// +externaldns:source:fqdn-template=false
// +externaldns:source:events=false
type crdSource struct {
crdClient rest.Interface
namespace string
Expand Down
1 change: 1 addition & 0 deletions source/fake.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import (
// +externaldns:source:filters=
// +externaldns:source:namespace=
// +externaldns:source:fqdn-template=true
// +externaldns:source:events=true
type fakeSource struct {
dnsName string
}
Expand Down
Loading