File: //usr/local/aegis/PythonLoader/third_party/apacheconfig/apacheconfigtool.py
#
# This file is part of apacheconfig software.
#
# Copyright (c) 2018-2019, Ilya Etingof <etingof@gmail.com>
# License: https://github.com/etingof/apacheconfig/LICENSE.rst
#
import argparse
import json
import os
import sys
from apacheconfig import ApacheConfigError, __version__, make_loader
def main():
parser = argparse.ArgumentParser(
description='Dump Apache config files into JSON')
parser.add_argument(
'-v', '--version', action='version', version='%(prog)s ' + __version__
)
parser.add_argument(
'--json-input', action='store_true',
help='Expect JSON file(s) on input, produce Apache configuration'
)
parser.add_argument(
'file', nargs='+',
help='Path to the configuration file to dump'
)
options = parser.add_argument_group('parsing options')
options.add_argument(
'--allowmultioptions', action='store_false',
help='Collect multiple identical options into a list'
)
options.add_argument(
'--forcearray', action='store_true',
help=('Force a single config line to get parsed into a list by '
'turning on this option and by surrounding the value of the '
'config entry by []')
)
options.add_argument(
'--lowercasenames', action='store_true',
help='All options found in the config will be converted to lowercase'
)
options.add_argument(
'--nostripvalues', action='store_true',
help='All values found in the config will not be right-stripped'
)
options.add_argument(
'--useapacheinclude', action='store_true',
help='Consider "include ..." as valid include statement'
)
options.add_argument(
'--includeagain', action='store_true',
help='Allow including sub-configfiles multiple times'
)
options.add_argument(
'--includerelative', action='store_true',
help=('Open included config files from within the location of the '
'configfile instead from within the location of the script')
)
options.add_argument(
'--includedirectories', action='store_true',
help=('Include statement may point to a directory, in which case '
'all files inside the directory will be loaded in ASCII order')
)
options.add_argument(
'--includeglob', action='store_true',
help=('Include statement may point to a glob pattern, in which case '
'all files matching the pattern will be loaded in ASCII order')
)
options.add_argument(
'--mergeduplicateblocks', action='store_true',
help=('Duplicate blocks (blocks and named blocks), will be merged '
'into a single one')
)
options.add_argument(
'--mergeduplicateoptions', action='store_true',
help=('If the same option occurs more than once, the last one will '
'be used in the resulting config dictionary')
)
options.add_argument(
'--namedblocks', action='store_false',
help='Do not split tags by the first whitespace and turn the trailing '
'part into a nested block')
options.add_argument(
'--autotrue', action='store_true',
help='Turn various forms of binary values in config into "1" and "0"'
)
options.add_argument(
'--interpolatevars', action='store_true',
help='Enable variable interpolation'
)
options.add_argument(
'--interpolateenv', action='store_true',
help='Enable process environment variable interpolation'
)
options.add_argument(
'--allowsinglequoteinterpolation', action='store_true',
help='Perform variable interpolation even when being in single quotes'
)
options.add_argument(
'--strictvars', action='store_false',
help=('Do not fail on an undefined variable when performing '
'interpolation')
)
options.add_argument(
'--noescape', action='store_true',
help=('Preserve special escape characters left outs in the '
'configuration values')
)
options.add_argument(
'--preservewhitespace', action='store_true',
help=('Preserve insignificant whitespaces, dump them them as is '
'on code generation')
)
options.add_argument(
'--disableemptyelementtags', action='store_true',
help=('Disables the parsing of empty element tags like <block/>')
)
options.add_argument(
'--ccomments', action='store_false',
help='Do not parse C-style comments'
)
options.add_argument(
'--multilinehashcomments', action='store_true',
help='Enable multi-line hash comments.'
)
options.add_argument(
'--configpath', action='append', default=[],
help=('Search path for the configuration files being included. Can '
'repeat.')
)
options.add_argument(
'--flagbits', metavar='<JSON>', type=str,
help=('Named bits for an option in form of a JSON object of the '
'following structure {"OPTION": {"NAME": "VALUE"}}')
)
options.add_argument(
'--defaultconfig', metavar='<JSON>', type=str,
help='Default values for parsed configuration in form of a JSON object'
)
args = parser.parse_args()
options = dict([(option, getattr(args, option)) for option in dir(args)
if not option.startswith('_') and
getattr(args, option) is not None])
options['programpath'] = os.path.dirname(sys.argv[0])
if 'flagbits' in options:
try:
options['flagbits'] = json.loads(options['flagbits'])
except Exception as ex:
sys.stderr.write('Malformed flagbits %s: %s\n' %
(options['flagbits'], ex))
return 1
if 'defaultconfig' in options:
try:
options['defaultconfig'] = json.loads(options['defaultconfig'])
except Exception as ex:
sys.stderr.write('Malformed defaultconfig %s: %s\n' %
(options['defaultconfig'], ex))
return 1
if args.json_input:
with make_loader(**options) as loader:
for json_file in args.file:
try:
with open(json_file) as f:
sys.stdout.write(loader.dumps(json.load(f)))
except Exception as ex:
sys.stderr.write(('Failed to dump JSON document %s into '
'Apache config: %s\n') % (json_file, ex))
return 1
else:
for config_file in args.file:
options['configroot'] = os.path.dirname(config_file)
with make_loader(**options) as loader:
try:
config = loader.load(config_file)
except ApacheConfigError as ex:
sys.stderr.write('Failed to parse Apache config %s: %s\n'
% (config_file, ex))
return 1
sys.stdout.write(json.dumps(config, indent=2) + '\n')
if __name__ == '__main__':
sys.exit(main())