fb-pdnstools 1.0.0__py3-none-any.whl → 1.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12,6 +12,7 @@ from __future__ import absolute_import
12
12
  # Standard modules
13
13
  import copy
14
14
  import ipaddress
15
+ import locale
15
16
  import logging
16
17
  import os
17
18
  import pathlib
@@ -21,12 +22,12 @@ from functools import cmp_to_key
21
22
 
22
23
  # Third party modules
23
24
  from fb_tools.app import BaseApplication
25
+ from fb_tools.argparse_actions import CfgFileOptionAction
24
26
  from fb_tools.common import compare_fqdn
25
27
  from fb_tools.common import pp
26
28
  from fb_tools.common import reverse_pointer
27
29
  from fb_tools.common import to_bool
28
30
  from fb_tools.common import to_str
29
- from fb_tools.config import CfgFileOptionAction
30
31
  from fb_tools.errors import FbAppError
31
32
 
32
33
  # Own modules
@@ -35,9 +36,15 @@ from . import DEFAULT_PORT
35
36
  from . import __version__ as GLOBAL_VERSION
36
37
  from .bulk_rm_cfg import PdnsBulkRmCfg
37
38
  from .server import PowerDNSServer
39
+ from .xlate import DOMAIN
40
+ from .xlate import LOCALE_DIR
38
41
  from .xlate import XLATOR
42
+ from .xlate import __base_dir__ as __xlate_base_dir__
43
+ from .xlate import __lib_dir__ as __xlate_lib_dir__
44
+ from .xlate import __mo_file__ as __xlate_mo_file__
45
+ from .xlate import __module_dir__ as __xlate_module_dir__
39
46
 
40
- __version__ = '0.7.3'
47
+ __version__ = "1.0.0"
41
48
  LOG = logging.getLogger(__name__)
42
49
 
43
50
  _ = XLATOR.gettext
@@ -61,10 +68,11 @@ class PdnsBulkRmApp(BaseApplication):
61
68
  def __init__(self, appname=None, verbose=0, version=GLOBAL_VERSION, *args, **kwargs):
62
69
  """Initialize the PdnsBulkRmApp object."""
63
70
  desc = _(
64
- 'Removes the given addresses (A-, AAAA- or CNAME-Records) completety from '
65
- 'PowerDNS. If there are multiple entries to a DNS-Name, all appropriate '
66
- 'records are removed. Additionally all appropriate reverse entries (PTR-records) '
67
- 'were also removed, if they are pointing back to the given A- or AAAA-record.')
71
+ "Removes the given addresses (A-, AAAA- or CNAME-Records) completety from "
72
+ "PowerDNS. If there are multiple entries to a DNS-Name, all appropriate "
73
+ "records are removed. Additionally all appropriate reverse entries (PTR-records) "
74
+ "were also removed, if they are pointing back to the given A- or AAAA-record."
75
+ )
68
76
 
69
77
  self._cfg_file = None
70
78
  self.config = None
@@ -78,10 +86,7 @@ class PdnsBulkRmApp(BaseApplication):
78
86
  self.expected_ptr = None
79
87
 
80
88
  super(PdnsBulkRmApp, self).__init__(
81
- description=desc,
82
- verbose=verbose,
83
- version=version,
84
- *args, **kwargs
89
+ *args, **kwargs, description=desc, verbose=verbose, version=version,
85
90
  )
86
91
 
87
92
  self.initialized = True
@@ -114,8 +119,20 @@ class PdnsBulkRmApp(BaseApplication):
114
119
  @rtype: dict
115
120
  """
116
121
  res = super(PdnsBulkRmApp, self).as_dict(short=short)
117
- res['cfg_file'] = self.cfg_file
118
- res['rm_reverse'] = self.rm_reverse
122
+ res["cfg_file"] = self.cfg_file
123
+ res["rm_reverse"] = self.rm_reverse
124
+
125
+ if "xlate" not in res:
126
+ res["xlate"] = {}
127
+
128
+ res["xlate"]["fb_vmware"] = {
129
+ "__module_dir__": __xlate_module_dir__,
130
+ "__lib_dir__": __xlate_lib_dir__,
131
+ "__base_dir__": __xlate_base_dir__,
132
+ "LOCALE_DIR": LOCALE_DIR,
133
+ "DOMAIN": DOMAIN,
134
+ "__mo_file__": __xlate_mo_file__,
135
+ }
119
136
 
120
137
  return res
121
138
 
@@ -138,8 +155,11 @@ class PdnsBulkRmApp(BaseApplication):
138
155
  self.perform_arg_parser()
139
156
 
140
157
  self.config = PdnsBulkRmCfg(
141
- appname=self.appname, verbose=self.verbose, base_dir=self.base_dir,
142
- config_file=self.cfg_file)
158
+ appname=self.appname,
159
+ verbose=self.verbose,
160
+ base_dir=self.base_dir,
161
+ config_file=self.cfg_file,
162
+ )
143
163
 
144
164
  self.config.read()
145
165
  if self.config.verbose > self.verbose:
@@ -147,7 +167,7 @@ class PdnsBulkRmApp(BaseApplication):
147
167
  self.config.initialized = True
148
168
 
149
169
  if self.verbose > 3:
150
- LOG.debug('Read configuration:\n{}'.format(pp(self.config.as_dict())))
170
+ LOG.debug("Read configuration:\n{}".format(pp(self.config.as_dict())))
151
171
 
152
172
  self.perform_arg_parser_pdns()
153
173
 
@@ -155,15 +175,21 @@ class PdnsBulkRmApp(BaseApplication):
155
175
  self.read_address_file()
156
176
 
157
177
  if not self.addresses:
158
- LOG.error(_('No addresses to remove given.'))
178
+ LOG.error(_("No addresses to remove given."))
159
179
  self.exit(1)
160
180
 
161
181
  self.pdns = PowerDNSServer(
162
- appname=self.appname, verbose=self.verbose, base_dir=self.base_dir,
163
- master_server=self.config.pdns_master, port=self.config.pdns_api_port,
164
- key=self.config.pdns_api_key, use_https=self.config.pdns_api_https,
182
+ appname=self.appname,
183
+ verbose=self.verbose,
184
+ base_dir=self.base_dir,
185
+ master_server=self.config.pdns_master,
186
+ port=self.config.pdns_api_port,
187
+ key=self.config.pdns_api_key,
188
+ use_https=self.config.pdns_api_https,
165
189
  path_prefix=self.config.pdns_api_prefix,
166
- simulate=self.simulate, force=self.force, initialized=True,
190
+ simulate=self.simulate,
191
+ force=self.force,
192
+ initialized=True,
167
193
  )
168
194
 
169
195
  self.pdns.initialized = True
@@ -174,69 +200,102 @@ class PdnsBulkRmApp(BaseApplication):
174
200
  """Public available method to initiate the argument parser."""
175
201
  super(PdnsBulkRmApp, self).init_arg_parser()
176
202
 
177
- default_cfg_file = self.base_dir.joinpath('etc').joinpath(self.appname + '.ini')
203
+ default_cfg_file = self.base_dir.joinpath("etc").joinpath(self.appname + ".ini")
178
204
 
179
205
  self.arg_parser.add_argument(
180
- '-c', '--config', '--config-file', dest='cfg_file', metavar=_('FILE'),
206
+ "-c",
207
+ "--config",
208
+ "--config-file",
209
+ dest="cfg_file",
210
+ metavar=_("FILE"),
181
211
  action=CfgFileOptionAction,
182
- help=_('Configuration file (default: {!r})').format(default_cfg_file)
212
+ help=_("Configuration file (default: {!r})").format(default_cfg_file),
183
213
  )
184
214
 
185
- pdns_group = self.arg_parser.add_argument_group(_('PowerDNS options'))
215
+ pdns_group = self.arg_parser.add_argument_group(_("PowerDNS options"))
186
216
 
187
217
  pdns_group.add_argument(
188
- '-H', '--host', dest='host', metavar=_('HOST'),
218
+ "-H",
219
+ "--host",
220
+ dest="host",
221
+ metavar=_("HOST"),
189
222
  help=_(
190
- 'Address or hostname of the PowerDNS server providing '
191
- 'the API (Default: {!r}).').format(PdnsBulkRmCfg.default_pdns_master)
223
+ "Address or hostname of the PowerDNS server providing " "the API (Default: {!r})."
224
+ ).format(PdnsBulkRmCfg.default_pdns_master),
192
225
  )
193
226
 
194
227
  pdns_group.add_argument(
195
- '-P', '--port', dest='port', type=int, metavar=_('PORT'),
196
- help=_('Port on PowerDNS server for API on (Default: {}).').format(DEFAULT_PORT))
228
+ "-P",
229
+ "--port",
230
+ dest="port",
231
+ type=int,
232
+ metavar=_("PORT"),
233
+ help=_("Port on PowerDNS server for API on (Default: {}).").format(DEFAULT_PORT),
234
+ )
197
235
 
198
236
  pdns_group.add_argument(
199
- '-K', '--key', '--api-key', metavar='KEY', dest='api_key',
200
- help=_('The API key for accessing the PowerDNS API.')
237
+ "-K",
238
+ "--key",
239
+ "--api-key",
240
+ metavar="KEY",
241
+ dest="api_key",
242
+ help=_("The API key for accessing the PowerDNS API."),
201
243
  )
202
244
 
203
245
  pdns_group.add_argument(
204
- '--https', action='store_true', dest='https',
205
- help=_('Use HTTPS to access the PowerDNS API (Default: {}).').format(
206
- PdnsBulkRmCfg.default_pdns_api_https),
246
+ "--https",
247
+ action="store_true",
248
+ dest="https",
249
+ help=_("Use HTTPS to access the PowerDNS API (Default: {}).").format(
250
+ PdnsBulkRmCfg.default_pdns_api_https
251
+ ),
207
252
  )
208
253
 
209
254
  pdns_group.add_argument(
210
- '--prefix', dest='api_path_prefix',
255
+ "--prefix",
256
+ dest="api_path_prefix",
211
257
  help=_(
212
- 'The global prefix for all paths for accessing the PowerDNS API '
213
- '(Default: {!r}).').format(DEFAULT_API_PREFIX)
258
+ "The global prefix for all paths for accessing the PowerDNS API "
259
+ "(Default: {!r})."
260
+ ).format(DEFAULT_API_PREFIX),
214
261
  )
215
262
 
216
263
  # Source of the addresses - file or cmdline arguments
217
264
  # source_group = self.arg_parser.add_mutually_exclusive_group()
218
265
 
219
266
  self.arg_parser.add_argument(
220
- '-N', '--no-reverse', action='store_true', dest='no_reverse',
267
+ "-N",
268
+ "--no-reverse",
269
+ action="store_true",
270
+ dest="no_reverse",
221
271
  help=_(
222
272
  "Don't remove reverse DNS entries (PTR records) to the given addresses. "
223
- '(Default: False - reverse entries will be removed).')
273
+ "(Default: False - reverse entries will be removed)."
274
+ ),
224
275
  )
225
276
 
226
277
  self.arg_parser.add_argument(
227
- '-F', '--file', metavar=_('FILE'), dest='addr_file', type=pathlib.Path,
278
+ "-F",
279
+ "--file",
280
+ metavar=_("FILE"),
281
+ dest="addr_file",
282
+ type=pathlib.Path,
228
283
  help=_(
229
- 'File containing the addresses to remove. The addresses must be '
230
- 'whitespace separeted, lines may be commented out by prepending them '
284
+ "File containing the addresses to remove. The addresses must be "
285
+ "whitespace separeted, lines may be commented out by prepending them "
231
286
  "with a hash sign '#'. This option is mutually exclusive with "
232
- 'giving the addresses as command line arguments.')
287
+ "giving the addresses as command line arguments."
288
+ ),
233
289
  )
234
290
 
235
291
  self.arg_parser.add_argument(
236
- 'addresses', metavar=_('ADDRESS'), type=str, nargs='*',
292
+ "addresses",
293
+ metavar=_("ADDRESS"),
294
+ type=str,
295
+ nargs="*",
237
296
  help=_(
238
- 'Addresses to remove. This option is mutually exclusive with '
239
- 'the {!r} option.').format('-F/--file'),
297
+ "Addresses to remove. This option is mutually exclusive with " "the {!r} option."
298
+ ).format("-F/--file"),
240
299
  )
241
300
 
242
301
  # -------------------------------------------------------------------------
@@ -250,8 +309,9 @@ class PdnsBulkRmApp(BaseApplication):
250
309
  """Execute some actions after parsing the command line parameters."""
251
310
  if self.args.addr_file and self.args.addresses:
252
311
  msg = _(
253
- 'The option {!r} is mutually exclusive with giving the addresses '
254
- 'as command line arguments.').format('-F/--file')
312
+ "The option {!r} is mutually exclusive with giving the addresses "
313
+ "as command line arguments."
314
+ ).format("-F/--file")
255
315
  LOG.error(msg)
256
316
  self.arg_parser.print_usage(sys.stderr)
257
317
  self.exit(1)
@@ -259,15 +319,15 @@ class PdnsBulkRmApp(BaseApplication):
259
319
  if self.args.addr_file:
260
320
  afile = self.args.addr_file
261
321
  if not afile.exists():
262
- msg = _('File {!r} does not exists.').format(str(afile))
322
+ msg = _("File {!r} does not exists.").format(str(afile))
263
323
  LOG.error(msg)
264
324
  self.exit(1)
265
325
  if not afile.is_file():
266
- msg = _('File {!r} is not a regular file.').format(str(afile))
326
+ msg = _("File {!r} is not a regular file.").format(str(afile))
267
327
  LOG.error(msg)
268
328
  self.exit(1)
269
329
  if not os.access(str(afile), os.R_OK):
270
- msg = _('No read access to file {!r}.').format(str(afile))
330
+ msg = _("No read access to file {!r}.").format(str(afile))
271
331
  LOG.error(msg)
272
332
  self.exit(1)
273
333
  self.address_file = afile
@@ -289,7 +349,7 @@ class PdnsBulkRmApp(BaseApplication):
289
349
  if self.args.addresses:
290
350
  for address in self.args.addresses:
291
351
  addr = address.strip().lower()
292
- if addr != '' and addr not in self.addresses:
352
+ if addr != "" and addr not in self.addresses:
293
353
  self.addresses.append(addr)
294
354
 
295
355
  # -------------------------------------------------------------------------
@@ -297,26 +357,26 @@ class PdnsBulkRmApp(BaseApplication):
297
357
  """Read the file containing all addresses to remove."""
298
358
  content = self.read_file(self.address_file)
299
359
  if self.verbose > 2:
300
- LOG.debug(_('Content of {!r}:').format(str(self.address_file)) + '\n' + content)
360
+ LOG.debug(_("Content of {!r}:").format(str(self.address_file)) + "\n" + content)
301
361
 
302
- re_comment = re.compile(r'\s*#.*')
303
- re_whitespace = re.compile(r'\s+')
362
+ re_comment = re.compile(r"\s*#.*")
363
+ re_whitespace = re.compile(r"\s+")
304
364
 
305
365
  addresses = []
306
366
  for line in content.splitlines():
307
- line_stripped = re_comment.sub('', line).strip()
308
- if line_stripped == '':
367
+ line_stripped = re_comment.sub("", line).strip()
368
+ if line_stripped == "":
309
369
  continue
310
370
  for token in re_whitespace.split(line_stripped):
311
371
  addr = token.strip().lower()
312
- if addr != '' and addr not in addresses:
372
+ if addr != "" and addr not in addresses:
313
373
  addresses.append(addr)
314
374
 
315
375
  if addresses:
316
376
  self.addresses = addresses
317
377
 
318
378
  if not self.addresses:
319
- LOG.error(_('No addresses to remove found in {!r}.').format(str(self.address_file)))
379
+ LOG.error(_("No addresses to remove found in {!r}.").format(str(self.address_file)))
320
380
  self.exit(1)
321
381
 
322
382
  # -------------------------------------------------------------------------
@@ -329,8 +389,7 @@ class PdnsBulkRmApp(BaseApplication):
329
389
  def _run(self):
330
390
 
331
391
  print()
332
- LOG.debug('Starting {a!r}, version {v!r} ...'.format(
333
- a=self.appname, v=self.version))
392
+ LOG.debug("Starting {a!r}, version {v!r} ...".format(a=self.appname, v=self.version))
334
393
 
335
394
  ret = 0
336
395
  try:
@@ -354,19 +413,20 @@ class PdnsBulkRmApp(BaseApplication):
354
413
  """Display the informotion to t screen about simulation mode."""
355
414
  if not self.simulate:
356
415
  return
357
- print(self.colored(_('Simulation mode - nothing will be removed in real.'), 'YELLOW'))
416
+ print(self.colored(_("Simulation mode - nothing will be removed in real."), "YELLOW"))
358
417
  print()
359
418
 
360
419
  # -------------------------------------------------------------------------
361
420
  def do_remove(self):
362
421
  """Remove finally all addresses in DNS."""
363
422
  for zone_name in sorted(
364
- self.records2remove.keys(), key=lambda x: cmp_to_key(compare_fqdn)(x)):
423
+ self.records2remove.keys(), key=lambda x: cmp_to_key(compare_fqdn)(x)
424
+ ):
365
425
  print()
366
426
  zone = self.pdns.zones[zone_name]
367
427
  rrsets_rm = []
368
428
  for rrset in self.records2remove[zone_name]:
369
- zone.add_rrset_for_remove(rrset['fqdn'], rrset['type'], rrsets_rm)
429
+ zone.add_rrset_for_remove(rrset["fqdn"], rrset["type"], rrsets_rm)
370
430
  zone.del_rrsets(rrsets_rm)
371
431
 
372
432
  print()
@@ -375,34 +435,34 @@ class PdnsBulkRmApp(BaseApplication):
375
435
  def _canon_addresses(self, addresses):
376
436
 
377
437
  if self.verbose > 1:
378
- LOG.debug(_('Canonizing all given addresses.'))
438
+ LOG.debug(_("Canonizing all given addresses."))
379
439
  all_fqdns = []
380
440
 
381
441
  for addr in addresses:
382
442
 
383
443
  fqdn = self.pdns.name2fqdn(addr)
384
444
  if not fqdn:
385
- LOG.warning(_('Address {!r} could not interpreted as a FQDN.').format(addr))
445
+ LOG.warning(_("Address {!r} could not interpreted as a FQDN.").format(addr))
386
446
  continue
387
447
  if fqdn not in all_fqdns:
388
448
  all_fqdns.append(fqdn)
389
449
 
390
450
  if self.verbose > 2:
391
- LOG.debug(_('Canonized addresses:') + '\n' + pp(all_fqdns))
451
+ LOG.debug(_("Canonized addresses:") + "\n" + pp(all_fqdns))
392
452
  return all_fqdns
393
453
 
394
454
  # -------------------------------------------------------------------------
395
455
  def _get_zones_of_addresses(self, fqdns):
396
456
 
397
457
  if self.verbose > 1:
398
- LOG.debug(_('Retrieve zones for canonized addresses.'))
458
+ LOG.debug(_("Retrieve zones for canonized addresses."))
399
459
  zones_of_records = {}
400
460
 
401
461
  for fqdn in fqdns:
402
462
 
403
463
  zones = self.pdns.get_all_zones_for_item(fqdn)
404
464
  if not zones:
405
- LOG.warning(_('Did not found an appropriate zone for address {!r}.').format(fqdn))
465
+ LOG.warning(_("Did not found an appropriate zone for address {!r}.").format(fqdn))
406
466
  continue
407
467
 
408
468
  for zone_name in zones:
@@ -411,14 +471,14 @@ class PdnsBulkRmApp(BaseApplication):
411
471
  zones_of_records[zone_name][fqdn] = {}
412
472
 
413
473
  if self.verbose > 2:
414
- LOG.debug(_('Zones of addresses:') + '\n' + pp(zones_of_records))
474
+ LOG.debug(_("Zones of addresses:") + "\n" + pp(zones_of_records))
415
475
  return zones_of_records
416
476
 
417
477
  # -------------------------------------------------------------------------
418
478
  def _verify_fqdns_in_pdns_zones(self, zone_name, zones_of_records, fqdns_found=None):
419
479
 
420
480
  if self.verbose > 1:
421
- LOG.debug(_('Verifying FQDNs for zone {!r}.').format(zone_name))
481
+ LOG.debug(_("Verifying FQDNs for zone {!r}.").format(zone_name))
422
482
 
423
483
  if fqdns_found is None:
424
484
  fqdns_found = []
@@ -426,8 +486,11 @@ class PdnsBulkRmApp(BaseApplication):
426
486
  zone = self.pdns.zones[zone_name]
427
487
  zone.update()
428
488
  if self.verbose > 1:
429
- LOG.debug(_('Found {c} resource record sets (RRSET) for zone {z!r}.').format(
430
- c=len(zone.rrsets), z=zone_name))
489
+ LOG.debug(
490
+ _("Found {c} resource record sets (RRSET) for zone {z!r}.").format(
491
+ c=len(zone.rrsets), z=zone_name
492
+ )
493
+ )
431
494
 
432
495
  for fqdn in zones_of_records[zone_name]:
433
496
  fqdns_in_zone_found = self._verify_fqdn_in_pdns_zone(zone_name, fqdn)
@@ -442,13 +505,16 @@ class PdnsBulkRmApp(BaseApplication):
442
505
  zone = self.pdns.zones[zone_name]
443
506
  fqdns_in_zone_found = []
444
507
 
445
- fqdn_puny = to_str(fqdn.encode('idna'))
508
+ fqdn_puny = to_str(fqdn.encode("idna"))
446
509
  if self.verbose > 1:
447
510
  if fqdn != fqdn_puny:
448
- LOG.debug(_('Searching {f!r} ({p!r}) in zone {z!r} ...').format(
449
- f=fqdn, p=fqdn_puny, z=zone_name))
511
+ LOG.debug(
512
+ _("Searching {f!r} ({p!r}) in zone {z!r} ...").format(
513
+ f=fqdn, p=fqdn_puny, z=zone_name
514
+ )
515
+ )
450
516
  else:
451
- LOG.debug(_('Searching {f!r} in zone {z!r} ...').format(f=fqdn, z=zone_name))
517
+ LOG.debug(_("Searching {f!r} in zone {z!r} ...").format(f=fqdn, z=zone_name))
452
518
 
453
519
  for rrset in zone.rrsets:
454
520
 
@@ -458,33 +524,35 @@ class PdnsBulkRmApp(BaseApplication):
458
524
  if rrset.name != fqdn_puny:
459
525
  continue
460
526
 
461
- rrset2remove = {'fqdn': fqdn_puny, 'type': rrset.type.upper(), 'records': []}
527
+ rrset2remove = {"fqdn": fqdn_puny, "type": rrset.type.upper(), "records": []}
462
528
  found = False
463
529
  if zone.reverse_zone:
464
- if rrset.type.upper() == 'PTR':
530
+ if rrset.type.upper() == "PTR":
465
531
  found = True
466
532
  else:
467
- if rrset.type.upper() in ('A', 'AAAA', 'CNAME'):
533
+ if rrset.type.upper() in ("A", "AAAA", "CNAME"):
468
534
  found = True
469
535
  if not found:
470
536
  continue
471
537
 
472
538
  for record in rrset.records:
473
- if zone.reverse_zone and rrset.type.upper() == 'PTR':
539
+ if zone.reverse_zone and rrset.type.upper() == "PTR":
474
540
  if self.expected_ptr is not None and fqdn_puny in self.expected_ptr:
475
541
  ptr = self.pdns.decanon_name(fqdn_puny)
476
542
  exp = self.pdns.decanon_name(self.expected_ptr[fqdn_puny])
477
543
  addr = self.pdns.decanon_name(record.content)
478
544
  if self.verbose > 1:
479
- LOG.debug(_('Expexted PTR: {p!r} => {a!r}.').format(p=ptr, a=exp))
545
+ LOG.debug(_("Expexted PTR: {p!r} => {a!r}.").format(p=ptr, a=exp))
480
546
  if record.content != self.expected_ptr[fqdn_puny]:
481
- LOG.warning(_(
482
- 'PTR {p!r} does not pointing to expected {e!r}, '
483
- 'but to {c!r} instead, ignoring for deletion.').format(
484
- p=ptr, e=exp, c=addr))
547
+ LOG.warning(
548
+ _(
549
+ "PTR {p!r} does not pointing to expected {e!r}, "
550
+ "but to {c!r} instead, ignoring for deletion."
551
+ ).format(p=ptr, e=exp, c=addr)
552
+ )
485
553
  continue
486
- record2remove = {'content': record.content, 'disabled': record.disabled}
487
- rrset2remove['records'].append(record2remove)
554
+ record2remove = {"content": record.content, "disabled": record.disabled}
555
+ rrset2remove["records"].append(record2remove)
488
556
  if zone_name not in self.records2remove:
489
557
  self.records2remove[zone_name] = []
490
558
  self.records2remove[zone_name].append(rrset2remove)
@@ -496,7 +564,7 @@ class PdnsBulkRmApp(BaseApplication):
496
564
  # -------------------------------------------------------------------------
497
565
  def verify_addresses(self, addresses):
498
566
  """Verify all given DNS addresses."""
499
- LOG.debug(_('Verifying all given DNS addresses.'))
567
+ LOG.debug(_("Verifying all given DNS addresses."))
500
568
 
501
569
  fqdns_found = []
502
570
 
@@ -504,35 +572,36 @@ class PdnsBulkRmApp(BaseApplication):
504
572
  zones_of_records = self._get_zones_of_addresses(all_fqdns)
505
573
 
506
574
  if not zones_of_records:
507
- msg = _('Did not found any addresses with an appropriate zone in PowerDNS.')
575
+ msg = _("Did not found any addresses with an appropriate zone in PowerDNS.")
508
576
  LOG.error(msg)
509
577
  return 1
510
578
 
511
579
  if self.verbose > 1:
512
- LOG.debug(_('Found zones for addresses:') + '\n' + pp(zones_of_records))
580
+ LOG.debug(_("Found zones for addresses:") + "\n" + pp(zones_of_records))
513
581
 
514
582
  for zone_name in zones_of_records:
515
583
  fqdns_found = self._verify_fqdns_in_pdns_zones(
516
- zone_name, zones_of_records, fqdns_found)
584
+ zone_name, zones_of_records, fqdns_found
585
+ )
517
586
  if self.verbose > 2:
518
- LOG.debug(_('The following FQDNs were found:') + '\n' + pp(fqdns_found))
587
+ LOG.debug(_("The following FQDNs were found:") + "\n" + pp(fqdns_found))
519
588
 
520
589
  fqdns_not_found = []
521
590
  for fqdn in all_fqdns:
522
591
  if fqdn not in fqdns_found:
523
592
  fqdns_not_found.append(fqdn)
524
593
  if fqdns_not_found:
525
- msg = _('The following addresses (FQDNs) are not found:')
594
+ msg = _("The following addresses (FQDNs) are not found:")
526
595
  for fqdn in fqdns_not_found:
527
- msg += '\n * {!r}'.format(fqdn)
596
+ msg += "\n * {!r}".format(fqdn)
528
597
  LOG.warning(msg)
529
598
 
530
599
  if not self.records2remove:
531
600
  return 1
532
601
 
533
602
  if self.verbose > 2:
534
- msg = _('Found resource record sets to remove:')
535
- msg += '\n' + pp(self.records2remove)
603
+ msg = _("Found resource record sets to remove:")
604
+ msg += "\n" + pp(self.records2remove)
536
605
  LOG.debug(msg)
537
606
 
538
607
  return 0
@@ -540,7 +609,7 @@ class PdnsBulkRmApp(BaseApplication):
540
609
  # -------------------------------------------------------------------------
541
610
  def get_reverse_records(self):
542
611
  """Evaluate reverse PTR records of A and AAAA records."""
543
- LOG.debug(_('Evaluating reverse PTR records of A and AAAA records.'))
612
+ LOG.debug(_("Evaluating reverse PTR records of A and AAAA records."))
544
613
 
545
614
  addresses = []
546
615
  self.expected_ptr = {}
@@ -549,12 +618,12 @@ class PdnsBulkRmApp(BaseApplication):
549
618
 
550
619
  for rrset in self.records2remove[zone_name]:
551
620
 
552
- if rrset['type'] not in ('A', 'AAAA'):
621
+ if rrset["type"] not in ("A", "AAAA"):
553
622
  continue
554
623
 
555
- for record in rrset['records']:
556
- addr_str = record['content']
557
- LOG.debug(_('Try to get reverse address of {!r} ...').format(addr_str))
624
+ for record in rrset["records"]:
625
+ addr_str = record["content"]
626
+ LOG.debug(_("Try to get reverse address of {!r} ...").format(addr_str))
558
627
  addr = None
559
628
  fqdn = None
560
629
 
@@ -562,100 +631,121 @@ class PdnsBulkRmApp(BaseApplication):
562
631
  addr = ipaddress.ip_address(addr_str)
563
632
  fqdn = self.pdns.canon_name(reverse_pointer(addr))
564
633
  except ValueError:
565
- msg = _('IP address {!r} seems not to be a valid IP address.').format(
566
- addr_str)
634
+ msg = _("IP address {!r} seems not to be a valid IP address.").format(
635
+ addr_str
636
+ )
567
637
  LOG.error(msg)
568
638
  continue
569
- LOG.debug(_('Found reverse address {!r}.').format(fqdn))
639
+ LOG.debug(_("Found reverse address {!r}.").format(fqdn))
570
640
  if fqdn not in addresses:
571
641
  addresses.append(fqdn)
572
- self.expected_ptr[fqdn] = rrset['fqdn']
642
+ self.expected_ptr[fqdn] = rrset["fqdn"]
573
643
 
574
644
  if not addresses:
575
645
  return 0
576
646
 
577
647
  if self.verbose > 1:
578
- LOG.debug(_('Expected PTR records:') + '\n' + pp(self.expected_ptr))
648
+ LOG.debug(_("Expected PTR records:") + "\n" + pp(self.expected_ptr))
579
649
 
580
650
  return self.verify_addresses(addresses)
581
651
 
582
652
  # -------------------------------------------------------------------------
583
653
  def show_records(self):
584
654
  """Display all DNS records to remove on screen."""
585
- title = _('All DNS records to remove')
655
+ title = _("All DNS records to remove")
586
656
  print()
587
657
  print(title)
588
- print('=' * len(title))
658
+ print("=" * len(title))
589
659
  print()
590
660
 
591
- disabled = _('Disabled.')
661
+ disabled = _("Disabled.")
592
662
  headers = {
593
- 'fqdn': _('Name'),
594
- 'z': _('Zone'),
595
- 'type': _('Type'),
596
- 'rec': _('Record'),
597
- 'dis': '',
663
+ "fqdn": _("Name"),
664
+ "z": _("Zone"),
665
+ "type": _("Type"),
666
+ "rec": _("Record"),
667
+ "dis": "",
598
668
  }
599
669
  lengths = {
600
- 'fqdn': len(headers['fqdn']),
601
- 'z': len(headers['z']),
602
- 'type': len(headers['type']),
603
- 'rec': len(headers['rec']),
604
- 'dis': len(disabled),
670
+ "fqdn": len(headers["fqdn"]),
671
+ "z": len(headers["z"]),
672
+ "type": len(headers["type"]),
673
+ "rec": len(headers["rec"]),
674
+ "dis": len(disabled),
605
675
  }
606
676
  count = 0
607
- if lengths['type'] < 8:
608
- lengths['type'] = 8
677
+ if lengths["type"] < 8:
678
+ lengths["type"] = 8
609
679
 
610
680
  for zone_name in self.records2remove.keys():
611
- if len(zone_name) > lengths['z']:
612
- lengths['z'] = len(zone_name)
681
+ if len(zone_name) > lengths["z"]:
682
+ lengths["z"] = len(zone_name)
613
683
  for rrset in self.records2remove[zone_name]:
614
- fqdn = self.pdns.decanon_name(rrset['fqdn'])
615
- rr_type = rrset['type']
616
- if len(fqdn) > lengths['fqdn']:
617
- lengths['fqdn'] = len(fqdn)
618
- if len(rr_type) > lengths['type']:
619
- lengths['type'] = len(rr_type)
620
- for record in rrset['records']:
684
+ fqdn = self.pdns.decanon_name(rrset["fqdn"])
685
+ rr_type = rrset["type"]
686
+ if len(fqdn) > lengths["fqdn"]:
687
+ lengths["fqdn"] = len(fqdn)
688
+ if len(rr_type) > lengths["type"]:
689
+ lengths["type"] = len(rr_type)
690
+ for record in rrset["records"]:
621
691
  count += 1
622
- content = self.pdns.decanon_name(record['content'])
623
- if len(content) > lengths['rec']:
624
- lengths['rec'] = len(content)
692
+ content = self.pdns.decanon_name(record["content"])
693
+ if len(content) > lengths["rec"]:
694
+ lengths["rec"] = len(content)
625
695
 
626
- tpl = '{{fqdn:<{}}} '.format(lengths['fqdn'])
627
- tpl += '{{z:<{}}} '.format(lengths['z'])
628
- tpl += '{{type:<{}}} '.format(lengths['type'])
629
- tpl += '{{rec:<{}}} '.format(lengths['rec'])
630
- tpl += '{{dis:<{}}}'.format(lengths['dis'])
696
+ tpl = "{{fqdn:<{}}} ".format(lengths["fqdn"])
697
+ tpl += "{{z:<{}}} ".format(lengths["z"])
698
+ tpl += "{{type:<{}}} ".format(lengths["type"])
699
+ tpl += "{{rec:<{}}} ".format(lengths["rec"])
700
+ tpl += "{{dis:<{}}}".format(lengths["dis"])
631
701
 
632
702
  header = tpl.format(**headers)
633
703
  print(header)
634
- print('-' * len(header))
704
+ print("-" * len(header))
635
705
 
636
706
  for zone_name in sorted(
637
- self.records2remove.keys(), key=lambda x: cmp_to_key(compare_fqdn)(x)):
707
+ self.records2remove.keys(), key=lambda x: cmp_to_key(compare_fqdn)(x)
708
+ ):
638
709
  for rrset in self.records2remove[zone_name]:
639
- for record in rrset['records']:
640
- content = self.pdns.decanon_name(record['content'])
710
+ for record in rrset["records"]:
711
+ content = self.pdns.decanon_name(record["content"])
641
712
  out = {}
642
- out['z'] = self.pdns.decanon_name(zone_name)
643
- out['fqdn'] = self.pdns.decanon_name(rrset['fqdn'])
644
- out['type'] = rrset['type']
645
- out['rec'] = content
646
- if record['disabled']:
647
- out['dis'] = disabled
713
+ out["z"] = self.pdns.decanon_name(zone_name)
714
+ out["fqdn"] = self.pdns.decanon_name(rrset["fqdn"])
715
+ out["type"] = rrset["type"]
716
+ out["rec"] = content
717
+ if record["disabled"]:
718
+ out["dis"] = disabled
648
719
  else:
649
- out['dis'] = ''
720
+ out["dis"] = ""
650
721
  print(tpl.format(**out))
651
722
  print()
652
- msg = ngettext('Total one DNS record to remove.', 'Total {} DNS records to remove.', count)
723
+ msg = ngettext("Total one DNS record to remove.", "Total {} DNS records to remove.", count)
653
724
  print(msg.format(count))
654
725
  print()
655
726
 
656
727
 
657
728
  # =============================================================================
658
- if __name__ == '__main__':
729
+ def main():
730
+ """Entrypoint for pdns-bulk-remove."""
731
+ my_path = pathlib.Path(__file__)
732
+ appname = my_path.name
733
+
734
+ locale.setlocale(locale.LC_ALL, "")
735
+
736
+ app = PdnsBulkRmApp(appname=appname)
737
+ app.initialized = True
738
+
739
+ if app.verbose > 2:
740
+ print(_("{c}-Object:\n{a}").format(c=app.__class__.__name__, a=app), file=sys.stderr)
741
+
742
+ app()
743
+
744
+ sys.exit(0)
745
+
746
+
747
+ # =============================================================================
748
+ if __name__ == "__main__":
659
749
 
660
750
  pass
661
751