def test_get_cloudformation_template_raises_exception_on_any_error(
            self, get_yaml_or_json_file_mock):
        get_yaml_or_json_file_mock.side_effect = Exception

        with self.assertRaises(TemplateErrorException):
            FileLoader.get_cloudformation_template(
                "s3://my-bucket/template.yml", None)
 def test_handle_yaml_constructors_raises_exception_on_unknown_tag(self):
     loader_mock = Mock()
     loader_mock.construct_scalar.return_value = "myResource"
     node_mock = Mock(spec=yaml.ScalarNode)
     with self.assertRaises(CfnSphereException):
         FileLoader.handle_yaml_constructors(loader_mock, "!anyTag",
                                             node_mock)
Example #3
0
def render_template(filename):
    check_update_available()

    loader = FileLoader()
    template = loader.get_file_from_url(filename, None)
    template = CloudFormationTemplateTransformer.transform_template(template)
    click.echo(template.get_template_json())
Example #4
0
    def test_get_yaml_or_json_file_parses_yaml_on_yml_suffix(
            self, get_file_mock, yaml_mock):
        get_file_return_value = Mock()
        get_file_mock.return_value = get_file_return_value

        FileLoader.get_yaml_or_json_file('foo.yml', 'baa')
        yaml_mock.load.assert_called_once_with(get_file_return_value)
    def test_get_yaml_or_json_file_parses_json_on_json_suffix(
            self, get_file_mock, json_mock):
        get_file_return_value = Mock()
        get_file_mock.return_value = get_file_return_value

        FileLoader.get_yaml_or_json_file('foo.json', 'baa')
        json_mock.loads.assert_called_once_with(get_file_return_value,
                                                encoding="utf-8")
Example #6
0
def render_template(template_file, confirm):
    if not confirm:
        check_update_available()

    loader = FileLoader()
    template = loader.get_file_from_url(template_file, None)
    template = CloudFormationTemplateTransformer.transform_template(template)
    click.echo(template.get_pretty_template_json())
Example #7
0
def render_template(template_file, confirm, yes):
    confirm = confirm or yes
    if not confirm:
        check_update_available()

    loader = FileLoader()
    template = loader.get_cloudformation_template(template_file, None)
    template = CloudFormationTemplateTransformer.transform_template(template)
    click.echo(template.get_pretty_template_json())
Example #8
0
def render_template(template_file, confirm, yes):
    confirm = confirm or yes
    if not confirm:
        check_update_available()

    loader = FileLoader()
    template = loader.get_cloudformation_template(template_file, None)
    template = CloudFormationTemplateTransformer.transform_template(template)
    click.echo(template.get_pretty_template_json())
    def test_get_yaml_or_json_file_parses_yaml_on_yaml_suffix(
            self, get_file_mock, yaml_mock):
        get_file_return_value = Mock()
        get_file_mock.return_value = get_file_return_value

        FileLoader.get_yaml_or_json_file('foo.yaml', 'baa')
        if hasattr(yaml_mock, 'FullLoader'):
            loader = yaml_mock.FullLoader
        else:
            loader = yaml_mock.Loader

        yaml_mock.load.assert_called_once_with(get_file_return_value,
                                               Loader=loader)
    def test_handle_yaml_constructors_converts_get_azs(self):
        loader_mock = Mock()
        loader_mock.construct_scalar.return_value = "region"
        node_mock = Mock(spec=yaml.ScalarNode)

        response = FileLoader.handle_yaml_constructors(loader_mock, "!GetAZs", node_mock)
        self.assertEqual({'Fn::GetAZs': "region"}, response)
    def test_handle_yaml_constructors_converts_getatt(self):
        loader_mock = Mock()
        loader_mock.construct_scalar.return_value = "logicalNameOfResource.attributeName"
        node_mock = Mock(spec=yaml.ScalarNode)

        response = FileLoader.handle_yaml_constructors(loader_mock, "!GetAtt", node_mock)
        self.assertEqual({'Fn::GetAtt': ["logicalNameOfResource", "attributeName"]}, response)
Example #12
0
    def test_handle_yaml_constructors_converts_getatt(self):
        loader_mock = Mock()
        loader_mock.construct_scalar.return_value = "logicalNameOfResource.attributeName"
        node_mock = Mock(spec=yaml.ScalarNode)

        response = FileLoader.handle_yaml_constructors(loader_mock, "!GetAtt", node_mock)
        self.assertEqual({'Fn::GetAtt': ["logicalNameOfResource", "attributeName"]}, response)
Example #13
0
    def test_handle_yaml_constructors_converts_base64(self):
        loader_mock = Mock()
        loader_mock.construct_scalar.return_value = "myString"
        node_mock = Mock(spec=yaml.ScalarNode)

        response = FileLoader.handle_yaml_constructors(loader_mock, "!base64", node_mock)
        self.assertEqual({'Fn::Base64': 'myString'}, response)
    def test_handle_yaml_constructors_converts_ref(self):
        loader_mock = Mock()
        loader_mock.construct_scalar.return_value = "myResource"
        node_mock = Mock(spec=yaml.ScalarNode)

        response = FileLoader.handle_yaml_constructors(loader_mock, "!ref", node_mock)
        self.assertEqual({'Ref': "myResource"}, response)
    def test_handle_yaml_constructors_converts_select(self):
        loader_mock = Mock()
        loader_mock.construct_scalar.return_value = ["index", "list"]
        node_mock = Mock(spec=yaml.ScalarNode)

        response = FileLoader.handle_yaml_constructors(loader_mock, "!select", node_mock)
        self.assertEqual({'Fn::Select': ["index", "list"]}, response)
Example #16
0
    def test_handle_yaml_constructors_converts_or(self):
        loader_mock = Mock()
        loader_mock.construct_scalar.return_value = ["myCondition", "myOtherCondition"]
        node_mock = Mock(spec=yaml.ScalarNode)

        response = FileLoader.handle_yaml_constructors(loader_mock, "!or", node_mock)
        self.assertEqual({'Fn::Or': ["myCondition", "myOtherCondition"]}, response)
Example #17
0
    def test_handle_yaml_constructors_converts_ref(self):
        loader_mock = Mock()
        loader_mock.construct_scalar.return_value = "myResource"
        node_mock = Mock(spec=yaml.ScalarNode)

        response = FileLoader.handle_yaml_constructors(loader_mock, "!ref", node_mock)
        self.assertEqual({'Ref': "myResource"}, response)
Example #18
0
    def test_handle_yaml_constructors_converts_sub(self):
        loader_mock = Mock()
        loader_mock.construct_scalar.return_value = ["string", {"key": "value"}]
        node_mock = Mock(spec=yaml.ScalarNode)

        response = FileLoader.handle_yaml_constructors(loader_mock, "!sub", node_mock)
        self.assertEqual({'Fn::Sub': ["string", {"key": "value"}]}, response)
Example #19
0
    def test_handle_yaml_constructors_converts_select(self):
        loader_mock = Mock()
        loader_mock.construct_scalar.return_value = ["index", "list"]
        node_mock = Mock(spec=yaml.ScalarNode)

        response = FileLoader.handle_yaml_constructors(loader_mock, "!select", node_mock)
        self.assertEqual({'Fn::Select': ["index", "list"]}, response)
Example #20
0
    def test_handle_yaml_constructors_converts_join(self):
        loader_mock = Mock()
        loader_mock.construct_scalar.return_value = ["delimiter", ["a", "b"]]
        node_mock = Mock(spec=yaml.ScalarNode)

        response = FileLoader.handle_yaml_constructors(loader_mock, "!join", node_mock)
        self.assertEqual({'Fn::Join': ["delimiter", ["a", "b"]]}, response)
Example #21
0
    def test_handle_yaml_constructors_converts_import_value(self):
        loader_mock = Mock()
        loader_mock.construct_scalar.return_value = "sharedValue"
        node_mock = Mock(spec=yaml.ScalarNode)

        response = FileLoader.handle_yaml_constructors(loader_mock, "!ImportValue", node_mock)
        self.assertEqual({'Fn::ImportValue': "sharedValue"}, response)
Example #22
0
    def test_handle_yaml_constructors_converts_get_azs(self):
        loader_mock = Mock()
        loader_mock.construct_scalar.return_value = "region"
        node_mock = Mock(spec=yaml.ScalarNode)

        response = FileLoader.handle_yaml_constructors(loader_mock, "!GetAZs", node_mock)
        self.assertEqual({'Fn::GetAZs': "region"}, response)
    def test_handle_yaml_constructors_converts_import_value(self):
        loader_mock = Mock()
        loader_mock.construct_scalar.return_value = "sharedValue"
        node_mock = Mock(spec=yaml.ScalarNode)

        response = FileLoader.handle_yaml_constructors(loader_mock, "!ImportValue", node_mock)
        self.assertEqual({'Fn::ImportValue': "sharedValue"}, response)
    def test_handle_yaml_constructors_converts_join(self):
        loader_mock = Mock()
        loader_mock.construct_scalar.return_value = ["delimiter", ["a", "b"]]
        node_mock = Mock(spec=yaml.ScalarNode)

        response = FileLoader.handle_yaml_constructors(loader_mock, "!join", node_mock)
        self.assertEqual({'Fn::Join': ["delimiter", ["a", "b"]]}, response)
    def test_handle_yaml_constructors_converts_base64(self):
        loader_mock = Mock()
        loader_mock.construct_scalar.return_value = "myString"
        node_mock = Mock(spec=yaml.ScalarNode)

        response = FileLoader.handle_yaml_constructors(loader_mock, "!base64", node_mock)
        self.assertEqual({'Fn::Base64': 'myString'}, response)
    def test_handle_yaml_constructors_converts_sub(self):
        loader_mock = Mock()
        loader_mock.construct_scalar.return_value = ["string", {"key": "value"}]
        node_mock = Mock(spec=yaml.ScalarNode)

        response = FileLoader.handle_yaml_constructors(loader_mock, "!sub", node_mock)
        self.assertEqual({'Fn::Sub': ["string", {"key": "value"}]}, response)
    def test_handle_yaml_constructors_converts_equals(self):
        loader_mock = Mock()
        loader_mock.construct_scalar.return_value = ["myValue", "myOtherValue"]
        node_mock = Mock(spec=yaml.ScalarNode)

        response = FileLoader.handle_yaml_constructors(loader_mock, "!equals", node_mock)
        self.assertEqual({'Fn::Equals': ["myValue", "myOtherValue"]}, response)
Example #28
0
    def test_handle_yaml_constructors_converts_equals(self):
        loader_mock = Mock()
        loader_mock.construct_scalar.return_value = ["myValue", "myOtherValue"]
        node_mock = Mock(spec=yaml.ScalarNode)

        response = FileLoader.handle_yaml_constructors(loader_mock, "!equals", node_mock)
        self.assertEqual({'Fn::Equals': ["myValue", "myOtherValue"]}, response)
    def test_handle_yaml_constructors_converts_or(self):
        loader_mock = Mock()
        loader_mock.construct_scalar.return_value = ["myCondition", "myOtherCondition"]
        node_mock = Mock(spec=yaml.ScalarNode)

        response = FileLoader.handle_yaml_constructors(loader_mock, "!or", node_mock)
        self.assertEqual({'Fn::Or': ["myCondition", "myOtherCondition"]}, response)
Example #30
0
    def __init__(self,
                 config_file=None,
                 config_dict=None,
                 cli_params=None,
                 stack_name_suffix=None):
        self.logger = get_logger()

        if isinstance(config_dict, dict):
            self.stack_config_base_dir = None
        elif config_file:
            self.stack_config_base_dir = os.path.dirname(
                os.path.realpath(config_file))
            config_dict = FileLoader.get_yaml_or_json_file(
                config_file, working_dir=os.getcwd())
        else:
            raise InvalidConfigException(
                "You need to pass either config_file (path to a file) or config_dict (python dict) property"
            )

        self.cli_params = self._parse_cli_parameters(cli_params)
        self.region = config_dict.get("region")
        self.stack_name_suffix = stack_name_suffix

        self.default_service_role = config_dict.get("service-role")
        self.default_stack_policy_url = config_dict.get("stack-policy-url")
        self.default_timeout = config_dict.get("timeout", 600)
        self.default_tags = config_dict.get("tags", {})
        self.default_failure_action = config_dict.get("on_failure", "ROLLBACK")
        self.default_disable_rollback = config_dict.get(
            "disable_rollback", False)

        self._validate(config_dict)

        stacks = self._parse_stack_configs(config_dict)
        self.stacks = self._apply_stack_name_suffix(stacks, stack_name_suffix)
    def test_handle_yaml_constructors_converts_find_in_map(self):
        loader_mock = Mock()
        loader_mock.construct_scalar.return_value = ["MapName", "TopLevelKey", "SecondLevelKey"]
        node_mock = Mock(spec=yaml.ScalarNode)

        response = FileLoader.handle_yaml_constructors(loader_mock, "!FindInMap", node_mock)
        self.assertEqual({'Fn::FindInMap': ["MapName", "TopLevelKey", "SecondLevelKey"]}, response)
    def handle_file_value(value, working_dir):
        components = value.split('|', 3)

        if len(components) == 3:
            url = components[2]
            return FileLoader.get_file(url, working_dir)
        elif len(components) == 4:
            url = components[2]
            pattern = components[3]
            file_content = FileLoader.get_yaml_or_json_file(url, working_dir)
            try:
                return jmespath.search(pattern, file_content)
            except JMESPathError as e:
                raise CfnSphereException(e)
        else:
            raise CfnSphereException("Invalid format for |File| macro, it must be |File|<path>[|<pattern>]")
Example #33
0
    def test_handle_yaml_constructors_converts_find_in_map(self):
        loader_mock = Mock()
        loader_mock.construct_scalar.return_value = ["MapName", "TopLevelKey", "SecondLevelKey"]
        node_mock = Mock(spec=yaml.ScalarNode)

        response = FileLoader.handle_yaml_constructors(loader_mock, "!FindInMap", node_mock)
        self.assertEqual({'Fn::FindInMap': ["MapName", "TopLevelKey", "SecondLevelKey"]}, response)
Example #34
0
    def create_or_update_stacks(self):
        existing_stacks = self.cfn.get_stack_names()
        desired_stacks = self.config.stacks
        stack_processing_order = DependencyResolver().get_stack_order(desired_stacks)

        if len(stack_processing_order) > 1:
            self.logger.info(
                "Will process stacks in the following order: {0}".format(", ".join(stack_processing_order)))

        for stack_name in stack_processing_order:
            stack_config = self.config.stacks.get(stack_name)

            raw_template = FileLoader.get_file_from_url(stack_config.template_url, stack_config.working_dir)
            template = CloudFormationTemplateTransformer.transform_template(raw_template)

            combined_tags = dict(self.config.tags)
            combined_tags.update(stack_config.tags)

            parameters = self.parameter_resolver.resolve_parameter_values(stack_config.parameters, stack_name)
            stack = CloudFormationStack(template=template, parameters=parameters, tags=combined_tags,
                                        name=stack_name, region=self.config.region, timeout=stack_config.timeout)

            if stack_name in existing_stacks:

                self.cfn.validate_stack_is_ready_for_action(stack)
                self.cfn.update_stack(stack)
            else:
                self.cfn.create_stack(stack)

            CustomResourceHandler.process_post_resources(stack)
def upload_cfn_to_s3(project, logger):
    """
    This task is separate since they only work with Python2 >2.6 by
    the time being. Python3 support is underway.

    This means, when using Python<2.7, this task is not visible
    (see __init__.py).
    """
    from cfn_sphere.file_loader import FileLoader
    from cfn_sphere.template.transformer import CloudFormationTemplateTransformer

    for path, filename in project.get_property('template_files'):
        template = FileLoader.get_file_from_url(filename, path)
        transformed = CloudFormationTemplateTransformer.transform_template(
                template)
        output = transformed.get_template_json()

        bucket_name = project.get_property('bucket_name')
        key_prefix = project.get_property('template_key_prefix')
        filename = filename.replace('.yml', '.json')
        filename = filename.replace('.yaml', '.json')
        version_path = '{0}v{1}/{2}'.format(
                key_prefix, project.version, filename)
        # latest_path = '{0}latest/{1}'.format(key_prefix, filename)

        acl = project.get_property('template_file_access_control')
        check_acl_parameter_validity('template_file_access_control', acl)
        upload_helper(logger, bucket_name, version_path, output, acl)
Example #36
0
def upload_cfn_to_s3(project, logger):
    """
    This task is separate since they only work with Python2 >2.6 by
    the time being. Python3 support is underway.

    This means, when using Python<2.7, this task is not visible
    (see __init__.py).
    """
    from cfn_sphere.file_loader import FileLoader
    from cfn_sphere.template.transformer import CloudFormationTemplateTransformer

    for path, filename in project.get_property('template_files'):
        template = FileLoader.get_cloudformation_template(filename, path)
        transformed = CloudFormationTemplateTransformer.transform_template(
            template)
        output = transformed.get_template_json()

        bucket_name = project.get_property('bucket_name')
        key_prefix = project.get_property('template_key_prefix')
        filename = filename.replace('.yml', '.json')
        filename = filename.replace('.yaml', '.json')
        version_path = '{0}v{1}/{2}'.format(key_prefix, project.version,
                                            filename)
        # latest_path = '{0}latest/{1}'.format(key_prefix, filename)

        acl = project.get_property('template_file_access_control')
        check_acl_parameter_validity('template_file_access_control', acl)
        upload_helper(logger, bucket_name, version_path, output, acl)
    def test_get_cloudformation_template_returns_template_with_transform_property(
            self, get_yaml_or_json_file_mock):
        expected = {
            'Conditions': {},
            'Mappings': {},
            'Metadata': {},
            'Resources': 'Foo',
            'Transform': 'transform-section',
            'Parameters': {},
            'Outputs': {},
            'AWSTemplateFormatVersion': '2010-09-09',
            'Description': ''
        }

        get_yaml_or_json_file_mock.return_value = {
            "Resources": "Foo",
            "Transform": "transform-section"
        }

        result = FileLoader.get_cloudformation_template(
            "s3://my-bucket/template.yml", None)

        self.assertEqual(expected, result.get_template_body_dict())
        get_yaml_or_json_file_mock.assert_called_once_with(
            's3://my-bucket/template.yml', None)
Example #38
0
    def create_or_update_stacks(self):
        existing_stacks = self.cfn.get_stack_names()
        desired_stacks = self.config.stacks
        stack_processing_order = DependencyResolver().get_stack_order(desired_stacks)

        if len(stack_processing_order) > 1:
            self.logger.info(
                "Will process stacks in the following order: {0}".format(", ".join(stack_processing_order)))

        for stack_name in stack_processing_order:
            stack_config = self.config.stacks.get(stack_name)

            template = FileLoader.get_cloudformation_template(stack_config.template_url,stack_config.working_dir)
            transformed_template = CloudFormationTemplateTransformer.transform_template(template)

            if stack_config.stack_policy_url:
                self.logger.info("Using stack policy from {0}".format(stack_config.stack_policy_url))
                stack_policy = FileLoader.get_yaml_or_json_file(stack_config.stack_policy_url, stack_config.working_dir)
            else:
                stack_policy = None

            parameters = self.parameter_resolver.resolve_parameter_values(stack_name, stack_config)
            merged_parameters = self.parameter_resolver.update_parameters_with_cli_parameters(
                parameters=parameters,
                cli_parameters=self.cli_parameters,
                stack_name=stack_name)

            self.logger.debug("Parameters after merging with cli options: {0}".format(merged_parameters))

            stack = CloudFormationStack(template=transformed_template,
                                        parameters=merged_parameters,
                                        tags=stack_config.tags,
                                        name=stack_name,
                                        region=self.config.region,
                                        timeout=stack_config.timeout,
                                        service_role=stack_config.service_role,
                                        stack_policy=stack_policy)

            if stack_name in existing_stacks:

                self.cfn.validate_stack_is_ready_for_action(stack)
                self.cfn.update_stack(stack)
            else:
                self.cfn.create_stack(stack)

            CustomResourceHandler.process_post_resources(stack)
    def test_handle_yaml_constructors_converts_split(self):
        loader_mock = Mock()
        loader_mock.construct_scalar.return_value = ["delimiter", "string"]
        node_mock = Mock(spec=yaml.ScalarNode)

        response = FileLoader.handle_yaml_constructors(loader_mock, "!split",
                                                       node_mock)
        self.assertEqual({'Fn::Split': ["delimiter", "string"]}, response)
 def test_get_yaml_or_json_file_accepts_yaml_template_with_getatt_constructor_tag(
         self, get_file_mock):
     get_file_mock.return_value = "myKey: !GetAtt myResource.attributeName"
     result = FileLoader.get_yaml_or_json_file("my-template.yaml", None)
     self.assertEqual(
         {"myKey": {
             "Fn::GetAtt": ["myResource", "attributeName"]
         }}, result)
Example #41
0
def validate_template(template_file, confirm):
    if not confirm:
        check_update_available()

    try:
        loader = FileLoader()
        template = loader.get_file_from_url(template_file, None)
        template = CloudFormationTemplateTransformer.transform_template(template)
        CloudFormation().validate_template(template)
        click.echo("Template is valid")
    except CfnSphereException as e:
        LOGGER.error(e)
        sys.exit(1)
    except Exception as e:
        LOGGER.error("Failed with unexpected error")
        LOGGER.exception(e)
        LOGGER.info("Please report at https://github.com/cfn-sphere/cfn-sphere/issues!")
        sys.exit(1)
Example #42
0
    def handle_file_value(value, working_dir):
        components = value.split('|', 3)

        if len(components) == 3:
            url = components[2]
            return FileLoader.get_file(url, working_dir)
        elif len(components) == 4:
            url = components[2]
            pattern = components[3]
            file_content = FileLoader.get_yaml_or_json_file(url, working_dir)
            try:
                return jmespath.search(pattern, file_content)
            except JMESPathError as e:
                raise CfnSphereException(e)
        else:
            raise CfnSphereException(
                "Invalid format for |File| macro, it must be |File|<path>[|<pattern>]"
            )
Example #43
0
def validate_template(template_file, confirm, yes):
    confirm = confirm or yes
    if not confirm:
        check_update_available()

    try:
        loader = FileLoader()
        template = loader.get_cloudformation_template(template_file, None)
        template = CloudFormationTemplateTransformer.transform_template(template)
        CloudFormation().validate_template(template)
        click.echo("Template is valid")
    except CfnSphereException as e:
        LOGGER.error(e)
        sys.exit(1)
    except Exception as e:
        LOGGER.error("Failed with unexpected error")
        LOGGER.exception(e)
        LOGGER.info("Please report at https://github.com/cfn-sphere/cfn-sphere/issues!")
        sys.exit(1)
Example #44
0
 def get_template(template_url, working_dir, region, package_bucket):
     template = FileLoader.get_cloudformation_template(
         template_url, working_dir)
     additional_stack_description = "Config repo url: {0}".format(
         get_git_repository_remote_url(working_dir))
     template = CloudFormationTemplateTransformer.transform_template(
         template, additional_stack_description)
     template = CloudFormationSamPackager.package(template_url, working_dir,
                                                  template, region,
                                                  package_bucket)
     return template
 def test_get_yaml_or_json_file_accepts_yaml_with_nested_constructor_tags(
         self, get_file_mock):
     get_file_mock.return_value = "myKey: !Join [ b, [ !ref a, !ref b] ]"
     result = FileLoader.get_yaml_or_json_file("my-template.yaml", None)
     self.assertEqual(
         {"myKey": {
             "Fn::Join": ["b", [{
                 "Ref": "a"
             }, {
                 "Ref": "b"
             }]]
         }}, result)
    def resolve_parameter_values(self, stack_name, stack_config, cli_parameters=None):
        resolved_parameters = {}
        stack_outputs = self.cfn.get_stacks_outputs()

        for key, value in stack_config.parameters.items():

            if isinstance(value, list):
                self.logger.debug("List parameter found for {0}".format(key))
                for i, item in enumerate(value):
                    if DependencyResolver.is_parameter_reference(item):
                        referenced_stack, output_name = DependencyResolver.parse_stack_reference_value(item)
                        value[i] = str(self.get_output_value(stack_outputs, referenced_stack, output_name))

                value_string = self.convert_list_to_string(value)
                resolved_parameters[key] = value_string

            elif isinstance(value, str):

                if DependencyResolver.is_parameter_reference(value):
                    referenced_stack, output_name = DependencyResolver.parse_stack_reference_value(value)
                    resolved_parameters[key] = str(self.get_output_value(stack_outputs, referenced_stack, output_name))

                elif self.is_keep_value(value):
                    resolved_parameters[key] = str(self.get_latest_value(key, value, stack_name))

                elif self.is_taupage_ami_reference(value):
                    resolved_parameters[key] = str(self.ec2.get_latest_taupage_image_id())

                elif self.is_kms(value):
                    resolved_parameters[key] = str(self.kms.decrypt(value.split('|', 2)[2]))

                elif self.is_file(value):
                    url = value.split('|', 2)[2]
                    resolved_parameters[key] = FileLoader.get_file(url, stack_config.working_dir)

                else:
                    resolved_parameters[key] = value

            elif isinstance(value, bool):
                resolved_parameters[key] = str(value).lower()
            elif isinstance(value, (int, float)):
                resolved_parameters[key] = str(value)
            else:
                raise NotImplementedError("Cannot handle {0} type for key: {1}".format(type(value), key))

        if cli_parameters:
            return self.update_parameters_with_cli_parameters(resolved_parameters, cli_parameters, stack_name)
        else:
            return resolved_parameters
    def test_get_cloudformation_template_returns_template(self, get_yaml_or_json_file_mock):
        expected = {
            'Conditions': {},
            'Mappings': {},
            'Resources': 'Foo',
            'Parameters': {},
            'Outputs': {},
            'AWSTemplateFormatVersion': '2010-09-09',
            'Description': ''
        }

        get_yaml_or_json_file_mock.return_value = {"Resources": "Foo"}

        response = FileLoader.get_cloudformation_template("s3://my-bucket/template.yml", None)

        self.assertEqual(expected, response.get_template_body_dict())
        get_yaml_or_json_file_mock.assert_called_once_with('s3://my-bucket/template.yml', None)
Example #48
0
    def create_or_update_stacks(self):
        existing_stacks = self.cfn.get_stack_names()
        desired_stacks = self.config.stacks
        stack_processing_order = DependencyResolver().get_stack_order(
            desired_stacks)

        if len(stack_processing_order) > 1:
            self.logger.info(
                "Will process stacks in the following order: {0}".format(
                    ", ".join(stack_processing_order)))

        for stack_name in stack_processing_order:
            stack_config = self.config.stacks.get(stack_name)

            if stack_config.stack_policy_url:
                self.logger.info("Using stack policy from {0}".format(
                    stack_config.stack_policy_url))
                stack_policy = FileLoader.get_yaml_or_json_file(
                    stack_config.stack_policy_url, stack_config.working_dir)
            else:
                stack_policy = None

            template = TemplateHandler.get_template(stack_config.template_url,
                                                    stack_config.working_dir)
            parameters = self.parameter_resolver.resolve_parameter_values(
                stack_name, stack_config, self.cli_parameters)

            stack = CloudFormationStack(
                template=template,
                parameters=parameters,
                tags=stack_config.tags,
                name=stack_name,
                region=self.config.region,
                timeout=stack_config.timeout,
                service_role=stack_config.service_role,
                stack_policy=stack_policy,
                failure_action=stack_config.failure_action)

            if stack_name in existing_stacks:

                self.cfn.validate_stack_is_ready_for_action(stack)
                self.cfn.update_stack(stack)
            else:
                self.cfn.create_stack(stack)

            CustomResourceHandler.process_post_resources(stack)
Example #49
0
    def create_or_update_stacks(self):
        existing_stacks = self.cfn.get_stack_names()
        desired_stacks = self.config.stacks
        stack_processing_order = DependencyResolver().get_stack_order(desired_stacks)

        if len(stack_processing_order) > 1:
            self.logger.info(
                "Will process stacks in the following order: {0}".format(", ".join(stack_processing_order))
            )

        for stack_name in stack_processing_order:
            stack_config = self.config.stacks.get(stack_name)

            if stack_config.stack_policy_url:
                self.logger.info("Using stack policy from {0}".format(stack_config.stack_policy_url))
                stack_policy = FileLoader.get_yaml_or_json_file(stack_config.stack_policy_url, stack_config.working_dir)
            else:
                stack_policy = None

            template = TemplateHandler.get_template(stack_config.template_url, stack_config.working_dir)
            parameters = self.parameter_resolver.resolve_parameter_values(stack_name, stack_config, self.cli_parameters)

            stack = CloudFormationStack(
                template=template,
                parameters=parameters,
                tags=stack_config.tags,
                name=stack_name,
                region=self.config.region,
                timeout=stack_config.timeout,
                service_role=stack_config.service_role,
                stack_policy=stack_policy,
                failure_action=stack_config.failure_action,
            )

            if stack_name in existing_stacks:

                self.cfn.validate_stack_is_ready_for_action(stack)
                self.cfn.update_stack(stack)
            else:
                self.cfn.create_stack(stack)

            CustomResourceHandler.process_post_resources(stack)
Example #50
0
    def create_or_update_stacks(self):
        existing_stacks = self.cfn.get_stack_names()
        desired_stacks = self.config.stacks
        stack_processing_order = DependencyResolver().get_stack_order(
            desired_stacks)

        if len(stack_processing_order) > 1:
            self.logger.info(
                "Will process stacks in the following order: {0}".format(
                    ", ".join(stack_processing_order)))

        for stack_name in stack_processing_order:
            stack_config = self.config.stacks.get(stack_name)

            raw_template = FileLoader.get_file_from_url(
                stack_config.template_url, stack_config.working_dir)
            template = CloudFormationTemplateTransformer.transform_template(
                raw_template)

            parameters = self.parameter_resolver.resolve_parameter_values(
                stack_config.parameters, stack_name)
            stack = CloudFormationStack(template=template,
                                        parameters=parameters,
                                        tags=(stack_config.tags),
                                        name=stack_name,
                                        region=self.region,
                                        timeout=stack_config.timeout)

            if stack_name in existing_stacks:

                self.cfn.validate_stack_is_ready_for_action(stack)
                self.cfn.update_stack(stack)
            else:
                self.cfn.create_stack(stack)

            CustomResourceHandler.process_post_resources(stack)
 def test_get_file_calls_correct_handler_for_S3_prefix(self, s3_get_file_mock):
     FileLoader.get_file("S3://foo/foo.yml", None)
     s3_get_file_mock.assert_called_with("S3://foo/foo.yml")
    def test_fs_get_file_raises_exception_on_json_error(self, _, yaml_mock):
        yaml_mock.load.side_effect = ValueError()

        with self.assertRaises(TemplateErrorException):
            FileLoader._fs_get_file('foo.json', 'baa')
    def test_s3_get_file_parses_yaml_for_yml_suffix(self, s3_mock, json_mock, yaml_mock):
        s3_mock.return_value.get_contents_from_url.return_value = "{}"

        FileLoader._s3_get_file('s3://foo/baa.yml')
        json_mock.assert_not_called()
        yaml_mock.assert_called_once_with("{}")
    def test_s3_get_file_raises_exception_on_error(self, s3_mock):
        s3_mock.return_value.get_contents_from_url.side_effect = CfnSphereBotoError

        with self.assertRaises(CfnSphereException):
            FileLoader._s3_get_file("s3://foo/foo.yml")
 def test_fs_get_file_raises_exception_on_any_error(self, open_mock):
     open_mock.side_effect = IOError
     with self.assertRaises(CfnSphereException):
         FileLoader._fs_get_file("/foo/foo.yml", None)
    def test_s3_get_file__raises_exception_for_unknown_suffix(self, s3_mock, json_mock, yaml_mock):
        s3_mock.return_value.get_contents_from_url.return_value = "{}"

        with self.assertRaises(TemplateErrorException):
            FileLoader._s3_get_file('s3://foo/baa.foo')
    def test_get_yaml_or_json_file_raises_exception_on_json_error(self, _, json_mock):
        json_mock.loads.side_effect = ValueError()

        with self.assertRaises(CfnSphereException):
            FileLoader.get_yaml_or_json_file('foo.json', 'baa')
    def test_get_yaml_or_json_file_raises_exception_on_yaml_error(self, _, yaml_mock):
        yaml_mock.load.side_effect = ScannerError()

        with self.assertRaises(CfnSphereException):
            FileLoader.get_yaml_or_json_file('foo.yml', 'baa')
 def test_get_yaml_or_json_file_raises_exception_invalid_file_extension(self, _):
     with self.assertRaises(CfnSphereException):
         FileLoader.get_yaml_or_json_file('foo.foo', 'baa')
 def test_get_file_calls_correct_handler_for_fs_path(self, fs_get_file_mock):
     FileLoader.get_file("foo/foo.yml", "/home/user")
     fs_get_file_mock.assert_called_with("foo/foo.yml", "/home/user")