Skip to content

Commit

Permalink
Provider PowerDNS implementation (#390)
Browse files Browse the repository at this point in the history
* Provider powerdns implementation

* Fix formatting

* Add documentation and example for PowerDNS provider
  • Loading branch information
simcod authored Oct 8, 2024
1 parent d0bdfdd commit 735cd31
Show file tree
Hide file tree
Showing 11 changed files with 397 additions and 0 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ It contains provisioning controllers for creating DNS records in one of the DNS
- [_Netlify DNS_](docs/netlify/README.md),
- [_remote_](docs/remote/README.md),
- [_DNS servers supporting RFC 2136 (DNS Update)_](docs/rfc2136/README.md) *(alpha - not recommended for productive usage)*,
- [_powerdns_](docs/powerdns/README.md),

and source controllers for services and ingresses to create DNS entries by annotations.

Expand Down Expand Up @@ -528,6 +529,7 @@ The following provider types can be selected (comma separated):
- `infoblox-dns`: Infoblox DNS provider
- `netlify-dns`: Netlify DNS provider
- `remote`: Remote DNS provider (a dns-controller-manager with enabled remote access service)
- `powerdns`: PowerDNS provider
If the compound DNS Provisioning Controller is enabled it is important to specify a
unique controller identity using the `--identifier` option.
Expand Down
1 change: 1 addition & 0 deletions cmd/compound/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import (
_ "github.com/gardener/external-dns-management/pkg/controller/provider/infoblox"
_ "github.com/gardener/external-dns-management/pkg/controller/provider/netlify"
_ "github.com/gardener/external-dns-management/pkg/controller/provider/openstack"
_ "github.com/gardener/external-dns-management/pkg/controller/provider/powerdns"
_ "github.com/gardener/external-dns-management/pkg/controller/provider/remote"
_ "github.com/gardener/external-dns-management/pkg/controller/provider/rfc2136"
_ "github.com/gardener/external-dns-management/pkg/controller/replication/dnsprovider"
Expand Down
26 changes: 26 additions & 0 deletions docs/powerdns/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# PowerDNS Provider

This DNS provider allows you to create and manage DNS entries with [PowerDNS](https://www.powerdns.com/).

## Required permissions

There are no special permissions for the `apiToken`.

## Credentials

You need to have an `apiToken` and the url of your PowerDNS `server` in place.

Create a `Secret` resource. All credentials need to be base64 encoded.

```yaml
apiVersion: v1
kind: Secret
metadata:
name: powerdns-credentials
namespace: default
type: Opaque
data:
# replace '...' with values encoded as base64
apiToken: ... # your PowerDNS token
server: ... # your PowerDNS server url
```
10 changes: 10 additions & 0 deletions examples/20-secret-powerdns-credentials.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
apiVersion: v1
kind: Secret
metadata:
name: powerdns-credentials
namespace: default
type: Opaque
data:
# replace '...' with values encoded as base64
apiToken: ... # your PowerDNS token
server: ... # your PowerDNS server url
12 changes: 12 additions & 0 deletions examples/30-provider-powerdns.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
apiVersion: dns.gardener.cloud/v1alpha1
kind: DNSProvider
metadata:
name: powerdns
namespace: default
spec:
type: powerdns
secretRef:
name: powerdns-credentials
domains:
include:
- my.own.domain.com
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ require (
github.com/gophercloud/gophercloud v0.24.0
github.com/gophercloud/utils v0.0.0-20220307143606-8e7800759d16
github.com/infobloxopen/infoblox-go-client/v2 v2.1.0
github.com/joeig/go-powerdns/v3 v3.10.0
github.com/miekg/dns v1.1.58
github.com/netlify/open-api v1.1.0
github.com/onsi/ginkgo/v2 v2.19.0
Expand Down
5 changes: 5 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -334,12 +334,16 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/ironcore-dev/vgopath v0.1.4 h1:hBMuv7+wnZp5JHkVfdg4mtP8hsIGvuv42+l+F2wmQxk=
github.com/ironcore-dev/vgopath v0.1.4/go.mod h1:PTGnX8xW/QDytFR7oU4kcXr1RPDLCgAJ0ZUa5Rp8vyI=
github.com/jarcoal/httpmock v1.3.1 h1:iUx3whfZWVf3jT01hQTO/Eo5sAYtB2/rqaUuOtpInww=
github.com/jarcoal/httpmock v1.3.1/go.mod h1:3yb8rc4BI7TCBhFY8ng0gjuLKJNquuDNiPaZjnENuYg=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/joeig/go-powerdns/v3 v3.10.0 h1:pUhC/8kdDJW4Y7/J/QawPXWlp0WcNrynABk0yX0WmRk=
github.com/joeig/go-powerdns/v3 v3.10.0/go.mod h1:SA9nmMT7kJr4vgSFTlYLMbomSwPxydacVWTPqSUoPFA=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
Expand Down Expand Up @@ -399,6 +403,7 @@ github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg=
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k=
github.com/maxatome/go-testdeep v1.12.0/go.mod h1:lPZc/HAcJMP92l7yI6TRz1aZN5URwUBUAfUNvrclaNM=
github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4=
github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
Expand Down
16 changes: 16 additions & 0 deletions pkg/controller/provider/powerdns/controller/controller.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Gardener contributors
//
// SPDX-License-Identifier: Apache-2.0

package controller

import (
"github.com/gardener/external-dns-management/pkg/controller/provider/powerdns"
"github.com/gardener/external-dns-management/pkg/dns/provider"
)

func init() {
provider.DNSController("", powerdns.Factory).
FinalizerDomain("dns.gardener.cloud").
MustRegister(provider.CONTROLLER_GROUP_DNS_CONTROLLERS)
}
100 changes: 100 additions & 0 deletions pkg/controller/provider/powerdns/execution.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors
//
// SPDX-License-Identifier: Apache-2.0

package powerdns

import (
"fmt"

"github.com/gardener/controller-manager-library/pkg/logger"
"github.com/joeig/go-powerdns/v3"

"github.com/gardener/external-dns-management/pkg/dns"
"github.com/gardener/external-dns-management/pkg/dns/provider"
)

type RecordSet struct {
Name string
RecordType powerdns.RRType
TTL uint32
Content []string
}

type Execution struct {
logger.LogContext
handler *Handler
zone provider.DNSHostedZone
}

func NewExecution(logger logger.LogContext, h *Handler, zone provider.DNSHostedZone) *Execution {
return &Execution{LogContext: logger, handler: h, zone: zone}
}

func (exec *Execution) buildRecordSet(req *provider.ChangeRequest) (*RecordSet, error) {
var dnsset *dns.DNSSet

switch req.Action {
case provider.R_CREATE, provider.R_UPDATE:
dnsset = req.Addition
case provider.R_DELETE:
dnsset = req.Deletion
}

name, rset := dns.MapToProvider(req.Type, dnsset, exec.zone.Domain())

if name.SetIdentifier != "" || dnsset.RoutingPolicy != nil {
return nil, fmt.Errorf("routing policies not supported for " + TYPE_CODE)
}

if name.DNSName == "" || len(rset.Records) == 0 {
return nil, nil
}

exec.Infof("Desired %s: %s record set %s[%s] with TTL %d: %s", req.Action, rset.Type, name.DNSName, exec.zone.Id(), rset.TTL, rset.RecordString())

recordSet := RecordSet{
Name: name.DNSName,
RecordType: powerdns.RRType(rset.Type),
}

switch req.Action {
case provider.R_CREATE, provider.R_UPDATE:
var content []string
for _, record := range rset.Records {
content = append(content, record.Value)
}

recordSet.Content = content
recordSet.TTL = uint32(rset.TTL)
}

return &recordSet, nil
}

func (exec *Execution) apply(action string, rset *RecordSet, metrics provider.Metrics) error {
var err error
switch action {
case provider.R_CREATE, provider.R_UPDATE:
err = exec.update(rset, metrics)
case provider.R_DELETE:
err = exec.delete(rset, metrics)
}
return err
}

func (exec *Execution) update(rset *RecordSet, metrics provider.Metrics) error {
exec.handler.config.RateLimiter.Accept()
zoneID := exec.zone.Id().ID
err := exec.handler.powerdns.Records.Change(exec.handler.ctx, zoneID, rset.Name, rset.RecordType, rset.TTL, rset.Content)
metrics.AddZoneRequests(zoneID, provider.M_UPDATERECORDS, 1)
return err
}

func (exec *Execution) delete(rset *RecordSet, metrics provider.Metrics) error {
exec.handler.config.RateLimiter.Accept()
zoneID := exec.zone.Id().ID
err := exec.handler.powerdns.Records.Delete(exec.handler.ctx, zoneID, rset.Name, rset.RecordType)
metrics.AddZoneRequests(zoneID, provider.M_DELETERECORDS, 1)
return err
}
25 changes: 25 additions & 0 deletions pkg/controller/provider/powerdns/factory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Gardener contributors
//
// SPDX-License-Identifier: Apache-2.0

package powerdns

import (
"github.com/gardener/external-dns-management/pkg/controller/provider/compound"
"github.com/gardener/external-dns-management/pkg/dns/provider"
)

const TYPE_CODE = "powerdns"

var rateLimiterDefaults = provider.RateLimiterOptions{
Enabled: true,
QPS: 50,
Burst: 10,
}

var Factory = provider.NewDNSHandlerFactory(TYPE_CODE, NewHandler).
SetGenericFactoryOptionDefaults(provider.GenericFactoryOptionDefaults.SetRateLimiterOptions(rateLimiterDefaults))

func init() {
compound.MustRegister(Factory)
}
Loading

0 comments on commit 735cd31

Please sign in to comment.