Skip to content
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

Add catalog (Producer) zone support. #218

Draft
wants to merge 12 commits into
base: master
Choose a base branch
from
Draft
9 changes: 9 additions & 0 deletions migrations/007.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php
$migration_name = 'Add catalog zone support';

$this->database->exec('ALTER TABLE ONLY zone ADD catalog text;');

$this->database->exec("INSERT INTO replication_type VALUES (3, 'Producer', 'A producer or catalog zone is a special zone that store the current list of zones assoicated with it. It can be used by secondary servers to update the list of zones for which they are authoritative')");

$this->database->exec("INSERT INTO soa_template VALUES (1, 'Producer', 'invalid.', 'invalid.', 3600, 600, 2147483646, 0, 0)");
$this->database->exec("INSERT INTO ns_template VALUES (1, 'Producer', 'invalid.')");
2 changes: 1 addition & 1 deletion model/migrationdirectory.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class MigrationDirectory extends DBDirectory {
/**
* Increment this constant to activate a new migration from the migrations directory
*/
const LAST_MIGRATION = 6;
const LAST_MIGRATION = 7;

public function __construct() {
parent::__construct();
Expand Down
2 changes: 2 additions & 0 deletions model/zone.php
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ public function update() {
global $config;
$update = new StdClass;
$update->kind = $this->kind;
$update->catalog = $this->catalog;
$update->account = $this->account;
if(isset($config['dns']['dnssec']) && $config['dns']['dnssec'] == 1) {
$update->dnssec = (bool)$this->dnssec;
Expand Down Expand Up @@ -648,6 +649,7 @@ public function restore() {
$data = new StdClass;
$data->name = $this->name;
$data->kind = $this->kind;
$data->catalog = $this->catalog;
$data->nameservers = array();
$data->rrsets = array();
foreach($rrsets as $rrset) {
Expand Down
52 changes: 50 additions & 2 deletions model/zonedirectory.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,14 @@ public function __construct() {
* @param Zone $zone to be added
*/
public function add_zone(Zone $zone) {
$stmt = $this->database->prepare('INSERT INTO zone (pdns_id, name, serial, kind, account, dnssec) VALUES (?, ?, ?, ?, ?, ?)');
$stmt = $this->database->prepare('INSERT INTO zone (pdns_id, name, serial, kind, account, dnssec, catalog) VALUES (?, ?, ?, ?, ?, ?, ?)');
$stmt->bindParam(1, $zone->pdns_id, PDO::PARAM_STR);
$stmt->bindParam(2, $zone->name, PDO::PARAM_STR);
$stmt->bindParam(3, $zone->serial, PDO::PARAM_INT);
$stmt->bindParam(4, $zone->kind, PDO::PARAM_STR);
$stmt->bindParam(5, $zone->account, PDO::PARAM_STR);
$stmt->bindParam(6, $zone->dnssec, PDO::PARAM_INT);
$stmt->bindParam(7, $zone->catalog, PDO::PARAM_STR);
try {
$stmt->execute();
$zone->id = $this->database->lastInsertId('zone_id_seq');
Expand Down Expand Up @@ -73,6 +74,7 @@ public function create_zone($zone) {
$data = new StdClass;
$data->name = $zone->name;
$data->kind = $zone->kind;
$data->catalog = $zone->catalog;
$data->nameservers = $zone->nameservers;
$data->rrsets = array();
foreach($zone->list_resource_record_sets() as $rrset) {
Expand Down Expand Up @@ -111,6 +113,16 @@ public function create_zone($zone) {
syslog_report(LOG_INFO, "zone={$zone->name};object=zone;action=add;status=succeeded");
}

/**
* Zone name comparison function, that will group zones by TLD, then SLD, etc.
* To be used as callback function with e.g. the "uasort" function
*/
private function compare_zones_by_name($a, $b) {
$aname = implode(',', array_reverse(explode('.', punycode_to_utf8($a->name))));
$bname = implode(',', array_reverse(explode('.', punycode_to_utf8($b->name))));
return strnatcasecmp($aname, $bname);
}

/**
* List all zones in PowerDNS and update list in database to match.
* @param array $include list of extra data to include in response
Expand Down Expand Up @@ -149,14 +161,15 @@ public function list_zones($include = array()) {
$zone->pdns_id = $pdns_zone->id;
$zone->name = $pdns_zone->name;
$zone->kind = $pdns_zone->kind;
$zone->catalog = $pdns_zone->catalog;
$zone->serial = $pdns_zone->serial;
$zone->account = $pdns_zone->account;
$zone->dnssec = $pdns_zone->dnssec;
$this->add_zone($zone);
$zones_by_pdns_id[$zone->pdns_id] = $zone;
$current_zones[$zone->pdns_id] = true;
} else {
$fields = array('serial' => PDO::PARAM_INT, 'kind' => PDO::PARAM_STR, 'account' => PDO::PARAM_STR, 'dnssec' => PDO::PARAM_INT);
$fields = array('serial' => PDO::PARAM_INT, 'kind' => PDO::PARAM_STR, 'account' => PDO::PARAM_STR, 'dnssec' => PDO::PARAM_INT, 'catalog' => PDO::PARAM_STR);
foreach($fields as $field => $type) {
if($zones_by_pdns_id[$pdns_zone->id]->{$field} != $pdns_zone->{$field}) {
$zones_by_pdns_id[$pdns_zone->id]->{$field} = $pdns_zone->{$field};
Expand Down Expand Up @@ -188,6 +201,41 @@ public function list_zones($include = array()) {
}
}
$this->database->query('COMMIT WORK');
uasort($zones_by_pdns_id, array($this, 'compare_zones_by_name'));
return $zones_by_pdns_id;
}

/**
* Fetch the list of zones matching the specific type
* @param string $type of the zones to list
* @return array of Zone objects indexed by pdns_id
*/
public function list_zones_by_kind($type) {
$stmt = $this->database->prepare('SELECT * FROM zone WHERE kind = ?');
$stmt->bindParam(1, $type, PDO::PARAM_STR);
$stmt->execute();
$zones_by_pdns_id = array();
while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$zones_by_pdns_id[$row['pdns_id']] = new Zone($row['id'], $row);
}
uasort($zones_by_pdns_id, array($this, 'compare_zones_by_name'));
return $zones_by_pdns_id;
}

/**
* Fetch the list of member zones having the specified catalog zone as producer
* @param string $catalog zone to list members
* @return array of member Zone objects indexed by pdns_id
*/
public function list_zones_by_catalog($catalog) {
$stmt = $this->database->prepare('SELECT * FROM zone WHERE catalog = ?');
$stmt->bindParam(1, $catalog, PDO::PARAM_STR);
$stmt->execute();
$zones_by_pdns_id = array();
while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$zones_by_pdns_id[$row['pdns_id']] = new Zone($row['id'], $row);
}
uasort($zones_by_pdns_id, array($this, 'compare_zones_by_name'));
return $zones_by_pdns_id;
}

Expand Down
42 changes: 40 additions & 2 deletions public_html/extra.js
Original file line number Diff line number Diff line change
Expand Up @@ -867,10 +867,45 @@ $(function() {
});
});


// Add template button functionality on zone add and zone soa edit form
// and handle constraints for 'Producer' zones
$('form.zoneadd, form.zoneeditsoa').each(function() {

function set_zone_settings_constraints(form) {
var zone_kind = $('select#kind', form).val()
if (zone_kind == 'Producer') {
$('button.soa-template, button.ns-template', form).each(function() {
$(this).prop('disabled', true)
});
$('button.soa-template:contains(Producer), ' +
'button.ns-template:contains(Producer)', form).each(function() {
$(this).prop('disabled', false).click();
});
$('#catalog', form).val('');
$('#dnssec', form).prop('checked', false);
} else {
$('button.soa-template, button.ns-template', form).each(function() {
$(this).prop('disabled', false)
});
$('button.soa-template:contains(Producer), ' +
'button.ns-template:contains(Producer)', form).each(function() {
$.each(this.dataset, function(index, value) { $('#' + index).val('') });
$(this).removeClass('btn-success').addClass('btn-default').prop('disabled', true);
});
$('button.soa-template[data-default="1"], ' +
'button.ns-template[data-default="1"]', form).each(function() {
$(this).click();
});
}
$('#catalog, #dnssec', form).each(function() {
$(this).prop('disabled', (zone_kind === 'Producer'))
});
}

var form = $(this);
$('button.soa-template[data-default="1"], button.ns-template[data-default="1"]', form).each(function() {
$('button.soa-template[data-default="1"], ' +
'button.ns-template[data-default="1"]', form).each(function() {
$.each(this.dataset, function(index, value) { $('#' + index).val(value) });
$(this).removeClass('btn-default').addClass('btn-success');
});
Expand All @@ -880,6 +915,9 @@ $(function() {
$(this).removeClass('btn-default').addClass('btn-success');
});

set_zone_settings_constraints(form);
$('select#kind', form).on('change', function() { set_zone_settings_constraints(form); });

$('input#ipv4_zone_prefix').on('keyup', function(event) { if(event.which == 13) prefill_reverse_ipv4_zone($(this)) });
$('button#ipv4_zone_create').on('click', function() { prefill_reverse_ipv4_zone($('input#ipv4_zone_prefix')) });
$('input#ipv6_zone_prefix').on('keyup', function(event) { if(event.which == 13) prefill_reverse_ipv6_zone($(this)) });
Expand All @@ -903,7 +941,7 @@ $(function() {
$('a[href=#create]').tab('show');
}
});

$('#changelog-expand-all').on('click', function() {
$('table.changelog tbody tr[data-changeset]').each(function() {
show_changes($(this), true);
Expand Down
2 changes: 1 addition & 1 deletion templates/template.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
<div class="form-group">
<label for="name" class="col-sm-2 control-label">Template name</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="name" name="name" value="<?php out($template->name)?>" required>
<input type="text" class="form-control" id="name" name="name" value="<?php out($template->name)?>" required<?php if($template->name == 'Producer') { ?> readonly<?php } ?>>
</div>
</div>
<?php if($type == 'soa') { ?>
Expand Down
2 changes: 2 additions & 0 deletions templates/templates.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,14 @@
<td><a href="<?php outurl('/templates/'.urlencode($t).'/'.urlencode($template->name))?>"><?php out($template->name)?></a></td>
<td>
<a href="<?php outurl('/templates/'.urlencode($t).'/'.urlencode($template->name))?>" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-cog"></span> Edit</a>
<?php if($template->name != 'Producer') { ?>
<button type="submit" class="btn btn-xs btn-default" name="delete_<?php out($t)?>_template" value="<?php out($template->id)?>"><span class="glyphicon glyphicon-trash"></span> Delete</button>
<?php if($template->default) { ?>
<button type="submit" class="btn btn-xs btn-success" disabled>Default</button>
<?php } else { ?>
<button type="submit" class="btn btn-xs btn-default" name="set_default_<?php out($t)?>_template" value="<?php out($template->id)?>">Set as default</button>
<?php } ?>
<?php } ?>
</td>
</tr>
<?php
Expand Down
Loading