如何使用powerdns的http-api ?
-
文档需知 powerdns文档
Swagger接入开发 powerdns的yaml配置文件 | swagger官网 -
Swagger 生成插件
Sign in 登录 (没有账号的免费注册一个)
Create New -> Create New API
创建完毕将powerdns的yaml配置文件粘贴到代码框中
右上角 -> Export -> Client SDK -> 指定的开发语言,像我就用PHP github创建一个新的 repository , 将导出来的文件上传上去 修改composer.json{ "repositories": [ { "type": "git", "url": "https://github.com/suguer/powerdns.git" } ], "require": { "suguer/powerdns": "*@dev" } }
-
开始使用 DnsPowerDnsClient.php
use Swagger\Client\Api\ZonesApi;
use Swagger\Client\ApiException;
use Swagger\Client\Model\RRSet;
use Swagger\Client\Model\Zone;
use Swagger\Client\Configuration;
class DnsPowerDnsClient {
private $server_id = "localhost";
/**
* @var \GuzzleHttp\Client
*/
private $client;
/**
* @var ZonesApi
*/
private $zoneApi;
private $currentNsList = ['ns1','ns2'];
public function __construct()
{
$config=[
"ip" => "",
"api_key" => "",
];
$this->client = new \GuzzleHttp\Client([
'timeout' => 40.0,
]);
$this->config = Configuration::getDefaultConfiguration()
->setHost("http://{$config['ip']}:8081/api/v1")
->setApiKey('X-API-Key', $config['api_key']);
$this->zoneApi = new ZonesApi($this->client, $this->config);
}
public function AddDomain($domain)
{
try {
$nameservers = [];
foreach ($this->currentNsList as $value) {
$nameservers[] = "{$value}.";
}
$zone = new Zone([
'name' => $domain['domain'] . ".",
'type' => 'Zone',
'kind' => 'Master',
'nameservers' => $nameservers,
]);
$this->zoneApi->createZoneWithHttpInfo($this->server_id, $zone, "false");
return true;
} catch (ApiException $e) {
$error = json_decode($e->getResponseBody(), 1);
if (isset($error['error']) && $error['error'] == "Conflict") return true;
return $error['error'];
}
}
public function DeleteDomain($domain)
{
try {
$this->zoneApi->deleteZone($this->server_id, $domain['domain']);
return true;
} catch (ApiException $e) {
$error = json_decode($e->getResponseBody(), 1);
if (isset($error['error']) && $error['error'] == "Conflict") return true;
return $error['error'];
}
}
public function AddDomainRecord($record, $domain = null)
{
try {
$domain = $record['domain'];
if (in_array($record['type'], ['REDIRECT_URL', 'FORWARD_URL'])) {
//还需要先判断是否有相同主机头的A记录,因为也会冲突
$exist_record = Record::where("host", $record['host'])
->where('platform', $record['platform'])
->where('domain', $record['domain'])
->whereIn('type', ["A", "CNAME", 'REDIRECT_URL', 'FORWARD_URL'])
->whereNotNull('record_id')
->where('id', '<>', $record['id'])
->first();
if ($exist_record) {
return "type-already-exists";
}
$functions = $record['type'] == "REDIRECT_URL" ? 1 : 2;
$UrlForwardBaseResp =
UrlForwardBase::createForwardAPI($this->FormatRRsetName($record) . "{$domain}",
$functions,
$record['value']);
if ($UrlForwardBaseResp !== 1) {
return $UrlForwardBaseResp;
}
}
$total_repeat_record = Record::where("host", $record['host'])
->where('platform', $record['platform'])
->where('domain', $record['domain'])
->where('type', $record['type'])
->whereNotNull('record_id')
->where('id', '<>', $record['id'])
->get();
$rrset = new RRSet([
"name" => $this->FormatRRsetName($record) . "{$domain}.",
"type" => $this->FormatRRsetType($record),
"ttl" => $record['ttl'],
"changetype" => "REPLACE",
]);
$rrset_record_list = [new \Swagger\Client\Model\Record([
"content" => $this->FormatRRsetContent($record),
"disabled" => $record['state'] == 2 ? true : false,
])];
if (count($total_repeat_record) > 0) {
foreach ($total_repeat_record as $repeat_record) {
$rrset_record_list[] =
new \Swagger\Client\Model\Record([
"content" => $this->FormatRRsetContent($repeat_record),
"disabled" => $repeat_record['state'] == 2 ? true : false,
]);
}
}
$rrset->setRecords($rrset_record_list);
$zone = new Zone([
'id' => $domain,
'name' => $domain,
'rrsets' => [$rrset]
]);
$this->zoneApi->patchZoneWithHttpInfo($this->server_id, $domain, $zone);
return true;
} catch (ApiException $e) {
$error = json_decode($e->getResponseBody(), 1);
return $error['error'];
}
}
public function DeleteDomainRecord($record, $param = [])
{
try {
$domain = $record['domain'];
if (in_array($record['type'], ['REDIRECT_URL', 'FORWARD_URL'])) {
$UrlForwardBaseResp =
UrlForwardBase::deleteForwardAPI($this->FormatRRsetName($record) . "{$domain}");
if ($UrlForwardBaseResp !== 1) {
return $UrlForwardBaseResp;
}
}
$total_repeat_record = Record::where("host", $record['host'])
->where('platform', $record['platform'])
->where('domain', $record['domain'])
->where('type', $record['type'])
->whereNotNull('record_id')
->where('id', '<>', $record['id'])
->get();
if (count($total_repeat_record) > 0) {
$rrset = null;
$rrset_record_list = [];
foreach ($total_repeat_record as $repeat_record) {
if (!$rrset) {
$rrset = new RRSet([
"name" => $this->FormatRRsetName($repeat_record) . "{$repeat_record['domain']}.",
"type" => $this->FormatRRsetType($repeat_record),
"ttl" => $repeat_record['ttl'],
"changetype" => "REPLACE",
]);
}
$rrset_record_list[] = new \Swagger\Client\Model\Record([
"content" => $this->FormatRRsetContent($repeat_record),
"disabled" => false,
]);
}
$rrset->setRecords($rrset_record_list);
} else {
$rrset = new RRSet([
"name" => $this->FormatRRsetName($record) . "{$domain}.",
"type" => $this->FormatRRsetType($record),
"ttl" => $record['ttl'],
"changetype" => "DELETE",
]);
}
$zone = new Zone([
'id' => $domain,
'name' => $domain,
'rrsets' => [$rrset]
]);
$this->zoneApi->patchZoneWithHttpInfo($this->server_id, $domain, $zone);
return true;
} catch (ApiException $e) {
$error = json_decode($e->getResponseBody(), 1);
return $error['error'];
}
}
public function UpdateDomainRecord($record, $domain = null)
{
try {
$old_record = Record::where('id', $record['id'])->first();
$domain = $record['domain'];
if (in_array($record['type'], ['REDIRECT_URL', 'FORWARD_URL'])) {
//还需要先判断是否有相同主机头的A记录,因为也会冲突
$exist_record = Record::where("host", $record['host'])
->where('platform', $record['platform'])
->where('domain', $record['domain'])
->whereIn('type', ["A", "CNAME", 'REDIRECT_URL', 'FORWARD_URL'])
->whereNotNull('record_id')
->where('id', '<>', $record['id'])
->first();
if ($exist_record) {
return "type-already-exists";
}
$functions = $record['type'] == "REDIRECT_URL" ? 1 : 2;
if ($this->FormatRRsetName($old_record) == $this->FormatRRsetName($record)) {
$UrlForwardBaseResp =
UrlForwardBase::updateForwardAPI($this->FormatRRsetName($record) . "{$domain}",
$functions,
$record['value']);
if ($UrlForwardBaseResp !== 1) {
return $UrlForwardBaseResp;
}
} else {
$UrlForwardBaseResp =
UrlForwardBase::deleteForwardAPI($this->FormatRRsetName($old_record) . "{$domain}");
if ($UrlForwardBaseResp !== 1) {
return $UrlForwardBaseResp;
}
$UrlForwardBaseResp =
UrlForwardBase::createForwardAPI($this->FormatRRsetName($record) . "{$domain}",
$functions,
$record['value']);
if ($UrlForwardBaseResp !== 1) {
return $UrlForwardBaseResp;
}
}
}
$total_repeat_record = Record::where("host", $record['host'])
->where('platform', $record['platform'])
->where('domain', $record['domain'])
->where('type', $record['type'])
->whereNotNull('record_id')
->where('id', '<>', $record['id'])
->get();
$rrset = new RRSet([
"name" => $this->FormatRRsetName($record) . "{$domain}.",
"type" => $this->FormatRRsetType($record),
"ttl" => $record['ttl'],
"changetype" => "REPLACE",
]);
$rrset_record_list = [new \Swagger\Client\Model\Record([
"content" => $this->FormatRRsetContent($record),
"disabled" => $record['state'] == 2 ? true : false,
])];
if (count($total_repeat_record) > 0) {
foreach ($total_repeat_record as $repeat_record) {
$rrset_record_list[] =
new \Swagger\Client\Model\Record([
"content" => $this->FormatRRsetContent($repeat_record),
"disabled" => $repeat_record['state'] == 2 ? true : false,
]);
}
}
$rrset->setRecords($rrset_record_list);
$rrsets = [$rrset];
if ($old_record['host'] != $record['host'] || $old_record['type'] != $record['type']) {
$rrset_record_list = [];
//和旧记录的解析头不同,还需要吧历史的清除一下
$total_repeat_record = Record::where("host", $old_record['host'])
->where('platform', $record['platform'])
->where('domain', $record['domain'])
->where('type', $record['type'])
->whereNotNull('record_id')
->where('id', '<>', $record['id'])
->get();
$rrset = new RRSet([
"name" => $this->FormatRRsetName($old_record) . "{$domain}.",
"type" => $this->FormatRRsetType($old_record),
"ttl" => $record['ttl'],
]);
if (count($total_repeat_record) == 0) {
$rrset->setChangetype("DELETE");
} else {
$rrset->setChangetype("REPLACE");
if (count($total_repeat_record) > 0) {
foreach ($total_repeat_record as $repeat_record) {
$rrset_record_list[] =
new \Swagger\Client\Model\Record([
"content" => $this->FormatRRsetContent($repeat_record),
"disabled" => false,
]);
}
$rrset->setRecords($rrset_record_list);
}
}
array_unshift($rrsets, $rrset);
}
$zone = new Zone([
'id' => $domain,
'name' => $domain,
'rrsets' => $rrsets
]);
$this->zoneApi->patchZoneWithHttpInfo($this->server_id, $domain, $zone);
return true;
} catch (ApiException $e) {
$error = json_decode($e->getResponseBody(), 1);
return $error['error'];
}
}
/**
* 获取解析记录列表
* @param $DomainName
* @param array $param
* @return array
*/
public function DescribeDomainRecords($DomainName, $param = [])
{
try {
$result = $this->zoneApi->listZone($this->server_id, $DomainName);
$list = [];
foreach ($result['rrsets'] as $key => $rrset) {
if ($rrset['type'] == "SOA") continue;
$host = str_replace("{$DomainName}.", "", $rrset['name']);
$mx = "";
foreach ($rrset['records'] as $rrset_record) {
$value = trim($rrset_record['content'], ".");
if ($rrset['type'] == "MX") {
$tmp = explode(" ", $value);
$mx = trim($tmp[0]);
$value = trim($tmp[1]);
}elseif ($rrset['type'] == "TXT") {
$value = trim($value,"\"");
}
if ($rrset['type'] == "NS" && in_array($value, self::$NSList)) continue;
$list[] = [
'DomainName' => $DomainName,
'RecordId' => $key + 1,
'RR' => trim($host, "."),
'Type' => $rrset['type'],
'MX' => $mx,
'Value' => $value,
'Line' => "",
'Priority' => "",
'TTL' => $rrset['ttl'],
'Status' => $rrset_record["disabled"] ? 2 : 0,
'Locked' => '0',
];
}
}
return $list;
} catch (ApiException $e) {
$error = json_decode($e->getResponseBody(), 1);
return $error['error'];
}
}
private function FormatRRsetName($record)
{
$name = "";
if ($record['host'] == "@") {
$name = "";
} elseif ($record['host']) {
$name = "{$record['host']}.";
}
return "{$name}";
}
private function FormatRRsetType($record)
{
if (in_array($record['type'], ['REDIRECT_URL', 'FORWARD_URL'])) {
return "A";
}
return $record['type'];
}
private function FormatRRsetContent($record, $defaultContent = "")
{
$content = $record['value'];
switch ($record['type']) {
case "MX":
$content = "{$record['mx']} {$record['value']}.";
break;
case "TXT":
$content = "\"{$content}\"";
break;
case "CNAME":
case "NS":
case "SRV":
$content = "{$record['value']}.";
break;
case "REDIRECT_URL": // 显性URL转发
case "FORWARD_URL": //隐性URL转发
// $content = UrlForwardBase::getFastDomain().".";
$content = gethostbyname(UrlForwardBase::getFastDomain());
//先请求添加转发服务器,添加成功往下走,否则失败
break;
default:
break;
}
return $content;
}
/**
* 更新解析状态
* @param $record
* @param $status
* @param array $param
* @return mixed
*/
public function SetDomainRecordStatus($record, $status, $param = [])
{
$record->state = $status == 'Disable' ? 2 : 0;
return $this->UpdateDomainRecord($record);
}
}
4.数据库表结构
CREATE TABLE `domains` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`domain` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL,
`remote_id` varchar(36) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL,
`created_at` timestamp(0) NULL,
`updated_at` timestamp(0) NULL,
`deleted_at` timestamp(0) NULL DEFAULT NULL,
`platform` varchar(16) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT 'dnscom',
`dns` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT '',
`status` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT '',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_unicode_ci ROW_FORMAT = Dynamic;
CREATE TABLE `records` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`domain` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL,
`record_id` bigint(32) NULL DEFAULT NULL,
`host` varchar(256) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL,
`state` int(11) NULL DEFAULT 0,
`type` varchar(32) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL,
`value` varchar(256) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL,
`ttl` int(11) NULL DEFAULT 0,
`mx` int(11) NULL DEFAULT 0,
`url_type` int(11) NULL DEFAULT 0,
`remark` varchar(32) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL,
`created_at` timestamp(0) NULL DEFAULT NULL,
`updated_at` timestamp(0) NULL DEFAULT NULL,
`deleted_at` timestamp(0) NULL DEFAULT NULL,
`platform` varchar(16) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT 'dnscom',
`dns` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT '',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_unicode_ci ROW_FORMAT = Dynamic;