def __validate_no_transforms_present(raw_fragments): if "transform" in raw_fragments or "Transform" in raw_fragments: raise FragmentValidationError( "Template fragment can't contain transform section.") if "Fn::Transform" in raw_fragments: raise FragmentValidationError( "Template fragment can't contain any transform.")
def __validate_no_exports_present(raw_fragments): if "Outputs" in raw_fragments: for _output_name, output in raw_fragments["Outputs"].items(): if "Export" in output: raise FragmentValidationError( "Template fragment cannot contain any Export. " "Found an Export statement in Output: " + _output_name)
def __validate_resource_limit(self, raw_fragments): resource_count = len(raw_fragments["Resources"].items()) if resource_count > self.resource_limit: raise FragmentValidationError( "The Module template fragment has " + str(resource_count) + " resources but must not exceed the limit of " + str(self.resource_limit) + " resources")
def __validate_parameters(raw_fragments): if "Parameters" in raw_fragments: for _parameter_name, parameter in raw_fragments["Parameters"].items(): if "Type" not in parameter: raise FragmentValidationError( "Parameter '" + _parameter_name + "' must have a Type" )
def __validate_file_size_limit(self): total_size = get_template_file_size_in_bytes(self.fragment_dir) if total_size > self.template_file_size_in_bytes_limit: raise FragmentValidationError( "The total file size of the template" " fragments exceeds the CloudFormation Template size limit" )
def _load_fragment(fragment_file): try: with open(fragment_file, "r", encoding="utf-8") as f: return load_yaml(__first_pass_syntax_check(f.read())) except (yaml.parser.ParserError, yaml.scanner.ScannerError) as e: raise FragmentValidationError( "Fragment file '{}' is invalid: {}".format(fragment_file, str(e)) ) from e
def _get_fragment_file(fragment_dir): all_fragment_files = [] for root, _directories, files in os.walk(fragment_dir): for f in files: ext = os.path.splitext(f)[-1].lower() if ext in ALLOWED_EXTENSIONS: all_fragment_files.append(os.path.join(root, f)) if len(all_fragment_files) == 0: raise FragmentValidationError( f"No module fragment files found in the fragments folder ending on one of {ALLOWED_EXTENSIONS}" ) if len(all_fragment_files) > 1: raise FragmentValidationError("A Module can only consist of a " "single template file, but there are " + str(len(all_fragment_files)) + ": " + str(all_fragment_files)) return all_fragment_files[0]
def __validate_output_limit(self, raw_fragments): if "Outputs" in raw_fragments: output_count = len(raw_fragments["Outputs"].items()) if output_count > self.output_limit: raise FragmentValidationError( "The Module template fragment has " + str(output_count) + " outputs but must not exceed the limit of " + str(self.output_limit) + " outputs")
def __validate_mapping_limit(self, raw_fragments): if "Mappings" in raw_fragments: mapping_count = len(raw_fragments["Mappings"].items()) if mapping_count > self.mapping_limit: raise FragmentValidationError( "The Module template fragment has " + str(mapping_count) + " mappings but must not exceed the limit of " + str(self.output_limit) + " mappings")
def _load_fragment(self, fragment_file): try: with open(fragment_file, "r", encoding="utf-8") as f: return yaml.safe_load( self.__first_pass_syntax_check( self.__convert_function(f.read()))) except (json.JSONDecodeError, yaml.parser.ParserError) as e: raise FragmentValidationError( "Fragment file '{}' is invalid: {}".format( fragment_file, str(e))) from e
def __validate_mapping_attribute_limit(self, raw_fragments): if "Mappings" in raw_fragments: for _mapping_name, mapping in raw_fragments["Mappings"].items(): attribute_count = len(mapping.items()) if attribute_count > self.mapping_attribute_limit: raise FragmentValidationError( "The mapping " + _mapping_name + " has " + str(attribute_count) + " attributes but must not exceed the limit of " + str(self.output_limit) + " mapping attributes")
def __validate_resources(self, raw_fragments): if "Resources" not in raw_fragments: raise FragmentValidationError( "A Module template fragment must have a Resources section" ) self.__validate_resource_limit(raw_fragments) for _resource_name, resource in raw_fragments["Resources"].items(): if "Type" in resource: self.__validate_no_nested_stacks(resource) self.__validate_no_macros(resource) elif "Name" in resource: self.__validate_no_include(resource) raise FragmentValidationError( "Resource '" + _resource_name + "' is invalid" ) else: raise FragmentValidationError( "Resource '" + _resource_name + "' has neither Type nor Name" )
def __validate_resources(self, raw_fragments): if "Resources" not in raw_fragments: raise FragmentValidationError( "A Module template fragment must have a Resources section" ) self.__validate_resource_limit(raw_fragments) for _resource_name, resource in raw_fragments["Resources"].items(): if "Type" in resource: if resource["Type"] == "AWS::CloudFormation::Stack": raise FragmentValidationError( "Template fragment can't contain nested stack." ) if resource["Type"] == "AWS::CloudFormation::Macro": raise FragmentValidationError( "Template fragment can't contain any macro." ) elif "Name" in resource: if resource["Name"] == "AWS::Include": raise FragmentValidationError( "Template fragment can't use AWS::Include transform." ) raise FragmentValidationError( "Resource '" + _resource_name + "' is invalid" ) else: raise FragmentValidationError( "Resource '" + _resource_name + "' has neither Type nor Name" )
def __first_pass_syntax_check(template): if "Fn::ImportValue" in template: raise FragmentValidationError( "Template fragment can't contain any Fn::ImportValue.") return template
def __validate_no_include(resource): if resource["Name"] == "AWS::Include": raise FragmentValidationError( "Template fragment can't use AWS::Include transform." )
def __validate_no_macros(resource): if resource["Type"] == "AWS::CloudFormation::Macro": raise FragmentValidationError("Template fragment can't contain any macro.")
def __validate_no_nested_stacks(resource): if resource["Type"] == "AWS::CloudFormation::Stack": raise FragmentValidationError( "Template fragment can't contain nested stack." )