Skip to content

Commit

Permalink
Implement account update method
Browse files Browse the repository at this point in the history
Allow syncing of all known accounts from PowerDNS, in the same
way that Domain().update() does for domains.
  • Loading branch information
LordGaav committed Aug 6, 2020
1 parent 4e63f83 commit 0ef57b2
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 6 deletions.
64 changes: 64 additions & 0 deletions powerdnsadmin/models/account.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import traceback
from flask import current_app
from urllib.parse import urljoin

from ..lib import utils
from .base import db
from .setting import Setting
from .user import User
from .account_user import AccountUser

Expand All @@ -20,6 +24,12 @@ def __init__(self, name=None, description=None, contact=None, mail=None):
self.contact = contact
self.mail = mail

# PDNS configs
self.PDNS_STATS_URL = Setting().get('pdns_api_url')
self.PDNS_API_KEY = Setting().get('pdns_api_key')
self.PDNS_VERSION = Setting().get('pdns_version')
self.API_EXTENDED_URL = utils.pdns_api_extended_uri(self.PDNS_VERSION)

if self.name is not None:
self.name = ''.join(c for c in self.name.lower()
if c in "abcdefghijklmnopqrstuvwxyz0123456789")
Expand Down Expand Up @@ -200,3 +210,57 @@ def remove_user(self, user):
'Cannot revoke user privileges on account {0}. DETAIL: {1}'.
format(self.name, e))
return False

def update(self):
"""
Fetch accounts from PowerDNS and syncs them into DB
"""
db_accounts = Account.query.all()
list_db_accounts = [d.name for d in db_accounts]
current_app.logger.info("Found {} accounts in PowerDNS-Admin".format(
len(list_db_accounts)))
headers = {'X-API-Key': self.PDNS_API_KEY}
try:
jdata = utils.fetch_json(
urljoin(self.PDNS_STATS_URL,
self.API_EXTENDED_URL + '/servers/localhost/zones'),
headers=headers,
timeout=int(Setting().get('pdns_api_timeout')),
verify=Setting().get('verify_ssl_connections'))
list_jaccount = set(d['account'] for d in jdata if d['account'])

try:
# Remove accounts that don't exist any more
should_removed_db_account = list(
set(list_db_accounts).difference(list_jaccount))
for account_name in should_removed_db_account:
account_id = self.get_id_by_name(account_name)
if not account_id:
continue
current_app.logger.info("Deleting account for {0}".format(account_name))
account = Account.query.get(account_id)
db.session.delete(account)
except Exception as e:
current_app.logger.error(
'Can not delete account from DB. DETAIL: {0}'.format(e))
current_app.logger.debug(traceback.format_exc())

for account_name in list_jaccount:
account_id = self.get_id_by_name(account_name)
if account_id:
continue
current_app.logger.info("Creating account for {0}".format(account_name))
account = Account(name=account_name)
db.session.add(account)

db.session.commit()
current_app.logger.info('Update accounts finished')
return {
'status': 'ok',
'msg': 'Account table has been updated successfully'
}
except Exception as e:
db.session.rollback()
current_app.logger.error(
'Cannot update account table. Error: {0}'.format(e))
return {'status': 'error', 'msg': 'Cannot update account table'}
8 changes: 4 additions & 4 deletions powerdnsadmin/models/domain.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def update(self):
db_domain = Domain.query.all()
list_db_domain = [d.name for d in db_domain]
dict_db_domain = dict((x.name, x) for x in db_domain)
current_app.logger.info("Found {} entries in PowerDNS-Admin".format(
current_app.logger.info("Found {} domains in PowerDNS-Admin".format(
len(list_db_domain)))
headers = {'X-API-Key': self.PDNS_API_KEY}
try:
Expand All @@ -128,7 +128,7 @@ def update(self):
verify=Setting().get('verify_ssl_connections'))
list_jdomain = [d['name'].rstrip('.') for d in jdata]
current_app.logger.info(
"Found {} entries in PowerDNS server".format(len(list_jdomain)))
"Found {} zones in PowerDNS server".format(len(list_jdomain)))

try:
# domains should remove from db since it doesn't exist in powerdns anymore
Expand Down Expand Up @@ -166,8 +166,8 @@ def update(self):
except Exception as e:
db.session.rollback()
current_app.logger.error(
'Can not update domain table. Error: {0}'.format(e))
return {'status': 'error', 'msg': 'Can not update domain table'}
'Cannot update domain table. Error: {0}'.format(e))
return {'status': 'error', 'msg': 'Cannot update domain table'}

def update_pdns_admin_domain(self, domain, account_id, data, do_commit=True):
# existing domain, only update if something actually has changed
Expand Down
33 changes: 33 additions & 0 deletions update_accounts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/usr/bin/env python3

####################################################################################################################################
# A CLI Script to update list of accounts. Can be useful for people who want to execute updates from a cronjob
#
# Tip:
# When running from a cron, use flock (you might need to install it) to be sure only one process is running a time. eg:
# */5 * * * * flock -xn "/tmp/pdns-update-zones.lock" python /var/www/html/apps/poweradmin/update_accounts.py >/dev/null 2>&1
#
##############################################################

### Imports
import sys
import logging

from powerdnsadmin import create_app
from powerdnsadmin.models.account import Account
from powerdnsadmin.models.domain import Domain
from powerdnsadmin.models.setting import Setting

app = create_app()
app.logger.setLevel(logging.INFO)

with app.app_context():
status = Setting().get('bg_domain_updates')

### Check if bg_domain_updates is set to true
if not status:
app.logger.error('Please turn on "bg_domain_updates" setting to run this job.')
sys.exit(1)

Account().update()
Domain().update()
4 changes: 2 additions & 2 deletions update_zones.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,6 @@
sys.exit(1)

### Start the update process
app.logger.info('Update zones from nameserver API')
app.logger.info('Update domains from nameserver API')

d = Domain().update()
Domain().update()

0 comments on commit 0ef57b2

Please sign in to comment.