import json
import logging
import re
import susepubliccloudinfoclient.infoserverrequests as ifsrequest
import yaml
import sys

RELEASE_DATE = re.compile('^.*-v(\d{8})-*.*')


def get_caasp_release_version():
    """Return the version from os-release"""
    os_release = open('/etc/os-release', 'r').readlines()
    for entry in os_release:
        if entry.startswith('VERSION_ID'):
            version_id = entry.split('=')[-1].strip()
            # We assume that os-release will always have '"' as
            # version delimiters
            version = version_id.strip('"\'')
            logging.info('Release version: "%s"' % version)
            return version


def get_cloud_config_path():
    """Return the path for the cloud configuration file"""
    return '/etc/salt/pillar/cloud.sls'


def get_from_config(config_option):
    """Get the value for the given config option"""
    # Expected low usage of this method, re-read the file on an as needed
    # basis. If this turns out to be an issue cache the content
    config_path = get_cloud_config_path()
    with open(config_path) as config_file:
            config = yaml.load(config_file.read())
    settings = config.get('cloud')
    if not settings:
        return
    return settings.get(config_option)


def get_cluster_image_identifier(framework, region):
    """Return the identifier for the latest cluster node image"""
    cluster_image = get_from_config('cluster_image')
    if cluster_image:
        # The data returned in this code path has built in knowledge
        # about the information consumed by the client from the
        # full pint data
        image_data = {}
        image_data['id'] = cluster_image
        image_data['name'] = cluster_image
        if framework == 'microsoft' and cluster_image.count(':') == 3:
            image_data['urn'] = cluster_image
        msg = 'Using cluster image from configuration. '
        msg += 'Image data for cluster node image: "%s"'
        logging.info(msg % image_data)
        return image_data
    name_filter = 'name~caasp,name~cluster'
    flavor = get_from_config('procurement_flavor')
    if flavor == 'byos':
        name_filter += ',name~byos'
    else:
        name_filter += ',name!byos'
    version = get_caasp_release_version()
    name_filter += ',name~' + version.replace('.', '-')
    # The cluster image we choose depends on the admin node version,
    # thus we cannot just query for active images. We need to get all
    # images and then process accordingly.
    try:
        image_info = ifsrequest.get_image_data(
            framework,
            None,
            'json',
            region,
            name_filter
        )
    except Exception as e:
        logging.error('Pint server access failed: "%s"' % e.message)
        # This message will bubble up through salt
        return 'See /var/log/caasp_cloud_setup.log'
    try:
        image_data = json.loads(image_info)
        available_images = image_data.get('images', [])
        target_image = None
        target_image_date = 0
        for image in available_images:
            image_name = image.get('name')
            try:
                date = int(RELEASE_DATE.match(image_name).group(1))
                if date > target_image_date:
                    # If we have multiple images with the same date that
                    # match our filter criteria we have a serious data problem
                    # we cannot really recover, the first one wins
                    target_image = image
            except Exception:
                # Image name with no date stamp skip it
                continue
    except Exception as e:
        logging.error('Could not load json data from pint: "%s"' % e.message)
        # This message will bubble up through salt
        return 'See /var/log/caasp_cloud_setup.log'

    if not target_image:
        logging.error('Could not determine image identifier for cluster node.')
        logging.error('This implies that the pint server is unreachable or the '
                      'data is incomplete, please report the issue, exiting.')
        sys.exit('pint lookup failed')

    logging.info('Image data for cluster node image: "%s"' % target_image)
    return target_image


def load_platform_module(platform_name):
    mod = __import__('caaspadminsetup.%s' % platform_name, fromlist=[''])
    return mod

[((8, 15, 8, 45), 're.compile', 're.compile', ({(8, 26, 8, 44): '"""^.*-v(\\\\d{8})-*.*"""'}, {}), "('^.*-v(\\\\d{8})-*.*')", False, 'import re\n'), ((109, 4, 109, 74), 'logging.info', 'logging.info', ({(109, 17, 109, 73): '(\'Image data for cluster node image: "%s"\' % target_image)'}, {}), '(\'Image data for cluster node image: "%s"\' % target_image)', False, 'import logging\n'), ((56, 8, 56, 38), 'logging.info', 'logging.info', ({(56, 21, 56, 37): '(msg % image_data)'}, {}), '(msg % image_data)', False, 'import logging\n'), ((70, 21, 76, 9), 'susepubliccloudinfoclient.infoserverrequests.get_image_data', 'ifsrequest.get_image_data', ({(71, 12, 71, 21): 'framework', (72, 12, 72, 16): 'None', (73, 12, 73, 18): '"""json"""', (74, 12, 74, 18): 'region', (75, 12, 75, 23): 'name_filter'}, {}), "(framework, None, 'json', region, name_filter)", True, 'import susepubliccloudinfoclient.infoserverrequests as ifsrequest\n'), ((82, 21, 82, 43), 'json.loads', 'json.loads', ({(82, 32, 82, 42): 'image_info'}, {}), '(image_info)', False, 'import json\n'), ((104, 8, 104, 79), 'logging.error', 'logging.error', ({(104, 22, 104, 78): '"""Could not determine image identifier for cluster node."""'}, {}), "('Could not determine image identifier for cluster node.')", False, 'import logging\n'), ((105, 8, 106, 78), 'logging.error', 'logging.error', ({(105, 22, 106, 77): '"""This implies that the pint server is unreachable or the data is incomplete, please report the issue, exiting."""'}, {}), "(\n    'This implies that the pint server is unreachable or the data is incomplete, please report the issue, exiting.'\n    )", False, 'import logging\n'), ((107, 8, 107, 38), 'sys.exit', 'sys.exit', ({(107, 17, 107, 37): '"""pint lookup failed"""'}, {}), "('pint lookup failed')", False, 'import sys\n'), ((20, 12, 20, 59), 'logging.info', 'logging.info', ({(20, 25, 20, 58): '(\'Release version: "%s"\' % version)'}, {}), '(\'Release version: "%s"\' % version)', False, 'import logging\n'), ((78, 8, 78, 68), 'logging.error', 'logging.error', ({(78, 22, 78, 67): '(\'Pint server access failed: "%s"\' % e.message)'}, {}), '(\'Pint server access failed: "%s"\' % e.message)', False, 'import logging\n'), ((99, 8, 99, 77), 'logging.error', 'logging.error', ({(99, 22, 99, 76): '(\'Could not load json data from pint: "%s"\' % e.message)'}, {}), '(\'Could not load json data from pint: "%s"\' % e.message)', False, 'import logging\n')]