-
Notifications
You must be signed in to change notification settings - Fork 2.7k
fix(pihole): crash when multiple targets are present with pihole API V6 #5423
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
fix(pihole): crash when multiple targets are present with pihole API V6 #5423
Conversation
The committers listed above are authorized under a signed CLA. |
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here.
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
Welcome @codeeno! |
Hi @codeeno. Thanks for your PR. I'm waiting for a kubernetes-sigs member to verify that this patch is reasonable to test. If it is, they should reply with Once the patch is verified, the new status will be reflected by the I understand the commands that are listed here. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. |
/ok-to-test |
@tJouve Do you think you can review this PR ? Wdyt of this approach ? |
Hi,
I think pi-hole does allow multiple records per domains. At least I am able to do configure that by hand in the web interface. |
This config multiple/single target should be discoverable |
Hello, @codeeno Your fix look good and fix a bug. I will just suggest to change the code to look like ( add Info message and use if len(ep.Targets) > 1 {
log.Infof("Skipping : more than one target, only the first one is keep : %s %s %s -> %s", action, ep.DNSName, ep.RecordType, ep.targets)
}
//
target := ep.Targets[0]
if p.cfg.DryRun {
log.Infof("DRY RUN: %s %s IN %s -> %s", action, ep.DNSName, ep.RecordType, target)
return nil
}
log.Infof("%s %s IN %s -> %s", action, ep.DNSName, ep.RecordType, target)
// Get the current record
if strings.Contains(ep.DNSName, "*") {
return provider.NewSoftError(errors.New("UNSUPPORTED: Pihole DNS names cannot return wildcard"))
}
switch ep.RecordType {
case endpoint.RecordTypeA, endpoint.RecordTypeAAAA:
apiUrl = p.generateApiUrl(apiUrl, fmt.Sprintf("%s %s", target, ep.DNSName))
case endpoint.RecordTypeCNAME:
if ep.RecordTTL.IsConfigured() {
apiUrl = p.generateApiUrl(apiUrl, fmt.Sprintf("%s,%s,%d", ep.DNSName, target, ep.RecordTTL))
} else {
apiUrl = p.generateApiUrl(apiUrl, fmt.Sprintf("%s,%s", ep.DNSName, target))
}
} But in fact it is possible to specify multiples IP for the same A/AAA record . This config is legit The definition with the api in one call is not possible, but it will work with 2 different calls {
"config": {
"dns": {
"hosts": [
"192.168.253.253 duplicate.example.net",
"192.168.253.254 duplicate.example.net"
]
}
},
"took": 0.000047206878662109375
} Deletion also work (one by one): Maybe we can support this feature by doing something like that : if len(ep.Targets) == 0 {
log.Infof("Skipping : missing targets %s %s %s", action, ep.DNSName, ep.RecordType)
return nil
}
// Get the current record
if strings.Contains(ep.DNSName, "*") {
return provider.NewSoftError(errors.New("UNSUPPORTED: Pihole DNS names cannot return wildcard"))
}
for _, target := range ep.Targets {
if p.cfg.DryRun {
log.Infof("DRY RUN: %s %s IN %s -> %s", action, ep.DNSName, ep.RecordType, target)
return nil
}
log.Infof("%s %s IN %s -> %s", action, ep.DNSName, ep.RecordType, target)
switch ep.RecordType {
case endpoint.RecordTypeA, endpoint.RecordTypeAAAA:
apiUrl = p.generateApiUrl(apiUrl, fmt.Sprintf("%s %s", target, ep.DNSName))
case endpoint.RecordTypeCNAME:
if ep.RecordTTL.IsConfigured() {
apiUrl = p.generateApiUrl(apiUrl, fmt.Sprintf("%s,%s,%d", ep.DNSName, target, ep.RecordTTL))
} else {
apiUrl = p.generateApiUrl(apiUrl, fmt.Sprintf("%s,%s", ep.DNSName, target))
}
}
req, err := http.NewRequestWithContext(ctx, action, apiUrl, nil)
if err != nil {
return err
}
_, err = p.do(req)
if err != nil {
return err
}
} What do you think about this implementation ? |
I'm running into this too, and I'd prefer to see the implementation that creates A records for each IP address, rather than only create a single record for the first IP address in the list. |
Hi @codeeno. Do you think you could address review suggestions? |
Description
Hello,
While trying to set up external-dns (v0.17.0) with Pi-hole (v6.0.6) in my homelab I've come across the following error, placing my pod into
CrashLoopBackOff
state:This was with:
The error happens because all targets are being passed to the generateApiUrl function, even though Pi-hole only supports one target per record and one record per domain. In my case, the targets
[10.0.1.10 10.0.1.11]
resulted in the API url ending inconfig/dns/hosts/10.0.1.10%3B10.0.1.11%20pihole.home
which the V6 API does not accept.In the previous implementation, we seemingly have only passed the first of multiple targets. This PR restores that implementation for V6.
Checklist