<reponame>MacFarlaneBro/compose-mode
#!/usr/bin/env python
# -*- coding: utf-8 -*-
""" Functions for generating the output yaml """
import compose.config
import sys
from compose.config import serialize, environment

import yaml

import compose_mode

_FILE_LIST_PREFIX = '#     '
HEADER_TEMPLATE = """
# ==============================================================================
# !! DO NOT EDIT !!
# This file was generated by compose-mode %s
# The selected mode was {} and the files that make that mode are:
%s{}
# If you wish to view this configuration without the interspersed comments,
# run `docker-compose config` instead of `cat docker-compose.yml`
# ==============================================================================

""".lstrip() % (compose_mode.__version__, _FILE_LIST_PREFIX)
# Use old school formatting so we can also put {} in it easily,
# lstrip to remove the newline at the start

_INTER_LINE_WARNING = '# DO NOT EDIT, GENERATED FILE, SEE TOP OF FILE\n'


def generate_header(selected_mode, modes):
    separator = '\n' + _FILE_LIST_PREFIX
    mode_files_str = separator.join(modes[selected_mode])
    return HEADER_TEMPLATE.format(selected_mode, mode_files_str)


def warn(config, selected_mode, modes):
    """ Adds a "do not edit" warning to the given configuration """
    lines = config.splitlines(True)
    header = generate_header(selected_mode, modes)
    warned_lines = _INTER_LINE_WARNING.join(lines)
    return header + warned_lines


def get_selected_mode_config(selected_mode, modes, containing_dir):
    """ Returns the string of the yaml configuration for the given mode """
    # entries in `modes` are each a list of filenames
    try:
        config_details = compose.config.find(
            containing_dir,
            modes[selected_mode],
            environment.Environment.from_env_file(containing_dir)
        )
    except KeyError:
        print(("Specified mode not '{}' found! Please check or spelling or add"
               " as a new mode.".format(selected_mode)))
        sys.exit()

    loaded_config = compose.config.load(config_details)

    broken_serialized = serialize.serialize_config(loaded_config)
    fixed_serialized = fix_merged_configs(broken_serialized)

    return fixed_serialized


def configuration(selected_mode, modes, containing_dir):
    """ The canonical entrypoint to this module

    Other modules should use this function to get the configuration.

    Name is so it sounds good when you do:

        from compose_mode import generate
        generate.configuration(...)
    """
    return warn(get_selected_mode_config(selected_mode, modes, containing_dir),
                selected_mode, modes)


def fix_restart(restart_config):
    """ Fix output of docker-compose.

    docker-compose's "show config" mechanism--the internals of which we use to
    merge configs--doesn't actually return valid configurations for the
    "restart" property as they convert it to an internal representation which
    they then forget to convert back to the yaml format. We do that by hand
    here.
    """
    try:
        mrc = restart_config['MaximumRetryCount']
    except TypeError:
        name = restart_config
    else:
        name = restart_config['Name']

    if name in ['always', 'unless-stopped', 'no']:
        return name
    else:
        return '{}:{}'.format(name, mrc)


def fix_network(network):
    try:
        del network['external_name']
    except KeyError:
        pass
    return network


def fix_merged_configs(input_yaml):
    """ Fix various merge problems for configs

    See docs for `fix_restart` for why.
    """
    config_dict = yaml.safe_load(input_yaml)
    for service in config_dict['services'].values():
        try:
            service['restart'] = fix_restart(service['restart'])
        except KeyError:
            pass

    if 'networks' in config_dict:
        networks = config_dict['networks']
        for name, network in networks.items():
            networks[name] = fix_network(network)

    return yaml.safe_dump(config_dict,
                          default_flow_style=False,
                          indent=4,
                          width=80)


def main():
    pass


if __name__ == '__main__':
    main()

#!/usr/bin/env python
# -*- coding: utf-8 -*-
""" Functions for generating the output yaml """
import compose.config
import sys
from compose.config import serialize, environment

import yaml

import compose_mode

_FILE_LIST_PREFIX = '#     '
HEADER_TEMPLATE = """
# ==============================================================================
# !! DO NOT EDIT !!
# This file was generated by compose-mode %s
# The selected mode was {} and the files that make that mode are:
%s{}
# If you wish to view this configuration without the interspersed comments,
# run `docker-compose config` instead of `cat docker-compose.yml`
# ==============================================================================

""".lstrip() % (compose_mode.__version__, _FILE_LIST_PREFIX)
# Use old school formatting so we can also put {} in it easily,
# lstrip to remove the newline at the start

_INTER_LINE_WARNING = '# DO NOT EDIT, GENERATED FILE, SEE TOP OF FILE\n'


def generate_header(selected_mode, modes):
    separator = '\n' + _FILE_LIST_PREFIX
    mode_files_str = separator.join(modes[selected_mode])
    return HEADER_TEMPLATE.format(selected_mode, mode_files_str)


def warn(config, selected_mode, modes):
    """ Adds a "do not edit" warning to the given configuration """
    lines = config.splitlines(True)
    header = generate_header(selected_mode, modes)
    warned_lines = _INTER_LINE_WARNING.join(lines)
    return header + warned_lines


def get_selected_mode_config(selected_mode, modes, containing_dir):
    """ Returns the string of the yaml configuration for the given mode """
    # entries in `modes` are each a list of filenames
    try:
        config_details = compose.config.find(
            containing_dir,
            modes[selected_mode],
            environment.Environment.from_env_file(containing_dir)
        )
    except KeyError:
        print(("Specified mode not '{}' found! Please check or spelling or add"
               " as a new mode.".format(selected_mode)))
        sys.exit()

    loaded_config = compose.config.load(config_details)

    broken_serialized = serialize.serialize_config(loaded_config)
    fixed_serialized = fix_merged_configs(broken_serialized)

    return fixed_serialized


def configuration(selected_mode, modes, containing_dir):
    """ The canonical entrypoint to this module

    Other modules should use this function to get the configuration.

    Name is so it sounds good when you do:

        from compose_mode import generate
        generate.configuration(...)
    """
    return warn(get_selected_mode_config(selected_mode, modes, containing_dir),
                selected_mode, modes)


def fix_restart(restart_config):
    """ Fix output of docker-compose.

    docker-compose's "show config" mechanism--the internals of which we use to
    merge configs--doesn't actually return valid configurations for the
    "restart" property as they convert it to an internal representation which
    they then forget to convert back to the yaml format. We do that by hand
    here.
    """
    try:
        mrc = restart_config['MaximumRetryCount']
    except TypeError:
        name = restart_config
    else:
        name = restart_config['Name']

    if name in ['always', 'unless-stopped', 'no']:
        return name
    else:
        return '{}:{}'.format(name, mrc)


def fix_network(network):
    try:
        del network['external_name']
    except KeyError:
        pass
    return network


def fix_merged_configs(input_yaml):
    """ Fix various merge problems for configs

    See docs for `fix_restart` for why.
    """
    config_dict = yaml.safe_load(input_yaml)
    for service in config_dict['services'].values():
        try:
            service['restart'] = fix_restart(service['restart'])
        except KeyError:
            pass

    if 'networks' in config_dict:
        networks = config_dict['networks']
        for name, network in networks.items():
            networks[name] = fix_network(network)

    return yaml.safe_dump(config_dict,
                          default_flow_style=False,
                          indent=4,
                          width=80)


def main():
    pass


if __name__ == '__main__':
    main()
#!/usr/bin/env python # -*- coding: utf-8 -*- Functions for generating the output yaml # ============================================================================== # !! DO NOT EDIT !! # This file was generated by compose-mode %s # The selected mode was {} and the files that make that mode are: %s{} # If you wish to view this configuration without the interspersed comments, # run `docker-compose config` instead of `cat docker-compose.yml` # ============================================================================== # Use old school formatting so we can also put {} in it easily, # lstrip to remove the newline at the start Adds a "do not edit" warning to the given configuration Returns the string of the yaml configuration for the given mode # entries in `modes` are each a list of filenames The canonical entrypoint to this module      Other modules should use this function to get the configuration.      Name is so it sounds good when you do:          from compose_mode import generate         generate.configuration(...) Fix output of docker-compose.      docker-compose's "show config" mechanism--the internals of which we use to     merge configs--doesn't actually return valid configurations for the     "restart" property as they convert it to an internal representation which     they then forget to convert back to the yaml format. We do that by hand     here. Fix various merge problems for configs      See docs for `fix_restart` for why.