コード例 #1
0
    def test_deployment_preference_with_conditional_custom_configuration(self):
        deployment_type = {'Fn::If': ['IsDevEnv', {'Fn::If':
                                                   ['IsDevEnv1', 'AllAtOnce', 'TestDeploymentConfiguration']},
                                      'Canary10Percent15Minutes']}

        expected_deployment_config_name = {'Fn::If':
                                           ['IsDevEnv', {'Fn::If':
                                                         ['IsDevEnv1', {'Fn::Sub': [
                                                                'CodeDeployDefault.Lambda${ConfigName}',
                                                                {
                                                                   'ConfigName': 'AllAtOnce'
                                                                }
                                                            ]
                                                         },
                                                            'TestDeploymentConfiguration']},
                                            {'Fn::Sub': [
                                               'CodeDeployDefault.Lambda${ConfigName}',
                                               {
                                                   'ConfigName': 'Canary10Percent15Minutes'
                                               }
                                                ]
                                             }
                                            ]
                                           }
        deployment_preference_collection = DeploymentPreferenceCollection()
        deployment_preference_collection.add(self.function_logical_id, {'Type': deployment_type})
        deployment_group = deployment_preference_collection.deployment_group(self.function_logical_id)
        print(deployment_group.DeploymentConfigName)
        self.assertEqual(expected_deployment_config_name, deployment_group.DeploymentConfigName)
コード例 #2
0
    def test_deployment_group_with_minimal_parameters(self):
        expected_deployment_group = CodeDeployDeploymentGroup(self.function_logical_id + 'DeploymentGroup')
        expected_deployment_group.ApplicationName = {'Ref': CODEDEPLOY_APPLICATION_LOGICAL_ID}
        expected_deployment_group.AutoRollbackConfiguration = {'Enabled': True,
                                                               'Events': ['DEPLOYMENT_FAILURE',
                                                                          'DEPLOYMENT_STOP_ON_ALARM',
                                                                          'DEPLOYMENT_STOP_ON_REQUEST']}
        expected_deployment_group.DeploymentConfigName = {
            'Fn::Sub': [
                'CodeDeployDefault.Lambda${ConfigName}',
                {
                    'ConfigName': self.deployment_type_global
                }
            ]
        }
        expected_deployment_group.DeploymentStyle = {'DeploymentType': 'BLUE_GREEN',
                                                     'DeploymentOption': 'WITH_TRAFFIC_CONTROL'}
        expected_deployment_group.ServiceRoleArn = {'Fn::GetAtt': [CODE_DEPLOY_SERVICE_ROLE_LOGICAL_ID, 'Arn']}

        deployment_preference_collection = DeploymentPreferenceCollection()
        deployment_preference_collection.add(self.function_logical_id, {'Type': self.deployment_type_global})
        deployment_group = deployment_preference_collection.deployment_group(self.function_logical_id)

        self.assertEqual(deployment_group.to_dict(),
                         expected_deployment_group.to_dict())
コード例 #3
0
    def test_deployment_group_with_all_parameters(self):
        expected_deployment_group = CodeDeployDeploymentGroup(self.function_logical_id + "DeploymentGroup")
        expected_deployment_group.AlarmConfiguration = {
            "Enabled": True,
            "Alarms": [{"Name": {"Ref": "alarm1"}}, {"Name": {"Ref": "alarm2"}}],
        }
        expected_deployment_group.ApplicationName = {"Ref": CODEDEPLOY_APPLICATION_LOGICAL_ID}
        expected_deployment_group.AutoRollbackConfiguration = {
            "Enabled": True,
            "Events": ["DEPLOYMENT_FAILURE", "DEPLOYMENT_STOP_ON_ALARM", "DEPLOYMENT_STOP_ON_REQUEST"],
        }
        expected_deployment_group.DeploymentConfigName = {
            "Fn::Sub": ["CodeDeployDefault.Lambda${ConfigName}", {"ConfigName": self.deployment_type_global}]
        }
        expected_deployment_group.DeploymentStyle = {
            "DeploymentType": "BLUE_GREEN",
            "DeploymentOption": "WITH_TRAFFIC_CONTROL",
        }
        expected_deployment_group.ServiceRoleArn = {"Fn::GetAtt": [CODE_DEPLOY_SERVICE_ROLE_LOGICAL_ID, "Arn"]}

        deployment_preference_collection = DeploymentPreferenceCollection()
        deployment_preference_collection.add(self.function_logical_id, self.global_deployment_preference_yaml_dict())
        deployment_group = deployment_preference_collection.deployment_group(self.function_logical_id)

        self.assertEqual(deployment_group.to_dict(), expected_deployment_group.to_dict())
コード例 #4
0
    def test_deployment_preference_with_conditional_custom_configuration(self):
        deployment_type = {
            "Fn::If": [
                "IsDevEnv",
                {"Fn::If": ["IsDevEnv1", "AllAtOnce", "TestDeploymentConfiguration"]},
                "Canary10Percent15Minutes",
            ]
        }

        expected_deployment_config_name = {
            "Fn::If": [
                "IsDevEnv",
                {
                    "Fn::If": [
                        "IsDevEnv1",
                        {"Fn::Sub": ["CodeDeployDefault.Lambda${ConfigName}", {"ConfigName": "AllAtOnce"}]},
                        "TestDeploymentConfiguration",
                    ]
                },
                {"Fn::Sub": ["CodeDeployDefault.Lambda${ConfigName}", {"ConfigName": "Canary10Percent15Minutes"}]},
            ]
        }
        deployment_preference_collection = DeploymentPreferenceCollection()
        deployment_preference_collection.add(self.function_logical_id, {"Type": deployment_type})
        deployment_group = deployment_preference_collection.deployment_group(self.function_logical_id)
        print(deployment_group.DeploymentConfigName)
        self.assertEqual(expected_deployment_config_name, deployment_group.DeploymentConfigName)
コード例 #5
0
    def test_deployment_preference_with_alarms_intrinsic_if_noref_else(self):
        deployment_preference = {
            "Type": "TestDeploymentConfiguration",
            "Alarms": {
                "Fn::If": [
                    "MyCondition", ["Alarm1", "Alarm2"],
                    [{
                        "Ref": "AWS::NoValue"
                    }]
                ]
            },
        }
        expected_alarm_configuration = {
            "Fn::If": [
                "MyCondition", {
                    "Enabled": True,
                    "Alarms": [{
                        "Name": "Alarm1"
                    }, {
                        "Name": "Alarm2"
                    }]
                }, {}
            ],
        }
        deployment_preference_collection = DeploymentPreferenceCollection()
        deployment_preference_collection.add(self.function_logical_id,
                                             deployment_preference)
        deployment_group = deployment_preference_collection.deployment_group(
            self.function_logical_id)

        self.assertEqual(expected_alarm_configuration,
                         deployment_group.AlarmConfiguration)
コード例 #6
0
    def test_deployment_preference_with_codedeploy_custom_configuration(self):
        deployment_type = "TestDeploymentConfiguration"
        deployment_preference_collection = DeploymentPreferenceCollection()
        deployment_preference_collection.add(self.function_logical_id, {'Type': deployment_type})
        deployment_group = deployment_preference_collection.deployment_group(self.function_logical_id)

        self.assertEqual(deployment_type, deployment_group.DeploymentConfigName)
コード例 #7
0
    def test_deployment_preference_with_codedeploy_predifined_configuration(self):
        deployment_type = "Canary10Percent5Minutes"
        expected_deployment_config_name = {
            "Fn::Sub": ["CodeDeployDefault.Lambda${ConfigName}", {"ConfigName": deployment_type}]
        }
        deployment_preference_collection = DeploymentPreferenceCollection()
        deployment_preference_collection.add(self.function_logical_id, {"Type": deployment_type})
        deployment_group = deployment_preference_collection.deployment_group(self.function_logical_id)

        print(deployment_group.DeploymentConfigName)
        self.assertEqual(expected_deployment_config_name, deployment_group.DeploymentConfigName)
コード例 #8
0
    def test_deployment_preference_with_alarms_empty(self):
        deployment_preference = {
            "Type": "TestDeploymentConfiguration",
            "Alarms": [],
        }
        deployment_preference_collection = DeploymentPreferenceCollection()
        deployment_preference_collection.add(self.function_logical_id,
                                             deployment_preference)
        deployment_group = deployment_preference_collection.deployment_group(
            self.function_logical_id)

        self.assertIsNone(deployment_group.AlarmConfiguration)
コード例 #9
0
    def test_update_policy_with_minimal_parameters(self):
        expected_update_policy = {
            'CodeDeployLambdaAliasUpdate': {
                'ApplicationName': {'Ref': CODEDEPLOY_APPLICATION_LOGICAL_ID},
                'DeploymentGroupName': {'Ref': self.function_logical_id + 'DeploymentGroup'},
            }
        }

        deployment_preference_collection = DeploymentPreferenceCollection()
        deployment_preference_collection.add(self.function_logical_id, {'Type': 'CANARY'})
        update_policy = deployment_preference_collection.update_policy(self.function_logical_id)

        self.assertEqual(expected_update_policy, update_policy.to_dict())
コード例 #10
0
    def test_update_policy_with_minimal_parameters(self):
        expected_update_policy = {
            "CodeDeployLambdaAliasUpdate": {
                "ApplicationName": {"Ref": CODEDEPLOY_APPLICATION_LOGICAL_ID},
                "DeploymentGroupName": {"Ref": self.function_logical_id + "DeploymentGroup"},
            }
        }

        deployment_preference_collection = DeploymentPreferenceCollection()
        deployment_preference_collection.add(self.function_logical_id, {"Type": "CANARY"})
        update_policy = deployment_preference_collection.update_policy(self.function_logical_id)

        self.assertEqual(expected_update_policy, update_policy.to_dict())
コード例 #11
0
    def test_deployment_preference_with_alarms_ref_novalue(self):
        deployment_preference = {
            "Type": "TestDeploymentConfiguration",
            "Alarms": {
                "Ref": "AWS::NoValue"
            },
        }
        deployment_preference_collection = DeploymentPreferenceCollection()
        deployment_preference_collection.add(self.function_logical_id,
                                             deployment_preference)
        deployment_group = deployment_preference_collection.deployment_group(
            self.function_logical_id)

        self.assertIsNone(deployment_group.AlarmConfiguration)
コード例 #12
0
    def test_update_policy_with_all_parameters(self):
        expected_update_polcy = {
            'CodeDeployLambdaAliasUpdate': {
                'ApplicationName': {'Ref': CODEDEPLOY_APPLICATION_LOGICAL_ID},
                'DeploymentGroupName': {'Ref': self.function_logical_id + 'DeploymentGroup'},
                'BeforeAllowTrafficHook': self.pre_traffic_hook_global,
                'AfterAllowTrafficHook': self.post_traffic_host_global,
            }
        }

        deployment_preference_collection = DeploymentPreferenceCollection()
        deployment_preference_collection.add(self.function_logical_id, self.global_deployment_preference_yaml_dict())
        update_policy = deployment_preference_collection.update_policy(self.function_logical_id)

        self.assertEqual(expected_update_polcy, update_policy.to_dict())
コード例 #13
0
    def test_any_enabled_true_if_all_of_three_enabled(self):
        deployment_preference_collection = DeploymentPreferenceCollection()
        deployment_preference_collection.add('1', {'Type': 'LINEAR'})
        deployment_preference_collection.add('2', {
            'Type': 'LINEAR',
            'Enabled': True
        })
        deployment_preference_collection.add('3', {
            'Type': 'CANARY',
            'Enabled': True
        })

        self.assertTrue(deployment_preference_collection.any_enabled())
    def test_any_enabled_true_if_all_of_three_enabled(self):
        deployment_preference_collection = DeploymentPreferenceCollection()
        deployment_preference_collection.add("1", {"Type": "LINEAR"})
        deployment_preference_collection.add("2", {
            "Type": "LINEAR",
            "Enabled": True
        })
        deployment_preference_collection.add("3", {
            "Type": "CANARY",
            "Enabled": True
        })

        self.assertTrue(deployment_preference_collection.any_enabled())
コード例 #15
0
    def test_codedeploy_application(self):
        expected_codedeploy_application_resource = CodeDeployApplication(CODEDEPLOY_APPLICATION_LOGICAL_ID)
        expected_codedeploy_application_resource.ComputePlatform = "Lambda"

        self.assertEqual(
            DeploymentPreferenceCollection().codedeploy_application.to_dict(),
            expected_codedeploy_application_resource.to_dict(),
        )
コード例 #16
0
    def test_any_enabled_false_if_all_of_three_disabled(self):
        deployment_preference_collection = DeploymentPreferenceCollection()
        deployment_preference_collection.add("1", {"Type": "Linear", "Enabled": False})
        deployment_preference_collection.add("2", {"Type": "LINEAR", "Enabled": False})
        deployment_preference_collection.add("3", {"Type": "CANARY", "Enabled": False})

        self.assertFalse(deployment_preference_collection.any_enabled())
コード例 #17
0
    def test_any_enabled_false_if_all_of_three_disabled(self):
        deployment_preference_collection = DeploymentPreferenceCollection()
        deployment_preference_collection.add('1', {'Type': 'Linear', 'Enabled': False})
        deployment_preference_collection.add('2', {'Type': 'LINEAR', 'Enabled': False})
        deployment_preference_collection.add('3', {'Type': 'CANARY', 'Enabled': False})

        self.assertFalse(deployment_preference_collection.any_enabled())
コード例 #18
0
    def test_enabled_logical_ids_returns_one_if_one_of_three_enabled(self):
        deployment_preference_collection = DeploymentPreferenceCollection()
        enabled_logical_id = "1"
        deployment_preference_collection.add(enabled_logical_id, {"Type": "LINEAR"})
        deployment_preference_collection.add("2", {"Type": "LINEAR", "Enabled": False})
        deployment_preference_collection.add("3", {"Type": "CANARY", "Enabled": False})

        enabled_logical_ids = deployment_preference_collection.enabled_logical_ids()
        self.assertEqual(1, len(enabled_logical_ids))
        self.assertEqual(enabled_logical_id, enabled_logical_ids[0])
コード例 #19
0
    def test_enabled_logical_ids_returns_one_if_one_of_three_enabled(self):
        deployment_preference_collection = DeploymentPreferenceCollection()
        enabled_logical_id = '1'
        deployment_preference_collection.add(enabled_logical_id,
                                             {'Type': 'LINEAR'})
        deployment_preference_collection.add('2', {
            'Type': 'LINEAR',
            'Enabled': False
        })
        deployment_preference_collection.add('3', {
            'Type': 'CANARY',
            'Enabled': False
        })

        enabled_logical_ids = deployment_preference_collection.enabled_logical_ids(
        )
        self.assertEqual(1, len(enabled_logical_ids))
        self.assertEqual(enabled_logical_id, enabled_logical_ids[0])
コード例 #20
0
    def test_codedeploy_iam_role(self):
        expected_codedeploy_iam_role = IAMRole('CodeDeployServiceRole')
        expected_codedeploy_iam_role.AssumeRolePolicyDocument = {
            'Version': '2012-10-17',
            'Statement': [{
                'Action': ['sts:AssumeRole'],
                'Effect': 'Allow',
                'Principal': {'Service': ['codedeploy.amazonaws.com']}
            }]
        }
        expected_codedeploy_iam_role.ManagedPolicyArns = ['arn:aws:iam::aws:policy/service-role/AWSCodeDeployRoleForLambda']

        self.assertEqual(DeploymentPreferenceCollection().codedeploy_iam_role.to_dict(),
                         expected_codedeploy_iam_role.to_dict())
コード例 #21
0
    def test_deployment_preference_with_alarms(self):
        deployment_preference = {
            "Type": "TestDeploymentConfiguration",
            "Alarms": ["Alarm1", "Alarm2", "Alarm3"],
        }
        expected_alarm_configuration = {
            "Enabled": True,
            "Alarms": [{
                "Name": "Alarm1"
            }, {
                "Name": "Alarm2"
            }, {
                "Name": "Alarm3"
            }],
        }
        deployment_preference_collection = DeploymentPreferenceCollection()
        deployment_preference_collection.add(self.function_logical_id,
                                             deployment_preference)
        deployment_group = deployment_preference_collection.deployment_group(
            self.function_logical_id)

        self.assertEqual(expected_alarm_configuration,
                         deployment_group.AlarmConfiguration)
コード例 #22
0
    def test_codedeploy_iam_role_contains_AWSCodeDeployRoleForLambda_managedpolicy(
            self, partition):

        with patch(
                "samtranslator.translator.arn_generator.ArnGenerator.get_partition_name"
        ) as get_partition_name_patch:
            get_partition_name_patch.return_value = partition

            iam_role = DeploymentPreferenceCollection().codedeploy_iam_role

            self.assertIn(
                "arn:{}:iam::aws:policy/service-role/AWSCodeDeployRoleForLambda"
                .format(partition),
                iam_role.ManagedPolicyArns,
            )
コード例 #23
0
    def test_codedeploy_iam_role(self):
        expected_codedeploy_iam_role = IAMRole("CodeDeployServiceRole")
        expected_codedeploy_iam_role.AssumeRolePolicyDocument = {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Action": ["sts:AssumeRole"],
                    "Effect": "Allow",
                    "Principal": {"Service": ["codedeploy.amazonaws.com"]},
                }
            ],
        }
        expected_codedeploy_iam_role.ManagedPolicyArns = [
            "arn:aws:iam::aws:policy/service-role/AWSCodeDeployRoleForLambda"
        ]

        self.assertEqual(
            DeploymentPreferenceCollection().codedeploy_iam_role.to_dict(), expected_codedeploy_iam_role.to_dict()
        )
コード例 #24
0
 def test_deployment_preference_with_alarms_not_list(self):
     deployment_preference = {
         "Type": "TestDeploymentConfiguration",
         "Alarms": "Alarm1",
     }
     deployment_preference_collection = DeploymentPreferenceCollection()
     deployment_preference_collection.add(self.function_logical_id,
                                          deployment_preference)
     with self.assertRaises(InvalidResourceException) as e:
         deployment_preference_collection.deployment_group(
             self.function_logical_id)
     self.assertEqual(
         e.exception.message,
         "Resource with id [{}] is invalid. Alarms must be a list".format(
             self.function_logical_id),
     )
コード例 #25
0
 def test_deployment_preference_with_alarms_intrinsic_if_missing_arg(self):
     deployment_preference = {
         "Type": "TestDeploymentConfiguration",
         "Alarms": {
             "Fn::If": ["MyCondition", ["Alarm1", "Alarm2"]]
         },
     }
     deployment_preference_collection = DeploymentPreferenceCollection()
     deployment_preference_collection.add(self.function_logical_id,
                                          deployment_preference)
     with self.assertRaises(InvalidResourceException) as e:
         deployment_preference_collection.deployment_group(
             self.function_logical_id)
     self.assertEqual(
         e.exception.message,
         "Resource with id [{}] is invalid. Fn::If requires 3 arguments".
         format(self.function_logical_id),
     )
コード例 #26
0
    def translate(self, sam_template, parameter_values, feature_toggle=None):
        """Loads the SAM resources from the given SAM manifest, replaces them with their corresponding
        CloudFormation resources, and returns the resulting CloudFormation template.

        :param dict sam_template: the SAM manifest, as loaded by json.load() or yaml.load(), or as provided by \
                CloudFormation transforms.
        :param dict parameter_values: Map of template parameter names to their values. It is a required parameter that
                should at least be an empty map. By providing an empty map, the caller explicitly opts-into the idea
                that some functionality that relies on resolving parameter references might not work as expected
                (ex: auto-creating new Lambda Version when CodeUri contains reference to template parameter). This is
                why this parameter is required

        :returns: a copy of the template with SAM resources replaced with the corresponding CloudFormation, which may \
                be dumped into a valid CloudFormation JSON or YAML template
        """
        self.feature_toggle = (feature_toggle
                               if feature_toggle else FeatureToggle(
                                   FeatureToggleDefaultConfigProvider(),
                                   stage=None,
                                   account_id=None,
                                   region=None))
        self.function_names = dict()
        self.redeploy_restapi_parameters = dict()
        sam_parameter_values = SamParameterValues(parameter_values)
        sam_parameter_values.add_default_parameter_values(sam_template)
        sam_parameter_values.add_pseudo_parameter_values(self.boto_session)
        parameter_values = sam_parameter_values.parameter_values
        # Create & Install plugins
        sam_plugins = prepare_plugins(self.plugins, parameter_values)

        self.sam_parser.parse(sam_template=sam_template,
                              parameter_values=parameter_values,
                              sam_plugins=sam_plugins)

        template = copy.deepcopy(sam_template)
        macro_resolver = ResourceTypeResolver(sam_resources)
        intrinsics_resolver = IntrinsicsResolver(parameter_values)
        mappings_resolver = IntrinsicsResolver(
            template.get("Mappings", {}),
            {FindInMapAction.intrinsic_name: FindInMapAction()})
        deployment_preference_collection = DeploymentPreferenceCollection()
        supported_resource_refs = SupportedResourceReferences()
        shared_api_usage_plan = SharedApiUsagePlan()
        document_errors = []
        changed_logical_ids = {}
        for logical_id, resource_dict in self._get_resources_to_iterate(
                sam_template, macro_resolver):
            try:
                macro = macro_resolver.resolve_resource_type(
                    resource_dict).from_dict(logical_id,
                                             resource_dict,
                                             sam_plugins=sam_plugins)

                kwargs = macro.resources_to_link(sam_template["Resources"])
                kwargs["managed_policy_map"] = self.managed_policy_map
                kwargs["intrinsics_resolver"] = intrinsics_resolver
                kwargs["mappings_resolver"] = mappings_resolver
                kwargs[
                    "deployment_preference_collection"] = deployment_preference_collection
                kwargs["conditions"] = template.get("Conditions")
                # add the value of FunctionName property if the function is referenced with the api resource
                self.redeploy_restapi_parameters[
                    "function_names"] = self._get_function_names(
                        resource_dict, intrinsics_resolver)
                kwargs[
                    "redeploy_restapi_parameters"] = self.redeploy_restapi_parameters
                kwargs["shared_api_usage_plan"] = shared_api_usage_plan
                translated = macro.to_cloudformation(**kwargs)

                supported_resource_refs = macro.get_resource_references(
                    translated, supported_resource_refs)

                # Some resources mutate their logical ids. Track those to change all references to them:
                if logical_id != macro.logical_id:
                    changed_logical_ids[logical_id] = macro.logical_id

                del template["Resources"][logical_id]
                for resource in translated:
                    if verify_unique_logical_id(resource,
                                                sam_template["Resources"]):
                        template["Resources"].update(resource.to_dict())
                    else:
                        document_errors.append(
                            DuplicateLogicalIdException(
                                logical_id, resource.logical_id,
                                resource.resource_type))
            except (InvalidResourceException, InvalidEventException) as e:
                document_errors.append(e)

        if deployment_preference_collection.any_enabled():
            template["Resources"].update(deployment_preference_collection.
                                         codedeploy_application.to_dict())

            if not deployment_preference_collection.can_skip_service_role():
                template["Resources"].update(deployment_preference_collection.
                                             codedeploy_iam_role.to_dict())

            for logical_id in deployment_preference_collection.enabled_logical_ids(
            ):
                try:
                    template["Resources"].update(
                        deployment_preference_collection.deployment_group(
                            logical_id).to_dict())
                except InvalidResourceException as e:
                    document_errors.append(e)

        # Run the after-transform plugin target
        try:
            sam_plugins.act(LifeCycleEvents.after_transform_template, template)
        except (InvalidDocumentException, InvalidResourceException) as e:
            document_errors.append(e)

        # Cleanup
        if "Transform" in template:
            del template["Transform"]

        if len(document_errors) == 0:
            template = intrinsics_resolver.resolve_sam_resource_id_refs(
                template, changed_logical_ids)
            template = intrinsics_resolver.resolve_sam_resource_refs(
                template, supported_resource_refs)
            return template
        else:
            raise InvalidDocumentException(document_errors)
コード例 #27
0
    def translate(self, sam_template, parameter_values):
        """Loads the SAM resources from the given SAM manifest, replaces them with their corresponding
        CloudFormation resources, and returns the resulting CloudFormation template.

        :param dict sam_template: the SAM manifest, as loaded by json.load() or yaml.load(), or as provided by \
                CloudFormation transforms.
        :param dict parameter_values: Map of template parameter names to their values. It is a required parameter that
                should at least be an empty map. By providing an empty map, the caller explicitly opts-into the idea
                that some functionality that relies on resolving parameter references might not work as expected
                (ex: auto-creating new Lambda Version when CodeUri contains reference to template parameter). This is
                why this parameter is required

        :returns: a copy of the template with SAM resources replaced with the corresponding CloudFormation, which may \
                be dumped into a valid CloudFormation JSON or YAML template
        """
        sam_parameter_values = SamParameterValues(parameter_values)
        sam_parameter_values.add_default_parameter_values(sam_template)
        sam_parameter_values.add_pseudo_parameter_values()
        parameter_values = sam_parameter_values.parameter_values
        # Create & Install plugins
        sam_plugins = prepare_plugins(self.plugins, parameter_values)

        self.sam_parser.parse(
            sam_template=sam_template,
            parameter_values=parameter_values,
            sam_plugins=sam_plugins
        )

        template = copy.deepcopy(sam_template)
        macro_resolver = ResourceTypeResolver(sam_resources)
        intrinsics_resolver = IntrinsicsResolver(parameter_values)
        deployment_preference_collection = DeploymentPreferenceCollection()
        supported_resource_refs = SupportedResourceReferences()
        document_errors = []
        changed_logical_ids = {}

        for logical_id, resource_dict in self._get_resources_to_iterate(sam_template, macro_resolver):
            try:
                macro = macro_resolver\
                    .resolve_resource_type(resource_dict)\
                    .from_dict(logical_id, resource_dict, sam_plugins=sam_plugins)

                kwargs = macro.resources_to_link(sam_template['Resources'])
                kwargs['managed_policy_map'] = self.managed_policy_map
                kwargs['intrinsics_resolver'] = intrinsics_resolver
                kwargs['deployment_preference_collection'] = deployment_preference_collection
                translated = macro.to_cloudformation(**kwargs)

                supported_resource_refs = macro.get_resource_references(translated, supported_resource_refs)

                # Some resources mutate their logical ids. Track those to change all references to them:
                if logical_id != macro.logical_id:
                    changed_logical_ids[logical_id] = macro.logical_id

                del template['Resources'][logical_id]
                for resource in translated:
                    if verify_unique_logical_id(resource, sam_template['Resources']):
                        template['Resources'].update(resource.to_dict())
                    else:
                        document_errors.append(DuplicateLogicalIdException(
                            logical_id, resource.logical_id, resource.resource_type))
            except (InvalidResourceException, InvalidEventException) as e:
                document_errors.append(e)

        if deployment_preference_collection.any_enabled():
            template['Resources'].update(deployment_preference_collection.codedeploy_application.to_dict())

            if not deployment_preference_collection.can_skip_service_role():
                template['Resources'].update(deployment_preference_collection.codedeploy_iam_role.to_dict())

            for logical_id in deployment_preference_collection.enabled_logical_ids():
                template['Resources'].update(deployment_preference_collection.deployment_group(logical_id).to_dict())

        # Run the after-transform plugin target
        try:
            sam_plugins.act(LifeCycleEvents.after_transform_template, template)
        except (InvalidDocumentException, InvalidResourceException) as e:
            document_errors.append(e)

        # Cleanup
        if 'Transform' in template:
            del template['Transform']

        if len(document_errors) == 0:
            template = intrinsics_resolver.resolve_sam_resource_id_refs(template, changed_logical_ids)
            template = intrinsics_resolver.resolve_sam_resource_refs(template, supported_resource_refs)
            return template
        else:
            raise InvalidDocumentException(document_errors)
コード例 #28
0
 def test_add_when_logical_id_previously_added_raises_value_error(self):
     with self.assertRaises(ValueError):
         deployment_preference_collection = DeploymentPreferenceCollection()
         deployment_preference_collection.add('1', {'Type': 'Canary'})
         deployment_preference_collection.add('1', {'Type': 'Linear'})
コード例 #29
0
    def translate(self, sam_template, parameter_values):
        """Loads the SAM resources from the given SAM manifest, replaces them with their corresponding
        CloudFormation resources, and returns the resulting CloudFormation template.

        :param dict sam_template: the SAM manifest, as loaded by json.load() or yaml.load(), or as provided by \
                CloudFormation transforms.
        :param dict parameter_values: Map of template parameter names to their values. It is a required parameter that
                should at least be an empty map. By providing an empty map, the caller explicitly opts-into the idea that
                some functionality that relies on resolving parameter references might not work as expected
                (ex: auto-creating new Lambda Version when CodeUri contains reference to template parameter). This is why
                this parameter is required

        :returns: a copy of the template with SAM resources replaced with the corresponding CloudFormation, which may \
                be dumped into a valid CloudFormation JSON or YAML template
        """
        # Create & Install plugins
        sam_plugins = prepare_plugins(self.plugins)
        parameter_values = self._add_default_parameter_values(
            sam_template, parameter_values)

        self.sam_parser.parse(sam_template=sam_template,
                              parameter_values=parameter_values,
                              sam_plugins=sam_plugins)

        template = copy.deepcopy(sam_template)
        macro_resolver = ResourceTypeResolver(sam_resources)
        intrinsics_resolver = IntrinsicsResolver(parameter_values)
        deployment_preference_collection = DeploymentPreferenceCollection()
        supported_resource_refs = SupportedResourceReferences()
        document_errors = []
        changed_logical_ids = {}

        for logical_id, resource_dict in self._get_resources_to_iterate(
                sam_template, macro_resolver):
            try:
                macro = macro_resolver\
                    .resolve_resource_type(resource_dict)\
                    .from_dict(logical_id, resource_dict, sam_plugins=sam_plugins)

                kwargs = macro.resources_to_link(sam_template['Resources'])
                kwargs['managed_policy_map'] = self.managed_policy_map
                kwargs['intrinsics_resolver'] = intrinsics_resolver
                kwargs[
                    'deployment_preference_collection'] = deployment_preference_collection
                translated = macro.to_cloudformation(**kwargs)

                supported_resource_refs = macro.get_resource_references(
                    translated, supported_resource_refs)

                # Some resources mutate their logical ids. Track those to change all references to them:
                if logical_id != macro.logical_id:
                    changed_logical_ids[logical_id] = macro.logical_id

                del template['Resources'][logical_id]
                for resource in translated:
                    if verify_unique_logical_id(resource,
                                                sam_template['Resources']):
                        template['Resources'].update(resource.to_dict())
                    else:
                        document_errors.append(
                            DuplicateLogicalIdException(
                                logical_id, resource.logical_id,
                                resource.resource_type))
            except (InvalidResourceException, InvalidEventException) as e:
                document_errors.append(e)

        if deployment_preference_collection.any_enabled():
            template['Resources'].update(deployment_preference_collection.
                                         codedeploy_application.to_dict())

            if not deployment_preference_collection.can_skip_service_role():
                template['Resources'].update(deployment_preference_collection.
                                             codedeploy_iam_role.to_dict())

            for logical_id in deployment_preference_collection.enabled_logical_ids(
            ):
                template['Resources'].update(
                    deployment_preference_collection.deployment_group(
                        logical_id).to_dict())

        # Run the after-transform plugin target
        try:
            sam_plugins.act(LifeCycleEvents.after_transform_template, template)
        except (InvalidDocumentException, InvalidResourceException) as e:
            document_errors.append(e)

        # Cleanup
        if 'Transform' in template:
            del template['Transform']

        if len(document_errors) is 0:
            template = intrinsics_resolver.resolve_sam_resource_id_refs(
                template, changed_logical_ids)
            template = intrinsics_resolver.resolve_sam_resource_refs(
                template, supported_resource_refs)
            return template
        else:
            raise InvalidDocumentException(document_errors)
 def test_add_when_logical_id_previously_added_raises_value_error(self):
     with self.assertRaises(ValueError):
         deployment_preference_collection = DeploymentPreferenceCollection()
         deployment_preference_collection.add("1", {"Type": "Canary"})
         deployment_preference_collection.add("1", {"Type": "Linear"})
 def test_when_no_global_dict_each_local_deployment_preference_requires_parameters(
         self):
     with self.assertRaises(InvalidResourceException):
         DeploymentPreferenceCollection().add("", dict())