ApiDnsBackendProvider
final class ApiDnsBackendProvider implements DnsBackendProviderInterface, ReportsWriteRejection (View source)
PowerDNS REST API-based DNS backend provider.
Performs all DNS operations through the PowerDNS REST API. Zone metadata is stored locally in the Poweradmin zones table. Records are identified by encoded composite keys (no PowerDNS DB access needed).
Constants
| private EXACT_SEARCH_LIMIT |
Exact record lookups ask for this many matches, the limit zone search uses too |
Methods
No description
The client carries per-request read caches, so anything needing raw API access shares this one rather than building a second.
Create a new zone in the DNS backend.
Delete a zone and all its associated DNS data (records, metadata, cryptokeys).
Change zone type (NATIVE, MASTER, SLAVE, PRODUCER, CONSUMER).
Update slave zone's master IP address.
Request an immediate AXFR transfer of a secondary (slave) zone from its master.
Queue a NOTIFY to the secondaries of a primary zone.
Update zone account field.
Zones carrying the given catalog.
Zones of one kind, with the catalog each currently belongs to.
Catalog the zone belongs to, lowercase and without a trailing dot, or '' when it is not a member.
Join $catalogName, or leave the current catalog when it is ''.
Rewrites the zone's SOA content from its current value as one step, so concurrent writers to the zone cannot both bump from the same serial. The SQL backend locks the SOA row for it; the API backend reads and rewrites the RRset.
Replace the content of a zone's SOA record. The SQL backend keeps the stored TTL; the API backend rewrites the whole RRset with the configured dns.ttl.
Add a DNS record.
Add a DNS record and return its ID.
Create a DNS record atomically with optional disabled flag.
Edit an existing DNS record.
The reason the service gave for refusing the last record write, or null when the write succeeded or failed without a verdict from the service.
The HTTP status of the service answer behind lastWriteRejection(), or null without one.
Delete a DNS record by ID.
Check if a zone exists by name.
Get zone info by ID.
Get zone name by domain ID.
Get zone ID by name.
Get zone type by domain ID.
Get zone master by domain ID, for any zone kind.
Get a single record by ID.
Get zone ID from a record ID.
Get bulk zone stats (DNSSEC state, SOA serials) keyed by zone name.
Count non-ENT records in a zone.
Check if a record with given attributes exists.
Get records by zone ID, optionally filtered by type.
Get the records at one name in a zone, optionally filtered by type.
Find the records at one name across every zone, optionally filtered by type.
Find the records whose content equals the given value across every zone, optionally filtered by type. The API backend answers through the PowerDNS search endpoint, which stops at 10,000 matches; use findAllRecordsByContent() when a missed record would let a check pass.
findRecordsByContent(), or null when the backend could not see every match.
Get SOA record content for a zone.
Find the best matching reverse zone ID for a PTR record name.
Get all zones from the DNS backend.
Get id, name and type for the given zone ids, sorted by name.
Count all zones in the DNS backend.
Count all record rows in the DNS backend, ENTs included.
Report SOA-record presence and disabled state for a zone, used by zone-list UIs to render "Disabled" / "No SOA" badges. SLAVE zones legitimately have no SOA (records arrive via AXFR), so callers may pass the zone kind to skip unnecessary lookups; implementations must return is_missing_soa=false for SLAVE.
Get all records for a zone from the DNS backend.
Search for zones and records matching a query.
Add a supermaster (autoprimary).
Delete a supermaster (autoprimary).
Get all supermasters.
Update a supermaster.
Check if this is the API backend.
Whether backend writes can be wrapped in a transaction on the Poweradmin database.
Whether record ids are the integer records.id values.
Whether the backend writes and maintains the apex SOA of the zones it creates.
Whether zone ids are allocated from the local zones table rather than the PowerDNS domains table.
Whether the zone list can carry the serial PowerDNS serves for signed zones.
Whether zone lists can be ordered by record count across every page.
Whether zone lists can be ordered by owning group.
Whether a secondary zone can be pulled from its primary on request.
Whether a primary zone can be told to send NOTIFY on request.
Whether the local zone list is a mirror that can be refreshed from the server.
Check whether the zone has soa_edit_api configured in PowerDNS.
Set the zone's SOA serial policy metadata.
The form the API backend reads hostname content in, which is also what the duplicate check compares.
Details
__construct(PowerdnsApiClient $client, PDO $db, ConfigurationInterface $config, ApiStatusRecorderInterface $apiStatus, LoggerInterface|null $logger = null, TransactionInterface|null $transaction = null)
No description
PowerdnsApiClient
getApiClient()
The client carries per-request read caches, so anything needing raw API access shares this one rather than building a second.
int|false
createZone(string $domain, string $type, string $slaveMaster = '')
Create a new zone in the DNS backend.
bool
deleteZone(int $domainId, string $zoneName)
Delete a zone and all its associated DNS data (records, metadata, cryptokeys).
Does NOT delete Poweradmin-internal data (zones table, records_zone_templ, etc.)
- those are handled by the caller.
bool
updateZoneType(int $domainId, string $type)
Change zone type (NATIVE, MASTER, SLAVE, PRODUCER, CONSUMER).
Masters are cleared unless the new kind replicates from a primary.
bool
updateZoneMaster(int $domainId, string $masterIp)
Update slave zone's master IP address.
bool
retrieveZone(int $domainId)
Request an immediate AXFR transfer of a secondary (slave) zone from its master.
Needs a configured PowerDNS API. Without one the SQL backend returns false, since PowerDNS then pulls secondaries on its own refresh schedule.
bool
notifyZone(int $domainId)
Queue a NOTIFY to the secondaries of a primary zone.
Needs a configured PowerDNS API; without one the SQL backend returns false.
bool
updateZoneAccount(int $domainId, string $account)
Update zone account field.
array
getCatalogMembers(string $catalogName)
Zones carrying the given catalog.
PowerDNS only publishes a member whose kind is MASTER or PRODUCER and which has an enabled apex SOA, so the kind is returned for callers to flag the rest.
array
getZonesByKind(string $kind)
Zones of one kind, with the catalog each currently belongs to.
string
getZoneCatalog(int $domainId)
Catalog the zone belongs to, lowercase and without a trailing dot, or '' when it is not a member.
bool
updateZoneCatalog(int $domainId, string $catalogName)
Join $catalogName, or leave the current catalog when it is ''.
bool
rewriteSoaContent(int $zoneId, callable $change)
Rewrites the zone's SOA content from its current value as one step, so concurrent writers to the zone cannot both bump from the same serial. The SQL backend locks the SOA row for it; the API backend reads and rewrites the RRset.
bool
replaceSoaContent(int $zoneId, string $content)
Replace the content of a zone's SOA record. The SQL backend keeps the stored TTL; the API backend rewrites the whole RRset with the configured dns.ttl.
bool
addRecord(int $domainId, string $name, string $type, string $content, int $ttl, int $prio)
Add a DNS record.
int|string|null
addRecordGetId(int $domainId, string $name, string $type, string $content, int $ttl, int $prio, array|null $comment = null)
Add a DNS record and return its ID.
int|string|null
createRecordAtomic(int $domainId, string $name, string $type, string $content, int $ttl, int $prio, int $disabled = 0, array|null $comment = null)
Create a DNS record atomically with optional disabled flag.
In SQL mode, wraps the INSERT in a transaction with deadlock retry. In API mode, one RRset REPLACE carries the record and the disabled flag.
bool
editRecord(int|string $recordId, string $name, string $type, string $content, int $ttl, int $prio, int $disabled, array|null $comment = null)
Edit an existing DNS record.
string|null
lastWriteRejection()
The reason the service gave for refusing the last record write, or null when the write succeeded or failed without a verdict from the service.
int|null
lastWriteRejectionStatus()
The HTTP status of the service answer behind lastWriteRejection(), or null without one.
400 and 422 are validation verdicts; other 4xx answers are not.
bool
deleteRecord(int|string $recordId)
Delete a DNS record by ID.
bool
zoneExists(string $zoneName)
Check if a zone exists by name.
array|null
getZoneById(int $domainId)
Get zone info by ID.
string|null
getZoneNameById(int $domainId)
Get zone name by domain ID.
int|null
getZoneIdByName(string $zoneName)
Get zone ID by name.
string
getZoneTypeById(int $domainId)
Get zone type by domain ID.
string|null
getZoneMasterById(int $domainId)
Get zone master by domain ID, for any zone kind.
array|null
getRecordById(int|string $recordId)
Get a single record by ID.
int
getZoneIdFromRecordId(int|string $recordId)
Get zone ID from a record ID.
array
getZoneStats(bool $withDnssec = true)
Get bulk zone stats (DNSSEC state, SOA serials) keyed by zone name.
SQL backends may return an empty array when this data is not needed; API backends fetch it in a single call to avoid N+1 lookups in zone lists. Record counts are not included - the PowerDNS zone list carries none.
int
countZoneRecords(int $domainId)
Count non-ENT records in a zone.
bool
recordExists(int $domainId, string $name, string $type, string $content)
Check if a record with given attributes exists.
array
getRecordsByZoneId(int $domainId, string|null $type = null)
Get records by zone ID, optionally filtered by type.
array
getRecordsByName(int $domainId, string $name, string|null $type = null)
Get the records at one name in a zone, optionally filtered by type.
Names match case-insensitively, per RFC 4343.
array
findRecordsByName(string $name, string|null $type = null)
Find the records at one name across every zone, optionally filtered by type.
Names match case-insensitively. The API backend reads the RRsets of the most specific zone that holds the name.
array
findRecordsByContent(string $content, string|null $type = null)
Find the records whose content equals the given value across every zone, optionally filtered by type. The API backend answers through the PowerDNS search endpoint, which stops at 10,000 matches; use findAllRecordsByContent() when a missed record would let a check pass.
array|null
findAllRecordsByContent(string $content, string|null $type = null)
findRecordsByContent(), or null when the backend could not see every match.
string
getSOARecord(int $domainId)
Get SOA record content for a zone.
int
getBestMatchingReverseZoneId(string $reverseName)
Find the best matching reverse zone ID for a PTR record name.
array
getZones(bool $withDnssec = true)
Get all zones from the DNS backend.
Returns raw zone data without Poweradmin metadata (ownership, comments). Each zone array contains: name, type, dnssec (bool), master (string).
array
getZonesByIds(array $domainIds)
Get id, name and type for the given zone ids, sorted by name.
Unknown ids are skipped.
int
countZones()
Count all zones in the DNS backend.
int|null
countRecords()
Count all record rows in the DNS backend, ENTs included.
array|null
getZoneSoaHealth(string $zoneName, string $kind)
Report SOA-record presence and disabled state for a zone, used by zone-list UIs to render "Disabled" / "No SOA" badges. SLAVE zones legitimately have no SOA (records arrive via AXFR), so callers may pass the zone kind to skip unnecessary lookups; implementations must return is_missing_soa=false for SLAVE.
Returns null on transient backend failure so callers can preserve any previously-cached state instead of overwriting it with an inferred default.
array
getZoneRecords(int $domainId, string $zoneName)
Get all records for a zone from the DNS backend.
Returns a flat array of record data. In SQL mode, records include numeric IDs. In API mode, IDs are resolved from the database. ENT records (null/empty type) are excluded.
array
searchDnsData(string $query, string $objectType = 'all', int $max = 100)
Search for zones and records matching a query.
Returns separate arrays for zone matches and record matches. Results contain only DNS data - callers must enrich with Poweradmin metadata (ownership, permissions).
bool
addSupermaster(string $masterIp, string $nsName, string $account)
Add a supermaster (autoprimary).
bool
deleteSupermaster(string $masterIp, string $nsName)
Delete a supermaster (autoprimary).
array
getSupermasters()
Get all supermasters.
bool
updateSupermaster(string $oldMasterIp, string $oldNsName, string $newMasterIp, string $newNsName, string $account)
Update a supermaster.
bool
isApiBackend()
Check if this is the API backend.
Callers can use this to adjust behavior (e.g., skip manual SOA serial updates, show notices about search limitations).
bool
supportsLocalWriteTransaction()
Whether backend writes can be wrapped in a transaction on the Poweradmin database.
True for the SQL backend, where the PowerDNS tables share the connection. False for the API backend: it writes over HTTP and then reads the local zones table for the new ids, and an open transaction would hide those rows.
bool
recordIdsAreNumeric()
Whether record ids are the integer records.id values.
True for the SQL backend. False for the API backend, whose record ids are encoded composite keys (see RecordIdentifier) that do not fit an INT column.
bool
managesSoaRecord()
Whether the backend writes and maintains the apex SOA of the zones it creates.
True for the API backend, where PowerDNS seeds the SOA on zone creation and template SOA records are skipped. False for the SQL backend, which stores whatever SOA Poweradmin writes.
bool
allocatesZoneIdsLocally()
Whether zone ids are allocated from the local zones table rather than the PowerDNS domains table.
True for the API backend: createZone() inserts the zones row itself and a zone is identified by that row alone. False for the SQL backend, where the id is domains.id, the caller adds the zones row and a zone without a domains row is stale.
bool
providesSignedSerial()
Whether the zone list can carry the serial PowerDNS serves for signed zones.
True for the API backend, whose zone list reports the signed serial. False for the SQL backend, which only sees the stored SOA serial.
bool
supportsRecordCountSort()
Whether zone lists can be ordered by record count across every page.
True for the SQL backend, which counts in the query. False for the API backend, where counts are resolved per page and a sort would only order the rows already on screen.
bool
supportsGroupSort()
Whether zone lists can be ordered by owning group.
True for the SQL backend, which joins the Poweradmin ownership tables in the list query. False for the API backend, whose zone list comes from PowerDNS and cannot join them.
bool
supportsZoneRetrieve()
Whether a secondary zone can be pulled from its primary on request.
True for the API backend, and for the SQL backend when a PowerDNS API is configured. False otherwise, as there is no way to trigger a transfer.
bool
supportsZoneNotify()
Whether a primary zone can be told to send NOTIFY on request.
True for the API backend, and for the SQL backend when a PowerDNS API is configured. False otherwise, as there is no way to trigger a NOTIFY.
bool
syncsZoneListFromServer()
Whether the local zone list is a mirror that can be refreshed from the server.
True for the API backend, where the zones table is synced from PowerDNS. False for the SQL backend, where the domains table is the source itself.
bool
hasSoaEditApi(int $domainId)
Check whether the zone has soa_edit_api configured in PowerDNS.
Returns false for SQL backends (not applicable).
bool
setZoneSerialPolicy(int $domainId, string $zoneName, array $properties)
Set the zone's SOA serial policy metadata.
Keys are the zone-object property names from MetadataDefinitions::SERIAL_POLICY_PROPERTY_KINDS. An empty string clears the policy. API backend updates the zone object; SQL backend replaces the matching domainmetadata rows.
static string
stripTrailingDotFromContent(string $type, string $content)
The form the API backend reads hostname content in, which is also what the duplicate check compares.