<reponame>3pillarlabs/hip-edit
"""
Tests for master.py
"""
from __future__ import print_function
from collections import namedtuple
import unittest
import botocore
from mock import MagicMock
from hip_edit import cf_template_builder
from hip_edit import cf_driver

FIELD_NAMES = ['name', 'region', 'instance_type', 'key_name', 'domain_suffix', 'vpc_id', 'subnet_id',
               'stack_halt']
CliOptions = namedtuple('CliOptions', FIELD_NAMES)

def _make_cli_options(name='Plop',
                      region='eu-west-1',
                      instance_type='t2.micro',
                      key_name='plop',
                      domain_suffix=None,
                      vpc_id=None,
                      subnet_id=None,
                      stack_halt=MagicMock(return_value=False)):

    return CliOptions(
        name=name,
        region=region,
        instance_type=instance_type,
        key_name=key_name,
        domain_suffix=domain_suffix,
        vpc_id=vpc_id,
        subnet_id=subnet_id,
        stack_halt=stack_halt
    )



class CfDriverTests(unittest.TestCase):
    """
    cf_driver.py tests
    """

    def setUp(self):
        self.cli_options = _make_cli_options()
        self.template = cf_template_builder.build(self.cli_options)


    def test_valid_cf_template(self):
        """Tests if the generated CF template is valid."""
        assert self.template is not None


    def test_creation_success(self):
        """CF stack creation in success path."""
        ite = iter([None, -2, -1, 0])
        initial_state = {
            'Stacks': [{
                'StackId': 'MockStack-1',
                'StackStatus': 'CREATE_IN_PROGRESS'
            }]
        }
        def _describe_stacks(*_args, **_kwargs):
            val = ite.next()
            if val is None:
                raise botocore.exceptions.ClientError({}, 'mock')
            elif val == -1:
                initial_state['Stacks'][0]['Outputs'] = [{
                    'Key': 'yada', 'Value': 'yada'
                }]
            elif val == 0:
                initial_state['Stacks'][0]['StackStatus'] = 'CREATE_COMPLETE'

            return initial_state

        client = MagicMock()
        client.describe_stacks = MagicMock(side_effect=_describe_stacks)
        client.create_stack = MagicMock(return_value={'StackId': 'MockStack-1'})

        cf_driver.update_or_create_cf_template(__name__, self.template, client=client, retry_seconds=0)


    def test_creation_failure_with_rollback_success(self):
        """CF stack creation in rollback path."""
        states_ite = iter([None, 'CREATE_IN_PROGRESS', 'CREATE_FAILED', 'ROLLBACK_IN_PROGRESS', 'ROLLBACK_COMPLETE'])
        initial_state = {
            'Stacks': [{'StackStatus': 'CREATE_IN_PROGRESS'}]
        }
        def _describe_stacks(*_args, **_kwargs):
            cur_state = states_ite.next()
            if cur_state is None:
                raise botocore.exceptions.ClientError({}, 'mock')
            else:
                initial_state['Stacks'][0]['StackStatus'] = cur_state
                return initial_state

        client = MagicMock()
        client.describe_stacks = MagicMock(side_effect=_describe_stacks)
        client.create_stack = MagicMock(return_value={'StackId': 'MockStack-1'})

        cf_driver.update_or_create_cf_template(__name__, self.template, client=client, retry_seconds=0)


    def test_update_success(self):
        """CF stack update in success path."""
        states_ite = iter(['UPDATE_IN_PROGRESS', 'UPDATE_COMPLETE_CLEANUP_IN_PROGRESS', 'UPDATE_COMPLETE'])
        initial_state = {
            'Stacks': [{
                'StackId': 'MockStack-1',
                'StackStatus': None
            }]
        }
        def _describe_stacks(*_args, **_kwargs):
            initial_state['Stacks'][0]['StackStatus'] = states_ite.next()
            return initial_state

        client = MagicMock()
        client.describe_stacks = MagicMock(side_effect=_describe_stacks)
        client.update_stack = MagicMock(return_value={'StackId': 'MockStack-1'})

        cf_driver.update_or_create_cf_template(__name__, self.template, client=client, retry_seconds=0)


    def test_stack_halt(self):
        """Should not attach the EIP"""
        self.cli_options = _make_cli_options(stack_halt=MagicMock(return_value=True))
        template = cf_template_builder.build(self.cli_options)
        assert 'MessageServerHost' not in template.to_dict()['Outputs']

"""
Tests for master.py
"""
from __future__ import print_function
from collections import namedtuple
import unittest
import botocore
from mock import MagicMock
from hip_edit import cf_template_builder
from hip_edit import cf_driver

FIELD_NAMES = ['name', 'region', 'instance_type', 'key_name', 'domain_suffix', 'vpc_id', 'subnet_id',
               'stack_halt']
CliOptions = namedtuple('CliOptions', FIELD_NAMES)

def _make_cli_options(name='Plop',
                      region='eu-west-1',
                      instance_type='t2.micro',
                      key_name='plop',
                      domain_suffix=None,
                      vpc_id=None,
                      subnet_id=None,
                      stack_halt=MagicMock(return_value=False)):

    return CliOptions(
        name=name,
        region=region,
        instance_type=instance_type,
        key_name=key_name,
        domain_suffix=domain_suffix,
        vpc_id=vpc_id,
        subnet_id=subnet_id,
        stack_halt=stack_halt
    )



class CfDriverTests(unittest.TestCase):
    """
    cf_driver.py tests
    """

    def setUp(self):
        self.cli_options = _make_cli_options()
        self.template = cf_template_builder.build(self.cli_options)


    def test_valid_cf_template(self):
        """Tests if the generated CF template is valid."""
        assert self.template is not None


    def test_creation_success(self):
        """CF stack creation in success path."""
        ite = iter([None, -2, -1, 0])
        initial_state = {
            'Stacks': [{
                'StackId': 'MockStack-1',
                'StackStatus': 'CREATE_IN_PROGRESS'
            }]
        }
        def _describe_stacks(*_args, **_kwargs):
            val = ite.next()
            if val is None:
                raise botocore.exceptions.ClientError({}, 'mock')
            elif val == -1:
                initial_state['Stacks'][0]['Outputs'] = [{
                    'Key': 'yada', 'Value': 'yada'
                }]
            elif val == 0:
                initial_state['Stacks'][0]['StackStatus'] = 'CREATE_COMPLETE'

            return initial_state

        client = MagicMock()
        client.describe_stacks = MagicMock(side_effect=_describe_stacks)
        client.create_stack = MagicMock(return_value={'StackId': 'MockStack-1'})

        cf_driver.update_or_create_cf_template(__name__, self.template, client=client, retry_seconds=0)


    def test_creation_failure_with_rollback_success(self):
        """CF stack creation in rollback path."""
        states_ite = iter([None, 'CREATE_IN_PROGRESS', 'CREATE_FAILED', 'ROLLBACK_IN_PROGRESS', 'ROLLBACK_COMPLETE'])
        initial_state = {
            'Stacks': [{'StackStatus': 'CREATE_IN_PROGRESS'}]
        }
        def _describe_stacks(*_args, **_kwargs):
            cur_state = states_ite.next()
            if cur_state is None:
                raise botocore.exceptions.ClientError({}, 'mock')
            else:
                initial_state['Stacks'][0]['StackStatus'] = cur_state
                return initial_state

        client = MagicMock()
        client.describe_stacks = MagicMock(side_effect=_describe_stacks)
        client.create_stack = MagicMock(return_value={'StackId': 'MockStack-1'})

        cf_driver.update_or_create_cf_template(__name__, self.template, client=client, retry_seconds=0)


    def test_update_success(self):
        """CF stack update in success path."""
        states_ite = iter(['UPDATE_IN_PROGRESS', 'UPDATE_COMPLETE_CLEANUP_IN_PROGRESS', 'UPDATE_COMPLETE'])
        initial_state = {
            'Stacks': [{
                'StackId': 'MockStack-1',
                'StackStatus': None
            }]
        }
        def _describe_stacks(*_args, **_kwargs):
            initial_state['Stacks'][0]['StackStatus'] = states_ite.next()
            return initial_state

        client = MagicMock()
        client.describe_stacks = MagicMock(side_effect=_describe_stacks)
        client.update_stack = MagicMock(return_value={'StackId': 'MockStack-1'})

        cf_driver.update_or_create_cf_template(__name__, self.template, client=client, retry_seconds=0)


    def test_stack_halt(self):
        """Should not attach the EIP"""
        self.cli_options = _make_cli_options(stack_halt=MagicMock(return_value=True))
        template = cf_template_builder.build(self.cli_options)
        assert 'MessageServerHost' not in template.to_dict()['Outputs']
Tests for master.py cf_driver.py tests Tests if the generated CF template is valid. CF stack creation in success path. CF stack creation in rollback path. CF stack update in success path. Should not attach the EIP