def on_before_transform_template(self, template_dict): """ Hook method that gets called before the SAM template is processed. The template has passed the validation and is guaranteed to contain a non-empty "Resources" section. :param dict template_dict: Dictionary of the SAM template :return: Nothing """ template = SamTemplate(template_dict) for api_type in [ SamResourceType.Api.value, SamResourceType.HttpApi.value ]: for logicalId, api in template.iterate({api_type}): if api.properties.get("DefinitionBody") or api.properties.get( "DefinitionUri"): continue if api_type is SamResourceType.HttpApi.value: # If "Properties" is not set in the template, set them here if not api.properties: template.set(logicalId, api) api.properties[ "DefinitionBody"] = OpenApiEditor.gen_skeleton() if api_type is SamResourceType.Api.value: api.properties[ "DefinitionBody"] = SwaggerEditor.gen_skeleton() api.properties["__MANAGE_SWAGGER"] = True
def _validate(self, sam_template, parameter_values): """ Validates the template and parameter values and raises exceptions if there's an issue :param dict sam_template: SAM template :param dict parameter_values: Dictionary of parameter values provided by the user """ if parameter_values is None: raise ValueError("`parameter_values` argument is required") if ("Resources" not in sam_template or not isinstance(sam_template["Resources"], dict) or not sam_template["Resources"]): raise InvalidDocumentException( [InvalidTemplateException("'Resources' section is required")]) if (not all(isinstance(sam_resource, dict) for sam_resource in sam_template["Resources"].values())): raise InvalidDocumentException( [InvalidTemplateException( "All 'Resources' must be Objects. If you're using YAML, this may be an " "indentation issue." )]) sam_template_instance = SamTemplate(sam_template) for resource_logical_id, sam_resource in sam_template_instance.iterate(): # NOTE: Properties isn't required for SimpleTable, so we can't check # `not isinstance(sam_resources.get("Properties"), dict)` as this would be a breaking change. # sam_resource.properties defaults to {} in SamTemplate init if (not isinstance(sam_resource.properties, dict)): raise InvalidDocumentException( [InvalidResourceException(resource_logical_id, "All 'Resources' must be Objects and have a 'Properties' Object. If " "you're using YAML, this may be an indentation issue." )]) SamTemplateValidator.validate(sam_template)
def on_before_transform_template(self, template_dict): """ Hook method that gets called before the SAM template is processed. The template has passed the validation and is guaranteed to contain a non-empty "Resources" section. This plugin needs to run as soon as possible to allow some time for templates to become available. This verifies that the user has access to all specified applications. :param dict template_dict: Dictionary of the SAM template :return: Nothing """ template = SamTemplate(template_dict) service_call = None if self._validate_only: service_call = self._handle_get_application_request else: service_call = self._handle_create_cfn_template_request for logical_id, app in template.iterate(SamResourceType.Application.value): if not self._can_process_application(app): # Handle these cases in the on_before_transform_resource event continue app_id = app.properties[self.LOCATION_KEY].get(self.APPLICATION_ID_KEY) semver = app.properties[self.LOCATION_KEY].get(self.SEMANTIC_VERSION_KEY) key = (app_id, semver) if key not in self._applications: try: service_call(app_id, semver, key, logical_id) except InvalidResourceException as e: # Catch all InvalidResourceExceptions, raise those in the before_resource_transform target. self._applications[key] = e
def on_before_transform_template(self, template_dict): """ Hook method that runs before a template gets transformed. In this method, we parse and process Globals section from the template (if present). :param dict template_dict: SAM template as a dictionary """ try: global_section = Globals(template_dict) except InvalidGlobalsSectionException as ex: raise InvalidDocumentException([ex]) # For each resource in template, try and merge with Globals if necessary template = SamTemplate(template_dict) for logicalId, resource in template.iterate(): resource.properties = global_section.merge(resource.type, resource.properties) template.set(logicalId, resource) # Remove the Globals section from template if necessary Globals.del_section(template_dict) # If there was a global openApiVersion flag, check and convert swagger # to the right version Globals.fix_openapi_definitions(template_dict)
def on_before_transform_template(self, template_dict): """ Hook method that gets called before the SAM template is processed. The template has passed the validation and is guaranteed to contain a non-empty "Resources" section. This plugin needs to run as soon as possible to allow some time for templates to become available. This verifies that the user has access to all specified applications. :param dict template_dict: Dictionary of the SAM template :return: Nothing """ template = SamTemplate(template_dict) intrinsic_resolvers = self._get_intrinsic_resolvers( template_dict.get("Mappings", {})) service_call = None if self._validate_only: service_call = self._handle_get_application_request else: service_call = self._handle_create_cfn_template_request for logical_id, app in template.iterate( {SamResourceType.Application.value}): if not self._can_process_application(app): # Handle these cases in the on_before_transform_resource event continue app_id = self._replace_value(app.properties[self.LOCATION_KEY], self.APPLICATION_ID_KEY, intrinsic_resolvers) semver = self._replace_value(app.properties[self.LOCATION_KEY], self.SEMANTIC_VERSION_KEY, intrinsic_resolvers) if isinstance(app_id, dict) or isinstance(semver, dict): key = (json.dumps(app_id), json.dumps(semver)) self._applications[key] = False continue key = (app_id, semver) if key not in self._applications: try: if not RegionConfiguration.is_sar_supported(): raise InvalidResourceException( logical_id, "Serverless Application Repository is not available in this region." ) # Lazy initialization of the client- create it when it is needed if not self._sar_client: self._sar_client = boto3.client("serverlessrepo") service_call(app_id, semver, key, logical_id) except InvalidResourceException as e: # Catch all InvalidResourceExceptions, raise those in the before_resource_transform target. self._applications[key] = e
def on_before_transform_template(self, template_dict): """ Hook method that gets called before the SAM template is processed. The template has pass the validation and is guaranteed to contain a non-empty "Resources" section. :param dict template_dict: Dictionary of the SAM template :return: Nothing """ template = SamTemplate(template_dict) # Temporarily add Serverless::Api resource corresponding to Implicit API to the template. # This will allow the processing code to work the same way for both Implicit & Explicit APIs # If there are no implicit APIs, we will remove from the template later. # If the customer has explicitly defined a resource with the id of "ServerlessRestApi", # capture it. If the template ends up not defining any implicit api's, instead of just # removing the "ServerlessRestApi" resource, we just restore what the author defined. self.existing_implicit_api_resource = copy.deepcopy( template.get(self.implicit_api_logical_id)) template.set(self.implicit_api_logical_id, self._generate_implicit_api_resource()) errors = [] for logicalId, resource in template.iterate({ SamResourceType.Function.value, SamResourceType.StateMachine.value }): api_events = self._get_api_events(resource) condition = resource.condition deletion_policy = resource.deletion_policy update_replace_policy = resource.update_replace_policy if len(api_events) == 0: continue try: self._process_api_events(resource, api_events, template, condition, deletion_policy, update_replace_policy) except InvalidEventException as ex: errors.append(InvalidResourceException(logicalId, ex.message)) self._maybe_add_condition_to_implicit_api(template_dict) self._maybe_add_deletion_policy_to_implicit_api(template_dict) self._maybe_add_update_replace_policy_to_implicit_api(template_dict) self._maybe_add_conditions_to_implicit_api_paths(template) self._maybe_remove_implicit_api(template) if len(errors) > 0: raise InvalidDocumentException(errors)
def on_before_transform_template(self, template_dict): """ Hook method that gets called before the SAM template is processed. The template has passed the validation and is guaranteed to contain a non-empty "Resources" section. :param dict template_dict: Dictionary of the SAM template :return: Nothing """ template = SamTemplate(template_dict) for logicalId, api in template.iterate(SamResourceType.Api.value): if api.properties.get('DefinitionBody') or api.properties.get('DefinitionUri'): continue api.properties['DefinitionBody'] = SwaggerEditor.gen_skeleton() api.properties['__MANAGE_SWAGGER'] = True
def _validate(self, sam_template, parameter_values): """ Validates the template and parameter values and raises exceptions if there's an issue :param dict sam_template: SAM template :param dict parameter_values: Dictionary of parameter values provided by the user """ if parameter_values is None: raise ValueError("`parameter_values` argument is required") if ( "Resources" not in sam_template or not isinstance(sam_template["Resources"], dict) or not sam_template["Resources"] ): raise InvalidDocumentException([InvalidTemplateException("'Resources' section is required")]) if not all(isinstance(sam_resource, dict) for sam_resource in sam_template["Resources"].values()): raise InvalidDocumentException( [ InvalidTemplateException( "All 'Resources' must be Objects. If you're using YAML, this may be an " "indentation issue." ) ] ) sam_template_instance = SamTemplate(sam_template) for resource_logical_id, sam_resource in sam_template_instance.iterate(): # NOTE: Properties isn't required for SimpleTable, so we can't check # `not isinstance(sam_resources.get("Properties"), dict)` as this would be a breaking change. # sam_resource.properties defaults to {} in SamTemplate init if not isinstance(sam_resource.properties, dict): raise InvalidDocumentException( [ InvalidResourceException( resource_logical_id, "All 'Resources' must be Objects and have a 'Properties' Object. If " "you're using YAML, this may be an indentation issue.", ) ] ) SamTemplateValidator.validate(sam_template)
def on_before_transform_template(self, template_dict): """ Hook method that gets called before the SAM template is processed. The template has pass the validation and is guaranteed to contain a non-empty "Resources" section. :param dict template_dict: Dictionary of the SAM template :return: Nothing """ template = SamTemplate(template_dict) # Temporarily add Serverless::Api resource corresponding to Implicit API to the template. # This will allow the processing code to work the same way for both Implicit & Explicit APIs # If there are no implicit APIs, we will remove from the template later. # If the customer has explicitly defined a resource with the id of "ServerlessRestApi", # capture it. If the template ends up not defining any implicit api's, instead of just # removing the "ServerlessRestApi" resource, we just restore what the author defined. self.existing_implicit_api_resource = copy.deepcopy(template.get(self.implicit_api_logical_id)) template.set(self.implicit_api_logical_id, ImplicitApiResource().to_dict()) errors = [] for logicalId, function in template.iterate(SamResourceType.Function.value): api_events = self._get_api_events(function) condition = function.condition if len(api_events) == 0: continue try: self._process_api_events(function, api_events, template, condition) except InvalidEventException as ex: errors.append(InvalidResourceException(logicalId, ex.message)) self._maybe_add_condition_to_implicit_api(template_dict) self._maybe_add_conditions_to_implicit_api_paths(template) self._maybe_remove_implicit_api(template) if len(errors) > 0: raise InvalidDocumentException(errors)
def on_before_transform_template(self, template_dict): """ Hook method that runs before a template gets transformed. In this method, we parse and process Globals section from the template (if present). :param dict template_dict: SAM template as a dictionary """ try: global_section = Globals(template_dict) except InvalidGlobalsSectionException as ex: raise InvalidDocumentException([ex]) # For each resource in template, try and merge with Globals if necessary template = SamTemplate(template_dict) for logicalId, resource in template.iterate(): resource.properties = global_section.merge(resource.type, resource.properties) template.set(logicalId, resource) # Remove the Globals section from template if necessary Globals.del_section(template_dict)