Exemplo n.º 1
0
def process(name, config, directory, config_translator=None):
    """
    Configures Nginx based on the input configuration.

    Supports Document Root and Gzip settings.

    :param name: Name of this section of the configuration
    :param config: The configuration dictionary for this section
    :param directory: The directory in which the input files are mounted
    :param config_translator: Optional callable method for preprocessing config items
    :return:
    """
    for required_key in ['configuration_file_name']:
        if required_key not in config:
            raise Exception(
                'Required key %s not present in %s section of internal configuration'
                % (name, required_key))
    logger.info('Configuring %s' % name)

    try:
        custom_values, file_format = custom_files.read_custom_file(
            os.path.join(directory, config['configuration_file_name']))
    except Exception as file_reading_exception:
        logger.error(
            str(file_reading_exception))  # don't log the full stack trace
        logger.info('Not configuring %s (not a critical failure)' % name)
        return  # abort but don't fail

    assert custom_values is not None and isinstance(custom_values, dict)

    if config_translator:
        for key, value in custom_values.iteritems():
            custom_values[key] = config_translator.process(key, value)

    nginx_directory = os.path.join('etc', 'nginx')

    sites_enabled_directory = os.path.join(nginx_directory, 'sites-enabled')

    #
    # Document Root
    #

    document_root_key = 'DOCUMENT_ROOT'
    document_root_default = 'html'

    if document_root_key.lower() in custom_values:

        document_root = custom_values[document_root_key.lower()]

        if os.environ.get(document_root_key, document_root_default) not in [
                document_root, document_root_default
        ]:
            raise Exception(
                'Legacy %s variable is present with a conflicting value' %
                document_root_key)

        document_root_path = os.path.join('var', 'www', document_root)
        if not os.path.exists(document_root_path):
            os.makedirs(document_root_path)

        #
        #  Update the on disk well known location so that other scripts
        #  which need to know the document root can look it up.
        #
        with open(os.path.join('etc', document_root_key), 'w') as file_handle:
            file_handle.write("%s\n" % document_root)

        #
        # Update the nginx configuration
        #

        variable_regex = re.compile('\${?%s}?' % document_root_key)

        root_command_regex = re.compile('root /var/www/.*;')
        new_root_command = 'root /var/www/%s;' % document_root

        for file_path in os.listdir(sites_enabled_directory):
            full_file_path = os.path.join(sites_enabled_directory, file_path)
            if os.path.isfile(full_file_path):
                write_needed = False
                with open(full_file_path, 'r') as file_handle:
                    lines = file_handle.readlines()
                    for index, line in enumerate(lines):
                        lines[index] = variable_regex.sub(
                            document_root, lines[index])
                        lines[index] = root_command_regex.sub(
                            new_root_command, lines[index])
                        write_needed = write_needed or lines[index] != line
                if write_needed:
                    with open(full_file_path, 'w') as file_handle:
                        file_handle.writelines(lines)

        logger.info('%13s = %s' % (document_root_key, document_root))

    #
    # Gzip
    #

    gzip_key = 'gzip'
    if gzip_key in custom_values:

        gzip = False

        if custom_values['gzip'].strip().upper() != 'OFF':
            gzip = True
            gzip_level = custom_values[gzip_key]

        #
        #  Update the nginx configuration
        #

        gzip_command_regex = re.compile('gzip \w*;')
        new_gzip_command = 'gzip %s;' % 'on' if gzip else 'off'

        if gzip:
            gzip_level_command_regex = re.compile('gzip_comp_level \d*;')
            new_gzip_level_command = 'gzip_comp_level %s;' % gzip_level

        full_file_path = os.path.join(nginx_directory, 'conf.d', 'gzip.conf')
        if os.path.isfile(full_file_path):

            write_needed = False
            with open(full_file_path, 'r') as file_handle:

                # Read
                lines = file_handle.readlines()

                # Modify
                for index, line in enumerate(lines):
                    lines[index] = gzip_command_regex.sub(
                        new_gzip_command, lines[index])
                    if gzip:
                        lines[index] = gzip_level_command_regex.sub(
                            new_gzip_level_command, lines[index])
                    write_needed = write_needed or lines[index] != line

            # Write
            if write_needed:
                with open(full_file_path, 'w') as file_handle:
                    file_handle.writelines(lines)

        logger.info('%13s = %s' % (gzip_key.upper(), gzip_level))
Exemplo n.º 2
0
def process(name, config, directory, config_translator=None):
    """
    Configures Nginx based on the input configuration.

    Supports Document Root and Gzip settings.

    :param name: Name of this section of the configuration
    :param config: The configuration dictionary for this section
    :param directory: The directory in which the input files are mounted
    :param config_translator: Optional callable method for preprocessing config items
    :return:
    """
    for required_key in [
        'configuration_file_name'
    ]:
        if required_key not in config:
            raise Exception(
                'Required key %s not present in %s section of internal configuration'
                % (name, required_key)
            )
    logger.info('Configuring %s' % name)

    try:
        custom_values, file_format = custom_files.read_custom_file(
            os.path.join(directory, config['configuration_file_name'])
        )
    except Exception as file_reading_exception:
        logger.error(str(file_reading_exception))  # don't log the full stack trace
        logger.info('Not configuring %s (not a critical failure)' % name)
        return  # abort but don't fail

    assert custom_values is not None and isinstance(custom_values, dict)

    if config_translator:
        for key, value in custom_values.iteritems():
            custom_values[key] = config_translator.process(key, value)

    nginx_directory = os.path.join('etc', 'nginx')

    sites_enabled_directory = os.path.join(nginx_directory, 'sites-enabled')

    #
    # Document Root
    #

    document_root_key = 'DOCUMENT_ROOT'
    document_root_default = 'html'

    if document_root_key.lower() in custom_values:

        document_root = custom_values[document_root_key.lower()]

        if os.environ.get(document_root_key, document_root_default) not in [document_root, document_root_default]:
            raise Exception('Legacy %s variable is present with a conflicting value' % document_root_key)

        document_root_path = os.path.join('var', 'www', document_root)
        if not os.path.exists(document_root_path):
            os.makedirs(document_root_path)

        #
        #  Update the on disk well known location so that other scripts
        #  which need to know the document root can look it up.
        #
        with open(os.path.join('etc', document_root_key), 'w') as file_handle:
            file_handle.write("%s\n" % document_root)

        #
        # Update the nginx configuration
        #

        variable_regex = re.compile('\${?%s}?' % document_root_key)

        root_command_regex = re.compile('root /var/www/.*;')
        new_root_command = 'root /var/www/%s;' % document_root

        for file_path in os.listdir(sites_enabled_directory):
            full_file_path = os.path.join(sites_enabled_directory, file_path)
            if os.path.isfile(full_file_path):
                write_needed = False
                with open(full_file_path, 'r') as file_handle:
                    lines = file_handle.readlines()
                    for index, line in enumerate(lines):
                        lines[index] = variable_regex.sub(document_root, lines[index])
                        lines[index] = root_command_regex.sub(new_root_command, lines[index])
                        write_needed = write_needed or lines[index] != line
                if write_needed:
                    with open(full_file_path, 'w') as file_handle:
                        file_handle.writelines(lines)

        logger.info('%13s = %s' % (document_root_key, document_root))

    #
    # Gzip
    #

    gzip_key = 'gzip'
    if gzip_key in custom_values:

        gzip = False

        if custom_values[gzip_key].strip().upper() != 'OFF':
            gzip = True
            gzip_level = custom_values[gzip_key]
        else:
            gzip_level = '0'

        #
        #  Update the nginx configuration
        #

        gzip_command_regex = re.compile('gzip \w*;')
        new_gzip_command = 'gzip on;' if gzip else 'gzip off;'

        if gzip:
            gzip_level_command_regex = re.compile('gzip_comp_level \d*;')
            new_gzip_level_command = 'gzip_comp_level %s;' % gzip_level

        full_file_path = os.path.join(nginx_directory, 'conf.d', 'gzip.conf')
        if os.path.isfile(full_file_path):

            write_needed = False
            with open(full_file_path, 'r') as file_handle:

                # Read
                lines = file_handle.readlines()

                # Modify
                for index, line in enumerate(lines):
                    lines[index] = gzip_command_regex.sub(new_gzip_command, lines[index])
                    if gzip:
                        lines[index] = gzip_level_command_regex.sub(new_gzip_level_command, lines[index])
                    write_needed = write_needed or lines[index] != line

            # Write
            if write_needed:
                with open(full_file_path, 'w') as file_handle:
                    file_handle.writelines(lines)

        logger.info('%13s = %s' % (gzip_key.upper(), gzip_level))
Exemplo n.º 3
0
def process(name, config, directory):
    """
    Requires the input file (configuration_file_name) in directory to
     be multidimensional representation of overrides for the target file (ini_file_path).

    Input may be any format. Output will always be an ini file.

    :param name: Name of this section of the configuration
    :param config: The configuration dictionary for this section
    :param directory: The directory in which the input files are mounted
    :return:
    """
    for required_key in [
        'ini_file_path',
        'configuration_file_name'
    ]:
        if required_key not in config:
            raise Exception(
                'Required key %s not present in %s section of internal configuration'
                % (name, required_key)
            )
    logger.info('Configuring %s' % name)

    error_occurred_while_reading_an_input_file = False

    try:
        current_values, file_format = custom_files.read_custom_file(
            config['ini_file_path']
        )
    except Exception as file_reading_exception:
        logger.error(str(file_reading_exception))  # don't log the full stack trace
        error_occurred_while_reading_an_input_file = True

    try:
        custom_values, file_format = custom_files.read_custom_file(
            os.path.join(directory, config['configuration_file_name'])
        )
    except Exception as file_reading_exception:
        logger.error(str(file_reading_exception))  # don't log the full stack trace
        error_occurred_while_reading_an_input_file = True

    if error_occurred_while_reading_an_input_file:
        logger.info('Not configuring %s (not a critical failure)' % name)
        return  # abort but don't fail

    assert custom_values is not None and isinstance(current_values, dict)
    assert custom_values is not None and isinstance(custom_values, dict)

    resulting_file = ConfigParser.ConfigParser()

    for section_name in set(current_values.keys() + custom_values.keys()):
        resulting_file.add_section(section_name)

    for section_name in current_values.keys():
        if not isinstance(current_values[section_name], dict):
            logger.error('%s is not a valid section in current values' % section_name)
            continue
        for key, value in current_values[section_name].items():
            resulting_file.set(section_name, key, value)

    display_values = {}
    for section_name in custom_values.keys():
        if not isinstance(custom_values[section_name], dict):
            logger.error('%s is not a valid section in custom values' % section_name)
            continue
        for key, value in custom_values[section_name].items():
            display_values['%s/%s' % (section_name, key)] = value
            resulting_file.set(section_name, key, value)
    length = len(max(display_values.keys(), key=len))
    for key in sorted(display_values.keys()):
        logger.info('%s = %s' % (key.rjust(length, ' '), display_values[key]))

    logger.info('Writing %s' % config['ini_file_path'])
    with open(config['ini_file_path'], 'wb') as file_handle:
        resulting_file.write(file_handle)
Exemplo n.º 4
0
def process(name, config, directory, config_translator):
    """
    Requires the input file (configuration_file_name) in directory to
     be multidimensional representation of overrides for the target file (ini_file_path).

    Input may be any format. Output will always be an ini file.

    :param name: Name of this section of the configuration
    :param config: The configuration dictionary for this section
    :param directory: The directory in which the input files are mounted
    :return:
    """
    for required_key in ['ini_file_path', 'configuration_file_name']:
        if required_key not in config:
            raise Exception(
                'Required key %s not present in %s section of internal configuration'
                % (required_key, name))
    logger.info('Configuring %s' % name)

    error_occurred_while_reading_an_input_file = False

    try:
        current_values, file_format = custom_files.read_custom_file(
            config['ini_file_path'])
    except Exception as file_reading_exception:
        logger.error(
            str(file_reading_exception))  # don't log the full stack trace
        error_occurred_while_reading_an_input_file = True

    try:
        custom_values, file_format = custom_files.read_custom_file(
            os.path.join(directory, config['configuration_file_name']))
    except Exception as file_reading_exception:
        logger.error(
            str(file_reading_exception))  # don't log the full stack trace
        error_occurred_while_reading_an_input_file = True

    if error_occurred_while_reading_an_input_file:
        logger.info('Not configuring %s (not a critical failure)' % name)
        return  # abort but don't fail

    assert custom_values is not None and isinstance(current_values, dict)
    assert custom_values is not None and isinstance(custom_values, dict)

    resulting_file = ConfigParser.ConfigParser(allow_no_value=True)

    for section_name in set(current_values.keys() + custom_values.keys()):
        resulting_file.add_section(section_name)

    for section_name in current_values.keys():
        if not isinstance(current_values[section_name], dict):
            logger.error('%s is not a valid section in current values' %
                         section_name)
            continue
        for key, value in current_values[section_name].items():
            resulting_file.set(section_name, key, value)

    display_values = {}
    for section_name in custom_values.keys():
        if not isinstance(custom_values[section_name], dict):
            logger.error('%s is not a valid section in custom values' %
                         section_name)
            continue
        for key, value in custom_values[section_name].items():
            if config_translator:
                value = config_translator.process(key, value)
            display_values['%s/%s' % (section_name, key)] = value
            resulting_file.set(section_name, key, value)
    length = len(max(display_values.keys(), key=len))
    for key in sorted(display_values.keys()):
        logger.info('%s = %s' % (key.rjust(length, ' '), display_values[key]))

    logger.info('Writing %s' % config['ini_file_path'])
    with open(config['ini_file_path'], 'wb') as file_handle:
        resulting_file.write(file_handle)
Exemplo n.º 5
0
def process(name, config, directory, config_translator=None):
    """
    Configures Apache 2 based on the input configuration.

    Supports Document Root and Gzip settings.

    :param name: Name of this section of the configuration
    :param config: The configuration dictionary for this section
    :param directory: The directory in which the input files are mounted
    :param config_translator: Optional callable method for preprocessing config items
    :return:
    """
    for required_key in [
        'configuration_file_name'
    ]:
        if required_key not in config:
            raise Exception(
                'Required key %s not present in %s section of internal configuration'
                % (name, required_key)
            )
    logger.info('Configuring %s' % name)

    try:
        custom_values, file_format = custom_files.read_custom_file(
            os.path.join(directory, config['configuration_file_name'])
        )
    except Exception as file_reading_exception:
        logger.error(str(file_reading_exception))  # don't log the full stack trace
        logger.info('Not configuring %s (not a critical failure)' % name)
        return  # abort but don't fail

    assert custom_values is not None and isinstance(custom_values, dict)

    if config_translator:
        for key, value in custom_values.iteritems():
            custom_values[key] = config_translator.process(key, value)

    apache2_directory = os.path.join('etc', 'apache2')

    sites_enabled_directory = os.path.join(apache2_directory, 'sites-enabled')
    conf_enabled_directory = os.path.join(apache2_directory, 'conf-enabled')
    mods_enabled_directory = os.path.join(apache2_directory, 'mods-enabled')

    document_root_key = 'DOCUMENT_ROOT'
    document_root_default = 'html'

    if document_root_key.lower() in custom_values:
        document_root = custom_values[document_root_key.lower()]

        document_root_path = os.path.join('var', 'www', document_root)
        if not os.path.exists(document_root_path):
            os.makedirs(document_root_path)

        regex = re.compile('\${?%s}?' % document_root_key)

        if os.environ.get(document_root_key, document_root_default) not in [document_root, document_root_default]:
            raise Exception('Legacy %s variable is present with a conflicting value' % document_root_key)

        #
        #  Update the on disk well known location so that other scripts
        #  which need to know the document root can look it up.
        #
        with open(os.path.join('etc', document_root_key), 'w') as file_handle:
            file_handle.write("%s\n" % document_root)

        #
        # Update the apache configuration
        #
        for target_directory in [sites_enabled_directory, conf_enabled_directory, mods_enabled_directory]:
            for file_path in os.listdir(target_directory):
                full_file_path = os.path.join(target_directory, file_path)
                if os.path.isfile(full_file_path):
                    write_needed = False
                    with open(full_file_path, 'r') as file_handle:
                        lines = file_handle.readlines()
                        for index, line in enumerate(lines):
                            lines[index] = regex.sub(document_root, lines[index])
                            write_needed = write_needed or lines[index] != line
                    if write_needed:
                        with open(full_file_path, 'w') as file_handle:
                            file_handle.writelines(lines)

        logger.info('%14s = %s' % (document_root_key, document_root))

    gzip_key = 'gzip'
    if gzip_key in custom_values:

        gzip = True

        if custom_values['gzip'].strip().upper() != 'OFF':
            gzip_level = custom_values[gzip_key]
        else:
            gzip_level = None
            gzip = False

        #
        #  Update the apache configuration
        #
        for file_path in os.listdir(mods_enabled_directory):
            if file_path not in ['deflate.conf', 'deflate.load']:
                continue
            full_file_path = os.path.join(mods_enabled_directory, file_path)

            if not gzip:
                # Remove the configuration to disable gzip
                os.unlink(full_file_path)

            if gzip and file_path.endswith('.conf'):
                # Add the level directive to the bottom of the configuration
                with open(full_file_path, 'a') as file_handle:
                    file_handle.write(
                        "DeflateCompressionLevel %s\n" % gzip_level
                    )

        if gzip_level:
            logger.info('%14s = %s' % (gzip_key.upper(), gzip_level))

    if 'fancy_indexing' in custom_values:
        mod_alias_file = "/etc/apache2/mods-available/alias.conf"
        mod_alias_content = ""
        with open(mod_alias_file) as fd:
            mod_alias_content = fd.readlines()

        fancy_indexing = custom_values['fancy_indexing']
        new_mod_alias_content = []
        found = False
        for mod_alias_content_line in mod_alias_content:
            if mod_alias_content_line.find("Alias /icons/ \"/usr/share/apache2/icons/\"") > -1:
                found = True
                if fancy_indexing:
                    new_mod_alias_content.append("\tAlias /icons/ \"/usr/share/apache2/icons/\"\n")
                else:
                    new_mod_alias_content.append("\t# Alias /icons/ \"/usr/share/apache2/icons/\"\n")
            else:
                new_mod_alias_content.append(mod_alias_content_line)

        mod_alias_content = new_mod_alias_content
        new_mod_alias_content = []
        if not found and fancy_indexing:
            for mod_alias_content_line in mod_alias_content:
                if mod_alias_content_line.find("<Directory") > -1:
                    new_mod_alias_content.append("\tAlias /icons/ \"/usr/share/apache2/icons/\"\n\n")
                new_mod_alias_content.append(mod_alias_content_line)
            mod_alias_content = new_mod_alias_content

        with open(mod_alias_file, 'w') as fd:
            for mod_alias_content_line in mod_alias_content:
                fd.write(mod_alias_content_line)
        logger.info('%14s = %s' % ("FANCY INDEXING", str(fancy_indexing)))