Initial YakPanel commit
This commit is contained in:
210
class/sewer/dns_providers/aliyundns.py
Normal file
210
class/sewer/dns_providers/aliyundns.py
Normal file
@@ -0,0 +1,210 @@
|
||||
import json
|
||||
|
||||
try:
|
||||
aliyun_dependencies = True
|
||||
from aliyunsdkcore import client
|
||||
from aliyunsdkalidns.request.v20150109 import DescribeDomainRecordsRequest
|
||||
from aliyunsdkalidns.request.v20150109 import AddDomainRecordRequest
|
||||
from aliyunsdkalidns.request.v20150109 import DeleteDomainRecordRequest
|
||||
except ImportError:
|
||||
aliyun_dependencies = False
|
||||
|
||||
from . import common
|
||||
|
||||
|
||||
class _ResponseForAliyun(object):
|
||||
"""
|
||||
wrapper aliyun resp to the format sewer wanted.
|
||||
"""
|
||||
|
||||
def __init__(self, status_code=200, content=None, headers=None):
|
||||
self.status_code = status_code
|
||||
self.headers = headers or {}
|
||||
self.content = content or {}
|
||||
self.content = json.dumps(content)
|
||||
super(_ResponseForAliyun, self).__init__()
|
||||
|
||||
def json(self):
|
||||
return json.loads(self.content)
|
||||
|
||||
|
||||
class AliyunDns(common.BaseDns):
|
||||
def __init__(self, key, secret, endpoint="cn-beijing", debug=False):
|
||||
"""
|
||||
aliyun model client
|
||||
:param str key: access key
|
||||
:param str secret: access sceret
|
||||
:param str endpoint: endpoint
|
||||
:param bool debug: if debug?
|
||||
"""
|
||||
super(AliyunDns, self).__init__()
|
||||
if not aliyun_dependencies:
|
||||
raise ImportError(
|
||||
"""You need to install aliyunDns dependencies. run; pip3 install sewer[aliyun]"""
|
||||
)
|
||||
self._key = key
|
||||
self._secret = secret
|
||||
self._endpoint = endpoint
|
||||
self._debug = debug
|
||||
self.clt = client.AcsClient(self._key, self._secret, self._endpoint, debug=self._debug)
|
||||
|
||||
def _send_reqeust(self, request):
|
||||
"""
|
||||
send request to aliyun
|
||||
"""
|
||||
request.set_accept_format("json")
|
||||
try:
|
||||
status, headers, result = self.clt.implementation_of_do_action(request)
|
||||
result = json.loads(result)
|
||||
if "Message" in result or "Code" in result:
|
||||
result["Success"] = False
|
||||
self.logger.warning("aliyundns resp error: %s", result)
|
||||
except Exception as exc:
|
||||
self.logger.warning("aliyundns failed to send request: %s, %s", str(exc), request)
|
||||
status, headers, result = 502, {}, '{"Success": false}'
|
||||
result = json.loads(result)
|
||||
|
||||
if self._debug:
|
||||
self.logger.info("aliyundns request name: %s", request.__class__.__name__)
|
||||
self.logger.info("aliyundns request query: %s", request.get_query_params())
|
||||
return _ResponseForAliyun(status, result, headers)
|
||||
|
||||
def query_recored_items(self, host, zone=None, tipe=None, page=1, psize=200):
|
||||
"""
|
||||
query recored items.
|
||||
:param str host: like example.com
|
||||
:param str zone: like menduo.example.com
|
||||
:param str tipe: TXT, CNAME, IP or other
|
||||
:param int page:
|
||||
:param int psize:
|
||||
:return dict: res = {
|
||||
'DomainRecords':
|
||||
{'Record': [
|
||||
{
|
||||
'DomainName': 'menduo.net',
|
||||
'Line': 'default',
|
||||
'Locked': False,
|
||||
'RR': 'zb',
|
||||
'RecordId': '3989515483698964',
|
||||
'Status': 'ENABLE',
|
||||
'TTL': 600,
|
||||
'Type': 'A',
|
||||
'Value': '127.0.0.1',
|
||||
'Weight': 1
|
||||
},
|
||||
{
|
||||
'DomainName': 'menduo.net',
|
||||
'Line': 'default',
|
||||
'Locked': False,
|
||||
'RR': 'a.sub',
|
||||
'RecordId': '3989515480778964',
|
||||
'Status': 'ENABLE',
|
||||
'TTL': 600,
|
||||
'Type': 'CNAME',
|
||||
'Value': 'h.p.menduo.net',
|
||||
'Weight': 1
|
||||
}
|
||||
]
|
||||
},
|
||||
'PageNumber': 1,
|
||||
'PageSize': 20,
|
||||
'RequestId': 'FC4D02CD-EDCC-4EE8-942F-1497CCC3B10E',
|
||||
'TotalCount': 95
|
||||
}
|
||||
"""
|
||||
request = DescribeDomainRecordsRequest.DescribeDomainRecordsRequest()
|
||||
request.get_action_name()
|
||||
request.set_DomainName(host)
|
||||
request.set_PageNumber(page)
|
||||
request.set_PageSize(psize)
|
||||
if zone:
|
||||
request.set_RRKeyWord(zone)
|
||||
if tipe:
|
||||
request.set_TypeKeyWord(tipe)
|
||||
resp = self._send_reqeust(request)
|
||||
body = resp.json()
|
||||
return body
|
||||
|
||||
def query_recored_id(self, root, zone, tipe="TXT"):
|
||||
"""
|
||||
find recored
|
||||
:param str root: root host, like example.com
|
||||
:param str zone: sub zone, like menduo.example.com
|
||||
:param str tipe: record tipe, TXT, CNAME, IP. we use TXT
|
||||
:return str:
|
||||
"""
|
||||
record_id = None
|
||||
recoreds = self.query_recored_items(root, zone, tipe=tipe)
|
||||
recored_list = recoreds.get("DomainRecords", {}).get("Record", [])
|
||||
recored_item_list = [i for i in recored_list if i["RR"] == zone]
|
||||
if len(recored_item_list):
|
||||
record_id = recored_item_list[0]["RecordId"]
|
||||
return record_id
|
||||
|
||||
@staticmethod
|
||||
def extract_zone(domain_name):
|
||||
"""
|
||||
extract domain to root, sub, acme_txt
|
||||
:param str domain_name: the value sewer client passed in, like *.menduo.example.com
|
||||
:return tuple: root, zone, acme_txt
|
||||
"""
|
||||
# if we have been given a wildcard name, strip wildcard
|
||||
domain_name = domain_name.lstrip("*.")
|
||||
if domain_name.count(".") > 1:
|
||||
zone, middle, last = str(domain_name).rsplit(".", 2)
|
||||
root = ".".join([middle, last])
|
||||
acme_txt = "_acme-challenge.%s" % zone
|
||||
else:
|
||||
zone = ""
|
||||
root = domain_name
|
||||
acme_txt = "_acme-challenge"
|
||||
return root, zone, acme_txt
|
||||
|
||||
def create_dns_record(self, domain_name, domain_dns_value):
|
||||
"""
|
||||
create a model record
|
||||
:param str domain_name: the value sewer client passed in, like *.menduo.example.com
|
||||
:param str domain_dns_value: the value sewer client passed in.
|
||||
:return _ResponseForAliyun:
|
||||
"""
|
||||
self.logger.info("create_dns_record start: %s", (domain_name, domain_dns_value))
|
||||
root, _, acme_txt = self.extract_zone(domain_name)
|
||||
|
||||
request = AddDomainRecordRequest.AddDomainRecordRequest()
|
||||
request.set_DomainName(root)
|
||||
request.set_TTL(600)
|
||||
request.set_RR(acme_txt)
|
||||
request.set_Type("TXT")
|
||||
request.set_Value(domain_dns_value)
|
||||
resp = self._send_reqeust(request)
|
||||
|
||||
self.logger.info("create_dns_record end: %s", (domain_name, domain_dns_value, resp.json()))
|
||||
|
||||
return resp
|
||||
|
||||
def delete_dns_record(self, domain_name, domain_dns_value):
|
||||
"""
|
||||
delete a txt record we created just now.
|
||||
:param str domain_name: the value sewer client passed in, like *.menduo.example.com
|
||||
:param str domain_dns_value: the value sewer client passed in. we do not use this.
|
||||
:return _ResponseForAliyun:
|
||||
:return:
|
||||
"""
|
||||
self.logger.info("delete_dns_record start: %s", (domain_name, domain_dns_value))
|
||||
|
||||
root, _, acme_txt = self.extract_zone(domain_name)
|
||||
|
||||
record_id = self.query_recored_id(root, acme_txt)
|
||||
if not record_id:
|
||||
msg = "failed to find record_id of domain: %s, value: %s", domain_name, domain_dns_value
|
||||
self.logger.warning(msg)
|
||||
return
|
||||
|
||||
self.logger.info("start to delete model record, id: %s", record_id)
|
||||
|
||||
request = DeleteDomainRecordRequest.DeleteDomainRecordRequest()
|
||||
request.set_RecordId(record_id)
|
||||
resp = self._send_reqeust(request)
|
||||
|
||||
self.logger.info("delete_dns_record end: %s", (domain_name, domain_dns_value, resp.json()))
|
||||
return resp
|
||||
Reference in New Issue
Block a user