-
Notifications
You must be signed in to change notification settings - Fork 163
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Modules] Support parsing Yaml fragments with CFN short forms (#699)
* Issue 693 [Modules] Support parsing Yaml fragments with CFN short forms * Issue 689 Only use cfn-flip for parsing module fragments * Issue 689 Apply cfn-lint to the original file To prevent any false warnings from we should apply cfn-lint to the original file and not rely on parsing and then serializing to json before running lint. * Issue 693 Better error message when there is no module fragment file * Issue 693 Ensure unhandled exceptions in cfn-lint don't block the user When something unexpected happens when cfn-lint parses the template we don't want to block the user from running cfn submit. This should be an edge case though as we already parse the template before running cfn-lint albeit using a different library.
- Loading branch information
1 parent
18399b2
commit 5b11f02
Showing
11 changed files
with
196 additions
and
133 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import json | ||
import logging | ||
|
||
import cfnlint.config | ||
import cfnlint.core | ||
|
||
from .module_fragment_reader import _get_fragment_file | ||
|
||
LOG = logging.getLogger(__name__) | ||
|
||
|
||
def print_cfn_lint_warnings(fragment_dir): | ||
lint_warnings = __get_cfn_lint_matches(fragment_dir) | ||
if not lint_warnings: | ||
LOG.warning("Module fragment is valid.") | ||
else: | ||
LOG.warning( | ||
"Module fragment might be valid, but there are " | ||
"warnings from cfn-lint " | ||
"(https://github.com/aws-cloudformation/cfn-python-lint):" | ||
) | ||
for lint_warning in lint_warnings: | ||
print( | ||
"\t{} (from rule {})".format(lint_warning.message, lint_warning.rule), | ||
) | ||
|
||
|
||
def __get_cfn_lint_matches(fragment_dir): | ||
filepath = _get_fragment_file(fragment_dir) | ||
try: | ||
try: | ||
template = cfnlint.decode.cfn_json.load(filepath) | ||
except json.decoder.JSONDecodeError: | ||
template = cfnlint.decode.cfn_yaml.load(filepath) | ||
except Exception as e: # pylint: disable=broad-except | ||
LOG.error( | ||
"Skipping cfn-lint validation due to an internal error.\n" | ||
"Please report this issue to the team (include rpdk.log file)\n" | ||
"Issue tracker: github.com/aws-cloudformation/cloudformation-cli/issues" | ||
) | ||
LOG.error(str(e)) | ||
return [] | ||
|
||
# Initialize the ruleset to be applied (no overrules, no excludes) | ||
rules = cfnlint.core.get_rules([], [], [], [], False, []) | ||
|
||
# Default region used by cfn-lint | ||
regions = ["us-east-1"] | ||
|
||
# Runs Warning and Error rules | ||
matches = cfnlint.core.run_checks(filepath, template, rules, regions) | ||
|
||
return matches |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import logging | ||
import os | ||
|
||
import yaml | ||
from cfn_tools import load_yaml | ||
|
||
from rpdk.core.exceptions import FragmentValidationError | ||
|
||
LOG = logging.getLogger(__name__) | ||
ALLOWED_EXTENSIONS = {".json", ".yaml", ".yml"} | ||
|
||
|
||
def read_raw_fragments(fragment_dir): | ||
return _load_fragment(_get_fragment_file(fragment_dir)) | ||
|
||
|
||
def get_template_file_size_in_bytes(fragment_dir): | ||
return os.stat(_get_fragment_file(fragment_dir)).st_size | ||
|
||
|
||
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 __first_pass_syntax_check(template): | ||
if "Fn::ImportValue" in template or "!ImportValue" in template: | ||
raise FragmentValidationError( | ||
"Template fragment can't contain any Fn::ImportValue." | ||
) | ||
return template |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
AWSTemplateFormatVersion: "2010-09-09" | ||
Resources: | ||
EC2Instance: | ||
Type: AWS::EC2::Instance | ||
Properties: | ||
ImageId: ami-09c5e030f74651050 | ||
UserData: | ||
Fn::Base64: !Sub | | ||
#!/bin/bash -e | ||
sudo yum install -y https://s3.region.amazonaws.com/amazon-ssm-region/latest/linux_amd64/amazon-ssm-agent.rpm | ||
sudo systemctl status amazon-ssm-agent | ||
sudo systemctl enable amazon-ssm-agent | ||
sudo systemctl start amazon-ssm-agent |
Oops, something went wrong.