dns_sprockets — dns_sprockets 1.0 documentation

# Source code for dns_sprockets

    #!/usr/bin/env python2.7
    '''
    dns_sprockets - A command-line tool to validate DNS zones.
    ----------------------------------------------------------
    .. Copyright (c) 2015 Neustar, Inc. All rights reserved.
    .. See COPYRIGHT.txt for full notice.  See LICENSE.txt for terms and conditions.
    '''

    import os
    import time

    from dns_sprockets_version import VERSION
    import dns_sprockets_lib.utils as utils
    import dns_sprockets_lib.loaders as loaders
    import dns_sprockets_lib.loader_classes as loader_classes
    import dns_sprockets_lib.validators as validators
    import dns_sprockets_lib.validator_classes as validator_classes
    from dns_sprockets_lib.dns_sprockets_impl import DNSSprocketsImpl

    _PRODUCT = 'dns_sprockets'
    _BANNER = '%s (%s) - A DNS Zone validation tool' % (_PRODUCT, VERSION)
    _DEFAULT_ZONE = 'www.ultradns.com'
    _DEFAULT_LOADER = 'xfr'
    _DEFAULT_SOURCE = '127.0.0.1#53'
    _FATAL_RETCODE = 255

    def _run_main(avail_loaders, avail_tests, args):
        '''
        Constructs and runs a DNSSprocketsImpl instance.
        '''
        start_time = time.time()

        # Construct and run a DNSSprocketsImpl instance:
        try:
            (load_time, _, ret_code) = DNSSprocketsImpl(avail_loaders, avail_tests, args).run()
            total_time = time.time() - start_time
            print '# TOTAL ELAPSED TIME: %f SECS  LOAD TIME: %f SECS  TEST TIME: %f SECS' % (
                total_time, load_time, total_time - load_time)
            os._exit(ret_code >= _FATAL_RETCODE and _FATAL_RETCODE - 1 or ret_code)

        except StandardError as err:
            print 'FATAL: {%s} %s' % (err.__class__.__name__, err)
            if args.verbose:
                raise
            os._exit(_FATAL_RETCODE)

    def run():
        '''
        Run the sprocket command-line application.
        '''
        # Print startup banner:
        print '#', _BANNER

        # Determine available loaders and tests:
        avail_loaders = utils.public_modules_in_package(loaders, ['tests'])
        avail_tests = utils.public_modules_in_package(validators, ['tests'])

        # Parse command-line:
        import argparse
        parser = argparse.ArgumentParser(
            epilog='''
    Use @filename to read some/all arguments from a file.\n\n
    Use -d's to define optional, module-specific parameters if desired (e.g. to tell
    'xfr' loader to use a specific source address, use "-d xfr_source=1.2.3.4").
    The optional parameters are listed under each loader and test description in
    DEFINE lines, if available.\n\n
    By default, all tests are run.  Use -i\'s to explicitly specify desired tests,
    or -x\'s to eliminate undesired tests.\n\n
    The list of available loaders is:
    ---------------------------------------------------------------------------\n%s\n\n
    The list of available tests is:
    ---------------------------------------------------------------------------\n%s
                ''' % (loader_classes.get_formatted_descriptions(),
                       validator_classes.get_formatted_descriptions()),
            formatter_class=argparse.RawDescriptionHelpFormatter,
            fromfile_prefix_chars='@')
        parser.add_argument('-z', '--zone', dest='zone',
            default=_DEFAULT_ZONE, metavar='s',
            help='Name of zone to validate [%(default)s]')
        parser.add_argument('-l', '--loader', dest='loader',
            default=_DEFAULT_LOADER, metavar='s', choices=avail_loaders,
            help='Zone loader method to use (one of: %(choices)s) [%(default)s]')
        parser.add_argument('-s', '--source', dest='source',
            default=_DEFAULT_SOURCE, metavar='s',
            help='Loader source to use [%(default)s]')
        parser.add_argument('-i', '--include', dest='include_tests',
            action='append', metavar='s', choices=avail_tests,
            help='Only include this test (can use multiple times)')
        parser.add_argument('-x', '--exclude', dest='exclude_tests',
            action='append', metavar='s', choices=avail_tests,
            help='Exclude this test (can use multiple times)')
        parser.add_argument('-d', '--define', dest='defines',
            action='append', metavar='s',
            help='Define other params (can use multiple times)')
        parser.add_argument('-f', '--force-dnssec-type', dest='force_dnssec_type',
            default='detect', metavar='s',
            choices=['detect', 'unsigned', 'NSEC', 'NSEC3'],
            help='Use DNSSEC type (one of: %(choices)s) [%(default)s]')
        parser.add_argument('-e', '--errors-only', dest='errors_only',
            default=False, action='store_true',
            help='Show validation errors only [%(default)s]')
        parser.add_argument('-v', '--verbose', dest='verbose',
            default=False, action='store_true',
            help='Show detailed processing info [%(default)s]')
        args = parser.parse_args()

        # Fix-up args:
        if args.include_tests is None:
            args.include_tests = []
        if args.exclude_tests is None:
            args.exclude_tests = []
        if args.defines is None:
            args.defines = []
        for sec_param in args.defines:
            (p_name, p_val) = sec_param.split('=')[:2]
            setattr(args, p_name, p_val)

        # Run the app:
        _run_main(avail_loaders, avail_tests, args)

    if __name__ == '__main__':
        run()

    # end of file